import { ChainInfo , Keplr as IKeplr , KeplrIntereactionOptions , KeplrMode , KeplrSignOptions , Key , } from "@keplr-wallet/types" ; import { BACKGROUND_PORT , MessageRequester } from "@keplr-wallet/router" ; import { BroadcastMode , AminoSignResponse , StdSignDoc , StdTx , OfflineSigner , StdSignature , } from "@cosmjs/launchpad" ; import { EnableAccessMsg , SuggestChainInfoMsg , GetKeyMsg , SuggestTokenMsg , SendTxMsg , GetSecret20ViewingKey , RequestSignAminoMsg , RequestSignDirectMsg , GetPubkeyMsg , ReqeustEncryptMsg , RequestDecryptMsg , GetTxEncryptionKeyMsg , RequestVerifyADR36AminoSignDoc , } from "./types" ; import { SecretUtils } from "secretjs/types/enigmautils" ; import { KeplrEnigmaUtils } from "./enigma" ; import { DirectSignResponse , OfflineDirectSigner } from "@cosmjs/proto-signing" ; import { CosmJSOfflineSigner , CosmJSOfflineSignerOnlyAmino } from "./cosmjs" ; import deepmerge from "deepmerge" ; import Long from "long" ; import { Buffer } from "buffer/" ; export class Keplr implements IKeplr { protected enigmaUtils : Map < string , SecretUtils > = new Map ( ) ; public defaultOptions : KeplrIntereactionOptions = { } ; constructor ( public readonly version , public readonly mode , protected readonly requester ) { } async enable ( chainIds ) { if ( typeof chainIds === "string" ) { chainIds = [ chainIds ] ; } await this . requester . sendMessage ( BACKGROUND_PORT , new EnableAccessMsg ( chainIds ) ) ; } async experimentalSuggestChain ( chainInfo ) { const msg = new SuggestChainInfoMsg ( chainInfo ) ; await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; } async getKey ( chainId ) { const msg = new GetKeyMsg ( chainId ) ; return await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; } async sendTx ( chainId , tx , mode ) { const msg = new SendTxMsg ( chainId , tx , mode ) ; return await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; } async signAmino ( chainId , signer , signDoc , signOptions = { } ) { const msg = new RequestSignAminoMsg ( chainId , signer , signDoc , deepmerge ( this . defaultOptions . sign ?? { } , signOptions ) ) ; return await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; } async signDirect ( chainId , signer , signDoc , signOptions = { } ) { const msg = new RequestSignDirectMsg ( chainId , signer , { bodyBytes : signDoc . bodyBytes , authInfoBytes : signDoc . authInfoBytes , chainId : signDoc . chainId , accountNumber : signDoc . accountNumber ? signDoc . accountNumber . toString ( ) : null , } , deepmerge ( this . defaultOptions . sign ?? { } , signOptions ) ) ; const response = await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; return { signed : { bodyBytes : response . signed . bodyBytes , authInfoBytes : response . signed . authInfoBytes , chainId : response . signed . chainId , accountNumber : Long . fromString ( response . signed . accountNumber ) , } , signature : response . signature , } ; } async signArbitrary ( chainId , signer , data ) { let isADR36WithString = false ; if ( typeof data === "string" ) { data = Buffer . from ( data ) . toString ( "base64" ) ; isADR36WithString = true ; } else { data = Buffer . from ( data ) . toString ( "base64" ) ; } const signDoc = { chain_id : "" , account_number : "0" , sequence : "0" , fee : { gas : "0" , amount : [ ] , } , msgs : [ { type : "sign/MsgSignData" , value : { signer , data , } , } , ] , memo : "" , } ; const msg = new RequestSignAminoMsg ( chainId , signer , signDoc , { isADR36WithString , } ) ; return ( await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ) . signature ; } async verifyArbitrary ( chainId , signer , data , signature ) { if ( typeof data === "string" ) { data = Buffer . from ( data ) ; } return await this . requester . sendMessage ( BACKGROUND_PORT , new RequestVerifyADR36AminoSignDoc ( chainId , signer , data , signature ) ) ; } getOfflineSigner ( chainId ) { return new CosmJSOfflineSigner ( chainId , this ) ; } getOfflineSignerOnlyAmino ( chainId ) { return new CosmJSOfflineSignerOnlyAmino ( chainId , this ) ; } async getOfflineSignerAuto ( chainId ) { const key = await this . getKey ( chainId ) ; if ( key . isNanoLedger ) { return new CosmJSOfflineSignerOnlyAmino ( chainId , this ) ; } return new CosmJSOfflineSigner ( chainId , this ) ; } async suggestToken ( chainId , contractAddress , viewingKey ? ) { const msg = new SuggestTokenMsg ( chainId , contractAddress , viewingKey ) ; await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; } async getSecret20ViewingKey ( chainId , contractAddress ) { const msg = new GetSecret20ViewingKey ( chainId , contractAddress ) ; return await this . requester . sendMessage ( BACKGROUND_PORT , msg ) ; } async getEnigmaPubKey ( chainId ) { return await this . requester . sendMessage ( BACKGROUND_PORT , new GetPubkeyMsg ( chainId ) ) ; } async getEnigmaTxEncryptionKey ( chainId , nonce ) { return await this . requester . sendMessage ( BACKGROUND_PORT , new GetTxEncryptionKeyMsg ( chainId , nonce ) ) ; } async enigmaEncrypt ( chainId , contractCodeHash , msg ) { return await this . requester . sendMessage ( BACKGROUND_PORT , new ReqeustEncryptMsg ( chainId , contractCodeHash , msg ) ) ; } async enigmaDecrypt ( chainId , ciphertext , nonce ) { if ( ! ciphertext || ciphertext . length === 0 ) { return new Uint8Array ( ) ; } return await this . requester . sendMessage ( BACKGROUND_PORT , new RequestDecryptMsg ( chainId , ciphertext , nonce ) ) ; } getEnigmaUtils ( chainId ) { if ( this . enigmaUtils . has ( chainId ) ) { return this . enigmaUtils . get ( chainId ) ! ; } const enigmaUtils = new KeplrEnigmaUtils ( chainId , this ) ; this . enigmaUtils . set ( chainId , enigmaUtils ) ; return enigmaUtils ; } }