From f864ed68044bd34835ce065387446ea6494a21d9 Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Sat, 14 Feb 2026 22:00:32 +0300 Subject: [PATCH] feat: update Be Citizen to new applyForCitizenship API - Single tx (applyForCitizenship) instead of 2-step setIdentity+applyForKyc - Keccak-256 identity hash via js-sha3 - Referral code replaced with referrer SS58 address - Success screen shows pending referral status instead of citizen ID - Updated all 6 translation files with new keys --- package-lock.json | 11 +- package.json | 3 +- src/components/citizen/CitizenForm.tsx | 14 +- src/components/citizen/CitizenProcessing.tsx | 39 ++--- src/components/citizen/CitizenSuccess.tsx | 29 ++-- src/i18n/translations/ar.ts | 13 +- src/i18n/translations/ckb.ts | 13 +- src/i18n/translations/en.ts | 13 +- src/i18n/translations/fa.ts | 13 +- src/i18n/translations/krd.ts | 13 +- src/i18n/translations/tr.ts | 13 +- src/i18n/types.ts | 15 +- src/lib/citizenship.ts | 152 ++++--------------- src/pages/CitizenPage.tsx | 10 +- src/version.json | 6 +- 15 files changed, 154 insertions(+), 203 deletions(-) diff --git a/package-lock.json b/package-lock.json index c2d9626..be6ab49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pezkuwi-telegram-miniapp", - "version": "1.0.169", + "version": "1.0.193", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pezkuwi-telegram-miniapp", - "version": "1.0.169", + "version": "1.0.193", "license": "MIT", "dependencies": { "@pezkuwi/api": "^16.5.36", @@ -20,6 +20,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0", + "js-sha3": "^0.9.3", "lucide-react": "^0.462.0", "qrcode": "^1.5.4", "react": "^18.3.1", @@ -7060,6 +7061,12 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-sha3": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", + "integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 1f8c616..5b99d6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pezkuwi-telegram-miniapp", - "version": "1.0.193", + "version": "1.0.194", "type": "module", "description": "Pezkuwichain Telegram Mini App - Forum, Announcements, Rewards", "author": "Pezkuwichain Team", @@ -48,6 +48,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0", + "js-sha3": "^0.9.3", "lucide-react": "^0.462.0", "qrcode": "^1.5.4", "react": "^18.3.1", diff --git a/src/components/citizen/CitizenForm.tsx b/src/components/citizen/CitizenForm.tsx index 102e72c..63b93af 100644 --- a/src/components/citizen/CitizenForm.tsx +++ b/src/components/citizen/CitizenForm.tsx @@ -38,7 +38,7 @@ export function CitizenForm({ walletAddress, onSubmit }: Props) { const [region, setRegion] = useState(''); const [email, setEmail] = useState(''); const [profession, setProfession] = useState(''); - const [referralCode, setReferralCode] = useState(''); + const [referrerAddress, setReferrerAddress] = useState(''); const [consent, setConsent] = useState(false); const [error, setError] = useState(''); @@ -120,7 +120,7 @@ export function CitizenForm({ walletAddress, onSubmit }: Props) { region: region as Region, email, profession, - referralCode: referralCode || undefined, + referrerAddress: referrerAddress || undefined, walletAddress, timestamp: Date.now(), }; @@ -319,15 +319,15 @@ export function CitizenForm({ walletAddress, onSubmit }: Props) { /> - {/* Referral Code */} + {/* Referrer Address */}
- + setReferralCode(e.target.value)} + value={referrerAddress} + onChange={(e) => setReferrerAddress(e.target.value)} className={inputClass} - placeholder={t('citizen.referralCodePlaceholder')} + placeholder={t('citizen.referrerPlaceholder')} />
diff --git a/src/components/citizen/CitizenProcessing.tsx b/src/components/citizen/CitizenProcessing.tsx index aec17b2..e17a876 100644 --- a/src/components/citizen/CitizenProcessing.tsx +++ b/src/components/citizen/CitizenProcessing.tsx @@ -11,16 +11,15 @@ import { useTelegram } from '@/hooks/useTelegram'; import { useWallet } from '@/contexts/WalletContext'; import type { CitizenshipData } from '@/lib/citizenship'; import { - generateCommitmentHash, - generateNullifierHash, + calculateIdentityHash, saveCitizenshipLocally, uploadToIPFS, - submitCitizenshipApplication, + applyCitizenship, } from '@/lib/citizenship'; interface Props { citizenshipData: CitizenshipData; - onSuccess: (blockHash?: string) => void; + onSuccess: (identityHash: string, blockHash?: string) => void; onError: (error: string) => void; } @@ -32,23 +31,24 @@ export function CitizenProcessing({ citizenshipData, onSuccess, onError }: Props const { peopleApi, keypair } = useWallet(); const [state, setState] = useState('preparing'); - const [ipfsCid, setIpfsCid] = useState(''); + const [identityHash, setIdentityHash] = useState(''); // Prepare data on mount useEffect(() => { const prepare = async () => { try { - // Generate commitment hash - generateCommitmentHash(citizenshipData); - generateNullifierHash(citizenshipData.walletAddress, citizenshipData.timestamp); + // Mock IPFS upload + const ipfsCid = await uploadToIPFS(citizenshipData); + + // Calculate identity hash (keccak256) + const hash = calculateIdentityHash(citizenshipData.fullName, citizenshipData.email, [ + ipfsCid, + ]); + setIdentityHash(hash); // Save encrypted data locally saveCitizenshipLocally(citizenshipData); - // Mock IPFS upload - const cid = await uploadToIPFS(citizenshipData); - setIpfsCid(cid); - // Small delay to show animation await new Promise((resolve) => setTimeout(resolve, 1500)); @@ -72,18 +72,16 @@ export function CitizenProcessing({ citizenshipData, onSuccess, onError }: Props hapticImpact('medium'); try { - const result = await submitCitizenshipApplication( + const result = await applyCitizenship( peopleApi, keypair, - citizenshipData.fullName, - citizenshipData.email, - ipfsCid, - `Citizenship application - ${citizenshipData.region}` + identityHash, + citizenshipData.referrerAddress || null ); if (result.success) { hapticNotification('success'); - onSuccess(result.blockHash); + onSuccess(identityHash, result.blockHash); } else { hapticNotification('error'); onError(result.error || t('citizen.submissionFailed')); @@ -96,7 +94,7 @@ export function CitizenProcessing({ citizenshipData, onSuccess, onError }: Props peopleApi, keypair, citizenshipData, - ipfsCid, + identityHash, hapticImpact, hapticNotification, onSuccess, @@ -124,6 +122,9 @@ export function CitizenProcessing({ citizenshipData, onSuccess, onError }: Props {state === 'preparing' && (

{citizenshipData.fullName}

)} + {state === 'ready' && ( +

{t('citizen.depositRequired')}

+ )} {/* Sign Button */} diff --git a/src/components/citizen/CitizenSuccess.tsx b/src/components/citizen/CitizenSuccess.tsx index 7a85e7d..8233714 100644 --- a/src/components/citizen/CitizenSuccess.tsx +++ b/src/components/citizen/CitizenSuccess.tsx @@ -1,27 +1,24 @@ /** * Citizen Success Screen * Shows after successful citizenship application submission + * Displays pending referral status instead of final approval */ -import { CheckCircle } from 'lucide-react'; +import { CheckCircle, Clock } from 'lucide-react'; import { useTranslation } from '@/i18n'; import { useTelegram } from '@/hooks/useTelegram'; import { formatAddress } from '@/lib/wallet-service'; -import { generateCitizenNumber } from '@/lib/citizenship'; interface Props { address: string; + identityHash: string; onOpenApp: () => void; } -export function CitizenSuccess({ address, onOpenApp }: Props) { +export function CitizenSuccess({ address, identityHash, onOpenApp }: Props) { const { t } = useTranslation(); const { hapticImpact } = useTelegram(); - // Generate a citizen number based on address - const citizenNumber = generateCitizenNumber(address, 42, 0); - const citizenId = `#42-0-${citizenNumber}`; - const handleOpenApp = () => { hapticImpact('medium'); onOpenApp(); @@ -36,15 +33,18 @@ export function CitizenSuccess({ address, onOpenApp }: Props) { {/* Title */}
-

{t('citizen.successTitle')}

-

{t('citizen.successSubtitle')}

+

{t('citizen.applicationSubmitted')}

+
+ +

{t('citizen.pendingReferral')}

+
- {/* Citizen ID Card */} + {/* Application Info Card */}
-

{t('citizen.citizenId')}

-

{citizenId}

+

{t('citizen.identityHash')}

+

{formatAddress(identityHash)}

{t('citizen.walletAddress')}

@@ -52,6 +52,11 @@ export function CitizenSuccess({ address, onOpenApp }: Props) {
+ {/* Info Note */} +

+ {t('citizen.applicationInfo')} +

+ {/* Open App Button */}