import type { Profile , Persona } from './types' ; import { ProfileRecord , queryProfilesDB , PersonaRecord , queryProfileDB , queryPersonaDB , queryPersonasDB , detachProfileDB , deletePersonaDB , safeDeletePersonaDB , queryPersonaByProfileDB , createPersonaDB , attachProfileDB , LinkedProfileDetails , consistentPersonaDBWriteAccess , updatePersonaDB , createOrUpdatePersonaDB , queryProfilesPagedDB , } from '../../../background/database/persona/db' ; import { queryAvatarDataURL } from '../../../background/database/avatar-cache/avatar' ; import { generate_ECDH_256k1_KeyPair_ByMnemonicWord , recover_ECDH_256k1_KeyPair_ByMnemonicWord , } from '../../utils/mnemonic-code' ; import { deriveLocalKeyFromECDHKey } from '../../utils/mnemonic-code/localKeyGenerate' ; import { validateMnemonic } from 'bip39' ; import { ProfileIdentifier , type , PersonaIdentifier , IdentifierMap , type , EC_Public_JsonWebKey , type , EC_Private_JsonWebKey , type , AESJsonWebKey , ECKeyIdentifierFromJsonWebKey , } from '@masknet/shared-base' ; export async function profileRecordToProfile ( record ) { const rec = { ... record } ; const persona = rec . linkedPersona ; delete rec . linkedPersona ; delete rec . localKey ; const _ = persona ? queryPersona ( persona ) : undefined ; const _2 = queryAvatarDataURL ( rec . identifier ) . catch ( ( ) => undefined ) ; return { ... rec , linkedPersona : await _ , avatar : await _2 , } ; } export function personaRecordToPersona ( record ) { const rec = { ... record } ; delete rec . localKey ; delete rec . publicKey ; const hasPrivateKey = ! ! rec . privateKey ; delete rec . privateKey ; return { ... rec , hasPrivateKey , fingerprint : rec . identifier . compressedPoint , } ; } param identifier export async function queryProfile ( identifier ) { const _ = await queryProfileDB ( identifier ) ; if ( _ ) return profileRecordToProfile ( _ ) ; return { identifier , createdAt : new Date ( ) , updatedAt : new Date ( ) , } ; } export async function queryProfilePaged ( ... args ) { const _ = await queryProfilesPagedDB ( ... args ) ; return Promise . all ( _ . map ( profileRecordToProfile ) ) ; } param identifier export async function queryPersona ( identifier ) { const _ = await queryPersonaDB ( identifier ) ; if ( _ ) return personaRecordToPersona ( _ ) ; return { identifier , createdAt : new Date ( ) , updatedAt : new Date ( ) , linkedProfiles : new IdentifierMap ( new Map ( ) , ProfileIdentifier ) , hasPrivateKey : false , hasLogout : false , fingerprint : identifier . compressedPoint , } ; } /**
 * Select a set of Profiles
 */ export async function queryProfilesWithQuery ( query ? ) { const _ = await queryProfilesDB ( query || ( ( _ ) => true ) ) ; return Promise . all ( _ . map ( profileRecordToProfile ) ) ; } /**
 * Select a set of Personas
 */ export async function queryPersonasWithQuery ( query ? ) { const _ = await queryPersonasDB ( query || ( ( _ ) => true ) ) ; return _ . map ( personaRecordToPersona ) ; } export async function deletePersona ( id , confirm ) { return consistentPersonaDBWriteAccess ( async ( t ) => { const d = await queryPersonaDB ( id , t ) ; if ( ! d ) return ; for ( const e of d . linkedProfiles ) { await detachProfileDB ( e [ 0 ] , t ) ; } if ( confirm === 'delete even with private' ) await deletePersonaDB ( id , 'delete even with private' , t ) ; else if ( confirm === 'safe delete' ) await safeDeletePersonaDB ( id , t ) ; } ) ; } export async function loginPersona ( identifier ) { return consistentPersonaDBWriteAccess ( ( t ) => updatePersonaDB ( { identifier , hasLogout : false } , { linkedProfiles : 'merge' , explicitUndefinedField : 'ignore' } , t ) ) ; } export async function logoutPersona ( identifier ) { return consistentPersonaDBWriteAccess ( ( t ) => updatePersonaDB ( { identifier , hasLogout : true } , { linkedProfiles : 'merge' , explicitUndefinedField : 'ignore' } , t ) ) ; } export async function renamePersona ( identifier , nickname ) { const personas = await queryPersonasWithQuery ( ( { nickname : name } ) => name === nickname ) ; if ( personas . length > 0 ) { throw new Error ( 'Nickname already exists' ) ; } return consistentPersonaDBWriteAccess ( ( t ) => updatePersonaDB ( { identifier , nickname } , { linkedProfiles : 'merge' , explicitUndefinedField : 'ignore' } , t ) ) ; } export async function setupPersona ( id ) { return consistentPersonaDBWriteAccess ( async ( t ) => { const d = await queryPersonaDB ( id , t ) ; if ( ! d ) throw new Error ( 'cannot find persona' ) ; if ( d . linkedProfiles . size === 0 ) throw new Error ( 'persona should link at least one profile' ) ; if ( d . uninitialized ) { await updatePersonaDB ( { identifier : id , uninitialized : false } , { linkedProfiles : 'merge' , explicitUndefinedField : 'ignore' } , t ) ; } } ) ; } export async function queryPersonaByProfile ( i ) { return ( await queryProfile ( i ) ) . linkedPersona ; } export function queryPersonaRecord ( i ) { return i instanceof ProfileIdentifier ? queryPersonaByProfileDB ( i ) : queryPersonaDB ( i ) ; } export async function queryPublicKey ( i ) { return queryPersonaRecord ( i ) . then ( ( x ) => x ?. publicKey ) ; } export async function queryPrivateKey ( i ) { return queryPersonaRecord ( i ) . then ( ( x ) => x ?. privateKey ) ; } export async function createPersonaByMnemonic ( nickname , password ) { const { key , mnemonicRecord : mnemonic } = await generate_ECDH_256k1_KeyPair_ByMnemonicWord ( password ) ; const { privateKey , publicKey } = key ; const localKey = await deriveLocalKeyFromECDHKey ( publicKey , mnemonic . words ) ; return createPersonaByJsonWebKey ( { privateKey , publicKey , localKey , mnemonic , nickname , uninitialized : false , } ) ; } export async function createPersonaByMnemonicV2 ( mnemonicWord , nickname , password ) { const personas = await queryPersonasWithQuery ( ( { nickname : name } ) => name === nickname ) ; if ( personas . length > 0 ) throw new Error ( 'Nickname already exists' ) ; const verify = validateMnemonic ( mnemonicWord ) ; if ( ! verify ) throw new Error ( 'Verify error' ) ; const { key , mnemonicRecord : mnemonic } = await recover_ECDH_256k1_KeyPair_ByMnemonicWord ( mnemonicWord , password ) ; const { privateKey , publicKey } = key ; const localKey = await deriveLocalKeyFromECDHKey ( publicKey , mnemonic . words ) ; return createPersonaByJsonWebKey ( { privateKey , publicKey , localKey , mnemonic , nickname , uninitialized : false , } ) ; } export async function createPersonaByJsonWebKey ( options ) { const identifier = ECKeyIdentifierFromJsonWebKey ( options . publicKey ) ; const record = { createdAt : new Date ( ) , updatedAt : new Date ( ) , identifier : identifier , linkedProfiles : new IdentifierMap ( new Map ( ) , ProfileIdentifier ) , publicKey : options . publicKey , privateKey : options . privateKey , nickname : options . nickname , mnemonic : options . mnemonic , localKey : options . localKey , hasLogout : false , uninitialized : options . uninitialized , } ; await consistentPersonaDBWriteAccess ( ( t ) => createPersonaDB ( record , t ) ) ; return identifier ; } export async function createProfileWithPersona ( profileID , data , keys ) { const ec_id = ECKeyIdentifierFromJsonWebKey ( keys . publicKey ) ; const rec = { createdAt : new Date ( ) , updatedAt : new Date ( ) , identifier : ec_id , linkedProfiles : new IdentifierMap ( new Map ( ) , ProfileIdentifier ) , nickname : keys . nickname , publicKey : keys . publicKey , privateKey : keys . privateKey , localKey : keys . localKey , mnemonic : keys . mnemonic , hasLogout : false , } ; await consistentPersonaDBWriteAccess ( async ( t ) => { await createOrUpdatePersonaDB ( rec , { explicitUndefinedField : 'ignore' , linkedProfiles : 'merge' } , t ) ; await attachProfileDB ( profileID , ec_id , data , t ) ; } ) ; } export async function queryLocalKey ( i ) { if ( i instanceof ProfileIdentifier ) { const profile = await queryProfileDB ( i ) ; if ( ! profile ) return null ; if ( profile . localKey ) return profile . localKey ; if ( ! profile . linkedPersona ) return null ; return queryLocalKey ( profile . linkedPersona ) ; } else { return ( await queryPersonaDB ( i ) ) ?. localKey ?? null ; } } function cover_ECDH_256k1_KeyPair_ByMnemonicWord ( password ) { throw new Error ( 'Function not implemented.' ) ; }