mirror of
https://github.com/luxfhe/research-ocp-fhe.git
synced 2026-11-03 06:05:38 +00:00
279 lines
8.4 KiB
TypeScript
279 lines
8.4 KiB
TypeScript
import { create } from 'zustand';
|
|
import { persist } from 'zustand/middleware';
|
|
|
|
export interface DecryptedData {
|
|
quantity: number;
|
|
sharePrice: number;
|
|
investment: number; // calculated: quantity * sharePrice
|
|
timestamp: number; // when decrypted
|
|
}
|
|
|
|
export interface DecryptedRoundData {
|
|
preMoneyValuation: number;
|
|
totalAmount: number;
|
|
postMoneyValuation: number; // calculated: preMoneyValuation + totalAmount
|
|
timestamp: number; // when decrypted
|
|
}
|
|
|
|
interface DecryptionState {
|
|
// Key format: `${companyAddress}:${securityId}`
|
|
decryptedSecurities: Record<string, DecryptedData>;
|
|
|
|
// Key format: `${companyAddress}:round:${roundId}`
|
|
decryptedRounds: Record<string, DecryptedRoundData>;
|
|
|
|
// Loading states - Key format: `${companyAddress}:${securityId}`
|
|
loadingDecryption: Record<string, boolean>;
|
|
|
|
// Loading states for rounds - Key format: `${companyAddress}:round:${roundId}`
|
|
loadingRoundDecryption: Record<string, boolean>;
|
|
|
|
// Actions for securities
|
|
setDecryptedData: (
|
|
companyAddress: string,
|
|
securityId: string,
|
|
data: DecryptedData
|
|
) => void;
|
|
setLoading: (
|
|
companyAddress: string,
|
|
securityId: string,
|
|
loading: boolean
|
|
) => void;
|
|
clearDecryptedData: (companyAddress: string, securityId?: string) => void;
|
|
clearAllDecryptedData: () => void;
|
|
isDecrypted: (companyAddress: string, securityId: string) => boolean;
|
|
isLoading: (companyAddress: string, securityId: string) => boolean;
|
|
getDecryptedData: (
|
|
companyAddress: string,
|
|
securityId: string
|
|
) => DecryptedData | null;
|
|
|
|
// Actions for rounds
|
|
setDecryptedRoundData: (
|
|
companyAddress: string,
|
|
roundId: string,
|
|
data: DecryptedRoundData
|
|
) => void;
|
|
setRoundLoading: (
|
|
companyAddress: string,
|
|
roundId: string,
|
|
loading: boolean
|
|
) => void;
|
|
clearDecryptedRoundData: (companyAddress: string, roundId?: string) => void;
|
|
isRoundDecrypted: (companyAddress: string, roundId: string) => boolean;
|
|
isRoundLoading: (companyAddress: string, roundId: string) => boolean;
|
|
getDecryptedRoundData: (
|
|
companyAddress: string,
|
|
roundId: string
|
|
) => DecryptedRoundData | null;
|
|
}
|
|
|
|
const generateKey = (companyAddress: string, securityId: string): string =>
|
|
`${companyAddress.toLowerCase()}:${securityId}`;
|
|
|
|
const generateRoundKey = (companyAddress: string, roundId: string): string =>
|
|
`${companyAddress.toLowerCase()}:round:${roundId}`;
|
|
|
|
export const useDecryptionStore = create<DecryptionState>()(
|
|
persist(
|
|
(set, get) => ({
|
|
decryptedSecurities: {},
|
|
decryptedRounds: {},
|
|
loadingDecryption: {},
|
|
loadingRoundDecryption: {},
|
|
|
|
setDecryptedData: (
|
|
companyAddress: string,
|
|
securityId: string,
|
|
data: DecryptedData
|
|
) => {
|
|
const key = generateKey(companyAddress, securityId);
|
|
set(state => ({
|
|
decryptedSecurities: {
|
|
...state.decryptedSecurities,
|
|
[key]: data,
|
|
},
|
|
}));
|
|
},
|
|
|
|
setLoading: (
|
|
companyAddress: string,
|
|
securityId: string,
|
|
loading: boolean
|
|
) => {
|
|
const key = generateKey(companyAddress, securityId);
|
|
set(state => ({
|
|
loadingDecryption: {
|
|
...state.loadingDecryption,
|
|
[key]: loading,
|
|
},
|
|
}));
|
|
},
|
|
|
|
clearDecryptedData: (companyAddress: string, securityId?: string) => {
|
|
if (securityId) {
|
|
// Clear specific security
|
|
const key = generateKey(companyAddress, securityId);
|
|
set(state => {
|
|
const newDecrypted = { ...state.decryptedSecurities };
|
|
const newLoading = { ...state.loadingDecryption };
|
|
delete newDecrypted[key];
|
|
delete newLoading[key];
|
|
return {
|
|
decryptedSecurities: newDecrypted,
|
|
loadingDecryption: newLoading,
|
|
};
|
|
});
|
|
} else {
|
|
// Clear all securities for this company
|
|
const companyPrefix = companyAddress.toLowerCase();
|
|
set(state => {
|
|
const newDecrypted = { ...state.decryptedSecurities };
|
|
const newLoading = { ...state.loadingDecryption };
|
|
|
|
Object.keys(newDecrypted).forEach(key => {
|
|
if (key.startsWith(companyPrefix)) {
|
|
delete newDecrypted[key];
|
|
}
|
|
});
|
|
|
|
Object.keys(newLoading).forEach(key => {
|
|
if (key.startsWith(companyPrefix)) {
|
|
delete newLoading[key];
|
|
}
|
|
});
|
|
|
|
return {
|
|
decryptedSecurities: newDecrypted,
|
|
loadingDecryption: newLoading,
|
|
};
|
|
});
|
|
}
|
|
},
|
|
|
|
clearAllDecryptedData: () => {
|
|
set(() => ({
|
|
decryptedSecurities: {},
|
|
decryptedRounds: {},
|
|
loadingDecryption: {},
|
|
loadingRoundDecryption: {},
|
|
}));
|
|
},
|
|
|
|
isDecrypted: (companyAddress: string, securityId: string): boolean => {
|
|
const key = generateKey(companyAddress, securityId);
|
|
return !!get().decryptedSecurities[key];
|
|
},
|
|
|
|
isLoading: (companyAddress: string, securityId: string): boolean => {
|
|
const key = generateKey(companyAddress, securityId);
|
|
return !!get().loadingDecryption[key];
|
|
},
|
|
|
|
getDecryptedData: (
|
|
companyAddress: string,
|
|
securityId: string
|
|
): DecryptedData | null => {
|
|
const key = generateKey(companyAddress, securityId);
|
|
return get().decryptedSecurities[key] || null;
|
|
},
|
|
|
|
// Round-related methods
|
|
setDecryptedRoundData: (
|
|
companyAddress: string,
|
|
roundId: string,
|
|
data: DecryptedRoundData
|
|
) => {
|
|
const key = generateRoundKey(companyAddress, roundId);
|
|
set(state => ({
|
|
decryptedRounds: {
|
|
...state.decryptedRounds,
|
|
[key]: data,
|
|
},
|
|
}));
|
|
},
|
|
|
|
setRoundLoading: (
|
|
companyAddress: string,
|
|
roundId: string,
|
|
loading: boolean
|
|
) => {
|
|
const key = generateRoundKey(companyAddress, roundId);
|
|
set(state => ({
|
|
loadingRoundDecryption: {
|
|
...state.loadingRoundDecryption,
|
|
[key]: loading,
|
|
},
|
|
}));
|
|
},
|
|
|
|
clearDecryptedRoundData: (companyAddress: string, roundId?: string) => {
|
|
if (roundId) {
|
|
// Clear specific round
|
|
const key = generateRoundKey(companyAddress, roundId);
|
|
set(state => {
|
|
const newDecrypted = { ...state.decryptedRounds };
|
|
const newLoading = { ...state.loadingRoundDecryption };
|
|
delete newDecrypted[key];
|
|
delete newLoading[key];
|
|
return {
|
|
decryptedRounds: newDecrypted,
|
|
loadingRoundDecryption: newLoading,
|
|
};
|
|
});
|
|
} else {
|
|
// Clear all rounds for this company
|
|
const companyPrefix = `${companyAddress.toLowerCase()}:round:`;
|
|
set(state => {
|
|
const newDecrypted = { ...state.decryptedRounds };
|
|
const newLoading = { ...state.loadingRoundDecryption };
|
|
|
|
Object.keys(newDecrypted).forEach(key => {
|
|
if (key.startsWith(companyPrefix)) {
|
|
delete newDecrypted[key];
|
|
}
|
|
});
|
|
|
|
Object.keys(newLoading).forEach(key => {
|
|
if (key.startsWith(companyPrefix)) {
|
|
delete newLoading[key];
|
|
}
|
|
});
|
|
|
|
return {
|
|
decryptedRounds: newDecrypted,
|
|
loadingRoundDecryption: newLoading,
|
|
};
|
|
});
|
|
}
|
|
},
|
|
|
|
isRoundDecrypted: (companyAddress: string, roundId: string): boolean => {
|
|
const key = generateRoundKey(companyAddress, roundId);
|
|
return !!get().decryptedRounds[key];
|
|
},
|
|
|
|
isRoundLoading: (companyAddress: string, roundId: string): boolean => {
|
|
const key = generateRoundKey(companyAddress, roundId);
|
|
return !!get().loadingRoundDecryption[key];
|
|
},
|
|
|
|
getDecryptedRoundData: (
|
|
companyAddress: string,
|
|
roundId: string
|
|
): DecryptedRoundData | null => {
|
|
const key = generateRoundKey(companyAddress, roundId);
|
|
return get().decryptedRounds[key] || null;
|
|
},
|
|
}),
|
|
{
|
|
name: 'decryption-store', // localStorage key
|
|
// Only persist decrypted data, not loading states
|
|
partialize: state => ({
|
|
decryptedSecurities: state.decryptedSecurities,
|
|
decryptedRounds: state.decryptedRounds,
|
|
}),
|
|
}
|
|
)
|
|
);
|