import * as CSL from '@emurgo/cardano-serialization-lib-browser';

/**
 * The recipient address types we support.
 */
export declare enum AddressType {
    Bech32 = 0,
    Email = 1
}

export declare function b64ToBn(b64: string): BigIntWrap;

/**
 * A wrapper for interaction with the backend.
 * @class
 */
export declare class Backend {
    private url;
    private secret;
    /**
     * Creates a new Backend object.
     * @param {string} url     - Backend's URL
     * @param {string} secret  - optional Backend's secret (API key)
     */
    constructor(url: string, secret?: string | null);
    private headers;
    /**
     * Get server settings including network and version information.
     * @async
     * @returns {Settings}
     */
    settings(): Promise<Settings>;
    /**
     * Get Google OAuth credentials
     * @async
     * @returns {ClientCredentials}
     */
    credentials(): Promise<ClientCredentials>;
    /**
     * Return wallet's address by email. The wallet can be not initialised, i.e. this function will return the address for any email.
     * @async
     * @param {string} email
     * @returns {CSL.Address}
     */
    walletAddress(email: string): Promise<CSL.Address>;
    /**
     * Activate a Smart Wallet.
     * This will create a minting transaction which should be signed and submitted.
     * @async
     * @param {string} jwt    - Base64url-decoded Google JSON web token without signature
     * @param {string} payment_key_hash  - Token name (the hash of a public key used to initialise the wallet)
     * @param {ProofBytes} proof_bytes   - Zero-knowledge proof that the user possesses a valid JWT
     * @returns {CreateWalletResponse}
     */
    activateWallet(jwt: string, payment_key_hash: string, proof_bytes: ProofBytes): Promise<CreateWalletResponse>;
    /**
     * Activate a Smart Wallet and send funds from it.
     * This will create transaction which should be signed and submitted.
     * @async
     * @param {string} jwt    - Base64url-decoded Google JSON web token without signature
     * @param {string} payment_key_hash  - Token name (the hash of a public key used to initialise the wallet)
     * @param {ProofBytes} proof_bytes   - Zero-knowledge proof that the user possesses a valid JWT
     * @param {Output[]} outs            - Transaction outputs (where to send funds)
     * @returns {CreateWalletResponse}
     */
    activateAndSendFunds(jwt: string, payment_key_hash: string, proof_bytes: ProofBytes, outs: Output[]): Promise<CreateWalletResponse>;
    /**
     * Send funds from an activated Smart Wallet.
     * This will create transaction which should be signed and submitted.
     * @async
     * @param {string} email
     * @param {Output[]} outs            - Transaction outputs (where to send funds)
     * @param {string} payment_key_hash  - Token name (the hash of a public key used to initialise the wallet)
     * @returns {SendFundsResponse}
     */
    sendFunds(email: string, outs: Output[], payment_key_hash: string): Promise<SendFundsResponse>;
    /**
     * Submit a CBOR-encoded transaction.
     * @async
     * @param {string} transaction
     * @param {string[]} email_recipients
     * @returns {SubmitTxResult} - Transaction ID and email delivery errors, if any
     */
    submitTx(transaction: string, email_recipients?: string[], sender?: string): Promise<SubmitTxResult>;
    /**
     * Add a witness to the transaction, submit it and notify recipients by email.
     * @async
     * @param {string} unsigned_transaction
     * @param {string} vkey_witness
     * @param {string[]} email_recipients
     * @returns {SubmitTxResult} - Transaction ID and email delivery errors, if any
     */
    addVkeyAndSubmitTx(unsigned_transaction: string, vkey_witness: string, email_recipients?: string[], sender?: string): Promise<SubmitTxResult>;
    /**
     * Get all UTxOs held by an address
     * @async
     * @param {CSL.Address} address
     * @returns {UTxO[]}
     */
    addressUtxo(address: CSL.Address): Promise<UTxO[]>;
    /**
     * Get assets held by an address and their approximate value in USD
     * @async
     * @param {CSL.Address} address
     * @returns {BalanceResponse}
     */
    balance(address: CSL.Address): Promise<BalanceResponse>;
    /**
     * Get transaction history of a email address
     * @async
     * @param {string} address
     * @returns {Transaction[]}
     */
    txHistory(email: string): Promise<Transaction[]>;
}

/**
 * Balance of a wallet
 *
 * @property {number} lovelace - The number of lovelace held
 * @property {Array}  tokens - The array of tokens held
 * @property {number} usd - the approximate value of the assets in USD
 */
export declare interface BalanceResponse {
    lovelace: number;
    tokens: PrettyToken[];
    usd: number;
}

/**
 * Convert BigInt to byte array
 */
export declare function bigIntToBytes(bigInt: bigint): Uint8Array;

/**
 * Wrapper for various integer types used in communication with the Backend, Prover, and CSL.
 * Provides a JSON representation unavailable for bignum.
 */
export declare class BigIntWrap {
    private int;
    constructor(num: string | number | bigint | CSL.BigNum);
    add(other: BigIntWrap): BigIntWrap;
    increase(other: BigIntWrap): void;
    toString(): string;
    toNumber(): number;
    toBigInt(): bigint;
    toBigNum(): CSL.BigNum;
    toJSON(): bigint;
}

/**
 * Convert bytes to base64url string
 */
export declare function bytesToBase64Url(bytes: Uint8Array): string;

/**
 * Convert bytes to hex string
 */
export declare function bytesToHex(bytes: Uint8Array): string;

/**
 *  OAuth client credentials
 *
 *  @property {string}      client_id         - OAuth client id
 *  @property {string}      client_secret     - OAuth client secret
 */
export declare interface ClientCredentials {
    client_id: string;
    client_secret: string;
}

/**
 *  This object is sent by the backend upon successful initialisation of a Gmail-based wallet.
 *
 *  @property {CSL.Address} address         - The new wallet's address
 *  @property {string}      transaction     - Transaction to be signed and submitted to initialise the wallet
 *  @property {number}      transaction_fee - The expected fee of the wallet initialisation transaction
 *  @property {string}      transaction_id  - The ID of the wallet initialisation transaction
 */
export declare interface CreateWalletResponse {
    address: CSL.Address;
    transaction: string;
    transaction_fee: number;
    transaction_id: string;
}

export declare function deserialize(jsonString: string): any;

/**
 * Email address to which notification couldn't be delivered and the reason.
 *
 * @property {string} email - Email address
 * @property {string} error - The reason why notification failed
 */
export declare interface FailedNotification {
    email: string;
    error: string;
}

export declare class GoogleApi {
    private clientId;
    private clientSecret;
    private redirectURL;
    constructor(clientId: string, clientSecret: string, redirectURL: string);
    /**
     * Generates the Google OAuth2 authorization URL.
     * @param {string} state - A unique state string to prevent CSRF attacks.
     * @returns {string} The Google OAuth2 authorization URL.
     */
    getAuthUrl(state: string): string;
    /**
     * Exchanges an authorization code for a JWT.
     * @param {string} code - The authorization code received from Google.
     * @returns {Promise<string | null>} A promise that resolves to the JWT or null if not found.
     */
    getJWTFromCode(code: string): Promise<string | null>;
    /**
     * Fetches Google's public keys and returns the one matching the given key ID.
     * @param {string} keyId - The key ID to match.
     * @returns {Promise<GoogleCertKey | null>} A promise that resolves to the matching key or null if not found.
     */
    getMatchingKey(keyId: string): Promise<GoogleCertKey | null>;
    /**
     * Extracts the key ID from a JWT.
     * @param {string} jwt - The JWT string.
     * @returns {string} The key ID.
     */
    getKeyId(jwt: string): string;
    /**
     * Extracts the user ID (email) from a JWT.
     * @param {string} jwt - The JWT string.
     * @returns {string} The user ID (email).
     */
    getUserId(jwt: string): string;
    /**
     * Extracts the signature from a JWT.
     * @param {string} jwt - The JWT string.
     * @returns {string} The signature.
     */
    getSignature(jwt: string): string;
    /**
     * Strips the signature from a JWT.
     * @param {string} jwt - The JWT string.
     * @returns {string} The JWT without the signature.
     */
    stripSignature(jwt: string): string;
}

export declare type GoogleCertKey = {
    kid: string;
    n: string;
    e: string;
    [key: string]: unknown;
};

export declare type GoogleTokenResponse = {
    id_token?: string;
    [key: string]: unknown;
};

export declare function harden(num: number): number;

/**
 * Convert a hex string to a byte array
 * https://stackoverflow.com/questions/14603205/how-to-convert-hex-string-into-a-bytes-array-and-a-bytes-array-in-the-hex-strin
 */
export declare function hexToBytes(hex: string): Uint8Array;

/**
 * Transaction output as expected by the backend.
 *
 * @property {string} address
 * @property {TxDatum} datum  - Optional datum (inline or just hash) to be included
 * @property {Value} value
 *
 * @example
 *
 * { "address": "addr_test1qrsuhwqdhz0zjgnf46unas27h93amfghddnff8lpc2n28rgmjv8f77ka0zshfgssqr5cnl64zdnde5f8q2xt923e7ctqu49mg5",
 *    "datum": {
 *      "datum": "some_datum_data",
 *      "is_inline": true
 *    },
 *    "value": {
 *      "ff80aaaf03a273b8f5c558168dc0e2377eea810badbae6eceefc14ef.474f4c44": 101,
 *      "lovelace": 22
 *    }
 * }
 */
export declare interface Output {
    address: string;
    datum?: TxDatum;
    value: Value;
}

/**
 * Details of a token from Cardano Token Registry
 *
 * @property {string} asset - The asset name <minting_policy_id>.<asset_name>
 * @property {string} ticker - The ticker of a token (e.g. SNEK)
 * @property {string} token_name - The token name (e.g. Snek)
 * @property {number} decimal_adjustment - The numeric value that specifies the number of decimal places that the token can have
 * @property {string} logo - The token logo as a base64 string
 */
export declare interface PrettyToken {
    asset: string;
    amount: number;
    ticker?: string;
    description: string;
    token_name: string;
    decimal_adjustment?: number;
    logo?: string;
}

/**
 *  ProofBytes used by Plonkup.
 *  This object will be sent to the backend as a proof that user possesses a valid JSON Web Token
 *  and used in the script redeemer.
 */
export declare interface ProofBytes {
    "a_xi_int": BigIntWrap;
    "b_xi_int": BigIntWrap;
    "c_xi_int": BigIntWrap;
    "cmA_bytes": string;
    "cmB_bytes": string;
    "cmC_bytes": string;
    "cmF_bytes": string;
    "cmH1_bytes": string;
    "cmH2_bytes": string;
    "cmQhigh_bytes": string;
    "cmQlow_bytes": string;
    "cmQmid_bytes": string;
    "cmZ1_bytes": string;
    "cmZ2_bytes": string;
    "f_xi_int": BigIntWrap;
    "h1_xi'_int": BigIntWrap;
    "h2_xi_int": BigIntWrap;
    "l1_xi": BigIntWrap;
    "l_xi": BigIntWrap[];
    "proof1_bytes": string;
    "proof2_bytes": string;
    "s1_xi_int": BigIntWrap;
    "s2_xi_int": BigIntWrap;
    "t_xi'_int": BigIntWrap;
    "t_xi_int": BigIntWrap;
    "z1_xi'_int": BigIntWrap;
    "z2_xi'_int": BigIntWrap;
}

/**
 *  ZK Proof input
 *
 *  @property {BigIntWrap}      piPubE         - Google's RSA public exponent
 *  @property {BigIntWrap}      piPubN         - Google's RSA public modulus
 *  @property {BigIntWrap}      piSignature    - Signature attached to the Google OAuth JSON Web Token
 *  @property {BigIntWrap}      piTokenName    - The name of the token minted in the wallet initialisation transaction
 */
export declare interface ProofInput {
    piPubE: BigIntWrap;
    piPubN: BigIntWrap;
    piSignature: BigIntWrap;
    piTokenName: BigIntWrap;
}

/**
 * A wrapper for interaction with the prover
 * @class
 */
export declare class Prover {
    private url;
    /**
     * Creates a new Prover object.
     * @param {string} url     - Prover's URL
     */
    constructor(url: string);
    private headers;
    /**
     * Get all public keys held by the Prover
     * @async
     * @returns {ProverPublicKey[]}
     */
    serverKeys(): Promise<ProverPublicKey[]>;
    /**
     * Submit a proof request to the Prover. It will return a Request ID which can be used to retrieve proof status
     * @async
     * @param {ProofInput} proofInput for the expMod circuit: exponent, modulus, signature and token name
     * @returns {string} proof request ID
     */
    requestProof(proofInput: ProofInput): Promise<string>;
    /**
     * Retrieve the status of a Proof Request
     * @async
     * @param {string} proofId request ID
     * @returns {ProofBytes | string} ProofBytes if the proof has finished or 'Pending' otherwise
     */
    proofStatus(proofId: string): Promise<ProofBytes | null>;
    /**
     * Obtain a Proof from the Prover. Unlike requestProof(), this method waits for the proof completion
     * @async
     * @param {ProofInput} proofInput for the expMod circuit: exponent, modulus, signature and token name
     * @returns {ProofBytes} ZK proof bytes for the expMod circuit
     */
    prove(proofInput: ProofInput): Promise<ProofBytes>;
    private parseProverKeys;
    private parseProofStatus;
    private parseProofBytes;
}

/**
 *  RSA public key provided by the prover with its unique identifier
 *
 *  @property {string}         pkbId        - Public key identifier
 *  @property {PublicKey}      pkbPublic    - Public key itself
 */
export declare interface ProverPublicKey {
    pkbId: string;
    pkbPublic: PublicKey;
}

/**
 *  RSA public key provided by the prover
 *
 *  @property {BigIntWrap}      public_e    - Public exponent
 *  @property {BigIntWrap}      public_n    - Public modulus
 *  @property {BigIntWrap}      public_size - Key size in bits
 */
export declare interface PublicKey {
    public_e: BigIntWrap;
    public_n: BigIntWrap;
    public_size: BigIntWrap;
}

/**
 * Transaction input reference containing transaction id and output index.
 *
 * @property {string} transaction_id
 * @property {number} output_index
 *
 * Will be serialised to JSON as `${transaction_id}#${output_index}`. For example,
 * "4293386fef391299c9886dc0ef3e8676cbdbc2c9f2773507f1f838e00043a189#1"
 */
export declare interface Reference {
    transaction_id: string;
    output_index: number;
}

/**
 *  This object is sent by the backend upon a successful request to the /send_funds endpoint
 *
 *  @property {string}      transaction     - Transaction to be signed and submitted
 *  @property {number}      transaction_fee - The expected fee of the transaction
 *  @property {string}      transaction_id  - The ID of the transaction
 */
export declare interface SendFundsResponse {
    transaction: string;
    transaction_fee: number;
    transaction_id: string;
}

/**
 * JSON serialization utilities to handle big integers
 */
export declare function serialize(data: any): string;

/**
 * Smart Wallet Backend settings
 */
export declare interface Settings {
    network: string;
    version: string;
}

/**
 * Describes the recipient of ADA
 * @property {AddressType} recipientType  - Type of wallet the recipient holds
 * @property {string} address             - Cardano address if recipientType is Bech32, email otherwise
 * @property {Asset} assets               - A dictionary of assets to send. For ADA, use 'lovelace' as the key. For other assets, use the format '<PolicyID>.<AssetName>'
 */
export declare interface SmartTxRecipient {
    recipientType: AddressType;
    address: string;
    assets: Value;
}

/**
 *  Transaction ID and email delivery errors, if any
 *
 * @property {string}      transaction_id         - Transaction ID
 * @property {Array}       notifier_errors        - Recipients who were not notified
 */
export declare interface SubmitTxResult {
    transaction_id: string;
    notifier_errors: FailedNotification[];
}

/**
 * Transaction from transaction history
 *
 * @property {string} transaction_id - Transaction id
 * @property {{ [asset: string]: number }}  value_diff - Dictionary with sent (negative value) and received (positive value) assets
 * @property {string} timestamp - Transaction date
 * @property {CSL.Address[]} from_addrs - Addresses in the transaction inputs
 * @property {CSL.Address[]} to_addrs - Addresses in the transaction outputs
 */
export declare interface Transaction {
    transaction_id: string;
    value_diff: {
        [asset: string]: number;
    };
    timestamp: string;
    from_addrs: CSL.Address[];
    to_addrs: CSL.Address[];
}

export declare interface TransactionRequest {
    recipient: string;
    recipientType: AddressType;
    asset: string;
    amount: string;
}

/**
 * Optional datum (inline or just hash) to be included.
 *
 * @property {any} datum - Datum data
 * @property {boolean} is_inline - true for inline datum, false for just datum hash
 */
export declare interface TxDatum {
    datum: any;
    is_inline: boolean;
}

/**
 * UTxO object containing transaction where it was created, address and assets.
 *
 * @param {Reference}   ref          - Transaction output reference
 * @param {CLS.Address} address      - UTxO address
 * @param {Value}       value        - UTxO assets
 *
 * @example
 *
 * {
 *      "address": "addr_test1qrsuhwqdhz0zjgnf46unas27h93amfghddnff8lpc2n28rgmjv8f77ka0zshfgssqr5cnl64zdnde5f8q2xt923e7ctqu49mg5",
 *      "ref": {
 *          "transaction_id": "4293386fef391299c9886dc0ef3e8676cbdbc2c9f2773507f1f838e00043a189",
 *          "output_index": 1
 *      }
 *      "value": {
 *          "ff80aaaf03a273b8f5c558168dc0e2377eea810badbae6eceefc14ef.474f4c44": 101,
 *          "lovelace": 22
 *      }
 *  }
 */
export declare interface UTxO {
    ref: Reference;
    address: CSL.Address;
    value: Value;
}

/**
 *  Value object representing assets (lovelace and tokens).
 *  The keys are asset identifiers (policy_id + '.' + asset_name in hex) or 'lovelace' for ADA.
 *  The values are BigIntWrap representing the quantity of each asset.
 */
export declare interface Value {
    [key: string]: BigIntWrap;
}

export declare type Version = 'v0';

/**
 * The Wallet which can be initialised with an email address.
 */
export declare class Wallet extends EventTarget {
    private jwt?;
    private tokenSKey?;
    private userId?;
    private activated;
    private proof;
    private storage;
    private session;
    private googleApi;
    private backend;
    private prover;
    /**
     *  @param {Backend} backend                 - A Backend object for interaction with the backend
     *  @param {Prover} prover                   - A Prover object for interaction with the prover
     *  @param {GoogleApi} googleApi             - A GoogleApi object for interaction with Google OAuth
     */
    constructor(backend: Backend, prover: Prover, googleApi: GoogleApi);
    login(): void;
    isActivated(): boolean;
    isLoggedIn(): boolean;
    hasProof(): boolean;
    logout(): void;
    oauthCallback(callbackData: string): Promise<void>;
    private getProof;
    getUserId(): string;
    /**
     * @async
     * Get the Cardano address for a gmail address
     */
    addressForGmail(gmail: string): Promise<CSL.Address>;
    /**
     * @async
     * Get the Wallet's address
     */
    getAddress(): Promise<CSL.Address>;
    /**
     * @async
     * Get wallet's balance as an object with asset names as property names and amounts as their values.
     */
    getBalance(): Promise<BalanceResponse>;
    /**
     * @async
     * Get the approximate USD value of all wallet's assets
     */
    getUSDValue(): Promise<number>;
    /**
     * @async
     * Get wallet's transaction history
     */
    getTxHistory(): Promise<Transaction[]>;
    /**
     * Get extensions turned on in the wallet
     */
    getExtensions(): string[];
    /**
     * @async
     * Get UTxOs held by the wallet
     */
    getUtxos(): Promise<UTxO[]>;
    /**
     * @async
     * Get wallet's used addresses (currently only wallet's main address)
     */
    getUsedAddresses(): Promise<CSL.Address[]>;
    /**
     * @async
     * Get wallet's unused addresses
     */
    getUnusedAddresses(): Promise<CSL.Address[]>;
    /**
     * @async
     * Get wallet's reward addresses (currently none)
     */
    getRewardAddresses(): Promise<CSL.Address[]>;
    /**
     * @async
     * Get wallet's change address (currently wallet's main address)
     */
    getChangeAddress(): Promise<CSL.Address>;
    /**
     * @async
     * Send a transaction from this wallet.
     *
     * @param {TransactionRequest} request - Transaction request object
     */
    sendTransaction(request: TransactionRequest): Promise<void>;
    private awaitTxConfirmed;
    private checkTransactionStatus;
    private sendTo;
}

/** Events emitted by the Wallet object.
 *
 *  'walletInitialized' - emitted when the wallet is successfully initialized
 *  'proofComputationComplete' - emitted when ZK proof computation is complete
 *  'transactionComplete' - emitted when a transaction is successfully completed
 *  'transactionFailed' - emitted when a transaction fails
 *  'walletLoggedOut' - emitted when the wallet is logged out
 */
export declare type WalletEvent = 'initialized' | 'proof_computed' | 'transaction_initiated' | 'transaction_pending' | 'transaction_confirmed' | 'transaction_failed' | 'logged_out';

/**
 * Data required to initialise a wallet.
 *
 *  data is Google JSON Web Token as a string
 *  rootKey is the private key to sign transactions (can be generated randomly)
 */
export declare interface WalletInitialiser {
    jwt: string;
    tokenSKey?: string;
}

export { }
