From 4d04defe61edbfafe15849860f5286fd660b3873 Mon Sep 17 00:00:00 2001 From: Benny Neugebauer Date: Fri, 24 Oct 2025 11:06:07 +0200 Subject: [PATCH 1/4] Replace unmaintained packages --- example/package.json | 3 +- example/src/hooks.tsx | 45 ++++++--- example/src/tests/clientTests.ts | 111 ++++++++++----------- example/src/tests/conversationTests.ts | 20 ++-- example/src/tests/fileSystemHelpers.ts | 45 +++++++++ example/src/tests/groupPerformanceTests.ts | 13 ++- example/src/tests/historySyncTests.ts | 44 ++++---- example/yarn.lock | 25 ++--- 8 files changed, 177 insertions(+), 129 deletions(-) create mode 100644 example/src/tests/fileSystemHelpers.ts diff --git a/example/package.json b/example/package.json index 63b6b653e..2e8164963 100644 --- a/example/package.json +++ b/example/package.json @@ -42,8 +42,7 @@ "react-native-blob-util": "^0.19.0", "react-native-config": "^1.5.1", "react-native-crypto": "^2.2.0", - "react-native-encrypted-storage": "^4.0.3", - "react-native-fs": "^2.20.0", + "expo-secure-store": "~14.0.1", "react-native-get-random-values": "^1.11.0", "react-native-mmkv": "^2.8.0", "react-native-quick-base64": "^2.0.8", diff --git a/example/src/hooks.tsx b/example/src/hooks.tsx index 1f196ba86..7c274d045 100644 --- a/example/src/hooks.tsx +++ b/example/src/hooks.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useRef, useState } from 'react' -import EncryptedStorage from 'react-native-encrypted-storage' -import RNFS from 'react-native-fs' +import * as SecureStore from 'expo-secure-store' +import * as FileSystem from 'expo-file-system' import crypto from 'react-native-quick-crypto' import { useMutation, useQuery, UseQueryResult } from 'react-query' import { @@ -762,16 +762,16 @@ export function useSavedAddress(): { } { const { data: address, refetch } = useQuery( ['xmtp', 'address'], - () => EncryptedStorage.getItem('xmtp.address') + () => SecureStore.getItem('xmtp.address') ) return { address, save: async (address: string) => { - await EncryptedStorage.setItem('xmtp.address', address) + SecureStore.setItem('xmtp.address', address) await refetch() }, clear: async () => { - await EncryptedStorage.removeItem('xmtp.address') + await SecureStore.deleteItemAsync('xmtp.address') await refetch() }, } @@ -784,11 +784,11 @@ export async function getDbEncryptionKey( try { const key = `xmtp-${network}` - const result = await EncryptedStorage.getItem(key) - if ((result && clear === true) || !result) { + const result = SecureStore.getItem(key) + if (!result || clear === true) { if (result) { console.log('Removing existing dbEncryptionKey', key) - await EncryptedStorage.removeItem(key) + await SecureStore.deleteItemAsync(key) } // Generate random bytes for the encryption key @@ -797,13 +797,13 @@ export async function getDbEncryptionKey( // Convert to string for storage const randomBytesString = uint8ArrayToHexString(randomBytes) - await EncryptedStorage.setItem(key, randomBytesString) + SecureStore.setItem(key, randomBytesString) return randomBytes - } else { - // Convert stored string back to Uint8Array - return hexStringToUint8Array(result) } + + // Convert stored string back to Uint8Array + return hexStringToUint8Array(result) } catch (error) { console.error('Error in getDbEncryptionKey:', error) // Re-throw or handle as needed @@ -831,9 +831,15 @@ function hexStringToUint8Array(hexString: string): Uint8Array { return new Uint8Array(byteArray) } +function ensureFileUri(path: string): string { + return path.startsWith('file://') ? path : `file://${path}` +} + async function fileExists(path: string): Promise { try { - return await RNFS.exists(path) + const uri = ensureFileUri(path) + const info = await FileSystem.getInfoAsync(uri) + return info.exists } catch (error) { console.error('Error checking file existence:', error) return false @@ -842,8 +848,12 @@ async function fileExists(path: string): Promise { async function getFileSize(path: string): Promise { try { - const stats = await RNFS.stat(path) - return stats.size + const uri = ensureFileUri(path) + const info = await FileSystem.getInfoAsync(uri, { size: true }) + if (info.exists) { + return info.size + } + return 0 } catch (error) { console.error('Error getting file size:', error) return 0 @@ -853,7 +863,10 @@ async function getFileSize(path: string): Promise { async function calculateFileDigest(path: string): Promise { try { // Read the file content - const fileContent = await RNFS.readFile(path, 'base64') + const uri = ensureFileUri(path) + const fileContent = await FileSystem.readAsStringAsync(uri, { + encoding: FileSystem.EncodingType.Base64, + }) const buffer = Buffer.from(fileContent, 'base64') // Create SHA-256 hash using react-native-quick-crypto diff --git a/example/src/tests/clientTests.ts b/example/src/tests/clientTests.ts index 080487d5f..3bb97be00 100644 --- a/example/src/tests/clientTests.ts +++ b/example/src/tests/clientTests.ts @@ -1,5 +1,4 @@ import { ethers, Wallet } from 'ethers' -import RNFS from 'react-native-fs' import { ArchiveOptions } from 'xmtp-react-native-sdk/lib/ArchiveOptions' import { InstallationId } from 'xmtp-react-native-sdk/lib/Client' @@ -13,9 +12,16 @@ import { } from './test-utils' import { Client, PublicIdentity } from '../../../src/index' import { LogLevel, LogRotation } from '../../../src/lib/types/LogTypes' +import { + documentDirectoryPath, + ensureDirectory, + joinDocumentPath, + pathExists, +} from './fileSystemHelpers' export const clientTests: Test[] = [] let counter = 1 +const DOCUMENT_DIRECTORY = documentDirectoryPath() function test(name: string, perform: () => Promise) { clientTests.push({ name: String(counter++) + '. ' + name, @@ -62,15 +68,13 @@ test('can manage revoke manually statically', async () => { 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - const directoryExists2 = await RNFS.exists(dbDirPath2) - if (!directoryExists2) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } const alixWallet = Wallet.createRandom() const alixSigner = adaptEthersWalletToSigner(alixWallet) @@ -134,15 +138,13 @@ test('static revoke all installations', async () => { 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - const directoryExists2 = await RNFS.exists(dbDirPath2) - if (!directoryExists2) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } const alixWallet = Wallet.createRandom() @@ -195,13 +197,15 @@ test('cannot create more than 10 installations', async () => { const [boClient] = await createClients(1) const keyBytes = new Uint8Array(32).fill(2) const wallet = Wallet.createRandom() - const basePath = `${RNFS.DocumentDirectoryPath}/xmtp_limit_test` + const basePath = `${DOCUMENT_DIRECTORY}/xmtp_limit_test` const paths: string[] = [] for (let i = 0; i < 11; i++) { const p = `${basePath}_${i}` paths.push(p) - if (!(await RNFS.exists(p))) await RNFS.mkdir(p) + if (!(await pathExists(p))) { + await ensureDirectory(p) + } } const clients = [] @@ -549,10 +553,9 @@ test('can delete a local database', async () => { test('can make a client with encryption key and database directory', async () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } const key = new Uint8Array([ 233, 120, 198, 96, 154, 65, 132, 17, 132, 96, 250, 40, 103, 35, 125, 64, @@ -922,20 +925,17 @@ test('can manage revoke manually', async () => { 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` - const dbDirPath3 = `${RNFS.DocumentDirectoryPath}/xmtp_db3` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') + const dbDirPath3 = joinDocumentPath('xmtp_db3') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - const directoryExists2 = await RNFS.exists(dbDirPath2) - if (!directoryExists2) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } - const directoryExists3 = await RNFS.exists(dbDirPath3) - if (!directoryExists3) { - await RNFS.mkdir(dbDirPath3) + if (!(await pathExists(dbDirPath3))) { + await ensureDirectory(dbDirPath3) } const alixWallet = Wallet.createRandom() const alixSigner = adaptEthersWalletToSigner(alixWallet) @@ -1052,20 +1052,17 @@ test('can revoke installations', async () => { 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` - const dbDirPath3 = `${RNFS.DocumentDirectoryPath}/xmtp_db3` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') + const dbDirPath3 = joinDocumentPath('xmtp_db3') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - const directoryExists2 = await RNFS.exists(dbDirPath2) - if (!directoryExists2) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } - const directoryExists3 = await RNFS.exists(dbDirPath3) - if (!directoryExists3) { - await RNFS.mkdir(dbDirPath3) + if (!(await pathExists(dbDirPath3))) { + await ensureDirectory(dbDirPath3) } const alixWallet = Wallet.createRandom() @@ -1136,13 +1133,13 @@ test('can create, inspect, import and resync archive', async () => { const key = crypto.getRandomValues(new Uint8Array(32)) const encryptionKey = crypto.getRandomValues(new Uint8Array(32)) - const dbPath1 = `${RNFS.DocumentDirectoryPath}/xmtp_test1` - const dbPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_test2` + const dbPath1 = joinDocumentPath('xmtp_test1') + const dbPath2 = joinDocumentPath('xmtp_test2') const allPath = `${dbPath1}/testAll.zstd` const consentPath = `${dbPath1}/testConsent.zstd` - await RNFS.mkdir(dbPath1) - await RNFS.mkdir(dbPath2) + await ensureDirectory(dbPath1) + await ensureDirectory(dbPath2) const alixWallet = Wallet.createRandom() const alix = await Client.create(adaptEthersWalletToSigner(alixWallet), { @@ -1222,12 +1219,12 @@ test('can stitch inactive DMs if duplicated after archive import', async () => { const key = crypto.getRandomValues(new Uint8Array(32)) const encryptionKey = crypto.getRandomValues(new Uint8Array(32)) - const dbPath1 = `${RNFS.DocumentDirectoryPath}/xmtp_test1` - const dbPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_test2` + const dbPath1 = joinDocumentPath('xmtp_test1') + const dbPath2 = joinDocumentPath('xmtp_test2') const archivePath = `${dbPath1}/testAll.zstd` - await RNFS.mkdir(dbPath1) - await RNFS.mkdir(dbPath2) + await ensureDirectory(dbPath1) + await ensureDirectory(dbPath2) const alixWallet = Wallet.createRandom() const alix = await Client.create(adaptEthersWalletToSigner(alixWallet), { @@ -1289,10 +1286,10 @@ test('can stitch inactive DMs if duplicated after archive import', async () => { test('can import archive on top of full database', async () => { const [alix, bo] = await createClients(2) const encryptionKey = crypto.getRandomValues(new Uint8Array(32)) - const dbPath = `${RNFS.DocumentDirectoryPath}/xmtp_test1` + const dbPath = joinDocumentPath('xmtp_test1') const archivePath = `${dbPath}/testAll.zstd` - await RNFS.mkdir(dbPath) + await ensureDirectory(dbPath) const group = await alix.conversations.newGroup([bo.inboxId]) const dm = await alix.conversations.findOrCreateDm(bo.inboxId) diff --git a/example/src/tests/conversationTests.ts b/example/src/tests/conversationTests.ts index e12494c7a..b48e40cba 100644 --- a/example/src/tests/conversationTests.ts +++ b/example/src/tests/conversationTests.ts @@ -1,6 +1,5 @@ import { content } from '@xmtp/proto' import { Wallet } from 'ethers' -import RNFS from 'react-native-fs' import { Test, @@ -20,6 +19,11 @@ import { GroupUpdatedContent, JSContentCodec, } from '../../../src/index' +import { + ensureDirectory, + joinDocumentPath, + pathExists, +} from './fileSystemHelpers' export const conversationTests: Test[] = [] let counter = 1 @@ -143,15 +147,13 @@ test('returns all push topics and validates HMAC keys', async () => { const keyBytes = crypto.getRandomValues(new Uint8Array(32)) const [bo] = await createClients(1) const eriWallet = Wallet.createRandom() - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - const directoryExists2 = await RNFS.exists(dbDirPath2) - if (!directoryExists2) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } const eriClient = await Client.create(adaptEthersWalletToSigner(eriWallet), { diff --git a/example/src/tests/fileSystemHelpers.ts b/example/src/tests/fileSystemHelpers.ts new file mode 100644 index 000000000..baa48e5ab --- /dev/null +++ b/example/src/tests/fileSystemHelpers.ts @@ -0,0 +1,45 @@ +import * as FileSystem from 'expo-file-system' + +const FILE_SCHEME = 'file://' + +function ensureDocumentDirectory(): string { + if (!FileSystem.documentDirectory) { + throw new Error('FileSystem.documentDirectory is unavailable') + } + return FileSystem.documentDirectory +} + +function stripTrailingSlash(path: string): string { + return path.endsWith('/') ? path.slice(0, -1) : path +} + +function toPath(uri: string): string { + return uri.startsWith(FILE_SCHEME) ? uri.slice(FILE_SCHEME.length) : uri +} + +function toUri(path: string): string { + return path.startsWith(FILE_SCHEME) ? path : `${FILE_SCHEME}${path}` +} + +export function documentDirectoryPath(): string { + const uri = ensureDocumentDirectory() + return stripTrailingSlash(toPath(uri)) +} + +export async function pathExists(path: string): Promise { + const info = await FileSystem.getInfoAsync(toUri(path)) + return info.exists +} + +export async function ensureDirectory(path: string): Promise { + const uri = toUri(path) + const info = await FileSystem.getInfoAsync(uri) + if (!info.exists) { + await FileSystem.makeDirectoryAsync(uri, { intermediates: true }) + } +} + +export function joinDocumentPath(relative: string): string { + const base = documentDirectoryPath() + return `${base}/${relative}` +} diff --git a/example/src/tests/groupPerformanceTests.ts b/example/src/tests/groupPerformanceTests.ts index f1cda13b6..b2e68c9d5 100644 --- a/example/src/tests/groupPerformanceTests.ts +++ b/example/src/tests/groupPerformanceTests.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-extra-non-null-assertion */ import { Wallet } from 'ethers' -import RNFS from 'react-native-fs' import { Client, GroupUpdatedCodec, @@ -16,6 +15,11 @@ import { createClients, adaptEthersWalletToSigner, } from './test-utils' +import { + ensureDirectory, + joinDocumentPath, + pathExists, +} from './fileSystemHelpers' export const groupPerformanceTests: Test[] = [] let counter = 1 @@ -31,10 +35,9 @@ test('building and creating', async () => { 233, 120, 198, 96, 154, 65, 132, 17, 132, 96, 250, 40, 103, 35, 125, 64, 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } const alixWallet = Wallet.createRandom() diff --git a/example/src/tests/historySyncTests.ts b/example/src/tests/historySyncTests.ts index 0e2ce9f2f..8c8d1fb5b 100644 --- a/example/src/tests/historySyncTests.ts +++ b/example/src/tests/historySyncTests.ts @@ -1,5 +1,4 @@ import { Wallet } from 'ethers' -import RNFS from 'react-native-fs' import { PreferenceUpdates } from 'xmtp-react-native-sdk/lib/PrivatePreferences' import { @@ -10,6 +9,11 @@ import { adaptEthersWalletToSigner, } from './test-utils' import { Client, ConsentRecord } from '../../../src/index' +import { + ensureDirectory, + joinDocumentPath, + pathExists, +} from './fileSystemHelpers' export const historySyncTests: Test[] = [] let counter = 1 @@ -27,15 +31,13 @@ test('can sync consent (expected to fail unless historySyncUrl is set)', async ( 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) // eslint-disable-next-line @typescript-eslint/no-unused-vars - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` - const directoryExists = await RNFS.exists(dbDirPath) - if (!directoryExists) { - await RNFS.mkdir(dbDirPath) + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - const directoryExists2 = await RNFS.exists(dbDirPath2) - if (!directoryExists2) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } const alixWallet = Wallet.createRandom() @@ -101,15 +103,15 @@ test('can stream consent (expected to fail unless historySyncUrl is set)', async 233, 120, 198, 96, 154, 65, 132, 17, 132, 96, 250, 40, 103, 35, 125, 64, 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') // Ensure the directories exist - if (!(await RNFS.exists(dbDirPath))) { - await RNFS.mkdir(dbDirPath) + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - if (!(await RNFS.exists(dbDirPath2))) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } const alixWallet = Wallet.createRandom() @@ -170,15 +172,15 @@ test('can preference updates (expected to fail unless historySyncUrl is set)', a 233, 120, 198, 96, 154, 65, 132, 17, 132, 96, 250, 40, 103, 35, 125, 64, 166, 83, 208, 224, 254, 44, 205, 227, 175, 49, 234, 129, 74, 252, 135, 145, ]) - const dbDirPath = `${RNFS.DocumentDirectoryPath}/xmtp_db` - const dbDirPath2 = `${RNFS.DocumentDirectoryPath}/xmtp_db2` + const dbDirPath = joinDocumentPath('xmtp_db') + const dbDirPath2 = joinDocumentPath('xmtp_db2') // Ensure the directories exist - if (!(await RNFS.exists(dbDirPath))) { - await RNFS.mkdir(dbDirPath) + if (!(await pathExists(dbDirPath))) { + await ensureDirectory(dbDirPath) } - if (!(await RNFS.exists(dbDirPath2))) { - await RNFS.mkdir(dbDirPath2) + if (!(await pathExists(dbDirPath2))) { + await ensureDirectory(dbDirPath2) } const alixWallet = Wallet.createRandom() diff --git a/example/yarn.lock b/example/yarn.lock index 39e5eeebf..406f9dea2 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -2718,7 +2718,7 @@ balanced-match@^1.0.0: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-64@0.1.0, base-64@^0.1.0: +base-64@0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== @@ -4196,6 +4196,11 @@ expo-modules-core@2.2.3: dependencies: invariant "^2.2.4" +expo-secure-store@~14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/expo-secure-store/-/expo-secure-store-14.0.1.tgz#8953d5966430f5ff262f4d99e7551205870078d7" + integrity sha512-QUS+j4+UG4jRQalgnpmTvvrFnMVLqPiUZRzYPnG3+JrZ5kwVW2w6YS3WWerPoR7C6g3y/a2htRxRSylsDs+TaQ== + expo-splash-screen@~0.29.24: version "0.29.24" resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.29.24.tgz#4e5f6d576d3fbb37c5e3e4ee6d3f3b3ece350f75" @@ -6955,19 +6960,6 @@ react-native-crypto@^2.2.0: public-encrypt "^4.0.0" randomfill "^1.0.3" -react-native-encrypted-storage@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/react-native-encrypted-storage/-/react-native-encrypted-storage-4.0.3.tgz#2a4d65459870511e8f4ccd22f02433dab7fa5e91" - integrity sha512-0pJA4Aj2S1PIJEbU7pN/Qvf7JIJx3hFywx+i+bLHtgK0/6Zryf1V2xVsWcrD50dfiu3jY1eN2gesQ5osGxE7jA== - -react-native-fs@^2.20.0: - version "2.20.0" - resolved "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz#05a9362b473bfc0910772c0acbb73a78dbc810f6" - integrity sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ== - dependencies: - base-64 "^0.1.0" - utf8 "^3.0.0" - react-native-get-random-values@^1.11.0: version "1.11.0" resolved "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz#1ca70d1271f4b08af92958803b89dccbda78728d" @@ -8382,11 +8374,6 @@ use-latest-callback@^0.2.1: resolved "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.3.tgz#2d644d3063040b9bc2d4c55bb525a13ae3de9e16" integrity sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ== -utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" From 626ef1f9e6e5a3660101b341d4e4ae3563ad5bdf Mon Sep 17 00:00:00 2001 From: Benny Neugebauer Date: Fri, 24 Oct 2025 11:35:18 +0200 Subject: [PATCH 2/4] test workflow --- .github/workflows/test-android.yml | 6 +- .github/workflows/test-ios.yml | 3 +- example/app.json | 7 ++ example/package.json | 12 ++-- example/src/hooks.tsx | 12 ++-- example/yarn.lock | 108 +++++------------------------ 6 files changed, 44 insertions(+), 104 deletions(-) diff --git a/.github/workflows/test-android.yml b/.github/workflows/test-android.yml index 9bb60e466..ddd503264 100644 --- a/.github/workflows/test-android.yml +++ b/.github/workflows/test-android.yml @@ -41,8 +41,10 @@ jobs: node-version-file: ".nvmrc" cache: yarn - - name: Install dependencies - run: yarn install --frozen-lockfile + - name: Install and test npm dependencies + run: | + yarn install --frozen-lockfile + yarn test - name: Install Maestro run: | diff --git a/.github/workflows/test-ios.yml b/.github/workflows/test-ios.yml index 2cdb1c26f..27c080ba5 100644 --- a/.github/workflows/test-ios.yml +++ b/.github/workflows/test-ios.yml @@ -42,11 +42,12 @@ jobs: node-version-file: ".nvmrc" cache: yarn - - name: Install dependencies + - name: Install and test npm dependencies run: | yarn install --frozen-lockfile cd ./example yarn install --frozen-lockfile + yarn test - name: Install Maestro run: | diff --git a/example/app.json b/example/app.json index 49759b798..a69551ecd 100644 --- a/example/app.json +++ b/example/app.json @@ -15,6 +15,13 @@ "**/*" ], "plugins": [ + [ + "expo-sqlite", + { + "enableFTS": true, + "useSQLCipher": true + } + ], [ "expo-image-picker", { diff --git a/example/package.json b/example/package.json index 2e8164963..2c93fc41f 100644 --- a/example/package.json +++ b/example/package.json @@ -41,16 +41,14 @@ "react-native": "0.76.9", "react-native-blob-util": "^0.19.0", "react-native-config": "^1.5.1", - "react-native-crypto": "^2.2.0", "expo-secure-store": "~14.0.1", "react-native-get-random-values": "^1.11.0", "react-native-mmkv": "^2.8.0", "react-native-quick-base64": "^2.0.8", - "react-native-quick-crypto": "^0.7.12", "react-native-randombytes": "^3.6.1", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", - "react-native-sqlite-storage": "^6.0.1", + "expo-sqlite": "~15.1.4", "react-native-svg": "15.8.0", "react-native-url-polyfill": "^2.0.0", "react-native-webview": "13.12.5", @@ -78,9 +76,11 @@ "expo": { "autolinking": { "nativeModulesDir": ".." + }, + "doctor": { + "reactNativeDirectoryCheck": { + "listUnknownPackages": false + } } - }, - "engines": { - "node": ">=20" } } diff --git a/example/src/hooks.tsx b/example/src/hooks.tsx index 7c274d045..bd6651a13 100644 --- a/example/src/hooks.tsx +++ b/example/src/hooks.tsx @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from 'react' +import * as ExpoCrypto from 'expo-crypto' import * as SecureStore from 'expo-secure-store' import * as FileSystem from 'expo-file-system' -import crypto from 'react-native-quick-crypto' import { useMutation, useQuery, UseQueryResult } from 'react-query' import { Conversation, @@ -869,10 +869,12 @@ async function calculateFileDigest(path: string): Promise { }) const buffer = Buffer.from(fileContent, 'base64') - // Create SHA-256 hash using react-native-quick-crypto - const hash = crypto.createHash('sha256') - hash.update(buffer.buffer) - return hash.digest('hex') + // Create SHA-256 hash + const digest = await ExpoCrypto.digest( + ExpoCrypto.CryptoDigestAlgorithm.SHA256, + buffer + ) + return Buffer.from(digest).toString('hex') } catch (error) { console.error('Error calculating file digest:', error) throw error diff --git a/example/yarn.lock b/example/yarn.lock index 406f9dea2..971c287e7 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -816,14 +816,6 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" -"@craftzdog/react-native-buffer@^6.0.5": - version "6.0.5" - resolved "https://registry.npmjs.org/@craftzdog/react-native-buffer/-/react-native-buffer-6.0.5.tgz#0d4fbe0dd104186d2806655e3c0d25cebdae91d3" - integrity sha512-Av+YqfwA9e7jhgI9GFE/gTpwl/H+dRRLmZyJPOpKTy107j9Oj7oXlm3/YiMNz+C/CEGqcKAOqnXDLs4OL6AAFw== - dependencies: - ieee754 "^1.2.1" - react-native-quick-base64 "^2.0.5" - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.5.1" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz#b0fc7e06d0c94f801537fd4237edc2706d3b8e4c" @@ -2841,7 +2833,7 @@ browserify-aes@^1.0.4, browserify-aes@^1.2.0: inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-cipher@^1.0.0, browserify-cipher@^1.0.1: +browserify-cipher@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== @@ -2869,7 +2861,7 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: randombytes "^2.1.0" safe-buffer "^5.2.1" -browserify-sign@^4.0.4, browserify-sign@^4.2.3: +browserify-sign@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== @@ -3300,7 +3292,7 @@ cosmiconfig@^5.0.5: js-yaml "^3.13.1" parse-json "^4.0.0" -create-ecdh@^4.0.0, create-ecdh@^4.0.4: +create-ecdh@^4.0.4: version "4.0.4" resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== @@ -3319,7 +3311,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -3563,7 +3555,7 @@ detect-node@^2.0.4, detect-node@^2.1.0: resolved "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== -diffie-hellman@^5.0.0, diffie-hellman@^5.0.3: +diffie-hellman@^5.0.3: version "5.0.3" resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== @@ -4058,7 +4050,7 @@ eventemitter3@5.0.1: resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== -events@^3.0.0, events@^3.3.0: +events@^3.0.0: version "3.3.0" resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -4208,6 +4200,11 @@ expo-splash-screen@~0.29.24: dependencies: "@expo/prebuild-config" "~8.2.0" +expo-sqlite@~15.1.4: + version "15.1.4" + resolved "https://registry.yarnpkg.com/expo-sqlite/-/expo-sqlite-15.1.4.tgz#7827db7e6d376747d9d2a3a4eea9760e5bd41c42" + integrity sha512-1SG5Qi6/L2SK/o5EKtvEmlMVGdra/wYYh/intI94/ovsUfZGFrDG31YGtTt4rLpE95M6FwHUVpALO8g9/G9B2Q== + expo-status-bar@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-2.0.1.tgz#fc07726346dc30fbb68aadb0d7890b34fba42eee" @@ -4929,14 +4926,6 @@ ipaddr.js@^1.9.0: resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-arguments@^1.0.4: - version "1.2.0" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" - integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== - dependencies: - call-bound "^1.0.2" - has-tostringtag "^1.0.2" - is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: version "3.0.5" resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" @@ -5038,7 +5027,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-function@^1.0.10, is-generator-function@^1.0.7: +is-generator-function@^1.0.10: version "1.1.0" resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== @@ -5144,7 +5133,7 @@ is-symbol@^1.0.4, is-symbol@^1.1.1: has-symbols "^1.1.0" safe-regex-test "^1.1.0" -is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15, is-typed-array@^1.1.3: +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: version "1.1.15" resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== @@ -6626,13 +6615,6 @@ path-type@^4.0.0: resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@3.0.8: - version "3.0.8" - resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.8.tgz#2f8abf16ebecc82277945d748aba1d78761f61e2" - integrity sha512-Bf7yBd61ChnMqPqf+PxHm34Iiq9M9Bkd/+JqzosPOqwG6FiTixtkpCs4PNd38+6/VYRvAxGe/GgPb4Q4GktFzg== - dependencies: - create-hmac "^1.1.2" - pbkdf2@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -6809,7 +6791,7 @@ protobufjs@^7.0.0: "@types/node" ">=13.7.0" long "^5.0.0" -public-encrypt@^4.0.0, public-encrypt@^4.0.3: +public-encrypt@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== @@ -6885,7 +6867,7 @@ randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -randomfill@^1.0.3, randomfill@^1.0.4: +randomfill@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== @@ -6944,22 +6926,6 @@ react-native-config@^1.5.1: resolved "https://registry.npmjs.org/react-native-config/-/react-native-config-1.5.5.tgz#5977db58ff20b6fe9dd6fb28c815a9ba43d018d2" integrity sha512-dGdLnBU0cd5xL5bF0ROTmHYbsstZnQKOEPfglvZi1vStvAjpld14X25K6mY3KGPTMWAzx6TbjKeq5dR+ILuMMA== -react-native-crypto@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/react-native-crypto/-/react-native-crypto-2.2.0.tgz#c999ed7c96064f830e1f958687f53d0c44025770" - integrity sha512-eZu9Y8pa8BN9FU2pIex7MLRAi+Cd1Y6bsxfiufKh7sfraAACJvjQTeW7/zcQAT93WMfM+D0OVk+bubvkrbrUkw== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.4" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "3.0.8" - public-encrypt "^4.0.0" - randomfill "^1.0.3" - react-native-get-random-values@^1.11.0: version "1.11.0" resolved "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz#1ca70d1271f4b08af92958803b89dccbda78728d" @@ -6972,24 +6938,13 @@ react-native-mmkv@^2.8.0: resolved "https://registry.npmjs.org/react-native-mmkv/-/react-native-mmkv-2.12.2.tgz#4bba0f5f04e2cf222494cce3a9794ba6a4894dee" integrity sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg== -react-native-quick-base64@^2.0.5, react-native-quick-base64@^2.0.8: +react-native-quick-base64@^2.0.8: version "2.1.2" resolved "https://registry.npmjs.org/react-native-quick-base64/-/react-native-quick-base64-2.1.2.tgz#062b09b165c1530095fe99b94544c948318dbe99" integrity sha512-xghaXpWdB0ji8OwYyo0fWezRroNxiNFCNFpGUIyE7+qc4gA/IGWnysIG5L0MbdoORv8FkTKUvfd6yCUN5R2VFA== dependencies: base64-js "^1.5.1" -react-native-quick-crypto@^0.7.12: - version "0.7.12" - resolved "https://registry.npmjs.org/react-native-quick-crypto/-/react-native-quick-crypto-0.7.12.tgz#2c2db1e63c18ee1fcd13b85de5b9327c734dc624" - integrity sha512-3x4SmFz44DN4RjnSWu85f9iGSBqVy8RKj++7eWcGRTir1gMosNH6IxbxQHO4GD/d3tIP21QIijcD+/Z5h7v6DA== - dependencies: - "@craftzdog/react-native-buffer" "^6.0.5" - events "^3.3.0" - readable-stream "^4.5.2" - string_decoder "^1.3.0" - util "^0.12.5" - react-native-randombytes@^3.6.1: version "3.6.1" resolved "https://registry.npmjs.org/react-native-randombytes/-/react-native-randombytes-3.6.1.tgz#cac578093b5ca38e3e085becffdc6cbcf6f0d654" @@ -7011,11 +6966,6 @@ react-native-screens@~4.4.0: react-freeze "^1.0.0" warn-once "^0.1.0" -react-native-sqlite-storage@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/react-native-sqlite-storage/-/react-native-sqlite-storage-6.0.1.tgz#ce6a6b852f07abbea68658d5363818c8bef45dfb" - integrity sha512-1tDFjrint6X6qSYKf3gDyz+XB+X79jfiL6xTugKHPRtF0WvqMtVgdLuNqZunIXjNEvNtNVEbXaeZ6MsguFu00A== - react-native-svg@15.8.0: version "15.8.0" resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-15.8.0.tgz#9b5fd4f5cf5675197b3f4cbfcc77c215de2b9502" @@ -7127,17 +7077,6 @@ readable-stream@^3.5.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^4.5.2: - version "4.7.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" - integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - string_decoder "^1.3.0" - readline@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" @@ -7866,7 +7805,7 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.0.0, string_decoder@^1.1.1, string_decoder@^1.3.0: +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -8393,17 +8332,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@^0.12.5: - version "0.12.5" - resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - utils-merge@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -8549,7 +8477,7 @@ which-collection@^1.0.2: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-typed-array@^1.1.16, which-typed-array@^1.1.18, which-typed-array@^1.1.2: +which-typed-array@^1.1.16, which-typed-array@^1.1.18: version "1.1.19" resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== From 0e740d93483bfa545d9cdf95c0b9ae11341d5335 Mon Sep 17 00:00:00 2001 From: Benny Neugebauer Date: Fri, 24 Oct 2025 11:39:54 +0200 Subject: [PATCH 3/4] format --- example/README.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/example/README.md b/example/README.md index 287ea3462..14d13c0c8 100644 --- a/example/README.md +++ b/example/README.md @@ -3,6 +3,7 @@ This basic messaging app has an intentionally unopinionated UI to help make it easier for you to build with. ## Run the example app + Follow the [React Native guide](https://reactnative.dev/docs/environment-setup) to set up a CLI environment. ### To use the example app, run: @@ -11,7 +12,6 @@ Follow the [React Native guide](https://reactnative.dev/docs/environment-setup) yarn cd example yarn -npx pod-install yarn run [ios or android] ``` @@ -43,34 +43,38 @@ First create a free account and download your client id from https://thirdweb.co cd example cp EXAMPLE.env .env ``` + Finally, insert your Thirdweb client id in specified location of `example/.env` file: + ``` THIRD_WEB_CLIENT_ID=INSERT_CLIENT_ID_HERE ``` If your app doesn't appear to be picking up changes in the .env file, you can try editing the TypeScript file you're reading the env variable from (`App.tsx`) or building the app with the `--no-build-cache` flag added. - ## Run example app unit tests on local emulators + Running tests locally is useful when updating GitHub actions, or locally testing between changes. 1. [Install Docker](https://docs.docker.com/get-started/get-docker/) 2. Start a local XMTP server - ```bash - git clone https://github.com/xmtp/libxmtp.git - cd libxmtp - dev/up - ``` + ```bash + git clone https://github.com/xmtp/libxmtp.git + cd libxmtp + dev/up + ``` 3. Verify the XMTP server is running - ```bash - docker-compose ls - NAME STATUS CONFIG FILES - libxmtp running(9) /libxmtp/dev/docker/docker-compose.yml - ``` + ```bash + docker-compose ls + + NAME STATUS CONFIG FILES + libxmtp running(9) /libxmtp/dev/docker/docker-compose.yml + ``` + 4. You can now run unit tests on your local emulators 5. You can stop the XMTP server with the following command: - ```bash - dev/down - ``` + ```bash + dev/down + ``` From 746a4d91c18bf59df01197eaf1685c97a6f35cfb Mon Sep 17 00:00:00 2001 From: Benny Neugebauer Date: Fri, 24 Oct 2025 11:50:53 +0200 Subject: [PATCH 4/4] macroscope --- example/src/hooks.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/src/hooks.tsx b/example/src/hooks.tsx index bd6651a13..528af11c7 100644 --- a/example/src/hooks.tsx +++ b/example/src/hooks.tsx @@ -767,7 +767,7 @@ export function useSavedAddress(): { return { address, save: async (address: string) => { - SecureStore.setItem('xmtp.address', address) + await SecureStore.setItemAsync('xmtp.address', address) await refetch() }, clear: async () => { @@ -797,7 +797,7 @@ export async function getDbEncryptionKey( // Convert to string for storage const randomBytesString = uint8ArrayToHexString(randomBytes) - SecureStore.setItem(key, randomBytesString) + await SecureStore.setItemAsync(key, randomBytesString) return randomBytes }