import { TezosSaplingExternalMethodProvider , TezosSaplingTransaction } from '@airgap/coinlib-core' ; import { SaplingPartialOutputDescription , SaplingUnsignedSpendDescription } from '@airgap/sapling-wasm' ; import { Inject , Injectable } from '@angular/core' ; import { Platform } from '@ionic/angular' ; import { SAPLING_PLUGIN } from '../..//capacitor-plugins/injection-tokens' ; import { SaplingNativePlugin } from '../../capacitor-plugins/definitions' ; @ Injectable ( { providedIn : 'root' } ) export class SaplingNativeService { constructor ( @ Inject ( SAPLING_PLUGIN ) private readonly sapling , private readonly platform ) { } public async createExternalMethodProvider ( ) { const isSupported = this . platform . is ( 'capacitor' ) && ! this . platform . is ( 'electron' ) && ( await this . sapling . isSupported ( ) ) . isSupported ; return isSupported ? { initParameters : this . initParameters ( this . sapling ) , withProvingContext : this . withProvingContext ( this . sapling ) , prepareSpendDescription : this . prepareSpendDescription ( this . sapling ) , preparePartialOutputDescription : this . preparePartialOutputDescription ( this . sapling ) , createBindingSignature : this . createBindingSignature ( this . sapling ) } : undefined ; } private initParameters ( saplingPlugin ) { return async ( _spendParams , _outputParams ) : Promise < void > => { return saplingPlugin . initParameters ( ) ; } ; } private withProvingContext ( saplingPlugin ) { return async ( action ) : Promise < TezosSaplingTransaction > => { const { context } = await saplingPlugin . initProvingContext ( ) ; const transaction = await action ( parseInt ( context ) ) ; await saplingPlugin . dropProvingContext ( { context } ) ; return transaction ; } ; } private prepareSpendDescription ( saplingPlugin ) { return async ( context , spendingKey , address , rcm , ar , value , root , merklePath ) : Promise < SaplingUnsignedSpendDescription > => { const { spendDescription : spendDescriptionHex } = await saplingPlugin . prepareSpendDescription ( { context : context . toString ( ) , spendingKey : spendingKey . toString ( 'hex' ) , address : address . toString ( 'hex' ) , rcm , ar : ar . toString ( 'hex' ) , value , root , merklePath } ) ; const spendDescription = Buffer . from ( spendDescriptionHex , 'hex' ) ; return { cv : spendDescription . slice ( 0 , 32 ) , rt : spendDescription . slice ( 32 , 64 ) , nf : spendDescription . slice ( 64 , 96 ) , rk : spendDescription . slice ( 96 , 128 ) , proof : spendDescription . slice ( 128 , 320 ) } ; } ; } private preparePartialOutputDescription ( saplingPlugin ) { return async ( context , address , rcm , esk , value ) : Promise < SaplingPartialOutputDescription > => { const { outputDescription : outputDescriptionHex } = await saplingPlugin . preparePartialOutputDescription ( { context : context . toString ( ) , address : address . toString ( 'hex' ) , rcm : rcm . toString ( 'hex' ) , esk : esk . toString ( 'hex' ) , value } ) ; const outputDescription = Buffer . from ( outputDescriptionHex , 'hex' ) ; return { cv : outputDescription . slice ( 0 , 32 ) , cm : outputDescription . slice ( 32 , 64 ) , proof : outputDescription . slice ( 64 , 256 ) } ; } ; } private createBindingSignature ( saplingPlugin ) { return async ( context , balance , sighash ) : Promise < Buffer > => { const { bindingSignature } = await saplingPlugin . createBindingSignature ( { context : context . toString ( ) , balance , sighash : sighash . toString ( 'hex' ) } ) ; return Buffer . from ( bindingSignature , 'hex' ) ; } ; } }