mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-05-15 22:26:58 +00:00
commit
eeb66f4fa5
36
src/App.tsx
36
src/App.tsx
@ -1028,12 +1028,7 @@ function App() {
|
|||||||
|
|
||||||
const logoutFunc = useCallback(async () => {
|
const logoutFunc = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
if (hasSettingsChanged) {
|
if (extState === 'authenticated') {
|
||||||
await showUnsavedChanges({
|
|
||||||
message:
|
|
||||||
'Your settings have changed. If you logout you will lose your changes. Click on the save button in the header to keep your changed settings.',
|
|
||||||
}); // TODO translate
|
|
||||||
} else if (extState === 'authenticated') {
|
|
||||||
await showUnsavedChanges({
|
await showUnsavedChanges({
|
||||||
message: 'Are you sure you would like to logout?',
|
message: 'Are you sure you would like to logout?',
|
||||||
});
|
});
|
||||||
@ -3014,13 +3009,16 @@ function App() {
|
|||||||
})}
|
})}
|
||||||
</TextP>
|
</TextP>
|
||||||
<Spacer height="100px" />
|
<Spacer height="100px" />
|
||||||
<CustomButton
|
<ButtonBase
|
||||||
|
autoFocus
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
returnToMain();
|
returnToMain();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('core:action.continue', { postProcess: 'capitalize' })}
|
<CustomButton>
|
||||||
</CustomButton>
|
{t('core:action.continue', { postProcess: 'capitalize' })}
|
||||||
|
</CustomButton>
|
||||||
|
</ButtonBase>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{extState === 'transfer-success-request' && (
|
{extState === 'transfer-success-request' && (
|
||||||
@ -3221,7 +3219,7 @@ function App() {
|
|||||||
onClick={onOkUnsavedChanges}
|
onClick={onOkUnsavedChanges}
|
||||||
autoFocus
|
autoFocus
|
||||||
>
|
>
|
||||||
{t('core:action.decline', {
|
{t('core:action.continue_logout', {
|
||||||
postProcess: 'capitalize',
|
postProcess: 'capitalize',
|
||||||
})}
|
})}
|
||||||
</Button>
|
</Button>
|
||||||
@ -3270,6 +3268,8 @@ function App() {
|
|||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
maxWidth: '90%',
|
maxWidth: '90%',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
fontSize: '16px',
|
||||||
|
marginBottom: '10px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{messageQortalRequestExtension?.text1}
|
{messageQortalRequestExtension?.text1}
|
||||||
@ -3316,8 +3316,8 @@ function App() {
|
|||||||
>
|
>
|
||||||
{messageQortalRequestExtension?.text3}
|
{messageQortalRequestExtension?.text3}
|
||||||
</TextP>
|
</TextP>
|
||||||
<Spacer height="15px" />
|
|
||||||
</Box>
|
</Box>
|
||||||
|
<Spacer height="15px" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -3342,11 +3342,15 @@ function App() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{messageQortalRequestExtension?.html && (
|
{messageQortalRequestExtension?.html && (
|
||||||
<div
|
<>
|
||||||
dangerouslySetInnerHTML={{
|
<Spacer height="15px" />
|
||||||
__html: messageQortalRequestExtension?.html,
|
|
||||||
}}
|
<div
|
||||||
/>
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: messageQortalRequestExtension?.html,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<Spacer height="15px" />
|
<Spacer height="15px" />
|
||||||
|
|
||||||
|
@ -3689,7 +3689,7 @@ export const checkThreads = async (bringBack) => {
|
|||||||
dataToBringBack.push(thread);
|
dataToBringBack.push(thread);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
conosle.log({ error });
|
console.log({ error });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,8 +414,23 @@ export const AppsDesktop = ({
|
|||||||
setDesktopViewMode('dev');
|
setDesktopViewMode('dev');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconWrapper label="Dev" disableWidth>
|
<IconWrapper
|
||||||
<AppsIcon height={30} />
|
color={
|
||||||
|
desktopViewMode === 'dev'
|
||||||
|
? theme.palette.text.primary
|
||||||
|
: theme.palette.text.secondary
|
||||||
|
}
|
||||||
|
label="Dev"
|
||||||
|
disableWidth
|
||||||
|
>
|
||||||
|
<AppsIcon
|
||||||
|
color={
|
||||||
|
desktopViewMode === 'dev'
|
||||||
|
? theme.palette.text.primary
|
||||||
|
: theme.palette.text.secondary
|
||||||
|
}
|
||||||
|
height={30}
|
||||||
|
/>
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
)}
|
)}
|
||||||
|
@ -180,7 +180,7 @@ export const AppsDevModeNavBar = () => {
|
|||||||
>
|
>
|
||||||
<RefreshIcon
|
<RefreshIcon
|
||||||
sx={{
|
sx={{
|
||||||
color: 'rgba(250, 250, 250, 0.5)',
|
color: theme.palette.text.primary,
|
||||||
width: '40px',
|
width: '40px',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
}}
|
}}
|
||||||
|
@ -253,6 +253,7 @@ export const listOfAllQortalRequests = [
|
|||||||
'SELL_NAME',
|
'SELL_NAME',
|
||||||
'CANCEL_SELL_NAME',
|
'CANCEL_SELL_NAME',
|
||||||
'BUY_NAME',
|
'BUY_NAME',
|
||||||
|
'SIGN_FOREIGN_FEES',
|
||||||
'MULTI_ASSET_PAYMENT_WITH_PRIVATE_DATA',
|
'MULTI_ASSET_PAYMENT_WITH_PRIVATE_DATA',
|
||||||
'TRANSFER_ASSET',
|
'TRANSFER_ASSET',
|
||||||
];
|
];
|
||||||
@ -315,6 +316,7 @@ export const UIQortalRequests = [
|
|||||||
'SELL_NAME',
|
'SELL_NAME',
|
||||||
'CANCEL_SELL_NAME',
|
'CANCEL_SELL_NAME',
|
||||||
'BUY_NAME',
|
'BUY_NAME',
|
||||||
|
'SIGN_FOREIGN_FEES',
|
||||||
'MULTI_ASSET_PAYMENT_WITH_PRIVATE_DATA',
|
'MULTI_ASSET_PAYMENT_WITH_PRIVATE_DATA',
|
||||||
'TRANSFER_ASSET',
|
'TRANSFER_ASSET',
|
||||||
];
|
];
|
||||||
|
@ -159,6 +159,9 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
},
|
},
|
||||||
...prev,
|
...prev,
|
||||||
]);
|
]);
|
||||||
|
setName('');
|
||||||
|
setDescription('');
|
||||||
|
setGroupType('1');
|
||||||
res(response);
|
res(response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -430,12 +433,12 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
onChange={handleChangeApprovalThreshold}
|
onChange={handleChangeApprovalThreshold}
|
||||||
>
|
>
|
||||||
<MenuItem value={0}>
|
<MenuItem value={0}>
|
||||||
{t('core.count.none', {
|
{t('core:count.none', {
|
||||||
postProcess: 'capitalize',
|
postProcess: 'capitalize',
|
||||||
})}
|
})}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={1}>
|
<MenuItem value={1}>
|
||||||
{t('core.count.one', {
|
{t('core:count.one', {
|
||||||
postProcess: 'capitalize',
|
postProcess: 'capitalize',
|
||||||
})}
|
})}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -454,7 +457,7 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Label>
|
<Label>
|
||||||
{t('group.block_delay.minimum', {
|
{t('group:block_delay.minimum', {
|
||||||
postProcess: 'capitalize',
|
postProcess: 'capitalize',
|
||||||
})}
|
})}
|
||||||
</Label>
|
</Label>
|
||||||
@ -466,40 +469,40 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
onChange={handleChangeMinBlock}
|
onChange={handleChangeMinBlock}
|
||||||
>
|
>
|
||||||
<MenuItem value={5}>
|
<MenuItem value={5}>
|
||||||
{t('core.time.minute', { count: 5 })}
|
{t('core:time.minute', { count: 5 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={10}>
|
<MenuItem value={10}>
|
||||||
{t('core.time.minute', { count: 10 })}
|
{t('core:time.minute', { count: 10 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={30}>
|
<MenuItem value={30}>
|
||||||
{t('core.time.minute', { count: 30 })}
|
{t('core:time.minute', { count: 30 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={60}>
|
<MenuItem value={60}>
|
||||||
{t('core.time.hour', { count: 1 })}
|
{t('core:time.hour', { count: 1 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={180}>
|
<MenuItem value={180}>
|
||||||
{t('core.time.hour', { count: 3 })}
|
{t('core:time.hour', { count: 3 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={300}>
|
<MenuItem value={300}>
|
||||||
{t('core.time.hour', { count: 5 })}
|
{t('core:time.hour', { count: 5 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={420}>
|
<MenuItem value={420}>
|
||||||
{t('core.time.hour', { count: 7 })}
|
{t('core:time.hour', { count: 7 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={720}>
|
<MenuItem value={720}>
|
||||||
{t('core.time.hour', { count: 12 })}
|
{t('core:time.hour', { count: 12 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={1440}>
|
<MenuItem value={1440}>
|
||||||
{t('core.time.day', { count: 1 })}
|
{t('core:time.day', { count: 1 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={4320}>
|
<MenuItem value={4320}>
|
||||||
{t('core.time.day', { count: 3 })}
|
{t('core:time.day', { count: 3 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={7200}>
|
<MenuItem value={7200}>
|
||||||
{t('core.time.day', { count: 5 })}
|
{t('core:time.day', { count: 5 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={10080}>
|
<MenuItem value={10080}>
|
||||||
{t('core.time.day', { count: 7 })}
|
{t('core:time.day', { count: 7 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</Box>
|
</Box>
|
||||||
@ -511,7 +514,7 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Label>
|
<Label>
|
||||||
{t('group.block_delay.maximum', {
|
{t('group:block_delay.maximum', {
|
||||||
postProcess: 'capitalize',
|
postProcess: 'capitalize',
|
||||||
})}
|
})}
|
||||||
</Label>
|
</Label>
|
||||||
@ -523,37 +526,37 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
onChange={handleChangeMaxBlock}
|
onChange={handleChangeMaxBlock}
|
||||||
>
|
>
|
||||||
<MenuItem value={60}>
|
<MenuItem value={60}>
|
||||||
{t('core.time.hour', { count: 1 })}
|
{t('core:time.hour', { count: 1 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={180}>
|
<MenuItem value={180}>
|
||||||
3{t('core.time.hour', { count: 3 })}
|
3{t('core:time.hour', { count: 3 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={300}>
|
<MenuItem value={300}>
|
||||||
{t('core.time.hour', { count: 5 })}
|
{t('core:time.hour', { count: 5 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={420}>
|
<MenuItem value={420}>
|
||||||
{t('core.time.hour', { count: 7 })}
|
{t('core:time.hour', { count: 7 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={720}>
|
<MenuItem value={720}>
|
||||||
{t('core.time.hour', { count: 12 })}
|
{t('core:time.hour', { count: 12 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={1440}>
|
<MenuItem value={1440}>
|
||||||
{t('core.time.day', { count: 1 })}
|
{t('core:time.day', { count: 1 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={4320}>
|
<MenuItem value={4320}>
|
||||||
{t('core.time.day', { count: 3 })}
|
{t('core:time.day', { count: 3 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={7200}>
|
<MenuItem value={7200}>
|
||||||
{t('core.time.day', { count: 5 })}
|
{t('core:time.day', { count: 5 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={10080}>
|
<MenuItem value={10080}>
|
||||||
{t('core.time.day', { count: 7 })}
|
{t('core:time.day', { count: 7 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={14400}>
|
<MenuItem value={14400}>
|
||||||
{t('core.time.day', { count: 10 })}
|
{t('core:time.day', { count: 10 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value={21600}>
|
<MenuItem value={21600}>
|
||||||
{t('core.time.day', { count: 15 })}
|
{t('core:time.day', { count: 15 })}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</Box>
|
</Box>
|
||||||
@ -570,7 +573,7 @@ export const AddGroup = ({ address, open, setOpen }) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
onClick={handleCreateGroup}
|
onClick={handleCreateGroup}
|
||||||
>
|
>
|
||||||
{t('group.action.create', {
|
{t('group:action.create_group', {
|
||||||
postProcess: 'capitalize',
|
postProcess: 'capitalize',
|
||||||
})}
|
})}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -97,16 +97,16 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => {
|
|||||||
label={t('group:invitation_expiry', { postProcess: 'capitalize' })}
|
label={t('group:invitation_expiry', { postProcess: 'capitalize' })}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
>
|
>
|
||||||
<MenuItem value={10800}>{t('core.time.hour', { count: 3 })}</MenuItem>
|
<MenuItem value={10800}>{t('core:time.hour', { count: 3 })}</MenuItem>
|
||||||
<MenuItem value={21600}>{t('core.time.hour', { count: 6 })}</MenuItem>
|
<MenuItem value={21600}>{t('core:time.hour', { count: 6 })}</MenuItem>
|
||||||
<MenuItem value={43200}>{t('core.time.hour', { count: 12 })}</MenuItem>
|
<MenuItem value={43200}>{t('core:time.hour', { count: 12 })}</MenuItem>
|
||||||
<MenuItem value={86400}>{t('core.time.day', { count: 1 })}</MenuItem>
|
<MenuItem value={86400}>{t('core:time.day', { count: 1 })}</MenuItem>
|
||||||
<MenuItem value={259200}>{t('core.time.day', { count: 3 })}</MenuItem>
|
<MenuItem value={259200}>{t('core:time.day', { count: 3 })}</MenuItem>
|
||||||
<MenuItem value={432000}>{t('core.time.day', { count: 5 })}</MenuItem>
|
<MenuItem value={432000}>{t('core:time.day', { count: 5 })}</MenuItem>
|
||||||
<MenuItem value={604800}>{t('core.time.day', { count: 7 })}</MenuItem>
|
<MenuItem value={604800}>{t('core:time.day', { count: 7 })}</MenuItem>
|
||||||
<MenuItem value={864000}>{t('core.time.day', { count: 10 })}</MenuItem>
|
<MenuItem value={864000}>{t('core:time.day', { count: 10 })}</MenuItem>
|
||||||
<MenuItem value={1296000}>{t('core.time.day', { count: 15 })}</MenuItem>
|
<MenuItem value={1296000}>{t('core:time.day', { count: 15 })}</MenuItem>
|
||||||
<MenuItem value={2592000}>{t('core.time.day', { count: 30 })}</MenuItem>
|
<MenuItem value={2592000}>{t('core:time.day', { count: 30 })}</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
<Spacer height="20px" />
|
<Spacer height="20px" />
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
|
@ -158,6 +158,12 @@ export const QortPayment = ({ balance, show, onSuccess, defaultPaymentTo }) => {
|
|||||||
value={paymentPassword}
|
value={paymentPassword}
|
||||||
onChange={(e) => setPaymentPassword(e.target.value)}
|
onChange={(e) => setPaymentPassword(e.target.value)}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
if (isLoadingSendCoin) return;
|
||||||
|
sendCoinFunc();
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
@ -27,15 +27,25 @@ export const ReactionPicker = ({ onReaction }) => {
|
|||||||
if (showPicker) {
|
if (showPicker) {
|
||||||
setShowPicker(false);
|
setShowPicker(false);
|
||||||
} else {
|
} else {
|
||||||
// Get the button's position
|
|
||||||
const buttonRect = buttonRef.current.getBoundingClientRect();
|
const buttonRect = buttonRef.current.getBoundingClientRect();
|
||||||
const pickerWidth = 350;
|
const pickerWidth = 350;
|
||||||
|
const pickerHeight = 400; // Match Picker height prop
|
||||||
|
|
||||||
// Calculate position to align the right edge of the picker with the button's right edge
|
// Initial position (below the button)
|
||||||
setPickerPosition({
|
let top = buttonRect.bottom + window.scrollY;
|
||||||
top: buttonRect.bottom + window.scrollY, // Position below the button
|
let left = buttonRect.right + window.scrollX - pickerWidth;
|
||||||
left: buttonRect.right + window.scrollX - pickerWidth, // Align right edges
|
|
||||||
});
|
// If picker would overflow bottom, show it above the button
|
||||||
|
const overflowBottom =
|
||||||
|
top + pickerHeight > window.innerHeight + window.scrollY;
|
||||||
|
if (overflowBottom) {
|
||||||
|
top = buttonRect.top + window.scrollY - pickerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: prevent overflow on the left too
|
||||||
|
if (left < 0) left = 0;
|
||||||
|
|
||||||
|
setPickerPosition({ top, left });
|
||||||
setShowPicker(true);
|
setShowPicker(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -92,12 +102,13 @@ export const ReactionPicker = ({ onReaction }) => {
|
|||||||
allowExpandReactions={true}
|
allowExpandReactions={true}
|
||||||
autoFocusSearch={false}
|
autoFocusSearch={false}
|
||||||
emojiStyle={EmojiStyle.NATIVE}
|
emojiStyle={EmojiStyle.NATIVE}
|
||||||
height="450"
|
height={400}
|
||||||
onEmojiClick={handlePicker}
|
onEmojiClick={handlePicker}
|
||||||
onReactionClick={handleReaction}
|
onReactionClick={handleReaction}
|
||||||
reactionsDefaultOpen={true}
|
// reactionsDefaultOpen={true}
|
||||||
|
// open={true}
|
||||||
theme={Theme.DARK}
|
theme={Theme.DARK}
|
||||||
width="350"
|
width={350}
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
document.body
|
document.body
|
||||||
|
@ -25,7 +25,7 @@ const ThemeContext = createContext({
|
|||||||
toggleTheme: () => {},
|
toggleTheme: () => {},
|
||||||
userThemes: [defaultTheme],
|
userThemes: [defaultTheme],
|
||||||
addUserTheme: (themes) => {},
|
addUserTheme: (themes) => {},
|
||||||
setUserTheme: (theme) => {},
|
setUserTheme: (theme, themes) => {},
|
||||||
currentThemeId: 'default',
|
currentThemeId: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -83,13 +83,13 @@ export const ThemeProvider = ({ children }) => {
|
|||||||
saveSettings(themes);
|
saveSettings(themes);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setUserTheme = (theme) => {
|
const setUserTheme = (theme, themes) => {
|
||||||
if (theme.id === 'default') {
|
if (theme.id === 'default') {
|
||||||
setCurrentThemeId('default');
|
setCurrentThemeId('default');
|
||||||
saveSettings(userThemes, themeMode, 'default');
|
saveSettings(themes || userThemes, themeMode, 'default');
|
||||||
} else {
|
} else {
|
||||||
setCurrentThemeId(theme.id);
|
setCurrentThemeId(theme.id);
|
||||||
saveSettings(userThemes, themeMode, theme.id);
|
saveSettings(themes || userThemes, themeMode, theme.id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ export default function ThemeManager() {
|
|||||||
const newTheme = { ...themeDraft, id: uid.rnd() };
|
const newTheme = { ...themeDraft, id: uid.rnd() };
|
||||||
const updatedThemes = [...userThemes, newTheme];
|
const updatedThemes = [...userThemes, newTheme];
|
||||||
addUserTheme(updatedThemes);
|
addUserTheme(updatedThemes);
|
||||||
setUserTheme(newTheme);
|
setUserTheme(newTheme, updatedThemes);
|
||||||
}
|
}
|
||||||
setOpenEditor(false);
|
setOpenEditor(false);
|
||||||
};
|
};
|
||||||
@ -135,19 +135,22 @@ export default function ThemeManager() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (defaultTheme) {
|
if (defaultTheme) {
|
||||||
setUserTheme(defaultTheme);
|
setUserTheme(defaultTheme, updatedThemes);
|
||||||
} else {
|
} else {
|
||||||
// Emergency fallback
|
// Emergency fallback
|
||||||
setUserTheme({
|
setUserTheme(
|
||||||
light: lightThemeOptions,
|
{
|
||||||
dark: darkThemeOptions,
|
light: lightThemeOptions,
|
||||||
});
|
dark: darkThemeOptions,
|
||||||
|
},
|
||||||
|
updatedThemes
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleApplyTheme = (theme) => {
|
const handleApplyTheme = (theme) => {
|
||||||
setUserTheme(theme);
|
setUserTheme(theme, null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleColorChange = (mode, fieldPath, color) => {
|
const handleColorChange = (mode, fieldPath, color) => {
|
||||||
@ -210,7 +213,8 @@ export default function ThemeManager() {
|
|||||||
const newTheme = { ...importedTheme, id: uid.rnd() };
|
const newTheme = { ...importedTheme, id: uid.rnd() };
|
||||||
const updatedThemes = [...userThemes, newTheme];
|
const updatedThemes = [...userThemes, newTheme];
|
||||||
addUserTheme(updatedThemes);
|
addUserTheme(updatedThemes);
|
||||||
setUserTheme(newTheme);
|
|
||||||
|
setUserTheme(newTheme, updatedThemes);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ import {
|
|||||||
buyNameRequest,
|
buyNameRequest,
|
||||||
sellNameRequest,
|
sellNameRequest,
|
||||||
cancelSellNameRequest,
|
cancelSellNameRequest,
|
||||||
|
signForeignFees,
|
||||||
multiPaymentWithPrivateData,
|
multiPaymentWithPrivateData,
|
||||||
transferAssetRequest,
|
transferAssetRequest,
|
||||||
} from './qortalRequests/get';
|
} from './qortalRequests/get';
|
||||||
@ -754,7 +755,7 @@ function setupMessageListenerQortalRequest() {
|
|||||||
|
|
||||||
case 'UPDATE_FOREIGN_FEE': {
|
case 'UPDATE_FOREIGN_FEE': {
|
||||||
try {
|
try {
|
||||||
const res = await updateForeignFee(request.payload);
|
const res = await updateForeignFee(request.payload, isFromExtension);
|
||||||
event.source.postMessage(
|
event.source.postMessage(
|
||||||
{
|
{
|
||||||
requestId: request.requestId,
|
requestId: request.requestId,
|
||||||
@ -806,7 +807,10 @@ function setupMessageListenerQortalRequest() {
|
|||||||
|
|
||||||
case 'SET_CURRENT_FOREIGN_SERVER': {
|
case 'SET_CURRENT_FOREIGN_SERVER': {
|
||||||
try {
|
try {
|
||||||
const res = await setCurrentForeignServer(request.payload);
|
const res = await setCurrentForeignServer(
|
||||||
|
request.payload,
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
event.source.postMessage(
|
event.source.postMessage(
|
||||||
{
|
{
|
||||||
requestId: request.requestId,
|
requestId: request.requestId,
|
||||||
@ -832,7 +836,7 @@ function setupMessageListenerQortalRequest() {
|
|||||||
|
|
||||||
case 'ADD_FOREIGN_SERVER': {
|
case 'ADD_FOREIGN_SERVER': {
|
||||||
try {
|
try {
|
||||||
const res = await addForeignServer(request.payload);
|
const res = await addForeignServer(request.payload, isFromExtension);
|
||||||
event.source.postMessage(
|
event.source.postMessage(
|
||||||
{
|
{
|
||||||
requestId: request.requestId,
|
requestId: request.requestId,
|
||||||
@ -858,7 +862,10 @@ function setupMessageListenerQortalRequest() {
|
|||||||
|
|
||||||
case 'REMOVE_FOREIGN_SERVER': {
|
case 'REMOVE_FOREIGN_SERVER': {
|
||||||
try {
|
try {
|
||||||
const res = await removeForeignServer(request.payload);
|
const res = await removeForeignServer(
|
||||||
|
request.payload,
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
event.source.postMessage(
|
event.source.postMessage(
|
||||||
{
|
{
|
||||||
requestId: request.requestId,
|
requestId: request.requestId,
|
||||||
@ -1892,6 +1899,32 @@ function setupMessageListenerQortalRequest() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'SIGN_FOREIGN_FEES': {
|
||||||
|
try {
|
||||||
|
const res = await signForeignFees(request.payload, isFromExtension);
|
||||||
|
event.source.postMessage(
|
||||||
|
{
|
||||||
|
requestId: request.requestId,
|
||||||
|
action: request.action,
|
||||||
|
payload: res,
|
||||||
|
type: 'backgroundMessageResponse',
|
||||||
|
},
|
||||||
|
event.origin
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
event.source.postMessage(
|
||||||
|
{
|
||||||
|
requestId: request.requestId,
|
||||||
|
action: request.action,
|
||||||
|
error: error.message,
|
||||||
|
type: 'backgroundMessageResponse',
|
||||||
|
},
|
||||||
|
event.origin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1302,10 +1302,7 @@ export const publishMultipleQDNResources = async (
|
|||||||
html: `
|
html: `
|
||||||
<div style="max-height: 30vh; overflow-y: auto;">
|
<div style="max-height: 30vh; overflow-y: auto;">
|
||||||
<style>
|
<style>
|
||||||
body {
|
|
||||||
background-color: #121212;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resource-container {
|
.resource-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1314,7 +1311,7 @@ export const publishMultipleQDNResources = async (
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #1e1e1e;
|
background-color: var(--background-default);
|
||||||
}
|
}
|
||||||
|
|
||||||
.resource-detail {
|
.resource-detail {
|
||||||
@ -1323,7 +1320,7 @@ export const publishMultipleQDNResources = async (
|
|||||||
|
|
||||||
.resource-detail span {
|
.resource-detail span {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #bb86fc;
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 600px) {
|
@media (min-width: 600px) {
|
||||||
@ -2658,7 +2655,12 @@ export const getForeignFee = async (data) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateForeignFee = async (data) => {
|
function calculateRateFromFee(totalFee, sizeInBytes) {
|
||||||
|
const fee = (totalFee / sizeInBytes) * 1000;
|
||||||
|
return fee.toFixed(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateForeignFee = async (data, isFromExtension) => {
|
||||||
const isGateway = await isRunningGateway();
|
const isGateway = await isRunningGateway();
|
||||||
if (isGateway) {
|
if (isGateway) {
|
||||||
throw new Error('This action cannot be done through a public node');
|
throw new Error('This action cannot be done through a public node');
|
||||||
@ -2679,33 +2681,52 @@ export const updateForeignFee = async (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { coin, type, value } = data;
|
const { coin, type, value } = data;
|
||||||
const url = `/crosschain/${coin.toLowerCase()}/update${type}`;
|
|
||||||
|
|
||||||
try {
|
const text3 =
|
||||||
const endpoint = await createEndpoint(url);
|
type === 'feerequired' ? `${value} sats` : `${value} sats per kb`;
|
||||||
const response = await fetch(endpoint, {
|
const text4 =
|
||||||
method: 'POST',
|
type === 'feerequired'
|
||||||
headers: {
|
? `*The ${value} sats fee is derived from ${calculateRateFromFee(value, 300)} sats per kb, for a transaction that is approximately 300 bytes in size.`
|
||||||
Accept: '*/*',
|
: '';
|
||||||
'Content-Type': 'application/json',
|
const resPermission = await getUserPermission(
|
||||||
},
|
{
|
||||||
body: JSON.stringify({ value }),
|
text1: `Do you give this application permission to update foreign fees on your node?`,
|
||||||
});
|
text2: `type: ${type === 'feerequired' ? 'unlocking' : 'locking'}`,
|
||||||
|
text3: `value: ${text3}`,
|
||||||
|
text4,
|
||||||
|
highlightedText: `Coin: ${coin}`,
|
||||||
|
},
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
|
|
||||||
if (!response.ok) throw new Error('Failed to update foreign fee');
|
const { accepted } = resPermission;
|
||||||
let res;
|
if (!accepted) {
|
||||||
try {
|
throw new Error('User declined request');
|
||||||
res = await response.clone().json();
|
|
||||||
} catch (e) {
|
|
||||||
res = await response.text();
|
|
||||||
}
|
|
||||||
if (res?.error && res?.message) {
|
|
||||||
throw new Error(res.message);
|
|
||||||
}
|
|
||||||
return res; // Return full response here
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(error?.message || 'Error in update foreign fee');
|
|
||||||
}
|
}
|
||||||
|
const url = `/crosschain/${coin.toLowerCase()}/update${type}`;
|
||||||
|
const valueStringified = JSON.stringify(+value);
|
||||||
|
|
||||||
|
const endpoint = await createEndpoint(url);
|
||||||
|
const response = await fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: valueStringified,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to update foreign fee');
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
res = await response.clone().json();
|
||||||
|
} catch (e) {
|
||||||
|
res = await response.text();
|
||||||
|
}
|
||||||
|
if (res?.error && res?.message) {
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
return res; // Return full response here
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getServerConnectionHistory = async (data) => {
|
export const getServerConnectionHistory = async (data) => {
|
||||||
@ -2758,7 +2779,7 @@ export const getServerConnectionHistory = async (data) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setCurrentForeignServer = async (data) => {
|
export const setCurrentForeignServer = async (data, isFromExtension) => {
|
||||||
const isGateway = await isRunningGateway();
|
const isGateway = await isRunningGateway();
|
||||||
if (isGateway) {
|
if (isGateway) {
|
||||||
throw new Error('This action cannot be done through a public node');
|
throw new Error('This action cannot be done through a public node');
|
||||||
@ -2780,6 +2801,21 @@ export const setCurrentForeignServer = async (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { coin, host, port, type } = data;
|
const { coin, host, port, type } = data;
|
||||||
|
|
||||||
|
const resPermission = await getUserPermission(
|
||||||
|
{
|
||||||
|
text1: `Do you give this application permission to set the current server?`,
|
||||||
|
text2: `type: ${type}`,
|
||||||
|
text3: `host: ${host}`,
|
||||||
|
highlightedText: `Coin: ${coin}`,
|
||||||
|
},
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
const { accepted } = resPermission;
|
||||||
|
if (!accepted) {
|
||||||
|
throw new Error('User declined request');
|
||||||
|
}
|
||||||
const body = {
|
const body = {
|
||||||
hostName: host,
|
hostName: host,
|
||||||
port: port,
|
port: port,
|
||||||
@ -2788,37 +2824,33 @@ export const setCurrentForeignServer = async (data) => {
|
|||||||
|
|
||||||
const url = `/crosschain/${coin.toLowerCase()}/setcurrentserver`;
|
const url = `/crosschain/${coin.toLowerCase()}/setcurrentserver`;
|
||||||
|
|
||||||
|
const endpoint = await createEndpoint(url); // Assuming createEndpoint is available
|
||||||
|
const response = await fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to set current server');
|
||||||
|
|
||||||
|
let res;
|
||||||
try {
|
try {
|
||||||
const endpoint = await createEndpoint(url); // Assuming createEndpoint is available
|
res = await response.clone().json();
|
||||||
const response = await fetch(endpoint, {
|
} catch (e) {
|
||||||
method: 'POST',
|
res = await response.text();
|
||||||
headers: {
|
|
||||||
Accept: '*/*',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) throw new Error('Failed to set current server');
|
|
||||||
|
|
||||||
let res;
|
|
||||||
try {
|
|
||||||
res = await response.clone().json();
|
|
||||||
} catch (e) {
|
|
||||||
res = await response.text();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res?.error && res?.message) {
|
|
||||||
throw new Error(res.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res; // Return the full response
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(error?.message || 'Error in set current server');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res?.error && res?.message) {
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res; // Return the full response
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addForeignServer = async (data) => {
|
export const addForeignServer = async (data, isFromExtension) => {
|
||||||
const isGateway = await isRunningGateway();
|
const isGateway = await isRunningGateway();
|
||||||
if (isGateway) {
|
if (isGateway) {
|
||||||
throw new Error('This action cannot be done through a public node');
|
throw new Error('This action cannot be done through a public node');
|
||||||
@ -2840,6 +2872,21 @@ export const addForeignServer = async (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { coin, host, port, type } = data;
|
const { coin, host, port, type } = data;
|
||||||
|
|
||||||
|
const resPermission = await getUserPermission(
|
||||||
|
{
|
||||||
|
text1: `Do you give this application permission to add a server?`,
|
||||||
|
text2: `type: ${type}`,
|
||||||
|
text3: `host: ${host}`,
|
||||||
|
highlightedText: `Coin: ${coin}`,
|
||||||
|
},
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
const { accepted } = resPermission;
|
||||||
|
if (!accepted) {
|
||||||
|
throw new Error('User declined request');
|
||||||
|
}
|
||||||
const body = {
|
const body = {
|
||||||
hostName: host,
|
hostName: host,
|
||||||
port: port,
|
port: port,
|
||||||
@ -2848,37 +2895,33 @@ export const addForeignServer = async (data) => {
|
|||||||
|
|
||||||
const url = `/crosschain/${coin.toLowerCase()}/addserver`;
|
const url = `/crosschain/${coin.toLowerCase()}/addserver`;
|
||||||
|
|
||||||
|
const endpoint = await createEndpoint(url); // Assuming createEndpoint is available
|
||||||
|
const response = await fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to add server');
|
||||||
|
|
||||||
|
let res;
|
||||||
try {
|
try {
|
||||||
const endpoint = await createEndpoint(url); // Assuming createEndpoint is available
|
res = await response.clone().json();
|
||||||
const response = await fetch(endpoint, {
|
} catch (e) {
|
||||||
method: 'POST',
|
res = await response.text();
|
||||||
headers: {
|
|
||||||
Accept: '*/*',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) throw new Error('Failed to add server');
|
|
||||||
|
|
||||||
let res;
|
|
||||||
try {
|
|
||||||
res = await response.clone().json();
|
|
||||||
} catch (e) {
|
|
||||||
res = await response.text();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res?.error && res?.message) {
|
|
||||||
throw new Error(res.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res; // Return the full response
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(error.message || 'Error in adding server');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res?.error && res?.message) {
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res; // Return the full response
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeForeignServer = async (data) => {
|
export const removeForeignServer = async (data, isFromExtension) => {
|
||||||
const isGateway = await isRunningGateway();
|
const isGateway = await isRunningGateway();
|
||||||
if (isGateway) {
|
if (isGateway) {
|
||||||
throw new Error('This action cannot be done through a public node');
|
throw new Error('This action cannot be done through a public node');
|
||||||
@ -2900,6 +2943,21 @@ export const removeForeignServer = async (data) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { coin, host, port, type } = data;
|
const { coin, host, port, type } = data;
|
||||||
|
|
||||||
|
const resPermission = await getUserPermission(
|
||||||
|
{
|
||||||
|
text1: `Do you give this application permission to remove a server?`,
|
||||||
|
text2: `type: ${type}`,
|
||||||
|
text3: `host: ${host}`,
|
||||||
|
highlightedText: `Coin: ${coin}`,
|
||||||
|
},
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
const { accepted } = resPermission;
|
||||||
|
if (!accepted) {
|
||||||
|
throw new Error('User declined request');
|
||||||
|
}
|
||||||
const body = {
|
const body = {
|
||||||
hostName: host,
|
hostName: host,
|
||||||
port: port,
|
port: port,
|
||||||
@ -2908,34 +2966,30 @@ export const removeForeignServer = async (data) => {
|
|||||||
|
|
||||||
const url = `/crosschain/${coin.toLowerCase()}/removeserver`;
|
const url = `/crosschain/${coin.toLowerCase()}/removeserver`;
|
||||||
|
|
||||||
|
const endpoint = await createEndpoint(url); // Assuming createEndpoint is available
|
||||||
|
const response = await fetch(endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to remove server');
|
||||||
|
|
||||||
|
let res;
|
||||||
try {
|
try {
|
||||||
const endpoint = await createEndpoint(url); // Assuming createEndpoint is available
|
res = await response.clone().json();
|
||||||
const response = await fetch(endpoint, {
|
} catch (e) {
|
||||||
method: 'POST',
|
res = await response.text();
|
||||||
headers: {
|
|
||||||
Accept: '*/*',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) throw new Error('Failed to remove server');
|
|
||||||
|
|
||||||
let res;
|
|
||||||
try {
|
|
||||||
res = await response.clone().json();
|
|
||||||
} catch (e) {
|
|
||||||
res = await response.text();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res?.error && res?.message) {
|
|
||||||
throw new Error(res.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res; // Return the full response
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(error?.message || 'Error in removing server');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res?.error && res?.message) {
|
||||||
|
throw new Error(res.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res; // Return the full response
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDaySummary = async () => {
|
export const getDaySummary = async () => {
|
||||||
@ -3493,6 +3547,35 @@ export const sendCoin = async (data, isFromExtension) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function calculateFeeFromRate(feePerKb, sizeInBytes) {
|
||||||
|
return (feePerKb / 1000) * sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBuyingFees = async (foreignBlockchain) => {
|
||||||
|
const ticker = sellerForeignFee[foreignBlockchain].ticker;
|
||||||
|
if (!ticker) throw new Error('invalid foreign blockchain');
|
||||||
|
const unlockFee = await getForeignFee({
|
||||||
|
coin: ticker,
|
||||||
|
type: 'feerequired',
|
||||||
|
});
|
||||||
|
const lockFee = await getForeignFee({
|
||||||
|
coin: ticker,
|
||||||
|
type: 'feekb',
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
ticker: ticker,
|
||||||
|
lock: {
|
||||||
|
sats: lockFee,
|
||||||
|
fee: lockFee / QORT_DECIMALS,
|
||||||
|
},
|
||||||
|
unlock: {
|
||||||
|
sats: unlockFee,
|
||||||
|
fee: unlockFee / QORT_DECIMALS,
|
||||||
|
feePerKb: +calculateRateFromFee(+unlockFee, 300) / QORT_DECIMALS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const createBuyOrder = async (data, isFromExtension) => {
|
export const createBuyOrder = async (data, isFromExtension) => {
|
||||||
const requiredFields = ['crosschainAtInfo', 'foreignBlockchain'];
|
const requiredFields = ['crosschainAtInfo', 'foreignBlockchain'];
|
||||||
const missingFields: string[] = [];
|
const missingFields: string[] = [];
|
||||||
@ -3528,6 +3611,7 @@ export const createBuyOrder = async (data, isFromExtension) => {
|
|||||||
|
|
||||||
const crosschainAtInfo = await Promise.all(atPromises);
|
const crosschainAtInfo = await Promise.all(atPromises);
|
||||||
try {
|
try {
|
||||||
|
const buyingFees = await getBuyingFees(foreignBlockchain);
|
||||||
const resPermission = await getUserPermission(
|
const resPermission = await getUserPermission(
|
||||||
{
|
{
|
||||||
text1:
|
text1:
|
||||||
@ -3541,10 +3625,45 @@ export const createBuyOrder = async (data, isFromExtension) => {
|
|||||||
return latest + +cur?.expectedForeignAmount;
|
return latest + +cur?.expectedForeignAmount;
|
||||||
}, 0)
|
}, 0)
|
||||||
)}
|
)}
|
||||||
${` ${crosschainAtInfo?.[0]?.foreignBlockchain}`}`,
|
${` ${buyingFees.ticker}`}`,
|
||||||
highlightedText: `Is using public node: ${isGateway}`,
|
highlightedText: `Is using public node: ${isGateway}`,
|
||||||
fee: '',
|
fee: '',
|
||||||
foreignFee: `${sellerForeignFee[foreignBlockchain].value} ${sellerForeignFee[foreignBlockchain].ticker}`,
|
html: `
|
||||||
|
<div style="max-height: 30vh; overflow-y: auto; font-family: sans-serif;">
|
||||||
|
<style>
|
||||||
|
.fee-container {
|
||||||
|
background-color: var(--background-default);
|
||||||
|
color: var(--text-primary);
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.fee-label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.fee-description {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="fee-container">
|
||||||
|
<div class="fee-label">Total Unlocking Fee:</div>
|
||||||
|
<div>${(+buyingFees?.unlock?.fee * atAddresses?.length)?.toFixed(8)} ${buyingFees.ticker}</div>
|
||||||
|
<div class="fee-description">
|
||||||
|
This fee is an estimate based on ${atAddresses?.length} ${atAddresses?.length > 1 ? 'orders' : 'order'}, assuming a 300-byte size at a rate of ${buyingFees?.unlock?.feePerKb?.toFixed(8)} ${buyingFees.ticker} per KB.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="fee-label">Total Locking Fee:</div>
|
||||||
|
<div>${+buyingFees?.lock.fee.toFixed(8)} ${buyingFees.ticker} per kb</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
isFromExtension
|
isFromExtension
|
||||||
);
|
);
|
||||||
@ -4934,6 +5053,70 @@ export const buyNameRequest = async (data, isFromExtension) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const signForeignFees = async (data, isFromExtension) => {
|
||||||
|
const resPermission = await getUserPermission(
|
||||||
|
{
|
||||||
|
text1: `Do you give this application permission to sign the required fees for all your trade offers?`,
|
||||||
|
},
|
||||||
|
isFromExtension
|
||||||
|
);
|
||||||
|
const { accepted } = resPermission;
|
||||||
|
if (accepted) {
|
||||||
|
const wallet = await getSaveWallet();
|
||||||
|
const address = wallet.address0;
|
||||||
|
const resKeyPair = await getKeyPair();
|
||||||
|
const parsedData = resKeyPair;
|
||||||
|
const uint8PrivateKey = Base58.decode(parsedData.privateKey);
|
||||||
|
const uint8PublicKey = Base58.decode(parsedData.publicKey);
|
||||||
|
const keyPair = {
|
||||||
|
privateKey: uint8PrivateKey,
|
||||||
|
publicKey: uint8PublicKey,
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsignedFeesUrl = await createEndpoint(
|
||||||
|
`/crosschain/unsignedfees/${address}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const unsignedFeesResponse = await fetch(unsignedFeesUrl);
|
||||||
|
|
||||||
|
const unsignedFees = await unsignedFeesResponse.json();
|
||||||
|
|
||||||
|
const signedFees = [];
|
||||||
|
|
||||||
|
unsignedFees.forEach((unsignedFee) => {
|
||||||
|
const unsignedDataDecoded = Base58.decode(unsignedFee.data);
|
||||||
|
|
||||||
|
const signature = nacl.sign.detached(
|
||||||
|
unsignedDataDecoded,
|
||||||
|
keyPair.privateKey
|
||||||
|
);
|
||||||
|
|
||||||
|
const signedFee = {
|
||||||
|
timestamp: unsignedFee.timestamp,
|
||||||
|
data: `${Base58.encode(signature)}`,
|
||||||
|
atAddress: unsignedFee.atAddress,
|
||||||
|
fee: unsignedFee.fee,
|
||||||
|
};
|
||||||
|
|
||||||
|
signedFees.push(signedFee);
|
||||||
|
});
|
||||||
|
|
||||||
|
const signedFeesUrl = await createEndpoint(`/crosschain/signedfees`);
|
||||||
|
|
||||||
|
await fetch(signedFeesUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: `${JSON.stringify(signedFees)}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Error('User declined request');
|
||||||
|
}
|
||||||
|
};
|
||||||
export const multiPaymentWithPrivateData = async (data, isFromExtension) => {
|
export const multiPaymentWithPrivateData = async (data, isFromExtension) => {
|
||||||
const requiredFields = ['payments', 'assetId'];
|
const requiredFields = ['payments', 'assetId'];
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -5075,19 +5258,15 @@ export const multiPaymentWithPrivateData = async (data, isFromExtension) => {
|
|||||||
html: `
|
html: `
|
||||||
<div style="max-height: 30vh; overflow-y: auto;">
|
<div style="max-height: 30vh; overflow-y: auto;">
|
||||||
<style>
|
<style>
|
||||||
body {
|
|
||||||
background-color: #121212;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resource-container {
|
.resource-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 1px solid #444;
|
border: 1px solid;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #1e1e1e;
|
background-color: var(--background-default);
|
||||||
}
|
}
|
||||||
|
|
||||||
.resource-detail {
|
.resource-detail {
|
||||||
@ -5096,7 +5275,7 @@ export const multiPaymentWithPrivateData = async (data, isFromExtension) => {
|
|||||||
|
|
||||||
.resource-detail span {
|
.resource-detail span {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #bb86fc;
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 600px) {
|
@media (min-width: 600px) {
|
||||||
|
@ -55,6 +55,11 @@ export const darkThemeOptions: ThemeOptions = {
|
|||||||
'--bg-primary': 'rgba(31, 32, 35, 1)',
|
'--bg-primary': 'rgba(31, 32, 35, 1)',
|
||||||
'--bg-2': 'rgb(39, 40, 44)',
|
'--bg-2': 'rgb(39, 40, 44)',
|
||||||
'--primary-main': theme.palette.primary.main,
|
'--primary-main': theme.palette.primary.main,
|
||||||
|
'--text-primary': theme.palette.text.primary,
|
||||||
|
'--text-secondary': theme.palette.text.secondary,
|
||||||
|
'--background-default': theme.palette.background.default,
|
||||||
|
'--background-paper': theme.palette.background.paper,
|
||||||
|
'--background-surface': theme.palette.background.surface,
|
||||||
},
|
},
|
||||||
'*, *::before, *::after': {
|
'*, *::before, *::after': {
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
|
@ -55,6 +55,11 @@ export const lightThemeOptions: ThemeOptions = {
|
|||||||
'--bg-primary': 'rgba(31, 32, 35, 1)',
|
'--bg-primary': 'rgba(31, 32, 35, 1)',
|
||||||
'--bg-2': 'rgba(39, 40, 44, 1)',
|
'--bg-2': 'rgba(39, 40, 44, 1)',
|
||||||
'--primary-main': theme.palette.primary.main,
|
'--primary-main': theme.palette.primary.main,
|
||||||
|
'--text-primary': theme.palette.text.primary,
|
||||||
|
'--text-secondary': theme.palette.text.secondary,
|
||||||
|
'--background-default': theme.palette.background.default,
|
||||||
|
'--background-paper': theme.palette.background.paper,
|
||||||
|
'--background-surface': theme.palette.background.surface,
|
||||||
},
|
},
|
||||||
|
|
||||||
'*, *::before, *::after': {
|
'*, *::before, *::after': {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user