import { requireNativeModule } from 'expo-modules-core' import { Platform } from 'react-native' import type { SecureEnvironment } from './SecureEnvironment' type UnwrapPromiseReturnTypes = { [K in keyof T]: K extends ExcludedKey ? T[K] : T[K] extends (...args: infer A) => Promise | infer S ? (...args: A) => Promise extends Promise ? U : Promise | S : T[K] } const nativeExpoSecureEnvironment = requireNativeModule< UnwrapPromiseReturnTypes, 'sign'> & { supportsSecureEnvironment: () => boolean } >('ExpoSecureEnvironment') export const expoSecureEnvironment = { generateKeypair: (keyId: string, biometricsBacked?: boolean): Uint8Array => { nativeExpoSecureEnvironment.generateKeypair(keyId, biometricsBacked) const publicKey = expoSecureEnvironment.getPublicBytesForKeyId(keyId) return publicKey }, batchGenerateKeyPair: (keyIds: Array): Record => { for (const keyId of keyIds) { expoSecureEnvironment.generateKeypair(keyId) } return keyIds .map((keyId) => ({ keyId, publicKey: expoSecureEnvironment.getPublicBytesForKeyId(keyId), })) .reduce((prev, curr) => ({ ...prev, [curr.keyId]: curr.publicKey }), {}) }, getPublicBytesForKeyId: (keyId: string): Uint8Array => { return nativeExpoSecureEnvironment.getPublicBytesForKeyId(keyId) }, sign: (keyId: string, message: Uint8Array, biometricsBacked?: boolean): Promise => { return Platform.OS === 'ios' ? nativeExpoSecureEnvironment.sign(keyId, message) : nativeExpoSecureEnvironment.sign(keyId, message, biometricsBacked) }, supportsSecureEnvironment: () => { return nativeExpoSecureEnvironment.supportsSecureEnvironment() }, deleteKey: (keyId: string) => { return nativeExpoSecureEnvironment.deleteKey(keyId) }, }