wallet-stack 1.0.0-alpha.132 → 1.0.0-alpha.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/locales/base/translation.json +5 -0
  2. package/package.json +1 -2
  3. package/src/analytics/Events.tsx +3 -10
  4. package/src/analytics/Properties.tsx +9 -25
  5. package/src/analytics/docs.ts +11 -8
  6. package/src/app/ErrorMessages.ts +0 -7
  7. package/src/identity/actions.ts +1 -97
  8. package/src/identity/contactMapping.test.ts +3 -28
  9. package/src/identity/contactMapping.ts +2 -88
  10. package/src/identity/reducer.ts +0 -77
  11. package/src/identity/saga.ts +2 -85
  12. package/src/identity/selectors.ts +0 -2
  13. package/src/images/Images.ts +2 -0
  14. package/src/images/assets/minipay.png +0 -0
  15. package/src/images/assets/minipay@1.5x.png +0 -0
  16. package/src/images/assets/minipay@2x.png +0 -0
  17. package/src/images/assets/minipay@3x.png +0 -0
  18. package/src/images/assets/minipay@4x.png +0 -0
  19. package/src/images/assets/valora.png +0 -0
  20. package/src/images/assets/valora@1.5x.png +0 -0
  21. package/src/images/assets/valora@2x.png +0 -0
  22. package/src/images/assets/valora@3x.png +0 -0
  23. package/src/images/assets/valora@4x.png +0 -0
  24. package/src/index.d.ts +0 -1
  25. package/src/navigator/Navigator.tsx +4 -14
  26. package/src/navigator/Screens.tsx +1 -2
  27. package/src/navigator/types.tsx +4 -6
  28. package/src/qrcode/utils.test.tsx +4 -96
  29. package/src/qrcode/utils.ts +5 -114
  30. package/src/redux/migrations.test.ts +13 -0
  31. package/src/redux/migrations.ts +4 -0
  32. package/src/redux/store.test.ts +1 -2
  33. package/src/redux/store.ts +1 -1
  34. package/src/send/SelectRecipientAddress.test.tsx +146 -0
  35. package/src/send/SelectRecipientAddress.tsx +166 -0
  36. package/src/send/SendSelectRecipient.test.tsx +16 -87
  37. package/src/send/SendSelectRecipient.tsx +12 -27
  38. package/src/send/actions.ts +0 -26
  39. package/src/send/saga.ts +1 -6
  40. package/src/components/AccountNumberCard.tsx +0 -23
  41. package/src/components/ErrorMessageInline.tsx +0 -78
  42. package/src/components/SingleDigitInput.tsx +0 -53
  43. package/src/icons/HamburgerCard.tsx +0 -55
  44. package/src/identity/saga.test.ts +0 -103
  45. package/src/identity/secureSend.ts +0 -171
  46. package/src/send/ValidateRecipientAccount.test.tsx +0 -182
  47. package/src/send/ValidateRecipientAccount.tsx +0 -392
  48. package/src/send/ValidateRecipientIntro.test.tsx +0 -61
  49. package/src/send/ValidateRecipientIntro.tsx +0 -136
  50. package/src/send/__snapshots__/ValidateRecipientAccount.test.tsx.snap +0 -777
@@ -2169,6 +2169,11 @@
2169
2169
  "importSuccess": "Successfully imported {{tokenSymbol}} token",
2170
2170
  "importButton": "Import"
2171
2171
  },
2172
+ "selectRecipientAddress": {
2173
+ "header": "Select wallet",
2174
+ "recipient": "Recipient",
2175
+ "explanation": "<0>{{name}}</0> has more than one wallet linked to the phone number. Choose which one to send to."
2176
+ },
2172
2177
  "sendSelectRecipient": {
2173
2178
  "searchText": "Search by name, phone, wallet...",
2174
2179
  "searchInputLabel": "To",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wallet-stack",
3
- "version": "1.0.0-alpha.132",
3
+ "version": "1.0.0-alpha.133",
4
4
  "author": "Valora Inc",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -148,7 +148,6 @@
148
148
  "bignumber.js": "^9.1.2",
149
149
  "country-data": "^0.0.31",
150
150
  "date-fns": "^4.1.0",
151
- "dot-prop-immutable": "^2.1.1",
152
151
  "expo": "^53.0.22",
153
152
  "expo-image": "~2.4.0",
154
153
  "fast-levenshtein": "^3.0.0",
@@ -269,16 +269,6 @@ export enum SendEvents {
269
269
  send_confirm_back = 'send_confirm_back',
270
270
  send_confirm_send = 'send_confirm_send',
271
271
 
272
- send_secure_start = 'send_secure_start',
273
- send_secure_back = 'send_secure_back',
274
- send_secure_cancel = 'send_secure_cancel',
275
-
276
- send_secure_info = 'send_secure_info',
277
- send_secure_info_dismissed = 'send_secure_info_dismissed',
278
- send_secure_submit = 'send_secure_submit',
279
- send_secure_incorrect = 'send_secure_incorrect',
280
- send_secure_complete = 'send_secure_complete',
281
-
282
272
  send_tx_start = 'send_tx_start',
283
273
  send_tx_complete = 'send_tx_complete',
284
274
  send_tx_error = 'send_tx_error',
@@ -305,6 +295,9 @@ export enum SendEvents {
305
295
  send_select_recipient_invite_press = 'send_select_recipient_invite_press',
306
296
  send_select_recipient_send_press = 'send_select_recipient_send_press',
307
297
  send_select_recipient_recent_press = 'send_select_recipient_recent_press',
298
+ send_select_recipient_address_open = 'send_select_recipient_address_open',
299
+ send_select_recipient_address_select = 'send_select_recipient_address_select',
300
+ send_select_recipient_address_back = 'send_select_recipient_address_back',
308
301
  }
309
302
 
310
303
  export enum QrScreenEvents {
@@ -71,6 +71,7 @@ import { NftOrigin } from 'src/nfts/types'
71
71
  import { NotificationReceiveState } from 'src/notifications/types'
72
72
  import { PointsActivityId } from 'src/points/types'
73
73
  import { RecipientType } from 'src/recipients/recipient'
74
+ import { Verifier } from 'src/send/SelectRecipientAddress'
74
75
  import { AmountEnteredIn, QrCode } from 'src/send/types'
75
76
  import { Field, SwapType } from 'src/swap/types'
76
77
  import { TokenActionName } from 'src/tokens/types'
@@ -521,31 +522,6 @@ interface SendEventsProperties {
521
522
  isTokenManuallyImported: boolean
522
523
  }
523
524
 
524
- [SendEvents.send_secure_start]: {
525
- confirmByScan: boolean
526
- }
527
- [SendEvents.send_secure_back]: undefined
528
- [SendEvents.send_secure_cancel]: undefined
529
- [SendEvents.send_secure_submit]: {
530
- partialAddressValidation: boolean
531
- address: string
532
- }
533
- [SendEvents.send_secure_complete]: {
534
- confirmByScan: boolean
535
- partialAddressValidation?: boolean
536
- }
537
- [SendEvents.send_secure_incorrect]: {
538
- confirmByScan: boolean
539
- partialAddressValidation?: boolean
540
- error: string
541
- }
542
- [SendEvents.send_secure_info]: {
543
- partialAddressValidation: boolean
544
- }
545
- [SendEvents.send_secure_info_dismissed]: {
546
- partialAddressValidation: boolean
547
- }
548
-
549
525
  [SendEvents.send_tx_start]: undefined
550
526
  [SendEvents.send_tx_complete]: {
551
527
  txId: string
@@ -605,6 +581,14 @@ interface SendEventsProperties {
605
581
  [SendEvents.send_select_recipient_recent_press]: {
606
582
  recipientType: RecipientType
607
583
  }
584
+
585
+ [SendEvents.send_select_recipient_address_open]: {
586
+ addressCount: number
587
+ }
588
+ [SendEvents.send_select_recipient_address_select]: {
589
+ verifier: Verifier
590
+ }
591
+ [SendEvents.send_select_recipient_address_back]: undefined
608
592
  }
609
593
 
610
594
  interface FeeEventsProperties {
@@ -259,14 +259,6 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
259
259
  [SendEvents.send_amount_continue]: `when next button pressed on amount enter page`,
260
260
  [SendEvents.send_confirm_back]: `when back button pressed on send confirmation screen`,
261
261
  [SendEvents.send_confirm_send]: `when send button pressed on send confirmation screen`,
262
- [SendEvents.send_secure_start]: `when either secure send scan or manual confirm button pressed`,
263
- [SendEvents.send_secure_back]: `when back button is pressed during secure send`,
264
- [SendEvents.send_secure_cancel]: `when secure send flow is canceled`,
265
- [SendEvents.send_secure_info]: `when "help" button is pressed`,
266
- [SendEvents.send_secure_info_dismissed]: `when "help" button is dismissed`,
267
- [SendEvents.send_secure_submit]: `when an account is submitted for validation`,
268
- [SendEvents.send_secure_incorrect]: `when there's been an error validating the account`,
269
- [SendEvents.send_secure_complete]: `when an account has been validated`,
270
262
  [SendEvents.send_tx_start]: `issued from the sendPayment saga, after a user confirms their intent to send and right before we build and send the transaction to the network`,
271
263
  [SendEvents.send_tx_complete]: `when a send transaction has successfully completed`,
272
264
  [SendEvents.send_tx_error]: `when there is an error sending a transaction`,
@@ -292,6 +284,9 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
292
284
  [SendEvents.send_select_recipient_send_press]: `When the send button is pressed after selecting a recipient`,
293
285
  [SendEvents.send_select_recipient_invite_press]: `When the invite button is pressed after selecting a recipient`,
294
286
  [SendEvents.send_select_recipient_recent_press]: `When a recent recipient is pressed`,
287
+ [SendEvents.send_select_recipient_address_open]: `When the address picker screen is shown (a phone recipient has multiple verified addresses)`,
288
+ [SendEvents.send_select_recipient_address_select]: `When a verified address is picked from the address picker screen`,
289
+ [SendEvents.send_select_recipient_address_back]: `When the back button is pressed on the address picker screen`,
295
290
  [JumpstartEvents.jumpstart_reclaim_press]:
296
291
  'When user taps on "Reclaim" button on the Jumpstart screen',
297
292
  [JumpstartEvents.jumpstart_reclaim_start]:
@@ -578,6 +573,14 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
578
573
 
579
574
  // Legacy event docs
580
575
  // The below events had docs, but are no longer produced by the latest app version.
576
+ // [SendEvents.send_secure_start]: `when either secure send scan or manual confirm button pressed`,
577
+ // [SendEvents.send_secure_back]: `when back button is pressed during secure send`,
578
+ // [SendEvents.send_secure_cancel]: `when secure send flow is canceled`,
579
+ // [SendEvents.send_secure_info]: `when "help" button is pressed`,
580
+ // [SendEvents.send_secure_info_dismissed]: `when "help" button is dismissed`,
581
+ // [SendEvents.send_secure_submit]: `when an account is submitted for validation`,
582
+ // [SendEvents.send_secure_incorrect]: `when there's been an error validating the account`,
583
+ // [SendEvents.send_secure_complete]: `when an account has been validated`,
581
584
  // [HomeEvents.home_send]: `when "send" button is pressed from home screen send or request bar (NOT from home screen actions)`,
582
585
  // [HomeEvents.view_nft_home_assets]: `When "NFTs" is clicked in Home Assets Pages`,
583
586
  // [DappExplorerEvents.dapp_open_info]: `when a user taps on the help icon`,
@@ -16,13 +16,6 @@ export enum ErrorMessages {
16
16
  FIREBASE_FAILED = 'firebaseFailed',
17
17
  IMPORT_CONTACTS_FAILED = 'importContactsFailed',
18
18
  QR_FAILED_INVALID_ADDRESS = 'qrFailedInvalidAddress',
19
- QR_FAILED_INVALID_RECIPIENT = 'qrFailedInvalidRecipient',
20
- ADDRESS_VALIDATION_ERROR = 'addressValidationError',
21
- ADDRESS_VALIDATION_NO_MATCH = 'addressValidationNoMatch',
22
- ADDRESS_VALIDATION_FULL_POORLY_FORMATTED = 'addressValidationFullPoorlyFormatted',
23
- ADDRESS_VALIDATION_PARTIAL_POORLY_FORMATTED = 'addressValidationPartialPoorlyFormatted',
24
- ADDRESS_VALIDATION_FULL_OWN_ADDRESS = 'addressValidationFullOwnAddress',
25
- ADDRESS_VALIDATION_PARTIAL_OWN_ADDRESS = 'addressValidationPartialOwnAddress',
26
19
  ACCOUNT_CLEAR_FAILED = 'accountClearFailed',
27
20
  KEYCHAIN_FETCH_ACCOUNTS = 'keychainFetchAccounts',
28
21
  KEYCHAIN_ACCOUNT_ALREADY_EXISTS = 'keychainAccountAlreadyExists',
@@ -2,26 +2,18 @@ import {
2
2
  AddressToDisplayNameType,
3
3
  AddressToE164NumberType,
4
4
  AddressToVerifiedByType,
5
- AddressValidationType,
6
5
  E164NumberToAddressType,
7
6
  } from 'src/identity/reducer'
8
7
  import { ImportContactsStatus } from 'src/identity/types'
9
- import { Recipient } from 'src/recipients/recipient'
10
- import { type E164Number } from 'src/utils/io'
11
8
 
12
9
  export enum Actions {
13
10
  UPDATE_E164_PHONE_NUMBER_ADDRESSES = 'IDENTITY/UPDATE_E164_PHONE_NUMBER_ADDRESSES',
14
11
  UPDATE_KNOWN_ADDRESSES = 'IDENTITY/UPDATE_KNOWN_ADDRESSES',
15
12
  FETCH_ADDRESSES_AND_VALIDATION_STATUS = 'IDENTITY/FETCH_ADDRESSES_AND_VALIDATION_STATUS',
16
- END_FETCHING_ADDRESSES = 'IDENTITY/END_FETCHING_ADDRESSES',
17
13
  IMPORT_CONTACTS = 'IDENTITY/IMPORT_CONTACTS',
18
14
  UPDATE_IMPORT_CONTACT_PROGRESS = 'IDENTITY/UPDATE_IMPORT_CONTACT_PROGRESS',
19
15
  CANCEL_IMPORT_CONTACTS = 'IDENTITY/CANCEL_IMPORT_CONTACTS',
20
16
  END_IMPORT_CONTACTS = 'IDENTITY/END_IMPORT_CONTACTS',
21
- VALIDATE_RECIPIENT_ADDRESS = 'IDENTITY/VALIDATE_RECIPIENT_ADDRESS',
22
- VALIDATE_RECIPIENT_ADDRESS_SUCCESS = 'IDENTITY/VALIDATE_RECIPIENT_ADDRESS_SUCCESS',
23
- VALIDATE_RECIPIENT_ADDRESS_RESET = 'IDENTITY/VALIDATE_RECIPIENT_ADDRESS_RESET',
24
- REQUIRE_SECURE_SEND = 'IDENTITY/REQUIRE_SECURE_SEND',
25
17
  FETCH_ADDRESS_VERIFICATION_STATUS = 'IDENTITY/FETCH_ADDRESS_VERIFICATION_STATUS',
26
18
  ADDRESS_VERIFICATION_STATUS_RECEIVED = 'IDENTITY/ADDRESS_VERIFICATION_STATUS_RECEIVED',
27
19
  CONTACTS_SAVED = 'IDENTITY/CONTACTS_SAVED',
@@ -43,13 +35,6 @@ export interface UpdateKnownAddressesAction {
43
35
  export interface FetchAddressesAndValidateAction {
44
36
  type: Actions.FETCH_ADDRESSES_AND_VALIDATION_STATUS
45
37
  e164Number: string
46
- requesterAddress?: string
47
- }
48
-
49
- export interface EndFetchingAddressesAction {
50
- type: Actions.END_FETCHING_ADDRESSES
51
- e164Number: string
52
- lastFetchSuccessful: boolean
53
38
  }
54
39
 
55
40
  export interface ImportContactsAction {
@@ -68,31 +53,6 @@ export interface EndImportContactsAction {
68
53
  success: boolean
69
54
  }
70
55
 
71
- export interface ValidateRecipientAddressAction {
72
- type: Actions.VALIDATE_RECIPIENT_ADDRESS
73
- userInputOfFullAddressOrLastFourDigits: string
74
- addressValidationType: AddressValidationType
75
- recipient: Recipient
76
- requesterAddress?: string
77
- }
78
-
79
- export interface ValidateRecipientAddressSuccessAction {
80
- type: Actions.VALIDATE_RECIPIENT_ADDRESS_SUCCESS
81
- e164Number: string
82
- validatedAddress: string
83
- }
84
-
85
- export interface ValidateRecipientAddressResetAction {
86
- type: Actions.VALIDATE_RECIPIENT_ADDRESS_RESET
87
- e164Number: string
88
- }
89
-
90
- export interface RequireSecureSendAction {
91
- type: Actions.REQUIRE_SECURE_SEND
92
- e164Number: E164Number
93
- addressValidationType: AddressValidationType
94
- }
95
-
96
56
  export interface FetchAddressVerificationAction {
97
57
  type: Actions.FETCH_ADDRESS_VERIFICATION_STATUS
98
58
  address: string
@@ -119,24 +79,15 @@ export type ActionTypes =
119
79
  | ImportContactsAction
120
80
  | UpdateImportContactProgress
121
81
  | EndImportContactsAction
122
- | ValidateRecipientAddressAction
123
- | ValidateRecipientAddressSuccessAction
124
- | ValidateRecipientAddressResetAction
125
- | RequireSecureSendAction
126
82
  | FetchAddressesAndValidateAction
127
- | EndFetchingAddressesAction
128
83
  | FetchAddressVerificationAction
129
84
  | AddressVerificationStatusReceivedAction
130
85
  | ContactsSavedAction
131
86
  | StoredPasswordRefreshedAction
132
87
 
133
- export const fetchAddressesAndValidate = (
134
- e164Number: string,
135
- requesterAddress?: string
136
- ): FetchAddressesAndValidateAction => ({
88
+ export const fetchAddressesAndValidate = (e164Number: string): FetchAddressesAndValidateAction => ({
137
89
  type: Actions.FETCH_ADDRESSES_AND_VALIDATION_STATUS,
138
90
  e164Number,
139
- requesterAddress,
140
91
  })
141
92
 
142
93
  export const addressVerificationStatusReceived = (
@@ -153,15 +104,6 @@ export const fetchAddressVerification = (address: string): FetchAddressVerificat
153
104
  address,
154
105
  })
155
106
 
156
- export const endFetchingAddresses = (
157
- e164Number: string,
158
- lastFetchSuccessful: boolean
159
- ): EndFetchingAddressesAction => ({
160
- type: Actions.END_FETCHING_ADDRESSES,
161
- e164Number,
162
- lastFetchSuccessful,
163
- })
164
-
165
107
  export const updateE164PhoneNumberAddresses = (
166
108
  e164NumberToAddress: E164NumberToAddressType,
167
109
  addressToE164Number: AddressToE164NumberType,
@@ -200,44 +142,6 @@ export const endImportContacts = (success: boolean): EndImportContactsAction =>
200
142
  success,
201
143
  })
202
144
 
203
- export const validateRecipientAddress = (
204
- userInputOfFullAddressOrLastFourDigits: string,
205
- addressValidationType: AddressValidationType,
206
- recipient: Recipient,
207
- requesterAddress?: string
208
- ): ValidateRecipientAddressAction => ({
209
- type: Actions.VALIDATE_RECIPIENT_ADDRESS,
210
- userInputOfFullAddressOrLastFourDigits,
211
- addressValidationType,
212
- recipient,
213
- requesterAddress,
214
- })
215
-
216
- export const validateRecipientAddressSuccess = (
217
- e164Number: E164Number,
218
- validatedAddress: string
219
- ): ValidateRecipientAddressSuccessAction => ({
220
- type: Actions.VALIDATE_RECIPIENT_ADDRESS_SUCCESS,
221
- e164Number,
222
- validatedAddress,
223
- })
224
-
225
- export const validateRecipientAddressReset = (
226
- e164Number: E164Number
227
- ): ValidateRecipientAddressResetAction => ({
228
- type: Actions.VALIDATE_RECIPIENT_ADDRESS_RESET,
229
- e164Number,
230
- })
231
-
232
- export const requireSecureSend = (
233
- e164Number: E164Number,
234
- addressValidationType: AddressValidationType
235
- ): RequireSecureSendAction => ({
236
- type: Actions.REQUIRE_SECURE_SEND,
237
- e164Number,
238
- addressValidationType,
239
- })
240
-
241
145
  export const contactsSaved = (hash: string): ContactsSavedAction => ({
242
146
  type: Actions.CONTACTS_SAVED,
243
147
  hash,
@@ -16,7 +16,6 @@ import {
16
16
  contactsSaved,
17
17
  fetchAddressVerification,
18
18
  fetchAddressesAndValidate,
19
- requireSecureSend,
20
19
  updateE164PhoneNumberAddresses,
21
20
  } from 'src/identity/actions'
22
21
  import {
@@ -25,12 +24,9 @@ import {
25
24
  fetchAddressesAndValidateSaga,
26
25
  saveContacts,
27
26
  } from 'src/identity/contactMapping'
28
- import { AddressValidationType } from 'src/identity/reducer'
29
27
  import {
30
28
  addressToVerificationStatusSelector,
31
- e164NumberToAddressSelector,
32
29
  lastSavedContactsHashSelector,
33
- secureSendPhoneNumberMappingSelector,
34
30
  } from 'src/identity/selectors'
35
31
  import { retrieveSignedMessage } from 'src/pincode/authentication'
36
32
  import { contactsToRecipients } from 'src/recipients/recipient'
@@ -98,18 +94,13 @@ describe('Fetch Addresses Saga', () => {
98
94
  })
99
95
 
100
96
  it('fetches and caches addresses correctly', async () => {
101
- const mockE164NumberToAddress = {
102
- [mockE164Number]: [mockAccount.toLowerCase()],
103
- }
104
97
  const updatedAccount = '0xAbC'
105
98
  mockFetch.mockResponseOnce(JSON.stringify({ data: { addresses: [updatedAccount] } }))
106
99
 
107
100
  await expectSaga(fetchAddressesAndValidateSaga, fetchAddressesAndValidate(mockE164Number))
108
101
  .provide([
109
- [select(e164NumberToAddressSelector), mockE164NumberToAddress],
110
102
  [select(walletAddressSelector), '0xxyz'],
111
103
  [call(retrieveSignedMessage), 'some signed message'],
112
- [select(secureSendPhoneNumberMappingSelector), {}],
113
104
  ])
114
105
  .put(updateE164PhoneNumberAddresses({ [mockE164Number]: undefined }, {}))
115
106
  .put(
@@ -135,18 +126,13 @@ describe('Fetch Addresses Saga', () => {
135
126
  })
136
127
 
137
128
  it('fetches and caches multiple addresses correctly', async () => {
138
- const mockE164NumberToAddress = {
139
- [mockE164Number]: [mockAccount.toLowerCase()],
140
- }
141
129
  const updatedAccounts = ['0xAbC', '0xdef']
142
130
  mockFetch.mockResponseOnce(JSON.stringify({ data: { addresses: updatedAccounts } }))
143
131
 
144
132
  await expectSaga(fetchAddressesAndValidateSaga, fetchAddressesAndValidate(mockE164Number))
145
133
  .provide([
146
- [select(e164NumberToAddressSelector), mockE164NumberToAddress],
147
- [select(walletAddressSelector), mockAccount],
134
+ [select(walletAddressSelector), '0xxyz'],
148
135
  [call(retrieveSignedMessage), 'some signed message'],
149
- [select(secureSendPhoneNumberMappingSelector), {}],
150
136
  ])
151
137
  .put(updateE164PhoneNumberAddresses({ [mockE164Number]: undefined }, {}))
152
138
  .put(
@@ -156,14 +142,10 @@ describe('Fetch Addresses Saga', () => {
156
142
  {}
157
143
  )
158
144
  )
159
- .put(requireSecureSend(mockE164Number, AddressValidationType.PARTIAL))
160
145
  .run()
161
146
  })
162
147
 
163
148
  it('uses verifiedAddresses as source of truth when present', async () => {
164
- const mockE164NumberToAddress = {
165
- [mockE164Number]: [mockAccount.toLowerCase()],
166
- }
167
149
  // addresses only contains DB-verified addresses (backward compat),
168
150
  // verifiedAddresses contains all (DB + SC) and is the source of truth
169
151
  mockFetch.mockResponseOnce(
@@ -180,10 +162,8 @@ describe('Fetch Addresses Saga', () => {
180
162
 
181
163
  await expectSaga(fetchAddressesAndValidateSaga, fetchAddressesAndValidate(mockE164Number))
182
164
  .provide([
183
- [select(e164NumberToAddressSelector), mockE164NumberToAddress],
184
- [select(walletAddressSelector), mockAccount],
165
+ [select(walletAddressSelector), '0xxyz'],
185
166
  [call(retrieveSignedMessage), 'some signed message'],
186
- [select(secureSendPhoneNumberMappingSelector), {}],
187
167
  ])
188
168
  .put(updateE164PhoneNumberAddresses({ [mockE164Number]: undefined }, {}))
189
169
  .put(
@@ -193,20 +173,15 @@ describe('Fetch Addresses Saga', () => {
193
173
  { '0xabc': 'valora', '0xdef': 'minipay' }
194
174
  )
195
175
  )
196
- .put(requireSecureSend(mockE164Number, AddressValidationType.PARTIAL))
197
176
  .run()
198
177
  })
199
178
 
200
179
  it('handles lookup errors correctly', async () => {
201
- const mockE164NumberToAddress = {
202
- [mockE164Number]: [mockAccount.toLowerCase()],
203
- }
204
180
  mockFetch.mockReject()
205
181
 
206
182
  await expectSaga(fetchAddressesAndValidateSaga, fetchAddressesAndValidate(mockE164Number))
207
183
  .provide([
208
- [select(e164NumberToAddressSelector), mockE164NumberToAddress],
209
- [select(walletAddressSelector), mockAccount],
184
+ [select(walletAddressSelector), '0xxyz'],
210
185
  [call(retrieveSignedMessage), 'some signed message'],
211
186
  ])
212
187
  .put(showErrorOrFallback(expect.anything(), ErrorMessages.ADDRESS_LOOKUP_FAILURE))
@@ -13,24 +13,14 @@ import {
13
13
  FetchAddressesAndValidateAction,
14
14
  addressVerificationStatusReceived,
15
15
  contactsSaved,
16
- endFetchingAddresses,
17
16
  endImportContacts,
18
- requireSecureSend,
19
17
  updateE164PhoneNumberAddresses,
20
18
  updateImportContactsProgress,
21
19
  } from 'src/identity/actions'
22
- import {
23
- AddressToE164NumberType,
24
- AddressValidationType,
25
- E164NumberToAddressType,
26
- SecureSendPhoneNumberMapping,
27
- } from 'src/identity/reducer'
28
- import { checkIfValidationRequired } from 'src/identity/secureSend'
20
+ import { AddressToE164NumberType, E164NumberToAddressType } from 'src/identity/reducer'
29
21
  import {
30
22
  addressToVerificationStatusSelector,
31
- e164NumberToAddressSelector,
32
23
  lastSavedContactsHashSelector,
33
- secureSendPhoneNumberMappingSelector,
34
24
  } from 'src/identity/selectors'
35
25
  import { ImportContactsStatus } from 'src/identity/types'
36
26
  import { retrieveSignedMessage } from 'src/pincode/authentication'
@@ -144,17 +134,10 @@ function* updateUserContact(e164NumberToRecipients: NumberToRecipient) {
144
134
  yield* put(setUserContactDetails(userRecipient.contactId, userRecipient.thumbnailPath || null))
145
135
  }
146
136
 
147
- export function* fetchAddressesAndValidateSaga({
148
- e164Number,
149
- requesterAddress,
150
- }: FetchAddressesAndValidateAction) {
137
+ export function* fetchAddressesAndValidateSaga({ e164Number }: FetchAddressesAndValidateAction) {
151
138
  AppAnalytics.track(IdentityEvents.phone_number_lookup_start)
152
139
  try {
153
140
  Logger.debug(TAG + '@fetchAddressesAndValidate', `Fetching addresses for number`)
154
- const oldE164NumberToAddress: E164NumberToAddressType = yield* select(
155
- e164NumberToAddressSelector
156
- )
157
- const oldAddresses = oldE164NumberToAddress[e164Number] || []
158
141
 
159
142
  // Clear existing entries for those numbers so our mapping consumers know new status is pending.
160
143
  yield* put(updateE164PhoneNumberAddresses({ [e164Number]: undefined }, {}))
@@ -186,28 +169,6 @@ export function* fetchAddressesAndValidateSaga({
186
169
  walletAddresses.map((a) => (addressToE164NumberUpdates[a] = e164Number))
187
170
  }
188
171
 
189
- const userAddress = yield* select(walletAddressSelector)
190
- if (!userAddress) {
191
- throw new Error('Wallet address not set')
192
- }
193
- const secureSendPossibleAddresses = [...walletAddresses]
194
- const secureSendPhoneNumberMapping = yield* select(secureSendPhoneNumberMappingSelector)
195
- // If fetch is being done as part of a payment request from an unverified address,
196
- // the unverified address should be considered in the Secure Send check
197
- if (requesterAddress && !secureSendPossibleAddresses.includes(requesterAddress)) {
198
- secureSendPossibleAddresses.push(requesterAddress)
199
- }
200
-
201
- const addressValidationType = checkIfValidationRequired(
202
- oldAddresses,
203
- secureSendPossibleAddresses,
204
- userAddress,
205
- secureSendPhoneNumberMapping,
206
- e164Number
207
- )
208
- if (addressValidationType !== AddressValidationType.NONE) {
209
- yield* put(requireSecureSend(e164Number, addressValidationType))
210
- }
211
172
  yield* put(
212
173
  updateE164PhoneNumberAddresses(
213
174
  e164NumberToAddressUpdates,
@@ -215,13 +176,11 @@ export function* fetchAddressesAndValidateSaga({
215
176
  addressToVerifiedByUpdates
216
177
  )
217
178
  )
218
- yield* put(endFetchingAddresses(e164Number, true))
219
179
  AppAnalytics.track(IdentityEvents.phone_number_lookup_complete)
220
180
  } catch (err) {
221
181
  const error = ensureError(err)
222
182
  Logger.debug(TAG + '@fetchAddressesAndValidate', `Error fetching addresses`, error)
223
183
  yield* put(showErrorOrFallback(error, ErrorMessages.ADDRESS_LOOKUP_FAILURE))
224
- yield* put(endFetchingAddresses(e164Number, false))
225
184
  AppAnalytics.track(IdentityEvents.phone_number_lookup_error, {
226
185
  error: error.message,
227
186
  })
@@ -340,51 +299,6 @@ function* fetchAddressVerification(address: string) {
340
299
  }
341
300
  }
342
301
 
343
- // Only use with multiple addresses if user has
344
- // gone through SecureSend
345
- export function getAddressFromPhoneNumber(
346
- e164Number: string,
347
- e164NumberToAddress: E164NumberToAddressType,
348
- secureSendPhoneNumberMapping: SecureSendPhoneNumberMapping,
349
- requesterAddress?: string
350
- ): string | null | undefined {
351
- const addresses = e164NumberToAddress[e164Number]
352
-
353
- // If there are no verified addresses for the number,
354
- // use the requester's given address
355
- if (!addresses && requesterAddress) {
356
- return requesterAddress
357
- }
358
-
359
- // If address is null (unverified) or undefined (in the process
360
- // of being updated) then just return that falsy value
361
- if (!addresses) {
362
- return addresses
363
- }
364
-
365
- // If there are multiple addresses, need to determine which to use
366
- if (addresses.length > 1) {
367
- // Check if the user has gone through Secure Send and validated a
368
- // recipient address
369
- const validatedAddress = secureSendPhoneNumberMapping[e164Number]
370
- ? secureSendPhoneNumberMapping[e164Number].address
371
- : undefined
372
-
373
- // If they have not, they shouldn't have been able to
374
- // get to this point
375
- if (!validatedAddress) {
376
- throw new Error(
377
- 'Multiple addresses but none were validated. Should have routed through Secure Send.'
378
- )
379
- }
380
-
381
- return validatedAddress
382
- }
383
-
384
- // Normal case when there is only one address in the mapping
385
- return addresses[0]
386
- }
387
-
388
302
  export function* saveContacts() {
389
303
  try {
390
304
  const saveContactsGate = getFeatureGate(StatsigFeatureGates.SAVE_CONTACTS)
@@ -1,4 +1,3 @@
1
- import dotProp from 'dot-prop-immutable'
2
1
  import { RehydrateAction } from 'redux-persist'
3
2
  import { Actions as AccountActions, ClearStoredAccountAction } from 'src/account/actions'
4
3
  import { ActionTypes, Actions } from 'src/identity/actions'
@@ -32,24 +31,6 @@ export interface ImportContactProgress {
32
31
  total: number
33
32
  }
34
33
 
35
- export enum AddressValidationType {
36
- FULL = 'full',
37
- PARTIAL = 'partial',
38
- NONE = 'none',
39
- }
40
-
41
- export interface SecureSendPhoneNumberMapping {
42
- [e164Number: string]: SecureSendDetails
43
- }
44
-
45
- export interface SecureSendDetails {
46
- address?: string
47
- addressValidationType: AddressValidationType
48
- isFetchingAddresses?: boolean
49
- lastFetchSuccessful?: boolean
50
- validationSuccessful?: boolean
51
- }
52
-
53
34
  export interface AddressToVerificationStatus {
54
35
  [address: string]: boolean | undefined
55
36
  }
@@ -67,8 +48,6 @@ interface State {
67
48
  // Has the user already been asked for contacts permission
68
49
  askedContactsPermission: boolean
69
50
  importContactsProgress: ImportContactProgress
70
- // Contacts found during the matchmaking process
71
- secureSendPhoneNumberMapping: SecureSendPhoneNumberMapping
72
51
  // Mapping of address to verification status; undefined entries represent a loading state
73
52
  addressToVerificationStatus: AddressToVerificationStatus
74
53
  // Mapping of address to the entity that verified it (e.g. "valora", "minipay")
@@ -87,7 +66,6 @@ const initialState: State = {
87
66
  current: 0,
88
67
  total: 0,
89
68
  },
90
- secureSendPhoneNumberMapping: {},
91
69
  addressToVerificationStatus: {},
92
70
  addressToVerifiedBy: {},
93
71
  lastSavedContactsHash: null,
@@ -159,66 +137,11 @@ export const reducer = (
159
137
  status: success ? ImportContactsStatus.Done : ImportContactsStatus.Failed,
160
138
  },
161
139
  }
162
- case Actions.VALIDATE_RECIPIENT_ADDRESS_SUCCESS:
163
- return {
164
- ...state,
165
- // Overwrite the previous mapping when a new address is validated
166
- secureSendPhoneNumberMapping: dotProp.set(
167
- state.secureSendPhoneNumberMapping,
168
- `${action.e164Number}`,
169
- {
170
- address: action.validatedAddress,
171
- addressValidationType: AddressValidationType.NONE,
172
- validationSuccessful: true,
173
- }
174
- ),
175
- }
176
- case Actions.VALIDATE_RECIPIENT_ADDRESS_RESET:
177
- return {
178
- ...state,
179
- secureSendPhoneNumberMapping: dotProp.set(
180
- state.secureSendPhoneNumberMapping,
181
- `${action.e164Number}.validationSuccessful`,
182
- false
183
- ),
184
- }
185
- case Actions.REQUIRE_SECURE_SEND:
186
- return {
187
- ...state,
188
- // Erase the previous mapping when new validation is required
189
- secureSendPhoneNumberMapping: dotProp.set(
190
- state.secureSendPhoneNumberMapping,
191
- `${action.e164Number}`,
192
- {
193
- address: undefined,
194
- addressValidationType: action.addressValidationType,
195
- }
196
- ),
197
- }
198
- case Actions.FETCH_ADDRESSES_AND_VALIDATION_STATUS:
199
- return {
200
- ...state,
201
- secureSendPhoneNumberMapping: dotProp.set(
202
- state.secureSendPhoneNumberMapping,
203
- `${action.e164Number}.isFetchingAddresses`,
204
- true
205
- ),
206
- }
207
- case Actions.END_FETCHING_ADDRESSES:
208
- return {
209
- ...state,
210
- secureSendPhoneNumberMapping: dotProp.merge(
211
- state.secureSendPhoneNumberMapping,
212
- `${action.e164Number}`,
213
- { isFetchingAddresses: false, lastFetchSuccessful: action.lastFetchSuccessful }
214
- ),
215
- }
216
140
  case AccountActions.CLEAR_STORED_ACCOUNT:
217
141
  return {
218
142
  ...initialState,
219
143
  addressToE164Number: state.addressToE164Number,
220
144
  e164NumberToAddress: state.e164NumberToAddress,
221
- secureSendPhoneNumberMapping: state.secureSendPhoneNumberMapping,
222
145
  }
223
146
  case Actions.FETCH_ADDRESS_VERIFICATION_STATUS:
224
147
  // If the current status is false or does not exist, we set it to undefined