diff --git a/packages/mobile/src/account/profileInfo.test.ts b/packages/mobile/src/account/profileInfo.test.ts index 4b51a21db03..1397245e264 100644 --- a/packages/mobile/src/account/profileInfo.test.ts +++ b/packages/mobile/src/account/profileInfo.test.ts @@ -1,3 +1,4 @@ +import { normalizeAddressWith0x } from '@celo/utils/lib/address' import RNFS from 'react-native-fs' import { expectSaga } from 'redux-saga-test-plan' import { call, select } from 'redux-saga/effects' @@ -10,6 +11,7 @@ import { uploadNameAndPicture, } from 'src/account/profileInfo' import { isProfileUploadedSelector, nameSelector, pictureSelector } from 'src/account/selectors' +import { walletToAccountAddressSelector } from 'src/identity/reducer' import { DEK, retrieveOrGeneratePepper } from 'src/pincode/authentication' import { getContractKit, getWallet } from 'src/web3/contracts' import { getAccountAddress, getConnectedUnlockedAccount } from 'src/web3/saga' @@ -128,11 +130,14 @@ describe(uploadNameAndPicture, () => { }) describe(giveProfileAccess, () => { - const recipients = [mockAccount2] + const walletAddress = mockAccount2 + const accountAddress = '0xTEST' + const walletToAccountAddress = { [normalizeAddressWith0x(walletAddress)]: accountAddress } it('gives profile access successfully', async () => { - await expectSaga(giveProfileAccess, recipients) + await expectSaga(giveProfileAccess, walletAddress) .provide([ + [select(walletToAccountAddressSelector), walletToAccountAddress], [call(getOffchainWrapper), null], [call(getConnectedUnlockedAccount), mockAccount], [select(nameSelector), mockName], @@ -141,14 +146,15 @@ describe(giveProfileAccess, () => { ]) .run() - expect(mockNameAllowAccess).toBeCalledWith(recipients) - expect(mockPictureAllowAccess).toBeCalledWith(recipients) + expect(mockNameAllowAccess).toBeCalledWith([accountAddress]) + expect(mockPictureAllowAccess).toBeCalledWith([accountAddress]) }) it('handles error when fails to give recipient access to name', async () => { mockNameAllowAccess.mockReturnValueOnce(Error('error')) - await expectSaga(giveProfileAccess, recipients) + await expectSaga(giveProfileAccess, walletAddress) .provide([ + [select(walletToAccountAddressSelector), walletToAccountAddress], [call(getOffchainWrapper), null], [call(getConnectedUnlockedAccount), mockAccount], [select(nameSelector), mockName], @@ -157,14 +163,15 @@ describe(giveProfileAccess, () => { ]) .run() .catch((error) => { - expect(error).toEqual(Error(`Unable to give ${recipients} access to name`)) + expect(error).toEqual(Error(`Unable to give ${walletAddress} access to name`)) }) }) it('handles error when fails to give recipient access to picture', async () => { mockPictureAllowAccess.mockReturnValueOnce(Error('error')) - await expectSaga(giveProfileAccess, recipients) + await expectSaga(giveProfileAccess, walletAddress) .provide([ + [select(walletToAccountAddressSelector), walletToAccountAddress], [call(getOffchainWrapper), null], [call(getConnectedUnlockedAccount), mockAccount], [select(nameSelector), mockName], @@ -173,7 +180,7 @@ describe(giveProfileAccess, () => { ]) .run() .catch((error) => { - expect(error).toEqual(Error(`Unable to give ${recipients} access to picture`)) + expect(error).toEqual(Error(`Unable to give ${walletAddress} access to picture`)) }) }) }) diff --git a/packages/mobile/src/account/profileInfo.ts b/packages/mobile/src/account/profileInfo.ts index 3e8cb7f6af9..861a816cd3c 100644 --- a/packages/mobile/src/account/profileInfo.ts +++ b/packages/mobile/src/account/profileInfo.ts @@ -9,6 +9,7 @@ import { call, put, select } from 'redux-saga/effects' import { profileUploaded } from 'src/account/actions' import { isProfileUploadedSelector, nameSelector, pictureSelector } from 'src/account/selectors' import UploadServiceDataWrapper from 'src/account/UploadServiceDataWrapper' +import { walletToAccountAddressSelector, WalletToAccountAddressType } from 'src/identity/reducer' import { DEK, retrieveOrGeneratePepper } from 'src/pincode/authentication' import { extensionToMimeType, getDataURL, saveRecipientPicture } from 'src/utils/image' import Logger from 'src/utils/Logger' @@ -90,33 +91,36 @@ export function* uploadNameAndPicture() { } // this function gives permission to the recipient to view the user's profile info -export function* giveProfileAccess(recipientAddresses: string[]) { +export function* giveProfileAccess(walletAddress: string) { + // TODO: check if key for recipient already exists, skip if yes try { - // TODO: check if key for recipient already exists, skip if yes + const walletToAccountAddress: WalletToAccountAddressType = yield select( + walletToAccountAddressSelector + ) + const accountAddress = + walletToAccountAddress[normalizeAddressWith0x(walletAddress)] ?? walletAddress + const offchainWrapper: UploadServiceDataWrapper = yield call(getOffchainWrapper) const nameAccessor = new PrivateNameAccessor(offchainWrapper) - let writeError = yield call([nameAccessor, 'allowAccess'], recipientAddresses) + let writeError = yield call([nameAccessor, 'allowAccess'], [accountAddress]) if (writeError) { Logger.error(TAG + '@giveProfileAccess', writeError) + return } const pictureUri = yield select(pictureSelector) if (pictureUri) { const pictureAccessor = new PrivatePictureAccessor(offchainWrapper) - writeError = yield call([pictureAccessor, 'allowAccess'], recipientAddresses) + writeError = yield call([pictureAccessor, 'allowAccess'], [accountAddress]) if (writeError) { Logger.error(TAG + '@giveProfileAccess', writeError) + return } } - // not throwing error, because possibility the recipient doesn't have a registered DEK - Logger.info(TAG + '@giveProfileAccess', 'uploaded symmetric keys for ' + recipientAddresses) + Logger.info(TAG + '@giveProfileAccess', 'uploaded symmetric keys for ' + accountAddress) } catch (error) { - Logger.error( - TAG + '@giveProfileAccess', - 'error when giving access to ' + recipientAddresses, - error - ) + Logger.error(TAG + '@giveProfileAccess', 'error when giving access to ' + walletAddress, error) } } @@ -165,6 +169,7 @@ export function* getOffchainWrapper(addAccount = false) { const contractKit = yield call(getContractKit) const account: Address = yield call(getAccountAddress) + Logger.info(TAG, 'uploading information for', account) const offchainWrapper = new UploadServiceDataWrapper( contractKit, toChecksumAddress(account), diff --git a/packages/mobile/src/send/saga.ts b/packages/mobile/src/send/saga.ts index de7bf424a0e..6f1b872a9d8 100644 --- a/packages/mobile/src/send/saga.ts +++ b/packages/mobile/src/send/saga.ts @@ -188,7 +188,7 @@ function* sendPayment( amount: amount.toString(), currency, }) - yield call(giveProfileAccess, [recipientAddress]) + yield call(giveProfileAccess, recipientAddress) } catch (error) { Logger.error(`${TAG}/sendPayment`, 'Could not send payment', error) ValoraAnalytics.track(SendEvents.send_tx_error, { error: error.message }) diff --git a/packages/mobile/src/web3/dataEncryptionKey.ts b/packages/mobile/src/web3/dataEncryptionKey.ts index 8e2d0c4e54e..efa002c60c8 100644 --- a/packages/mobile/src/web3/dataEncryptionKey.ts +++ b/packages/mobile/src/web3/dataEncryptionKey.ts @@ -13,7 +13,12 @@ import { OdisUtils } from '@celo/identity' import { AuthSigner } from '@celo/identity/lib/odis/query' import { FetchError, TxError } from '@celo/komencikit/src/errors' import { KomenciKit } from '@celo/komencikit/src/kit' -import { ensureLeading0x, eqAddress, hexToBuffer } from '@celo/utils/lib/address' +import { + ensureLeading0x, + eqAddress, + hexToBuffer, + normalizeAddressWith0x, +} from '@celo/utils/lib/address' import { CURRENCY_ENUM } from '@celo/utils/lib/currencies' import { compressedPubKey, deriveDek } from '@celo/utils/lib/dataEncryptionKey' import * as bip39 from 'react-native-bip39' @@ -63,7 +68,8 @@ export function* doFetchDataEncryptionKey(walletAddress: string) { const walletToAccountAddress: WalletToAccountAddressType = yield select( walletToAccountAddressSelector ) - const accountAddress = walletToAccountAddress[walletAddress] ?? walletAddress + const accountAddress = + walletToAccountAddress[normalizeAddressWith0x(walletAddress)] ?? walletAddress const dek: string = yield call(accountsWrapper.getDataEncryptionKey, accountAddress) yield put(updateAddressDekMap(accountAddress, dek || null)) return !dek ? null : hexToBuffer(dek)