# CICADA

### File

`src/app/_services/user.service.ts`

### Index

###### Properties

- accounts
- Private accountsList
- accountsSubject
- actions
- Private actionsList
- actionsSubject
- categories
- Private categoriesList
- categoriesSubject
- headers
- keystore
- registry
- signer

###### Methods

- addAccount
- approveAction
- Async changeAccountInfo
- Async getAccountByAddress
- Async getAccountByPhone
- getAccountDetailsFromMeta
- getAccountStatus
- getAccountTypes
- getActionById
- getActions
- getCategories
- getCategoryByProduct
- getGenders
- getLockedAccounts
- getTransactionTypes
- Async init
- Async loadAccounts
- resetAccountsList
- resetPin
- revokeAction
- searchAccountByName
- Async updateMeta
- wrap

### Constructor

`constructor(httpClient: HttpClient, loggingService: LoggingService, tokenService: TokenService, authService: AuthService)`
Defined in src/app/_services/user.service.ts:41

Parameters :

Name | Type | Optional
httpClient | `HttpClient` | No
loggingService | `LoggingService` | No
tokenService | `TokenService` | No
authService | `AuthService` | No

### Methods

addAccount
`addAccount(account: AccountDetails, cacheSize: number)`
Defined in src/app/_services/user.service.ts:302

Parameters :

Name | Type | Optional
account | `AccountDetails` | No
cacheSize | `number` | No

Returns : `void`

approveAction
`approveAction(id: string)`
Defined in src/app/_services/user.service.ts:179

Parameters :

Name | Type | Optional
id | `string` | No

Returns : `Observable<any>`

Async changeAccountInfo
`changeAccountInfo(address: string, name: string, phoneNumber: string, age: string, type: string, bio: string, gender: string, businessCategory: string, userLocation: string, location: string, locationType: string)`
Defined in src/app/_services/user.service.ts:72

Parameters :

Name | Type | Optional
address | `string` | No
name | `string` | No
phoneNumber | `string` | No
age | `string` | No
type | `string` | No
bio | `string` | No
gender | `string` | No
businessCategory | `string` | No
userLocation | `string` | No
location | `string` | No
locationType | `string` | No

Returns : `Promise<any>`

Async getAccountByAddress
`getAccountByAddress(accountAddress: string, limit: number)`
Defined in src/app/_services/user.service.ts:218

Parameters :

Name | Type | Optional | Default value
accountAddress | `string` | No |
limit | `number` | No | `100`

Returns : `Promise<Observable<AccountDetails>>`

Async getAccountByPhone
`getAccountByPhone(phoneNumber: string, limit: number)`
Defined in src/app/_services/user.service.ts:244

Parameters :

Name | Type | Optional | Default value
phoneNumber | `string` | No |
limit | `number` | No | `100`

Returns : `Promise<Observable<AccountDetails>>`

getAccountDetailsFromMeta
`getAccountDetailsFromMeta(userKey: string)`
Defined in src/app/_services/user.service.ts:187

Parameters :

Name | Type | Optional
userKey | `string` | No

Returns : `Observable<any>`

getAccountStatus
`getAccountStatus(phone: string)`
Defined in src/app/_services/user.service.ts:63

Parameters :

Name | Type | Optional
phone | `string` | No

Returns : `Observable<any>`

getAccountTypes
`getAccountTypes()`
Defined in src/app/_services/user.service.ts:290
Returns : `Observable<any>`

getActionById
`getActionById(id: string)`
Defined in src/app/_services/user.service.ts:175

Parameters :

Name | Type | Optional
id | `string` | No

Returns : `Observable<any>`

getActions
`getActions()`
Defined in src/app/_services/user.service.ts:168
Returns : `void`

getCategories
`getCategories()`
Defined in src/app/_services/user.service.ts:271
Returns : `void`

getCategoryByProduct
`getCategoryByProduct(product: string, categories: object)`
Defined in src/app/_services/user.service.ts:278

Parameters :

Name | Type | Optional
product | `string` | No
categories | `object` | No

Returns : `string`

getGenders
`getGenders()`
Defined in src/app/_services/user.service.ts:298
Returns : `Observable<any>`

getLockedAccounts
`getLockedAccounts(offset: number, limit: number)`
Defined in src/app/_services/user.service.ts:68

Parameters :

Name | Type | Optional
offset | `number` | No
limit | `number` | No

Returns : `Observable<any>`

getTransactionTypes
`getTransactionTypes()`
Defined in src/app/_services/user.service.ts:294
Returns : `Observable<any>`

Async init
`init()`
Defined in src/app/_services/user.service.ts:50
Returns : `Promise<void>`

Async loadAccounts
`loadAccounts(limit: number, offset: number)`
Defined in src/app/_services/user.service.ts:205

Parameters :

Name | Type | Optional | Default value
limit | `number` | No | `100`
offset | `number` | No | `0`

Returns : `Promise<void>`

resetAccountsList
`resetAccountsList()`
Defined in src/app/_services/user.service.ts:262
Returns : `void`

resetPin
`resetPin(phone: string)`
Defined in src/app/_services/user.service.ts:58

Parameters :

Name | Type | Optional
phone | `string` | No

Returns : `Observable<any>`

revokeAction
`revokeAction(id: string)`
Defined in src/app/_services/user.service.ts:183

Parameters :

Name | Type | Optional
id | `string` | No

Returns : `Observable<any>`

searchAccountByName
`searchAccountByName(name: string)`
Defined in src/app/_services/user.service.ts:267

Parameters :

Name | Type | Optional
name | `string` | No

Returns : `any`

Async updateMeta
`updateMeta(syncableAccount: Syncable, accountKey: string, headers: HttpHeaders)`
Defined in src/app/_services/user.service.ts:153

Parameters :

Name | Type | Optional
syncableAccount | `Syncable` | No
accountKey | `string` | No
headers | `HttpHeaders` | No

Returns : `Promise<any>`

wrap
`wrap(syncable: Syncable, signer: Signer)`
Defined in src/app/_services/user.service.ts:191

Parameters :

Name | Type | Optional
syncable | `Syncable` | No
signer | `Signer` | No

Returns : `Promise<Envelope>`

### Properties

accounts
Type : `Array<AccountDetails>`
Default value : `[]`
Defined in src/app/_services/user.service.ts:29

Private accountsList
Type : `BehaviorSubject<Array<AccountDetails>>`
Default value : `new BehaviorSubject< Array<AccountDetails> >(this.accounts)`
Defined in src/app/_services/user.service.ts:30

accountsSubject
Type : `Observable<Array<AccountDetails>>`
Default value : `this.accountsList.asObservable()`
Defined in src/app/_services/user.service.ts:33

actions
Type : `Array<any>`
Default value : `[]`
Defined in src/app/_services/user.service.ts:35

Private actionsList
Type : `BehaviorSubject<any>`
Default value : `new BehaviorSubject<any>(this.actions)`
Defined in src/app/_services/user.service.ts:36

actionsSubject
Type : `Observable<Array<any>>`
Default value : `this.actionsList.asObservable()`
Defined in src/app/_services/user.service.ts:37

categories
Type : `object`
Default value : `{}`
Defined in src/app/_services/user.service.ts:39

Private categoriesList
Type : `BehaviorSubject<object>`
Default value : `new BehaviorSubject<object>(this.categories)`
Defined in src/app/_services/user.service.ts:40

categoriesSubject
Type : `Observable<object>`
Default value : `this.categoriesList.asObservable()`
Defined in src/app/_services/user.service.ts:41

headers
Type : `HttpHeaders`
Default value : `new HttpHeaders({ 'x-cic-automerge': 'client' })`
Defined in src/app/_services/user.service.ts:24

keystore
Type : `MutableKeyStore`
Defined in src/app/_services/user.service.ts:25

registry
Type : `CICRegistry`
Defined in src/app/_services/user.service.ts:27

signer
Type : `Signer`
Defined in src/app/_services/user.service.ts:26

    import { Injectable } from '@angular/core';
    import { BehaviorSubject, Observable, Subject } from 'rxjs';
    import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
    import { environment } from '@src/environments/environment';
    import { first } from 'rxjs/operators';
    import { ArgPair, Envelope, Phone, Syncable, User } from 'cic-client-meta';
    import { AccountDetails } from '@app/_models';
    import { LoggingService } from '@app/_services/logging.service';
    import { TokenService } from '@app/_services/token.service';
    import { AccountIndex } from '@app/_eth';
    import { MutableKeyStore, PGPSigner, Signer } from '@app/_pgp';
    import { RegistryService } from '@app/_services/registry.service';
    import { CICRegistry } from '@cicnet/cic-client';
    import { AuthService } from '@app/_services/auth.service';
    import { personValidation, updateSyncable, vcardValidation } from '@app/_helpers';
    import { add0x } from '@src/assets/js/ethtx/dist/hex';
    import { KeystoreService } from '@app/_services/keystore.service';
    const vCard = require('vcard-parser');

    @Injectable({
      providedIn: 'root',
    })
    export class UserService {
      headers: HttpHeaders = new HttpHeaders({ 'x-cic-automerge': 'client' });
      keystore: MutableKeyStore;
      signer: Signer;
      registry: CICRegistry;

      accounts: Array<AccountDetails> = [];
      private accountsList: BehaviorSubject<Array<AccountDetails>> = new BehaviorSubject<
        Array<AccountDetails>
      >(this.accounts);
      accountsSubject: Observable<Array<AccountDetails>> = this.accountsList.asObservable();

      actions: Array<any> = [];
      private actionsList: BehaviorSubject<any> = new BehaviorSubject<any>(this.actions);
      actionsSubject: Observable<Array<any>> = this.actionsList.asObservable();

      categories: object = {};
      private categoriesList: BehaviorSubject<object> = new BehaviorSubject<object>(this.categories);
      categoriesSubject: Observable<object> = this.categoriesList.asObservable();

      constructor(
        private httpClient: HttpClient,
        private loggingService: LoggingService,
        private tokenService: TokenService,
        private authService: AuthService
      ) {}

      async init(): Promise<void> {
        await this.authService.init();
        await this.tokenService.init();
        this.keystore = await KeystoreService.getKeystore();
        this.signer = new PGPSigner(this.keystore);
        this.registry = await RegistryService.getRegistry();
      }

      resetPin(phone: string): Observable<any> {
        const params: HttpParams = new HttpParams().set('phoneNumber', phone);
        return this.httpClient.put(`${environment.cicUssdUrl}/pin`, { params });
      }

      getAccountStatus(phone: string): Observable<any> {
        const params: HttpParams = new HttpParams().set('phoneNumber', phone);
        return this.httpClient.get(`${environment.cicUssdUrl}/pin`, { params });
      }

      getLockedAccounts(offset: number, limit: number): Observable<any> {
        return this.httpClient.get(`${environment.cicUssdUrl}/accounts/locked/${offset}/${limit}`);
      }

      async changeAccountInfo(
        address: string,
        name: string,
        phoneNumber: string,
        age: string,
        type: string,
        bio: string,
        gender: string,
        businessCategory: string,
        userLocation: string,
        location: string,
        locationType: string
      ): Promise<any> {
        const accountInfo: any = {
          vcard: {
            fn: [{}],
            n: [{}],
            tel: [{}],
          },
          location: {},
        };
        if (name) {
          accountInfo.vcard.fn[0].value = name;
          accountInfo.vcard.n[0].value = name.split(' ');
        }
        if (phoneNumber) {
          accountInfo.vcard.tel[0].value = phoneNumber;
        }
        if (bio) {
          accountInfo.products = [bio];
        }
        if (gender) {
          accountInfo.gender = gender;
        }
        if (age) {
          accountInfo.age = age;
        }
        if (type) {
          accountInfo.type = type;
        }
        if (businessCategory) {
          accountInfo.category = businessCategory;
        }
        if (location) {
          accountInfo.location.area = location;
        }
        if (userLocation) {
          accountInfo.location.area_name = userLocation;
        }
        if (locationType) {
          accountInfo.location.area_type = locationType;
        }
        await vcardValidation(accountInfo.vcard);
        accountInfo.vcard = btoa(vCard.generate(accountInfo.vcard));
        const accountKey: string = await User.toKey(address);
        this.getAccountDetailsFromMeta(accountKey)
          .pipe(first())
          .subscribe(
            async (res) => {
              const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
              const update: Array<ArgPair> = [];
              for (const prop of Object.keys(accountInfo)) {
                update.push(new ArgPair(prop, accountInfo[prop]));
              }
              updateSyncable(update, 'client-branch', syncableAccount);
              await personValidation(syncableAccount.m.data);
              await this.updateMeta(syncableAccount, accountKey, this.headers);
            },
            async (error) => {
              this.loggingService.sendErrorLevelMessage(
                'Cannot find account info in meta service',
                this,
                { error }
              );
              const syncableAccount: Syncable = new Syncable(accountKey, accountInfo);
              await this.updateMeta(syncableAccount, accountKey, this.headers);
            }
          );
        return accountKey;
      }

      async updateMeta(
        syncableAccount: Syncable,
        accountKey: string,
        headers: HttpHeaders
      ): Promise<any> {
        const envelope: Envelope = await this.wrap(syncableAccount, this.signer);
        const reqBody: string = envelope.toJSON();
        this.httpClient
          .put(`${environment.cicMetaUrl}/${accountKey}`, reqBody, { headers })
          .pipe(first())
          .subscribe((res) => {
            this.loggingService.sendInfoLevelMessage(`Response: ${res}`);
          });
      }

      getActions(): void {
        this.httpClient
          .get(`${environment.cicCacheUrl}/actions`)
          .pipe(first())
          .subscribe((res) => this.actionsList.next(res));
      }

      getActionById(id: string): Observable<any> {
        return this.httpClient.get(`${environment.cicCacheUrl}/actions/${id}`);
      }

      approveAction(id: string): Observable<any> {
        return this.httpClient.post(`${environment.cicCacheUrl}/actions/${id}`, { approval: true });
      }

      revokeAction(id: string): Observable<any> {
        return this.httpClient.post(`${environment.cicCacheUrl}/actions/${id}`, { approval: false });
      }

      getAccountDetailsFromMeta(userKey: string): Observable<any> {
        return this.httpClient.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
      }

      wrap(syncable: Syncable, signer: Signer): Promise<Envelope> {
        return new Promise<Envelope>(async (resolve, reject) => {
          syncable.setSigner(signer);
          syncable.onwrap = async (env) => {
            if (env === undefined) {
              reject();
              return;
            }
            resolve(env);
          };
          await syncable.sign();
        });
      }

      async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> {
        this.resetAccountsList();
        const accountIndexAddress: string = await this.registry.getContractAddressByName(
          'AccountRegistry'
        );
        const accountIndexQuery = new AccountIndex(accountIndexAddress);
        const accountAddresses: Array<string> = await accountIndexQuery.last(limit);
        this.loggingService.sendInfoLevelMessage(accountAddresses);
        for (const accountAddress of accountAddresses.slice(offset, offset + limit)) {
          await this.getAccountByAddress(accountAddress, limit);
        }
      }

      async getAccountByAddress(
        accountAddress: string,
        limit: number = 100
      ): Promise<Observable<AccountDetails>> {
        const accountSubject: Subject<any> = new Subject<any>();
        this.getAccountDetailsFromMeta(await User.toKey(add0x(accountAddress)))
          .pipe(first())
          .subscribe(async (res) => {
            const account: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
            const accountInfo = account.m.data;
            await personValidation(accountInfo);
            this.tokenService.load.subscribe(async (status: boolean) => {
              if (status) {
                accountInfo.balance = await this.tokenService.getTokenBalance(
                  accountInfo.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0]
                );
              }
            });
            accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
            await vcardValidation(accountInfo.vcard);
            this.addAccount(accountInfo, limit);
            accountSubject.next(accountInfo);
          });
        return accountSubject.asObservable();
      }

      async getAccountByPhone(
        phoneNumber: string,
        limit: number = 100
      ): Promise<Observable<AccountDetails>> {
        const accountSubject: Subject<any> = new Subject<any>();
        this.getAccountDetailsFromMeta(await Phone.toKey(phoneNumber))
          .pipe(first())
          .subscribe(async (res) => {
            const response: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
            const address: string = response.m.data;
            const account: Observable<AccountDetails> = await this.getAccountByAddress(address, limit);
            account.subscribe((result) => {
              accountSubject.next(result);
            });
          });
        return accountSubject.asObservable();
      }

      resetAccountsList(): void {
        this.accounts = [];
        this.accountsList.next(this.accounts);
      }

      searchAccountByName(name: string): any {
        return;
      }

      getCategories(): void {
        this.httpClient
          .get(`${environment.cicMetaUrl}/categories`)
          .pipe(first())
          .subscribe((res: object) => this.categoriesList.next(res));
      }

      getCategoryByProduct(product: string, categories: object): string {
        const keywords = product.toLowerCase().split(' ');
        for (const keyword of keywords) {
          const queriedCategory: string = Object.keys(categories).find((key) =>
            categories[key].includes(keyword)
          );
          if (queriedCategory) {
            return queriedCategory;
          }
        }
      }

      getAccountTypes(): Observable<any> {
        return this.httpClient.get(`${environment.cicMetaUrl}/accounttypes`);
      }

      getTransactionTypes(): Observable<any> {
        return this.httpClient.get(`${environment.cicMetaUrl}/transactiontypes`);
      }

      getGenders(): Observable<any> {
        return this.httpClient.get(`${environment.cicMetaUrl}/genders`);
      }

      addAccount(account: AccountDetails, cacheSize: number): void {
        const savedIndex = this.accounts.findIndex(
          (acc) =>
            acc.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0] ===
            account.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0]
        );
        if (savedIndex === 0) {
          return;
        }
        if (savedIndex > 0) {
          this.accounts.splice(savedIndex, 1);
        }
        this.accounts.unshift(account);
        if (this.accounts.length > cacheSize) {
          this.accounts.length = Math.min(this.accounts.length, cacheSize);
        }
        this.accountsList.next(this.accounts);
      }
    }

# result-matching ""

# No results matching ""