Initializing camera...
++ Point your camera at a QR code to scan +
++ {{ tempSigner ? 'Private key loaded. Ready to sign transaction.' : 'Scan your private key QR code to sign the transfer without logging in.' }} +
+ + ++ Protect your keys with a password (recommended) +
++ Passwords do not match +
+- Your public display name (max 50 characters) -
-+ Your public display name (max 50 characters) +
+- Create a password to encrypt and secure your HTM wallet locally -
-- Passwords do not match -
+ ++ Warning: The QR code contains your PRIVATE KEY. Keep it secure and never share it with anyone. +
++ When enabled, tka application will create a HTM wallet + for you and store there your private keys immediately. + Otherwise only account will be created. +
+| + Asset + | ++ Balances + | ++ Total + | ++ Actions + | +
|---|---|---|---|
|
+
+
+
+
+
+
+
+
+ {{ balance.liquid.name }}
+
+
+
+ STAKED
+
+
+
+ {{ balance.liquid.symbol }}
+
+
+ {{ balance.liquid.assetNum }}
+
+ |
+
+
+
+
+
+
+
+ Liquid
+
+
+ {{ balance.liquid.displayBalance }}
+
+
+
+
+
+ Staked
+
+
+ {{ balance.vesting.displayBalance }}
+
+
+
+
+
+
+
+
+
+ Distribution
+
+ {{ (Number((balance.liquid.balance * 10000n / (balance.liquid.balance + balance.vesting.balance))) / 100).toFixed(1) }}% liquid ·
+ {{ (Number((balance.vesting.balance * 10000n / (balance.liquid.balance + balance.vesting.balance))) / 100).toFixed(1) }}% staked
+
+
+
+
+
+ No balance yet
+
+ |
+
+
+
+
+ {{ balance.displayTotal }}
+
+ |
+
+
+
+
+
+ |
+
+ {{ user.about }} +
++ No bio provided +
+ + ++ {{ user.name }} +
++ {{ user.about }} +
+Operational Key
+{{ user.operationalKey }}
+ Management Key
+{{ user.managementKey }}
+ Generating QR code...
diff --git a/src/components/htm/tokens/TokenCreationCard.vue b/src/components/htm/tokens/TokenCreationCard.vue
index c5f0df7fd0fadfa665e3847376e092b942a97f5f..178c434c7a40cdfdc30824c094306e86729fa7a2 100644
--- a/src/components/htm/tokens/TokenCreationCard.vue
+++ b/src/components/htm/tokens/TokenCreationCard.vue
@@ -11,6 +11,7 @@ import { Separator } from '@/components/ui/separator';
import { Textarea } from '@/components/ui/textarea';
import type { CTokenDisplayBase } from '@/stores/tokens.store';
import { copyText } from '@/utils/copy';
+import { toastError } from '@/utils/parse-error';
import type { validateTokenSymbol } from '@/utils/validators';
interface Props {
@@ -63,8 +64,8 @@ const copyAssetNum = async () => {
try {
copyText(String(props.generatedAssetNum));
toast.success('Asset Num copied to clipboard!');
- } catch (_error) {
- toast.error('Failed to copy Asset Num');
+ } catch {
+ toastError('Failed to copy Asset Num');
}
};
diff --git a/src/components/htm/tokens/TokenCreationForm.vue b/src/components/htm/tokens/TokenCreationForm.vue
index 8a371adf4e1a4273ca48793241753beb886cfeda..7aa5d13e93f5e7012e76f1e18202e96653aaa1e5 100644
--- a/src/components/htm/tokens/TokenCreationForm.vue
+++ b/src/components/htm/tokens/TokenCreationForm.vue
@@ -2,7 +2,6 @@
import type { asset, ITransaction } from '@hiveio/wax';
import { mdiRocket, mdiLoading } from '@mdi/js';
import type { asset_definition, asset_metadata_update, htm_operation } from '@mtyszczak-cargo/htm';
-import { toast } from 'vue-sonner';
import HTMTokenPreview from '@/components/htm/HTMTokenPreview.vue';
import TokenCreationCard from '@/components/htm/tokens/TokenCreationCard.vue';
@@ -15,6 +14,7 @@ import type { CTokenDisplayBase } from '@/stores/tokens.store';
import { useTokensStore } from '@/stores/tokens.store';
import { useWalletStore } from '@/stores/wallet.store';
import { getWax } from '@/stores/wax.store';
+import { debounce } from '@/utils/debouncers';
import { generateNAI as generateHTMNAI, parseAssetAmount, toVesting, assetNumFromNAI, naiFromAssetNum } from '@/utils/nai-tokens';
import { toastError } from '@/utils/parse-error';
import { waitForTransactionStatus } from '@/utils/transaction-status';
@@ -60,19 +60,19 @@ const createButtonState = computed(() => {
// Create token using HTM
const createToken = async () => {
if (!isFormValid.value) {
- toast.error('Please fill all required fields and agree to disclaimer');
+ toastError('Please fill all required fields and agree to disclaimer');
return;
}
// Check if user has a wallet connected
if (!tokensStore.wallet) {
- toast.error('Please connect your HTM wallet first');
+ toastError('Please connect your HTM wallet first');
return;
}
// Check if user has a wallet connected
if (walletStore.isL2Wallet) {
- toast.error('Please connect your L1 wallet first');
+ toastError('Please connect your L1 wallet first');
return;
}
@@ -83,7 +83,7 @@ const createToken = async () => {
const assetNum = generateAssetNum();
if (!assetNum) {
- toast.error('Failed to generate token Asset Num. Please try again.');
+ toastError('Failed to generate token Asset Num. Please try again.');
return;
}
}
@@ -107,7 +107,7 @@ const createToken = async () => {
nai: toVesting(nai, identifierPrecision),
precision: identifierPrecision
};
- const owner = CTokensProvider.getOperationalPublicKey()!;
+ const owner = tokensStore.getUserPublicKey()!;
const assetTokenName = tokenName.value.trim();
const trimmedSymbol = tokenSymbol.value.trim();
const trimmedDescription = tokenDescription.value.trim();
@@ -206,7 +206,7 @@ const previewToken = computed(() => {
return {
...formToken.value,
- ownerPublicKey: CTokensProvider.getOperationalPublicKey() || '',
+ ownerPublicKey: tokensStore.getUserPublicKey() || '',
displayTotalSupply: initialSupply.value || '0',
totalSupply: supplyValue,
maxSupply: capped.value ? supplyValue : BigInt(0),
@@ -249,27 +249,21 @@ const isFormValid = computed(() => {
// Symbol validation state
const symbolValidation = computed(() => validateTokenSymbol(tokenSymbol.value));
-// Debounced token ID generation
-let debounceTimer: NodeJS.Timeout | null = null;
-
// Auto-generate token ID when symbol changes (debounced)
-watch(tokenSymbol, (newSymbol) => {
- // Clear previous timer
- if (debounceTimer)
- clearTimeout(debounceTimer);
-
+watch(tokenSymbol, debounce((newSymbol) => {
// Reset state immediately when symbol is invalid
if (!validateTokenSymbol(newSymbol).isValid) {
generatedAssetNum.value = '';
return;
}
- // Debounce the generation to avoid excessive calls
- debounceTimer = setTimeout(() => {
- if (symbolValidation.value.isValid)
- generateAssetNum();
- }, 300); // Wait 300ms after user stops typing
-});
+ generateAssetNum();
+}));
+
+// Auto-generate token ID when symbol changes (debounced)
+watch(precision, debounce(() => {
+ generateAssetNum();
+}));
// Generate unique token ID
const generateAssetNum = (): string | undefined => {
diff --git a/src/components/htm/tokens/TokenStakeCard.vue b/src/components/htm/tokens/TokenStakeCard.vue
index 822c61f5effc07f69150603121911367f6a6d117..30ae45d4af68e52b97a68abf27fe917422d03d76 100644
--- a/src/components/htm/tokens/TokenStakeCard.vue
+++ b/src/components/htm/tokens/TokenStakeCard.vue
@@ -8,7 +8,7 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/com
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useSettingsStore } from '@/stores/settings.store';
-import type { CTokenBalanceDisplay, CTokenDefinitionDisplay } from '@/stores/tokens.store';
+import { useTokensStore, type CTokenBalanceDisplay, type CTokenDefinitionDisplay } from '@/stores/tokens.store';
import { useWalletStore } from '@/stores/wallet.store';
import { isVesting, toLiquid, toVesting } from '@/utils/nai-tokens';
import { toastError } from '@/utils/parse-error';
@@ -30,6 +30,7 @@ const emit = defineEmits<{
const settingsStore = useSettingsStore();
const walletStore = useWalletStore();
+const tokensStore = useTokensStore();
const router = useRouter();
const isStaking = ref(false);
@@ -100,7 +101,7 @@ const handleStake = async () => {
await waitForTransactionStatus(
() => ([{
token_transform_operation: {
- holder: CTokensProvider.getOperationalPublicKey()!,
+ holder: tokensStore.getUserPublicKey()!,
receiver: stakeForm.value.receiver || undefined,
amount: {
amount: stakeForm.value.amount,
@@ -170,7 +171,7 @@ const handleUnstake = async () => {
await waitForTransactionStatus(
() => ([{
token_transform_operation: {
- holder: CTokensProvider.getOperationalPublicKey()!,
+ holder: tokensStore.getUserPublicKey()!,
receiver: stakeForm.value.receiver || undefined,
amount: {
amount: stakeForm.value.amount,
diff --git a/src/components/htm/tokens/TokenTopHoldersCard.vue b/src/components/htm/tokens/TokenTopHoldersCard.vue
index 378c048fb8cd2ab152dedaecab669873ec7206f1..7e977b7381317b6ec94c886fcd5fa0502ef15aba 100644
--- a/src/components/htm/tokens/TokenTopHoldersCard.vue
+++ b/src/components/htm/tokens/TokenTopHoldersCard.vue
@@ -1,8 +1,12 @@
@@ -60,10 +91,11 @@ const props = defineProps<{
v-else-if="props.topHolders.length > 0"
class="space-y-2"
>
-
{{ holder.displayName }}
Copy holder address Copy holder address {{ favoritesStore.isAccountFavorited(holder.operationalKey) ? 'Remove from favorites' : 'Add to favorites' }}
Rank #{{ holder.rank }}
@@ -118,7 +178,7 @@ const props = defineProps<{
{{ props.token.symbol || 'tokens' }}
- Connect your wallet to transfer tokens -
-