import * as CSL from '@emurgo/cardano-serialization-lib-browser';

/**
 * We support Bech32 addresses and Gmail-locked smart contracts.
 */
export declare enum AddressType {
    Bech32 = 0,
    Email = 1
}

/**
 * Describes assets and their amounts
 */
export declare interface Asset {
    [key: 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;
    /**
     * Return wallet's address by email. The wallet can be not initialised, i.e. this function will return the adress for any email.
     * @async
     * @param {string} email
     * @param {string} version - Version of the on=chain wallet script. Defaults to the most recent one
     * @returns {CSL.Address}
     */
    walletAddress(email: string, version?: string): Promise<CSL.Address>;
    /**
     * Check if a Gmail-based wallet has been initialised (i.e. the token minting transaction has been submitted).
     * @async
     * @param {string} email
     * @param {string} pubKeyHash - Token name (the hash of a public key used to initialise the wallet)
     * @param {string} version    - Version of the on=chain wallet script. Defaults to the most recent one
     * @returns {boolean}
     */
    isWalletInitialised(email: string, pubKeyHash: string, version?: string): Promise<boolean>;
    /**
     * Create a Gmail-based wallet.
     * This will create a minting transaction which should be signed and submitted.
     * @async
     * @param {string} email
     * @param {string} jwt    - Base64url-decoded Google JSON web token without signature
     * @param {string} paymenk_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 {CSL.Address} fund_address - Address which wll fund the transaction (defaults to the wallet's address)
     * @param {string} version           - Version of the on=chain wallet script. Defaults to the most recent one
     * @returns {CreateWalletResponse}
     */
    createWallet(email: string, jwt: string, payment_key_hash: string, proof_bytes: ProofBytes, fund_address?: CSL.Address, version?: string): Promise<CreateWalletResponse>;
    /**
     * Create a Gmail-based wallet and send funds from it.
     * This will create transaction which should be signed and submitted.
     * @async
     * @param {string} email
     * @param {string} jwt    - Base64url-decoded Google JSON web token without signature
     * @param {string} paymenk_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)
     * @param {string} version           - Version of the on=chain wallet script. Defaults to the most recent one
     * @returns {CreateWalletResponse}
     */
    createAndSendFunds(email: string, jwt: string, payment_key_hash: string, proof_bytes: ProofBytes, outs: Output[], version?: string): Promise<CreateWalletResponse>;
    /**
     * 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} paymenk_key_hash  - Token name (the hash of a public key used to initialise the wallet)
     * @param {string} version           - Version of the on=chain wallet script. Defaults to the most recent one
     * @returns {SendFundsResponse}
     */
    sendFunds(email: string, outs: Output[], payment_key_hash: string, version?: string): Promise<SendFundsResponse>;
    /**
     * Submit a CBOR-encoded transaction.
     * @async
     * @param {string} tx
     * @returns {SubmitTxResult} - Transaction ID and email delivery errors, if any
     */
    submitTx(tx: string, email_recipients?: string[]): Promise<SubmitTxResult>;
    /**
     * Get all UTxOs held by an address
     * @async
     * @param {CSL.Address} address
     * @returns {UTxO[]}
     */
    addressUtxo(address: CSL.Address): Promise<UTxO[]>;
    /**
     * Get Google OAuth credentials
     * @async
     * @param {string} clientName
     * @returns {ClientCredentials}
     */
    credentials(clientName: string): Promise<ClientCredentials>;
}

/**
 *  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 BackendKey {
    pkbId: string;
    pkbPublic: PublicKey;
}

/**
 * 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;

/**
 *  Google OAuth client credentials
 *
 *  @property {string}      client_id         - Google OAuth client id
 *  @property {string}      client_secret     - Google 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;

export declare class GoogleApi {
    private clientId;
    private clientSecret;
    private redirectURL;
    constructor(clientId: string, clientSecret: string, redirectURL: string);
    getAuthUrl(state: string): string;
    getJWT(code: string): Promise<string | undefined>;
}

/**
 * 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 {Array}  datum
 * @property {object} value
 *
 * @example
 *
 * { "address": "addr_test1qrsuhwqdhz0zjgnf46unas27h93amfghddnff8lpc2n28rgmjv8f77ka0zshfgssqr5cnl64zdnde5f8q2xt923e7ctqu49mg5",
 *    "datum": [
 *      "?"
 *    ],
 *    "value": {
 *      "ff80aaaf03a273b8f5c558168dc0e2377eea810badbae6eceefc14ef.474f4c44": 101,
 *      "lovelace": 22
 *    }
 * }
 */
export declare interface Output {
    address: string;
    datum?: string[];
    value: {
        [key: string]: BigIntWrap;
    };
}

export declare function parseBackendKeys(json: any[]): BackendKey[];

export declare function parseProofBytes(json: string): ProofBytes | null;

export declare function parseProofStatus(json: string): ProofBytes | 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 {BackendKey[]}
     */
    serverKeys(): Promise<BackendKey[]>;
    /**
     * Submit a proof request to the Prover. It will return a Request ID which can be used to retrieve proof status
     * @async
     * @param {ProofInput} inputs 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} Proof request ID
     * @returns {ProofBytes | string} ProofBytes if the proof has finished or 'Pending' otherwise
     */
    proofStatus(proofId: string): Promise<ProofBytes | string>;
    /**
     * Obtain a Proof from the Prover. Unlike requestProof(), this method waits for the proof completion
     * @async
     * @param {ProofInput} inputs for the expMod circuit: exponent, modulus, signature and token name
     * @returns {ProofBytes} ZK proof bytes for the expMod circuit
     */
    prove(proofInput: ProofInput): Promise<ProofBytes>;
}

/**
 *  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;
}

export declare function serialize(data: any): 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 class SmartTxRecipient {
    recipientType: AddressType;
    address: string;
    assets: Asset;
    constructor(recipientType: AddressType, address: string, assets: Asset);
}

/**
 *  Transaction ID and email delivery errors, if any
 *
 *  @property {string}      client_id         - Google OAuth client id
 *  @property {string}      tx_is             - Transaction ID
 */
export declare interface SubmitTxResult {
    notifier_errors: string[][];
    tx_id: string;
}

/**
 * UTxO object containing transaction where it was created, address and assets.
 *
 * @param {Reference}   ref          - Transaction output reference
 * @param {CLS.Address} address      - UTxO address
 * @param {object}      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: {
        [key: string]: BigIntWrap;
    };
}

/**
 * The Wallet which can be initialised with an email address.
 */
export declare class Wallet {
    private tokenSKey;
    private jwt;
    private userId;
    private freshKey;
    private backend;
    private prover;
    /**
     *  @param {Prover} prover                 - A Prover object for interaction with the prover
     *  @param {Backend} backend               - A Backend object for interaction with the backend
     *  @param {WalletInitialiser} initialiser - Data to initialise the wallet
     */
    constructor(backend: Backend, prover: Prover, initialiser: WalletInitialiser);
    /**
     * @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<Asset>;
    /**
     * 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>;
    /**
     * Send funds from this wallet to a recipient.
     *
     * @async
     * @param {SmartTxRecipient} rec - A recipient with a Cardano or a email address
     */
    sendTo(rec: SmartTxRecipient): Promise<SubmitTxResult>;
}

/**
 * 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 { }
