import { APP_PLUGIN , IACMessageTransport , LanguageService , ProtocolService , SPLASH_SCREEN_PLUGIN , STATUS_BAR_PLUGIN } from '@airgap/angular-core' ; import { TezosSaplingExternalMethodProvider } from '@airgap/coinlib-core' ; import { TezosSaplingProtocolOptions , TezosShieldedTezProtocolConfig } from '@airgap/coinlib-core/protocols/tezos/sapling/TezosSaplingProtocolOptions' ; import { TezosShieldedTezProtocol } from '@airgap/coinlib-core/protocols/tezos/sapling/TezosShieldedTezProtocol' ; import { HttpClient } from '@angular/common/http' ; import { AfterViewInit , Component , Inject , NgZone } from '@angular/core' ; import { AppPlugin , URLOpenListenerEvent } from '@capacitor/app' ; import { SplashScreenPlugin } from '@capacitor/splash-screen' ; import { StatusBarPlugin , Style } from '@capacitor/status-bar' ; import { Platform } from '@ionic/angular' ; import { first } from 'rxjs/operators' ; import { SecurityUtilsPlugin } from './capacitor-plugins/definitions' ; import { SECURITY_UTILS_PLUGIN } from './capacitor-plugins/injection-tokens' ; import { DEEPLINK_VAULT_ADD_ACCOUNT , DEEPLINK_VAULT_PREFIX } from './constants/constants' ; import { ExposedPromise , exposedPromise } from './functions/exposed-promise' ; import { MnemonicSecret } from './models/secret' ; import { ErrorCategory , handleErrorLocal } from './services/error-handler/error-handler.service' ; import { IACService } from './services/iac/iac.service' ; import { NavigationService } from './services/navigation/navigation.service' ; import { SaplingNativeService } from './services/sapling-native/sapling-native.service' ; import { SecretsService } from './services/secrets/secrets.service' ; import { StartupChecksService } from './services/startup-checks/startup-checks.service' ; declare let window ; @ Component ( { selector : 'airgap-root' , templateUrl : 'app.component.html' } ) export class AppComponent implements AfterViewInit { public isInitialized : ExposedPromise < void > = exposedPromise < void > ( ) ; constructor ( private readonly platform , private readonly startupChecks , private readonly iacService , private readonly languageService , private readonly protocolService , private readonly secretsService , private readonly ngZone , private readonly navigationService , private readonly httpClient , private readonly saplingNativeService , @ Inject ( APP_PLUGIN ) private readonly app , @ Inject ( SECURITY_UTILS_PLUGIN ) private readonly securityUtils , @ Inject ( SPLASH_SCREEN_PLUGIN ) private readonly splashScreen , @ Inject ( STATUS_BAR_PLUGIN ) private readonly statusBar ) { window . airGapHasStarted = true ; this . initializeApp ( ) . catch ( handleErrorLocal ( ErrorCategory . OTHER ) ) ; } public async initializeApp ( ) { await Promise . all ( [ this . platform . ready ( ) , this . initializeTranslations ( ) , this . initializeProtocols ( ) ] ) ; if ( this . platform . is ( 'hybrid' ) ) { this . statusBar . setStyle ( { style : Style . Dark } ) ; this . statusBar . setBackgroundColor ( { color : '#311B58' } ) ; this . splashScreen . hide ( ) ; await this . securityUtils . toggleAutomaticAuthentication ( { automatic : true } ) ; } this . initChecks ( ) ; } public async initChecks ( ) { await this . startupChecks . initChecks ( ) ; this . isInitialized . resolve ( ) ; } public async ngAfterViewInit ( ) { await this . platform . ready ( ) ; this . app . addListener ( 'appUrlOpen' , async ( data ) => { await this . isInitialized . promise ; if ( data . url === DEEPLINK_VAULT_PREFIX || data . url . startsWith ( DEEPLINK_VAULT_ADD_ACCOUNT ) ) { console . log ( 'Successfully matched route' , data . url ) ; this . secretsService . getSecretsObservable ( ) . pipe ( first ( ) ) . subscribe ( ( secrets ) => { if ( secrets . length > 0 ) { this . ngZone . run ( async ( ) => { this . navigationService . routeToAccountsTab ( ) . catch ( handleErrorLocal ( ErrorCategory . IONIC_NAVIGATION ) ) ; const protocol = data . url . substr ( DEEPLINK_VAULT_ADD_ACCOUNT . length ) ; if ( protocol . length > 0 ) { this . navigationService . routeWithState ( 'account-add' , { protocol } ) . catch ( handleErrorLocal ( ErrorCategory . IONIC_NAVIGATION ) ) ; } else { this . navigationService . route ( 'account-add' ) . catch ( handleErrorLocal ( ErrorCategory . IONIC_NAVIGATION ) ) ; } } ) . catch ( handleErrorLocal ( ErrorCategory . OTHER ) ) ; } } ) ; } else { this . ngZone . run ( async ( ) => { this . iacService . handleRequest ( data . url , IACMessageTransport . DEEPLINK ) . catch ( handleErrorLocal ( ErrorCategory . SCHEME_ROUTING ) ) ; } ) ; } } ) ; } private async initializeTranslations ( ) { return this . languageService . init ( { supportedLanguages : [ 'en' , 'de' , 'zh-cn' ] , defaultLanguage : 'en' } ) ; } private async initializeProtocols ( ) { const externalMethodProvider = await this . saplingNativeService . createExternalMethodProvider ( ) ; const shieldedTezProtocol = new TezosShieldedTezProtocol ( new TezosSaplingProtocolOptions ( undefined , new TezosShieldedTezProtocolConfig ( undefined , undefined , undefined , externalMethodProvider ) ) ) ; this . protocolService . init ( { extraActiveProtocols : [ shieldedTezProtocol ] } ) ; await shieldedTezProtocol . initParameters ( await this . getSaplingParams ( 'spend' ) , await this . getSaplingParams ( 'output' ) ) ; } private async getSaplingParams ( type ) { if ( this . platform . is ( 'hybrid' ) ) { return Buffer . alloc ( 0 ) ; } const params = await this . httpClient . get ( `./assets/sapling/sapling-${ type }.params` , { responseType : 'arraybuffer' } ) . toPromise ( ) ; return Buffer . from ( params ) ; } }