mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-06-13 00:51:02 +00:00
fix: universal getSigner helper for WalletConnect + extension signing
Replace all web3FromAddress calls with getSigner() that auto-detects walletSource and uses WC signer or extension signer accordingly. This fixes all signing operations when connected via WalletConnect.
This commit is contained in:
@@ -4,11 +4,13 @@
|
|||||||
// Handles citizenship verification, status checks, and workflow logic
|
// Handles citizenship verification, status checks, and workflow logic
|
||||||
|
|
||||||
import type { ApiPromise } from '@pezkuwi/api';
|
import type { ApiPromise } from '@pezkuwi/api';
|
||||||
import { web3Enable, web3FromAddress as web3FromAddressOriginal } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import type { InjectedAccountWithMeta } from '@pezkuwi/extension-inject/types';
|
import type { InjectedAccountWithMeta } from '@pezkuwi/extension-inject/types';
|
||||||
|
|
||||||
import type { Signer } from '@pezkuwi/api/types';
|
import type { Signer } from '@pezkuwi/api/types';
|
||||||
|
|
||||||
|
type WalletSource = 'extension' | 'walletconnect' | 'native' | null;
|
||||||
|
|
||||||
interface SignRawPayload {
|
interface SignRawPayload {
|
||||||
address: string;
|
address: string;
|
||||||
data: string;
|
data: string;
|
||||||
@@ -23,20 +25,6 @@ interface InjectedSigner {
|
|||||||
signRaw?: (payload: SignRawPayload) => Promise<SignRawResult>;
|
signRaw?: (payload: SignRawPayload) => Promise<SignRawResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InjectedExtension {
|
|
||||||
signer: Signer & InjectedSigner;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use real extension in browser, throw error in unsupported environments
|
|
||||||
const web3FromAddress = async (address: string): Promise<InjectedExtension> => {
|
|
||||||
// Check if we're in a browser environment with extension support
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
await web3Enable('PezkuwiChain');
|
|
||||||
return web3FromAddressOriginal(address) as Promise<InjectedExtension>;
|
|
||||||
}
|
|
||||||
throw new Error('Pezkuwi Wallet extension not available. Please install the extension.');
|
|
||||||
};
|
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
// TYPE DEFINITIONS
|
// TYPE DEFINITIONS
|
||||||
// ========================================
|
// ========================================
|
||||||
@@ -477,7 +465,8 @@ export async function submitKycApplication(
|
|||||||
api: ApiPromise,
|
api: ApiPromise,
|
||||||
account: InjectedAccountWithMeta,
|
account: InjectedAccountWithMeta,
|
||||||
identityHash: string,
|
identityHash: string,
|
||||||
referrerAddress?: string
|
referrerAddress?: string,
|
||||||
|
walletSource?: WalletSource
|
||||||
): Promise<{ success: boolean; error?: string; blockHash?: string }> {
|
): Promise<{ success: boolean; error?: string; blockHash?: string }> {
|
||||||
try {
|
try {
|
||||||
if (!api?.tx?.identityKyc?.applyForCitizenship) {
|
if (!api?.tx?.identityKyc?.applyForCitizenship) {
|
||||||
@@ -502,7 +491,7 @@ export async function submitKycApplication(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const injector = await web3FromAddress(account.address);
|
const injector = await getSigner(account.address, walletSource ?? 'extension', api);
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.log('=== submitKycApplication Debug ===');
|
console.log('=== submitKycApplication Debug ===');
|
||||||
@@ -629,14 +618,15 @@ export function subscribeToKycApproval(
|
|||||||
export async function approveReferral(
|
export async function approveReferral(
|
||||||
api: ApiPromise,
|
api: ApiPromise,
|
||||||
account: InjectedAccountWithMeta,
|
account: InjectedAccountWithMeta,
|
||||||
applicantAddress: string
|
applicantAddress: string,
|
||||||
|
walletSource?: WalletSource
|
||||||
): Promise<{ success: boolean; error?: string; blockHash?: string }> {
|
): Promise<{ success: boolean; error?: string; blockHash?: string }> {
|
||||||
try {
|
try {
|
||||||
if (!api?.tx?.identityKyc?.approveReferral) {
|
if (!api?.tx?.identityKyc?.approveReferral) {
|
||||||
return { success: false, error: 'Identity KYC pallet not available' };
|
return { success: false, error: 'Identity KYC pallet not available' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const injector = await web3FromAddress(account.address);
|
const injector = await getSigner(account.address, walletSource ?? 'extension', api);
|
||||||
|
|
||||||
const result = await new Promise<{ success: boolean; error?: string; blockHash?: string }>((resolve, reject) => {
|
const result = await new Promise<{ success: boolean; error?: string; blockHash?: string }>((resolve, reject) => {
|
||||||
api.tx.identityKyc
|
api.tx.identityKyc
|
||||||
@@ -679,14 +669,15 @@ export async function approveReferral(
|
|||||||
*/
|
*/
|
||||||
export async function cancelApplication(
|
export async function cancelApplication(
|
||||||
api: ApiPromise,
|
api: ApiPromise,
|
||||||
account: InjectedAccountWithMeta
|
account: InjectedAccountWithMeta,
|
||||||
|
walletSource?: WalletSource
|
||||||
): Promise<{ success: boolean; error?: string }> {
|
): Promise<{ success: boolean; error?: string }> {
|
||||||
try {
|
try {
|
||||||
if (!api?.tx?.identityKyc?.cancelApplication) {
|
if (!api?.tx?.identityKyc?.cancelApplication) {
|
||||||
return { success: false, error: 'Identity KYC pallet not available' };
|
return { success: false, error: 'Identity KYC pallet not available' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const injector = await web3FromAddress(account.address);
|
const injector = await getSigner(account.address, walletSource ?? 'extension', api);
|
||||||
|
|
||||||
const result = await new Promise<{ success: boolean; error?: string }>((resolve, reject) => {
|
const result = await new Promise<{ success: boolean; error?: string }>((resolve, reject) => {
|
||||||
api.tx.identityKyc
|
api.tx.identityKyc
|
||||||
@@ -723,14 +714,15 @@ export async function cancelApplication(
|
|||||||
*/
|
*/
|
||||||
export async function confirmCitizenship(
|
export async function confirmCitizenship(
|
||||||
api: ApiPromise,
|
api: ApiPromise,
|
||||||
account: InjectedAccountWithMeta
|
account: InjectedAccountWithMeta,
|
||||||
|
walletSource?: WalletSource
|
||||||
): Promise<{ success: boolean; error?: string; blockHash?: string }> {
|
): Promise<{ success: boolean; error?: string; blockHash?: string }> {
|
||||||
try {
|
try {
|
||||||
if (!api?.tx?.identityKyc?.confirmCitizenship) {
|
if (!api?.tx?.identityKyc?.confirmCitizenship) {
|
||||||
return { success: false, error: 'Identity KYC pallet not available' };
|
return { success: false, error: 'Identity KYC pallet not available' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const injector = await web3FromAddress(account.address);
|
const injector = await getSigner(account.address, walletSource ?? 'extension', api);
|
||||||
|
|
||||||
const result = await new Promise<{ success: boolean; error?: string; blockHash?: string }>((resolve, reject) => {
|
const result = await new Promise<{ success: boolean; error?: string; blockHash?: string }>((resolve, reject) => {
|
||||||
api.tx.identityKyc
|
api.tx.identityKyc
|
||||||
@@ -850,10 +842,12 @@ export function generateAuthChallenge(tikiNumber: string): AuthChallenge {
|
|||||||
*/
|
*/
|
||||||
export async function signChallenge(
|
export async function signChallenge(
|
||||||
account: InjectedAccountWithMeta,
|
account: InjectedAccountWithMeta,
|
||||||
challenge: AuthChallenge
|
challenge: AuthChallenge,
|
||||||
|
walletSource?: WalletSource,
|
||||||
|
api?: ApiPromise | null
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
try {
|
try {
|
||||||
const injector = await web3FromAddress(account.address);
|
const injector = await getSigner(account.address, walletSource ?? 'extension', api);
|
||||||
|
|
||||||
if (!injector?.signer?.signRaw) {
|
if (!injector?.signer?.signRaw) {
|
||||||
throw new Error('Signer not available');
|
throw new Error('Signer not available');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { X, Plus, Info, AlertCircle } from 'lucide-react';
|
import { X, Plus, Info, AlertCircle } from 'lucide-react';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
||||||
import { useWallet } from '@/contexts/WalletContext';
|
import { useWallet } from '@/contexts/WalletContext';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -62,7 +62,7 @@ export const AddLiquidityModal: React.FC<AddLiquidityModalProps> = ({
|
|||||||
asset1 = 1 // Default to PEZ
|
asset1 = 1 // Default to PEZ
|
||||||
}) => {
|
}) => {
|
||||||
// Use Asset Hub API for DEX operations (assetConversion pallet is on Asset Hub)
|
// Use Asset Hub API for DEX operations (assetConversion pallet is on Asset Hub)
|
||||||
const { assetHubApi, selectedAccount, isAssetHubReady } = usePezkuwi();
|
const { assetHubApi, selectedAccount, isAssetHubReady, walletSource } = usePezkuwi();
|
||||||
const { balances, refreshBalances } = useWallet();
|
const { balances, refreshBalances } = useWallet();
|
||||||
|
|
||||||
const [amount0, setAmount0] = useState('');
|
const [amount0, setAmount0] = useState('');
|
||||||
@@ -357,9 +357,8 @@ export const AddLiquidityModal: React.FC<AddLiquidityModalProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the signer from the extension
|
// Get the signer (extension or WalletConnect)
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Convert amounts to proper decimals
|
// Convert amounts to proper decimals
|
||||||
const amount0BN = BigInt(Math.floor(parseFloat(amount0) * Math.pow(10, asset0Decimals)));
|
const amount0BN = BigInt(Math.floor(parseFloat(amount0) * Math.pow(10, asset0Decimals)));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { X, Lock, AlertCircle, Loader2, Clock } from 'lucide-react';
|
import { X, Lock, AlertCircle, Loader2, Clock } from 'lucide-react';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||||
@@ -50,7 +50,7 @@ export const LPStakeModal: React.FC<LPStakeModalProps> = ({
|
|||||||
onStakeSuccess,
|
onStakeSuccess,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { assetHubApi, selectedAccount, isAssetHubReady } = usePezkuwi();
|
const { assetHubApi, selectedAccount, isAssetHubReady, walletSource } = usePezkuwi();
|
||||||
const [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [success, setSuccess] = useState<string | null>(null);
|
const [success, setSuccess] = useState<string | null>(null);
|
||||||
@@ -85,8 +85,7 @@ export const LPStakeModal: React.FC<LPStakeModalProps> = ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const amountBN = BigInt(Math.floor(amount * 1e12));
|
const amountBN = BigInt(Math.floor(amount * 1e12));
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
const tx = assetHubApi.tx.assetRewards.stake(poolId, amountBN.toString());
|
const tx = assetHubApi.tx.assetRewards.stake(poolId, amountBN.toString());
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { X, Lock, Unlock, Gift, AlertCircle, Loader2, Info } from 'lucide-react';
|
import { X, Lock, Unlock, Gift, AlertCircle, Loader2, Info } from 'lucide-react';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||||
@@ -31,7 +31,7 @@ const LP_TOKEN_NAMES: Record<number, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const LPStakingModal: React.FC<LPStakingModalProps> = ({ isOpen, onClose }) => {
|
export const LPStakingModal: React.FC<LPStakingModalProps> = ({ isOpen, onClose }) => {
|
||||||
const { assetHubApi, selectedAccount, isAssetHubReady } = usePezkuwi();
|
const { assetHubApi, selectedAccount, isAssetHubReady, walletSource } = usePezkuwi();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [pools, setPools] = useState<StakingPool[]>([]);
|
const [pools, setPools] = useState<StakingPool[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@@ -143,8 +143,7 @@ export const LPStakingModal: React.FC<LPStakingModalProps> = ({ isOpen, onClose
|
|||||||
if (!pool) throw new Error('Pool not found');
|
if (!pool) throw new Error('Pool not found');
|
||||||
|
|
||||||
const amountBN = BigInt(Math.floor(parseFloat(stakeAmount) * 1e12));
|
const amountBN = BigInt(Math.floor(parseFloat(stakeAmount) * 1e12));
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
const tx = assetHubApi.tx.assetRewards.stake(selectedPool, amountBN.toString());
|
const tx = assetHubApi.tx.assetRewards.stake(selectedPool, amountBN.toString());
|
||||||
|
|
||||||
@@ -190,8 +189,7 @@ export const LPStakingModal: React.FC<LPStakingModalProps> = ({ isOpen, onClose
|
|||||||
if (!pool) throw new Error('Pool not found');
|
if (!pool) throw new Error('Pool not found');
|
||||||
|
|
||||||
const amountBN = BigInt(Math.floor(parseFloat(unstakeAmount) * 1e12));
|
const amountBN = BigInt(Math.floor(parseFloat(unstakeAmount) * 1e12));
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
const tx = assetHubApi.tx.assetRewards.unstake(selectedPool, amountBN.toString());
|
const tx = assetHubApi.tx.assetRewards.unstake(selectedPool, amountBN.toString());
|
||||||
|
|
||||||
@@ -233,8 +231,7 @@ export const LPStakingModal: React.FC<LPStakingModalProps> = ({ isOpen, onClose
|
|||||||
setSuccess(null);
|
setSuccess(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
const tx = assetHubApi.tx.assetRewards.harvestRewards(selectedPool);
|
const tx = assetHubApi.tx.assetRewards.harvestRewards(selectedPool);
|
||||||
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { X, Minus, AlertCircle, Info } from 'lucide-react';
|
import { X, Minus, AlertCircle, Info } from 'lucide-react';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
||||||
import { useWallet } from '@/contexts/WalletContext';
|
import { useWallet } from '@/contexts/WalletContext';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -63,7 +63,7 @@ export const RemoveLiquidityModal: React.FC<RemoveLiquidityModalProps> = ({
|
|||||||
asset1,
|
asset1,
|
||||||
}) => {
|
}) => {
|
||||||
// Use Asset Hub API for DEX operations (assetConversion pallet is on Asset Hub)
|
// Use Asset Hub API for DEX operations (assetConversion pallet is on Asset Hub)
|
||||||
const { assetHubApi, selectedAccount } = usePezkuwi();
|
const { assetHubApi, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { refreshBalances } = useWallet();
|
const { refreshBalances } = useWallet();
|
||||||
|
|
||||||
const [percentage, setPercentage] = useState(100);
|
const [percentage, setPercentage] = useState(100);
|
||||||
@@ -159,9 +159,8 @@ export const RemoveLiquidityModal: React.FC<RemoveLiquidityModalProps> = ({
|
|||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get the signer from the extension
|
// Get the signer (extension or WalletConnect)
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Get decimals for each asset
|
// Get decimals for each asset
|
||||||
const asset0Decimals = getAssetDecimals(asset0);
|
const asset0Decimals = getAssetDecimals(asset0);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const AVAILABLE_TOKENS = [
|
|||||||
|
|
||||||
const TokenSwap = () => {
|
const TokenSwap = () => {
|
||||||
// Use Asset Hub API for DEX operations (assetConversion pallet is on Asset Hub)
|
// Use Asset Hub API for DEX operations (assetConversion pallet is on Asset Hub)
|
||||||
const { assetHubApi, isAssetHubReady, selectedAccount } = usePezkuwi();
|
const { assetHubApi, isAssetHubReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { balances, refreshBalances } = useWallet();
|
const { balances, refreshBalances } = useWallet();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -583,10 +583,9 @@ const TokenSwap = () => {
|
|||||||
minAmountOut: minAmountOut.toString()
|
minAmountOut: minAmountOut.toString()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get signer from extension
|
// Get signer (extension or WalletConnect)
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Build transaction based on token types
|
// Build transaction based on token types
|
||||||
let tx;
|
let tx;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const TOKENS: Token[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const TransferModal: React.FC<TransferModalProps> = ({ isOpen, onClose, selectedAsset }) => {
|
export const TransferModal: React.FC<TransferModalProps> = ({ isOpen, onClose, selectedAsset }) => {
|
||||||
const { api, assetHubApi, isApiReady, isAssetHubReady, selectedAccount } = usePezkuwi();
|
const { api, assetHubApi, isApiReady, isAssetHubReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -129,10 +129,9 @@ export const TransferModal: React.FC<TransferModalProps> = ({ isOpen, onClose, s
|
|||||||
setTxStatus('signing');
|
setTxStatus('signing');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Import web3FromAddress to get the injector
|
// Get signer (extension or WalletConnect)
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, isAssetHubTransfer ? assetHubApi : api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Convert amount to smallest unit
|
// Convert amount to smallest unit
|
||||||
const amountInSmallestUnit = BigInt(parseFloat(amount) * Math.pow(10, currentToken.decimals));
|
const amountInSmallestUnit = BigInt(parseFloat(amount) * Math.pow(10, currentToken.decimals));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { X, ArrowDown, ArrowUp, AlertCircle, Info, Clock, CheckCircle2 } from 'lucide-react';
|
import { X, ArrowDown, ArrowUp, AlertCircle, Info, Clock, CheckCircle2 } from 'lucide-react';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
||||||
import { useWallet } from '@/contexts/WalletContext';
|
import { useWallet } from '@/contexts/WalletContext';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -30,7 +30,7 @@ export const USDTBridge: React.FC<USDTBridgeProps> = ({
|
|||||||
specificAddresses = {},
|
specificAddresses = {},
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { api, selectedAccount, isApiReady } = usePezkuwi();
|
const { api, selectedAccount, isApiReady, walletSource } = usePezkuwi();
|
||||||
const { refreshBalances } = useWallet();
|
const { refreshBalances } = useWallet();
|
||||||
|
|
||||||
const [depositAmount, setDepositAmount] = useState('');
|
const [depositAmount, setDepositAmount] = useState('');
|
||||||
@@ -114,8 +114,7 @@ export const USDTBridge: React.FC<USDTBridgeProps> = ({
|
|||||||
setSuccess(null);
|
setSuccess(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Burn wUSDT
|
// Burn wUSDT
|
||||||
const amountBN = BigInt(Math.floor(amount * 1e6)); // 6 decimals
|
const amountBN = BigInt(Math.floor(amount * 1e6)); // 6 decimals
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ interface XCMTeleportModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const XCMTeleportModal: React.FC<XCMTeleportModalProps> = ({ isOpen, onClose }) => {
|
export const XCMTeleportModal: React.FC<XCMTeleportModalProps> = ({ isOpen, onClose }) => {
|
||||||
const { api, assetHubApi, peopleApi, isApiReady, isAssetHubReady, isPeopleReady, selectedAccount } = usePezkuwi();
|
const { api, assetHubApi, peopleApi, isApiReady, isAssetHubReady, isPeopleReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -157,9 +157,8 @@ export const XCMTeleportModal: React.FC<XCMTeleportModalProps> = ({ isOpen, onCl
|
|||||||
setTxStatus('signing');
|
setTxStatus('signing');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Convert to smallest unit (12 decimals)
|
// Convert to smallest unit (12 decimals)
|
||||||
const amountInSmallestUnit = BigInt(Math.floor(parseFloat(amount) * 1e12));
|
const amountInSmallestUnit = BigInt(Math.floor(parseFloat(amount) * 1e12));
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert';
|
|||||||
|
|
||||||
export function CommissionSetupTab() {
|
export function CommissionSetupTab() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { api, isApiReady, selectedAccount } = usePezkuwi();
|
const { api, isApiReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -70,9 +70,8 @@ export function CommissionSetupTab() {
|
|||||||
|
|
||||||
setProcessing(true);
|
setProcessing(true);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Parse addresses (one per line, trim whitespace)
|
// Parse addresses (one per line, trim whitespace)
|
||||||
const newAddresses = newMemberAddress
|
const newAddresses = newMemberAddress
|
||||||
@@ -175,9 +174,8 @@ export function CommissionSetupTab() {
|
|||||||
|
|
||||||
setProcessing(true);
|
setProcessing(true);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
if (import.meta.env.DEV) console.log('Initializing KYC Commission...');
|
if (import.meta.env.DEV) console.log('Initializing KYC Commission...');
|
||||||
if (import.meta.env.DEV) console.log('Proxy account:', COMMISSIONS.KYC.proxyAccount);
|
if (import.meta.env.DEV) console.log('Proxy account:', COMMISSIONS.KYC.proxyAccount);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ interface Proposal {
|
|||||||
|
|
||||||
export function CommissionVotingTab() {
|
export function CommissionVotingTab() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { api, isApiReady, selectedAccount } = usePezkuwi();
|
const { api, isApiReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -150,9 +150,8 @@ export function CommissionVotingTab() {
|
|||||||
|
|
||||||
setVoting(proposal.hash);
|
setVoting(proposal.hash);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
if (import.meta.env.DEV) console.log(`Voting ${approve ? 'AYE' : 'NAY'} on proposal:`, proposal.hash);
|
if (import.meta.env.DEV) console.log(`Voting ${approve ? 'AYE' : 'NAY'} on proposal:`, proposal.hash);
|
||||||
|
|
||||||
@@ -258,9 +257,8 @@ export function CommissionVotingTab() {
|
|||||||
|
|
||||||
setVoting(proposal.hash);
|
setVoting(proposal.hash);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
if (import.meta.env.DEV) console.log('Executing proposal:', proposal.hash);
|
if (import.meta.env.DEV) console.log('Executing proposal:', proposal.hash);
|
||||||
|
|
||||||
@@ -433,9 +431,8 @@ export function CommissionVotingTab() {
|
|||||||
if (!api || !selectedAccount) return;
|
if (!api || !selectedAccount) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Get current members
|
// Get current members
|
||||||
const currentMembers = await api.query.dynamicCommissionCollective.members();
|
const currentMembers = await api.query.dynamicCommissionCollective.members();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import type { PendingApproval } from '@pezkuwi/lib/citizenship-workflow';
|
|||||||
export function KycApprovalTab() {
|
export function KycApprovalTab() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
// identityKyc pallet is on People Chain - use peopleApi
|
// identityKyc pallet is on People Chain - use peopleApi
|
||||||
const { peopleApi, isPeopleReady, selectedAccount, connectWallet } = usePezkuwi();
|
const { peopleApi, isPeopleReady, selectedAccount, connectWallet, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -75,7 +75,7 @@ export function KycApprovalTab() {
|
|||||||
|
|
||||||
setProcessingAddress(applicantAddress);
|
setProcessingAddress(applicantAddress);
|
||||||
try {
|
try {
|
||||||
const result = await approveReferral(peopleApi, selectedAccount, applicantAddress);
|
const result = await approveReferral(peopleApi, selectedAccount, applicantAddress, walletSource);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ interface ExistingCitizenAuthProps {
|
|||||||
|
|
||||||
export const ExistingCitizenAuth: React.FC<ExistingCitizenAuthProps> = ({ onClose }) => {
|
export const ExistingCitizenAuth: React.FC<ExistingCitizenAuthProps> = ({ onClose }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { peopleApi, isPeopleReady, selectedAccount, connectWallet } = usePezkuwi();
|
const { peopleApi, isPeopleReady, selectedAccount, connectWallet, walletSource } = usePezkuwi();
|
||||||
|
|
||||||
const [citizenNumber, setCitizenNumber] = useState('');
|
const [citizenNumber, setCitizenNumber] = useState('');
|
||||||
const [step, setStep] = useState<'input' | 'verifying' | 'signing' | 'success' | 'error'>('input');
|
const [step, setStep] = useState<'input' | 'verifying' | 'signing' | 'success' | 'error'>('input');
|
||||||
@@ -69,7 +69,7 @@ export const ExistingCitizenAuth: React.FC<ExistingCitizenAuthProps> = ({ onClos
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Sign the challenge
|
// Sign the challenge
|
||||||
const signature = await signChallenge(selectedAccount, challenge);
|
const signature = await signChallenge(selectedAccount, challenge, walletSource, peopleApi);
|
||||||
|
|
||||||
// Verify signature (self-verification for demonstration)
|
// Verify signature (self-verification for demonstration)
|
||||||
const isValid = await verifySignature(signature, challenge, selectedAccount.address);
|
const isValid = await verifySignature(signature, challenge, selectedAccount.address);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type FormData = Omit<CitizenshipData, 'walletAddress' | 'timestamp'>;
|
|||||||
|
|
||||||
export const NewCitizenApplication: React.FC<NewCitizenApplicationProps> = ({ onClose, referrerAddress }) => {
|
export const NewCitizenApplication: React.FC<NewCitizenApplicationProps> = ({ onClose, referrerAddress }) => {
|
||||||
// identityKyc pallet is on People Chain
|
// identityKyc pallet is on People Chain
|
||||||
const { peopleApi, isPeopleReady, selectedAccount, connectWallet } = usePezkuwi();
|
const { peopleApi, isPeopleReady, selectedAccount, connectWallet, walletSource } = usePezkuwi();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { register, handleSubmit, watch, setValue, formState: { errors } } = useForm<FormData>();
|
const { register, handleSubmit, watch, setValue, formState: { errors } } = useForm<FormData>();
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ export const NewCitizenApplication: React.FC<NewCitizenApplicationProps> = ({ on
|
|||||||
setConfirming(true);
|
setConfirming(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const result = await confirmCitizenship(peopleApi, selectedAccount);
|
const result = await confirmCitizenship(peopleApi, selectedAccount, walletSource);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
setError(result.error || t('newCitizen.failedToConfirm'));
|
setError(result.error || t('newCitizen.failedToConfirm'));
|
||||||
@@ -83,7 +83,7 @@ export const NewCitizenApplication: React.FC<NewCitizenApplicationProps> = ({ on
|
|||||||
setCanceling(true);
|
setCanceling(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const result = await cancelApplication(peopleApi, selectedAccount);
|
const result = await cancelApplication(peopleApi, selectedAccount, walletSource);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
setError(result.error || t('newCitizen.failedToCancel'));
|
setError(result.error || t('newCitizen.failedToCancel'));
|
||||||
@@ -243,7 +243,8 @@ export const NewCitizenApplication: React.FC<NewCitizenApplicationProps> = ({ on
|
|||||||
peopleApi,
|
peopleApi,
|
||||||
selectedAccount,
|
selectedAccount,
|
||||||
identityHash,
|
identityHash,
|
||||||
effectiveReferrer
|
effectiveReferrer,
|
||||||
|
walletSource
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ interface Proposal {
|
|||||||
|
|
||||||
export function CommissionProposalsCard() {
|
export function CommissionProposalsCard() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { api, isApiReady, selectedAccount } = usePezkuwi();
|
const { api, isApiReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -109,9 +109,8 @@ export function CommissionProposalsCard() {
|
|||||||
|
|
||||||
setVoting(proposal.hash);
|
setVoting(proposal.hash);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
const tx = api.tx.dynamicCommissionCollective.vote(
|
const tx = api.tx.dynamicCommissionCollective.vote(
|
||||||
proposal.hash,
|
proposal.hash,
|
||||||
@@ -200,9 +199,8 @@ export function CommissionProposalsCard() {
|
|||||||
|
|
||||||
setVoting(proposal.hash);
|
setVoting(proposal.hash);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
// Get proposal length bound
|
// Get proposal length bound
|
||||||
const proposalOption = await api.query.dynamicCommissionCollective.proposalOf(proposal.hash);
|
const proposalOption = await api.query.dynamicCommissionCollective.proposalOf(proposal.hash);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ interface InviteUserModalProps {
|
|||||||
|
|
||||||
export const InviteUserModal: React.FC<InviteUserModalProps> = ({ isOpen, onClose }) => {
|
export const InviteUserModal: React.FC<InviteUserModalProps> = ({ isOpen, onClose }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { peopleApi, isPeopleReady, selectedAccount } = usePezkuwi();
|
const { peopleApi, isPeopleReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const [inviteeAddress, setInviteeAddress] = useState('');
|
const [inviteeAddress, setInviteeAddress] = useState('');
|
||||||
const [initiating, setInitiating] = useState(false);
|
const [initiating, setInitiating] = useState(false);
|
||||||
@@ -81,9 +81,8 @@ export const InviteUserModal: React.FC<InviteUserModalProps> = ({ isOpen, onClos
|
|||||||
setInitiateSuccess(false);
|
setInitiateSuccess(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const { getSigner } = await import('@/lib/get-signer');
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
if (import.meta.env.DEV) console.log(`Initiating referral from ${selectedAccount.address} to ${inviteeAddress}...`);
|
if (import.meta.env.DEV) console.log(`Initiating referral from ${selectedAccount.address} to ${inviteeAddress}...`);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import type { PendingApproval } from '@pezkuwi/lib/citizenship-workflow';
|
|||||||
export const ReferralDashboard: React.FC = () => {
|
export const ReferralDashboard: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { stats, myReferrals, loading } = useReferral();
|
const { stats, myReferrals, loading } = useReferral();
|
||||||
const { peopleApi, isPeopleReady, selectedAccount } = usePezkuwi();
|
const { peopleApi, isPeopleReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [showInviteModal, setShowInviteModal] = useState(false);
|
const [showInviteModal, setShowInviteModal] = useState(false);
|
||||||
const [pendingApprovals, setPendingApprovals] = useState<PendingApproval[]>([]);
|
const [pendingApprovals, setPendingApprovals] = useState<PendingApproval[]>([]);
|
||||||
@@ -45,7 +45,7 @@ export const ReferralDashboard: React.FC = () => {
|
|||||||
|
|
||||||
setProcessingAddress(applicantAddress);
|
setProcessingAddress(applicantAddress);
|
||||||
try {
|
try {
|
||||||
const result = await approveReferral(peopleApi, selectedAccount, applicantAddress);
|
const result = await approveReferral(peopleApi, selectedAccount, applicantAddress, walletSource);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
toast({
|
toast({
|
||||||
title: 'Referral Approved',
|
title: 'Referral Approved',
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { usePezkuwi } from '@/contexts/PezkuwiContext';
|
|||||||
import { useWallet } from '@/contexts/WalletContext';
|
import { useWallet } from '@/contexts/WalletContext';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { web3FromAddress, web3Enable } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import {
|
import {
|
||||||
getStakingInfo,
|
getStakingInfo,
|
||||||
getActiveValidators,
|
getActiveValidators,
|
||||||
@@ -31,21 +31,8 @@ import { LoadingState } from '@pezkuwi/components/AsyncComponent';
|
|||||||
import { ValidatorPoolDashboard } from './ValidatorPoolDashboard';
|
import { ValidatorPoolDashboard } from './ValidatorPoolDashboard';
|
||||||
import { handleBlockchainError, handleBlockchainSuccess } from '@pezkuwi/lib/error-handler';
|
import { handleBlockchainError, handleBlockchainSuccess } from '@pezkuwi/lib/error-handler';
|
||||||
|
|
||||||
// Get signer with auto-reconnect if extension session expired
|
|
||||||
async function getInjectorSigner(address: string) {
|
|
||||||
let injector = await web3FromAddress(address);
|
|
||||||
if (!injector?.signer) {
|
|
||||||
await web3Enable('PezkuwiChain');
|
|
||||||
injector = await web3FromAddress(address);
|
|
||||||
if (!injector?.signer) {
|
|
||||||
throw new Error('Wallet signer not available. Please reconnect your wallet.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return injector;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StakingDashboard: React.FC = () => {
|
export const StakingDashboard: React.FC = () => {
|
||||||
const { assetHubApi, peopleApi, selectedAccount, isAssetHubReady, isPeopleReady } = usePezkuwi();
|
const { assetHubApi, peopleApi, selectedAccount, isAssetHubReady, isPeopleReady, walletSource } = usePezkuwi();
|
||||||
const { balances, refreshBalances } = useWallet();
|
const { balances, refreshBalances } = useWallet();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -129,7 +116,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
|
|
||||||
setIsRecordingScore(true);
|
setIsRecordingScore(true);
|
||||||
try {
|
try {
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer);
|
const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -157,7 +144,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
|
|
||||||
setIsClaimingReward(true);
|
setIsClaimingReward(true);
|
||||||
try {
|
try {
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer);
|
const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -198,7 +185,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
throw new Error(t('staking.insufficientHez'));
|
throw new Error(t('staking.insufficientHez'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
|
|
||||||
// If already bonded, use bondExtra, otherwise use bond
|
// If already bonded, use bondExtra, otherwise use bond
|
||||||
let tx;
|
let tx;
|
||||||
@@ -251,7 +238,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
|
|
||||||
const tx = assetHubApi.tx.staking.nominate(selectedValidators);
|
const tx = assetHubApi.tx.staking.nominate(selectedValidators);
|
||||||
|
|
||||||
@@ -294,7 +281,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
throw new Error(t('staking.insufficientStaked'));
|
throw new Error(t('staking.insufficientStaked'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
const tx = assetHubApi.tx.staking.unbond(amount);
|
const tx = assetHubApi.tx.staking.unbond(amount);
|
||||||
|
|
||||||
await tx.signAndSend(
|
await tx.signAndSend(
|
||||||
@@ -338,7 +325,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, assetHubApi);
|
||||||
|
|
||||||
// Number of slashing spans (usually 0)
|
// Number of slashing spans (usually 0)
|
||||||
const tx = assetHubApi.tx.staking.withdrawUnbonded(0);
|
const tx = assetHubApi.tx.staking.withdrawUnbonded(0);
|
||||||
@@ -381,7 +368,7 @@ export const StakingDashboard: React.FC = () => {
|
|||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const injector = await getInjectorSigner(selectedAccount.address);
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
// stakingScore pallet is on People Chain - uses cached staking data from Asset Hub
|
// stakingScore pallet is on People Chain - uses cached staking data from Asset Hub
|
||||||
const tx = peopleApi.tx.stakingScore.startScoreTracking();
|
const tx = peopleApi.tx.stakingScore.startScoreTracking();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Universal signer helper - works with both browser extension and WalletConnect
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* const injector = await getSigner(selectedAccount.address, walletSource, api);
|
||||||
|
* // injector.signer works for signAndSend, signRaw, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
||||||
|
import { createWCSigner, isWCConnected, validateSession } from '@/lib/walletconnect-service';
|
||||||
|
import type { ApiPromise } from '@pezkuwi/api';
|
||||||
|
|
||||||
|
type WalletSource = 'extension' | 'walletconnect' | 'native' | null;
|
||||||
|
|
||||||
|
interface SignerResult {
|
||||||
|
signer: any; // Compatible with @pezkuwi/api Signer
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getSigner(
|
||||||
|
address: string,
|
||||||
|
walletSource: WalletSource,
|
||||||
|
api?: ApiPromise | null
|
||||||
|
): Promise<SignerResult> {
|
||||||
|
if (walletSource === 'walletconnect') {
|
||||||
|
if (!isWCConnected() || !validateSession()) {
|
||||||
|
throw new Error('WalletConnect session expired. Please reconnect your wallet.');
|
||||||
|
}
|
||||||
|
if (!api) {
|
||||||
|
throw new Error('API not ready');
|
||||||
|
}
|
||||||
|
const genesisHash = api.genesisHash.toHex();
|
||||||
|
const wcSigner = createWCSigner(genesisHash, address);
|
||||||
|
return { signer: wcSigner };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extension or native: use web3FromAddress
|
||||||
|
await web3Enable('PezkuwiChain');
|
||||||
|
const injector = await web3FromAddress(address);
|
||||||
|
return injector;
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ import { User, Mail, Phone, Globe, MapPin, Calendar, Shield, AlertCircle, ArrowL
|
|||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { fetchUserTikis, getPrimaryRole, getTikiDisplayName, getTikiColor, getTikiEmoji, getUserRoleCategories, getAllTikiNFTDetails, generateCitizenNumber, type TikiNFTDetails } from '@pezkuwi/lib/tiki';
|
import { fetchUserTikis, getPrimaryRole, getTikiDisplayName, getTikiColor, getTikiEmoji, getUserRoleCategories, getAllTikiNFTDetails, generateCitizenNumber, type TikiNFTDetails } from '@pezkuwi/lib/tiki';
|
||||||
import { getAllScores, getStakingScoreStatus, startScoreTracking, getPezRewards, recordTrustScore, claimPezReward, type UserScores, type StakingScoreStatus, type PezRewardInfo, formatDuration } from '@pezkuwi/lib/scores';
|
import { getAllScores, getStakingScoreStatus, startScoreTracking, getPezRewards, recordTrustScore, claimPezReward, type UserScores, type StakingScoreStatus, type PezRewardInfo, formatDuration } from '@pezkuwi/lib/scores';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { getKycStatus } from '@pezkuwi/lib/kyc';
|
import { getKycStatus } from '@pezkuwi/lib/kyc';
|
||||||
import { ReferralDashboard } from '@/components/referral/ReferralDashboard';
|
import { ReferralDashboard } from '@/components/referral/ReferralDashboard';
|
||||||
// Commission proposals card removed - no longer using notary system for KYC approval
|
// Commission proposals card removed - no longer using notary system for KYC approval
|
||||||
@@ -21,7 +21,7 @@ import { ReferralDashboard } from '@/components/referral/ReferralDashboard';
|
|||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { api, isApiReady, peopleApi, isPeopleReady, selectedAccount } = usePezkuwi();
|
const { api, isApiReady, peopleApi, isPeopleReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [profile, setProfile] = useState<Record<string, unknown> | null>(null);
|
const [profile, setProfile] = useState<Record<string, unknown> | null>(null);
|
||||||
@@ -157,8 +157,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
setStartingScoreTracking(true);
|
setStartingScoreTracking(true);
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
// startScoreTracking on People Chain - staking data comes from Asset Hub via XCM
|
// startScoreTracking on People Chain - staking data comes from Asset Hub via XCM
|
||||||
const result = await startScoreTracking(peopleApi, selectedAccount.address, injector.signer);
|
const result = await startScoreTracking(peopleApi, selectedAccount.address, injector.signer);
|
||||||
|
|
||||||
@@ -193,8 +192,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
setIsRecordingScore(true);
|
setIsRecordingScore(true);
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer);
|
const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -215,8 +213,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
setIsClaimingReward(true);
|
setIsClaimingReward(true);
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer);
|
const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@@ -332,9 +329,7 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
setRenouncingCitizenship(true);
|
setRenouncingCitizenship(true);
|
||||||
try {
|
try {
|
||||||
const { web3Enable, web3FromAddress } = await import('@pezkuwi/extension-dapp');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
await web3Enable('PezkuwiChain');
|
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
|
|
||||||
if (import.meta.env.DEV) console.log('Renouncing citizenship...');
|
if (import.meta.env.DEV) console.log('Renouncing citizenship...');
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { NftList } from '@/components/NftList';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { ArrowUpRight, ArrowDownRight, History, ArrowLeft, RefreshCw, Coins, Loader2 } from 'lucide-react';
|
import { ArrowUpRight, ArrowDownRight, History, ArrowLeft, RefreshCw, Coins, Loader2 } from 'lucide-react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { web3Enable, web3FromAddress } from '@pezkuwi/extension-dapp';
|
import { getSigner } from '@/lib/get-signer';
|
||||||
import { getPezRewards, recordTrustScore, claimPezReward, type PezRewardInfo } from '@pezkuwi/lib/scores';
|
import { getPezRewards, recordTrustScore, claimPezReward, type PezRewardInfo } from '@pezkuwi/lib/scores';
|
||||||
|
|
||||||
interface Transaction {
|
interface Transaction {
|
||||||
@@ -29,7 +29,7 @@ interface Transaction {
|
|||||||
const WalletDashboard: React.FC = () => {
|
const WalletDashboard: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { api, isApiReady, peopleApi, isPeopleReady, selectedAccount } = usePezkuwi();
|
const { api, isApiReady, peopleApi, isPeopleReady, selectedAccount, walletSource } = usePezkuwi();
|
||||||
const [isTransferModalOpen, setIsTransferModalOpen] = useState(false);
|
const [isTransferModalOpen, setIsTransferModalOpen] = useState(false);
|
||||||
const [isReceiveModalOpen, setIsReceiveModalOpen] = useState(false);
|
const [isReceiveModalOpen, setIsReceiveModalOpen] = useState(false);
|
||||||
const [isHistoryModalOpen, setIsHistoryModalOpen] = useState(false);
|
const [isHistoryModalOpen, setIsHistoryModalOpen] = useState(false);
|
||||||
@@ -239,8 +239,7 @@ const WalletDashboard: React.FC = () => {
|
|||||||
if (!peopleApi || !selectedAccount) return;
|
if (!peopleApi || !selectedAccount) return;
|
||||||
setIsRecordingScore(true);
|
setIsRecordingScore(true);
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer);
|
const result = await recordTrustScore(peopleApi, selectedAccount.address, injector.signer);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
toast.success(t('wallet.trustScoreRecorded'));
|
toast.success(t('wallet.trustScoreRecorded'));
|
||||||
@@ -260,8 +259,7 @@ const WalletDashboard: React.FC = () => {
|
|||||||
if (!peopleApi || !selectedAccount) return;
|
if (!peopleApi || !selectedAccount) return;
|
||||||
setIsClaimingReward(true);
|
setIsClaimingReward(true);
|
||||||
try {
|
try {
|
||||||
await web3Enable('PezkuwiChain');
|
const injector = await getSigner(selectedAccount.address, walletSource, peopleApi);
|
||||||
const injector = await web3FromAddress(selectedAccount.address);
|
|
||||||
const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer);
|
const result = await claimPezReward(peopleApi, selectedAccount.address, epochIndex, injector.signer);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const rewardInfo = pezRewards?.claimableRewards.find(r => r.epoch === epochIndex);
|
const rewardInfo = pezRewards?.claimableRewards.find(r => r.epoch === epochIndex);
|
||||||
|
|||||||
Reference in New Issue
Block a user