zkfold-smart-wallet-api
Version:
Smart Wallet API - Browser and extension compatible
686 lines (645 loc) • 22.6 kB
TypeScript
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 { }