UNPKG

shield-bridge-sdk

Version:
512 lines (511 loc) 22.7 kB
import { ContractMethodObject, Estimate, TezosToolkit, Wallet } from '@taquito/taquito'; import { Contract } from '@tzkt/sdk-api'; export declare const tzktApiMap: { mainnet: string; ghostnet: string; }; export declare const saplingStateMapContract: { mainnet: string; ghostnet: string; }; type OrderedTransactionList = [ ContractMethodObject<Wallet>[], ContractMethodObject<Wallet>[], { txns: (string | void)[]; contract?: string; token_id?: number; amount?: number | string; }[], ContractMethodObject<Wallet>[] ]; interface SaplingDeposits { amount: number | string; saplingTransactions: (string | void)[]; owner?: string; contract?: string; tokenId?: number; } interface SaplingTransactions { saplingTransactions: (string | void)[]; contract?: string; tokenId?: number; } interface ShieldParams { amount: number; shieldedAddress?: string; contract?: string; tokenId?: number; memo?: string; } interface UnshieldParams { amount: number; unshieldedAddress?: string; contract?: string; tokenId?: number; } interface TransferParams { contract?: string; tokenId?: number; transfers: { amount: number; to: string; memo?: string; }[]; } interface SaplingTokenInfo { saplingId?: number; contract?: string; tokenId?: number; } /** * Progress callbacks for transaction operations * Provides real-time updates during shield, unshield, and transfer operations * * @example * // Basic usage with progress tracking * await shieldBridge.shield([{ amount: 1, contract: 'KT1...' }], { * onGenerating: (data) => console.log(`Generating sapling transaction`), * onSigning: () => console.log('Signing transaction...'), * onSubmitting: () => console.log('Submitting to network...'), * onConfirmed: (data) => console.log(`Confirmed! Op: ${data.opHash}`) * }); * * @example * // With a progress bar UI * let progress = 0; * await shieldBridge.transfer([...], { * onGenerating: () => setProgress(50), * onSigning: () => setProgress(65), * onSubmitting: () => setProgress(80), * onConfirmed: () => setProgress(100), * }); * * @example * // With detailed step tracking * await shieldBridge.unshield([...], { * onGenerating: ({ step, total, contract }) => * console.log(`Generating proof ${step}/${total} for ${contract}`), * onConfirmed: ({ opHash }) => * window.open(`https://tzkt.io/${opHash}`, '_blank') * }); */ interface TransactionProgressCallbacks { /** Called when preparing transaction parameters and generating sapling proofs */ onGenerating?: (params: ShieldParams[] | TransferParams[] | UnshieldParams[]) => void; /** Called when signing the transaction */ onSigning?: () => void; /** Called when submitting to the network */ onSubmitting?: (data: { opHash: string; }) => void; /** Called when transaction is confirmed */ onConfirmed?: (data: { opHash: string; block?: any; }) => void; } type ShieldBridgeSDKConfig = { client: TezosToolkit; tzktApi?: 'mainnet' | 'ghostnet'; minConfirmations?: number; saplingStateMapContract?: string; gasLimitBuffer?: number; storageLimitBuffer?: number; useBaseUnits?: boolean; parallelThreads?: boolean; } & ({ saplingSecret: string; saplingMnemonic?: never; saplingViewingKey?: never; } | { saplingSecret?: never; saplingMnemonic: string; saplingViewingKey?: never; } | { saplingSecret?: never; saplingMnemonic?: never; saplingViewingKey: string; }); /** * ShieldBridgeSDK provides an abstraction to interact with the Shield Bridge smart contract * to shield, unshield, and transfer sapling tokens. * * The SDK supports two modes of operation: * * 1. **Full Access Mode** (with spending key or mnemonic): * - Can perform all operations: shield, unshield, transfer * - Can query balances and transactions * - Can export viewing keys for read-only access * * 2. **View-Only Mode** (with viewing key): * - Can only query balances and transactions * - Cannot perform transaction operations * - Useful for auditing, monitoring, and compliance * * @class * @param {ShieldBridgeSDKConfig} config The configuration object for the Shield Bridge SDK * @param {TezosToolkit} config.client The TezosToolkit instance * @param {'mainnet' | 'ghostnet'} [config.tzktApi='mainnet'] The tzkt API to use * @param {number} [config.minConfirmations=1] The minimum number of confirmations for the transaction * @param {string} [config.saplingStateMapContract='KT1RYEs6rfXgHqeb2XzfHKRii5NsNyKbS6WM'] The sapling state map contract address * @param {number} [config.gasLimitBuffer=2_000] The buffer to add to the estimated gas limit * @param {number} [config.storageLimitBuffer=500] The buffer to add to the estimated storage limit * @param {boolean} [config.useBaseUnits=false] Whether to use base unit for the token amounts (mutez or token units with decimals) * @param {boolean} [config.parallelThreads=false] Whether to spawn parallel threads for the sapling worker * @param {string} [config.saplingSecret] The sapling secret key (for full access mode) * @param {string} [config.saplingMnemonic] The sapling mnemonic (for full access mode) * @param {string} [config.saplingViewingKey] The sapling viewing key (for view-only mode) * @returns {ShieldBridgeSDK} The Shield Bridge SDK instance * * @example * // Full access mode with secret key * const tezos = new TezosToolkit('https://mainnet.api.tez.ie'); * const signerProvider = await InMemorySigner.fromSecretKey('edsk...'); * tezos.setSignerProvider(signerProvider); * const shieldBridge = new ShieldBridgeSDK({ * client: tezos, * saplingSecret: 'sask...' * }); * await shieldBridge.shield([ * { * amount: 1, * contract: 'KT1...', * tokenId: 0, * memo: 'abcdefgh' * } * ]); * * @example * // Export viewing key for read-only access * const viewingKey = await shieldBridge.getViewingKey(); * * @example * // View-only mode with viewing key * const viewOnlySdk = new ShieldBridgeSDK({ * client: tezos, * saplingViewingKey: 'abc123...' * }); * const balance = await viewOnlySdk.getShieldedBalance(); * console.log('View-only mode:', viewOnlySdk.isViewOnlyMode); // true */ export declare class ShieldBridgeSDK { private config; private tezosClient; private saplingWorker; saplingStateMapContract: string; minConfirmations: number; gasLimitBuffer: number; storageLimitBuffer: number; useBaseUnits: boolean; parallelThreads: boolean; ready: Promise<boolean>; /** * Indicates whether the SDK is in view-only mode (using a viewing key) * When true, only read operations (balance, transactions, address) are available * Transaction operations (shield, unshield, transfer) will throw errors */ readonly isViewOnlyMode: boolean; private saplingIdCache; private tokenDecimalsCache; private tokenMetadataCache; private walletContractCache; private estimatorContractCache; constructor(config: ShieldBridgeSDKConfig); initializeSaplingWorker: () => Promise<boolean>; /** * @description Validate amount is positive and not NaN * @param amount The amount to validate * @param context Context for error message */ private static validateAmount; /** * @description Validate Tezos address format (basic validation) * @param address The address to validate * @param context Context for error message */ private static validateAddress; /** * @description Get cached wallet contract or fetch and cache it * @param contractAddress The contract address */ private getWalletContract; /** * @description Get cached estimator contract or fetch and cache it * @param contractAddress The contract address */ private getEstimatorContract; /** * @description Helper method to initialize a sapling worker with the sapling secret and state * @param contract The token contract address (optional) * @param tokenId The token id (optional) * @param providedSaplingId The sapling id if already known (optional, to avoid redundant API call) * @returns The initialized sapling worker and sapling id */ private initializeSaplingWorkerWithState; /** * @description Get the sapling id for the token contract and token id if provided * @param {string} [contract] The token contract address * @param {number} [tokenId] The token id * @returns The sapling id for the token contract and token id if provided */ getSaplingId: (contract?: string, tokenId?: number) => Promise<number | undefined>; /** * @description Get the metadata for the token contract and token id if provided * @param {string} contract The token contract address * @param {number} [tokenId] The token id * @returns The metadata for the token contract and token id if provided */ getTokenMetadata: (contract: string, tokenId?: number) => Promise<any>; /** * @description Get the number of decimals for the token contract and token id if provided * @param {string} contract The token contract address * @param {number} [tokenId] The token id * @returns The number of decimals for the token contract and token id if provided */ getTokenDecimals: (contract: string, tokenId?: number) => Promise<number>; /** * @description Get the total shielded pool balances for the sapling state map contract * @returns The total shielded pool balances */ getTotalShieldedPoolBalances: () => Promise<{ balance: string | number; id?: number; account?: import("@tzkt/sdk-api").Alias | null; token?: import("@tzkt/sdk-api").TokenInfo | null; transfersCount?: number; firstLevel?: number; firstTime?: string; lastLevel?: number; lastTime?: string; }[]>; /** * @description Get the sapling state map contract data * @returns The sapling state map contract data */ getContractData: () => Promise<Contract>; /** * @description Estimate the gas and storage limits for the transaction list of shielding transactions * @param {OrderedTransactionList} transactionList The constructed transaction list * @returns The estimated gas and storage limits for the transaction list */ estimateShieldTransactionLimits: (transactionList: OrderedTransactionList) => Promise<Estimate[]>; /** * @description Get the estimated fee for the transaction * @param {Estimate} estimate The estimate object * @returns The estimated fee for the transaction */ getEstimatedFee: (estimate: Estimate) => number; /** * @description Submit sapling deposits/shielding transactions * @param {SaplingDeposits} saplingDeposits Sapling deposits/shielding transactions to be submitted * @param {number} saplingDeposits.amount The amount to be shielded * @param {string[]} saplingDeposits.saplingTransactions The sapling transactions to be submitted * @param {string} [saplingDeposits.contract] The token contract address * @param {number} [saplingDeposits.tokenId] The token id * @param {string} [saplingDeposits.owner] The shielded address to apply the shielded tokens * @returns The confirmation of the submitted sapling deposits/shielding transactions */ submitSaplingShieldTransaction: (saplingDeposits: SaplingDeposits[], callbacks?: TransactionProgressCallbacks) => Promise<{ opHash: string; block?: import("@taquito/rpc").BlockResponse | undefined; expectedConfirmation?: number | undefined; currentConfirmation?: number | undefined; completed?: boolean | undefined; isInCurrentBranch?: (() => Promise<boolean>) | undefined; }>; /** * @description Submit sapling transactions (shared implementation for unshield and transfer) * @param {SaplingTransactions} saplingTransactions Sapling transactions to be submitted * @param {string[]} saplingTransactions.saplingTransactions The sapling transactions to be submitted * @param {string} [saplingTransactions.contract] The token contract address * @param {number} [saplingTransactions.tokenId] The token id * @returns The confirmation of the submitted sapling transactions */ submitSaplingTransaction: (saplingTransactions: SaplingTransactions[], callbacks?: TransactionProgressCallbacks) => Promise<any>; /** * @description Submit sapling withdrawals/unshielding transactions * @param {SaplingTransactions} saplingWithdrawals Sapling withdrawals/unshielding transactions to be submitted * @param {string[]} saplingWithdrawals.saplingTransactions The sapling transactions to be submitted * @param {string} [saplingWithdrawals.contract] The token contract address * @param {number} [saplingWithdrawals.tokenId] The token id * @returns The confirmation of the submitted sapling withdrawals/unshielding transactions */ submitSaplingUnshieldTransaction: (saplingWithdrawals: SaplingTransactions[], callbacks?: TransactionProgressCallbacks) => Promise<any>; /** * @description Submit sapling transfers transactions * @param {SaplingTransactions} saplingTransfers Sapling transfers to be submitted * @param {string[]} saplingTransfers.saplingTransactions The sapling transactions to be submitted * @param {string} [saplingTransfers.contract] The token contract address * @param {number} [saplingTransfers.tokenId] The token id * @returns The confirmation of the submitted sapling transfers */ submitSaplingTransferTransaction: (saplingTransfers: SaplingTransactions[], callbacks?: TransactionProgressCallbacks) => Promise<any>; /** * @description Construct the sapling parameters for the shielded transaction * @param shieldParam The sapling shielding parameters * @param {number} shieldParam.amount The amount to be shielded * @param {string} [shieldParam.shieldedAddress] The shielded address to apply the shielded tokens * @param {string} [shieldParam.contract] The token contract address * @param {number} [shieldParam.tokenId] The token id * @param {string} [shieldParam.memo] The memo to be included in the sapling transaction * @returns The sapling parameters for the shielded transaction */ constructShieldTokenParams: (shieldParam: ShieldParams) => Promise<{ saplingTransactions: string[]; owner: string; amount: string | number; contract: string | undefined; tokenId: number | undefined; }>; /** * @description Shield the specified amount of unshielded tokens to the sapling address * @param {ShieldParams} shieldParams Sapling shielding parameters to be constructed into sapling transactions * @param {number} shieldParams.amount The amount to be shielded * @param {string} [shieldParams.shieldedAddress] The shielded address to apply the shielded tokens * @param {string} [shieldParams.contract] The token contract address * @param {number} [shieldParams.tokenId] The token id * @param {string} [shieldParams.memo] The memo to be included in the sapling transaction * @param {TransactionProgressCallbacks} [callbacks] Optional callbacks for operation progress updates * @returns The confirmation of the submitted sapling shielding transactions * @throws {Error} If called in view-only mode (with a viewing key) */ shield: (shieldParams: ShieldParams[], callbacks?: TransactionProgressCallbacks) => Promise<{ opHash: string; block?: import("@taquito/rpc").BlockResponse | undefined; expectedConfirmation?: number | undefined; currentConfirmation?: number | undefined; completed?: boolean | undefined; isInCurrentBranch?: (() => Promise<boolean>) | undefined; }>; /** * @description Construct the sapling parameters for the unshielded transaction * @param unshieldParam The sapling unshielding parameters * @param {number} unshieldParam.amount The amount to be unshielded * @param {string} [unshieldParam.unshieldedAddress] The unshielded address to apply the unshielded tokens * @param {string} [unshieldParam.contract] The token contract address * @param {number} [unshieldParam.tokenId] The token id * @returns The sapling parameters for the unshielded transaction */ constructUnshieldTokenParams: (unshieldParam: UnshieldParams) => Promise<{ saplingTransactions: string[]; contract: string | undefined; tokenId: number | undefined; }>; /** * @description Unshield the specified amount of shielded tokens from the sapling address * @param {UnshieldParams} unshieldParams Sapling unshielding parameters to be constructed into sapling transactions * @param {number} unshieldParams.amount The amount to be unshielded * @param {string} [unshieldParams.unshieldedAddress] The unshielded address to apply the unshielded tokens * @param {string} [unshieldParams.contract] The token contract address * @param {number} [unshieldParams.tokenId] The token id * @param {TransactionProgressCallbacks} [callbacks] Optional callbacks for operation progress updates * @returns The confirmation of the submitted sapling unshielding transactions * @throws {Error} If called in view-only mode (with a viewing key) */ unshield: (unshieldParams: UnshieldParams[], callbacks?: TransactionProgressCallbacks) => Promise<any>; /** * @description Construct the sapling parameters for the transfer transaction * @param transferParam The sapling transfer parameters * @param {string} [transferParam.contract] The token contract address * @param {number} [transferParam.tokenId] The token id * @param {object} transferParam.transfers The transfers to be made * @returns The sapling parameters for the transfer transaction */ constructTransferTokenParams: (transferParam: TransferParams) => Promise<{ saplingTransactions: string[]; contract: string | undefined; tokenId: number | undefined; }>; /** * @description Transfer the specified amount of shielded tokens to the specified shielded address * @param {TransferParams[]} transferParams Sapling transfer parameters to be constructed into sapling transactions * @param {string} [transferParams.contract] The token contract address * @param {number} [transferParams.tokenId] The token id * @param {object} transferParams.transfers The transfers to be made * @param {TransactionProgressCallbacks} [callbacks] Optional callbacks for operation progress updates * @returns The confirmation of the submitted sapling transfer transactions * @throws {Error} If called in view-only mode (with a viewing key) */ transfer: (transferParams: TransferParams[], callbacks?: TransactionProgressCallbacks) => Promise<any>; /** * @description Get the shielded sapling token balance for the currently loaded shielded address * @param {SaplingTokenInfo} saplingTokenInfo The sapling token information * @param {number} [saplingTokenInfo.saplingId] The sapling id * @param {string} [saplingTokenInfo.contract] The token contract address * @param {number} [saplingTokenInfo.tokenId] The token id * @returns The shielded sapling token balance for the currently loaded shielded address */ getShieldedBalance: ({ saplingId, contract, tokenId, }: SaplingTokenInfo) => Promise<number>; /** * @description Get all the shielded sapling tokens * @param includeMetadata Include the metadata for the shielded sapling tokens * @returns The shielded sapling tokens */ getAllShieldedAssets: (includeMetadata?: boolean) => Promise<{ saplingId: number; contract?: string; tokenId?: number; metadata?: any; }[]>; /** * @description Get the shielded sapling token balances for all the sapling tokens * @returns The shielded sapling token balances for all the sapling tokens */ getAllShieldedBalances: () => Promise<{ saplingId: number; contract?: string; tokenId?: number; balance: number; }[]>; /** * @description Get the shielded incoming and outgoing transactions for the specified sapling contract and token id * @param {string} [contract] Sapling contract address * @param {number} [tokenId] Token id * @returns The shielded incoming and outgoing transactions for the specified sapling contract and token id */ getShieldedTransactions: (contract?: string, tokenId?: number) => Promise<{ incoming: any[]; outgoing: any[]; }>; /** * @description Get the sapling payment address of the currently loaded sapling key * @returns The sapling payment address */ getShieldedAddress: () => Promise<string>; /** * @description Export the viewing key for the currently loaded sapling key * * The viewing key can be used to initialize the SDK in view-only mode, allowing * read-only operations (balance queries, transaction history) without exposing * the spending key. This is useful for: * - Auditing and compliance purposes * - Sharing balance visibility without spending ability * - Creating monitoring applications * * @returns The viewing key as a hex string * @throws {Error} If no spending key or viewing key is loaded * * @example * // Export viewing key from spending key * const viewingKey = await sdk.getViewingKey(); * * // Use it to create a view-only SDK instance * const viewOnlySdk = new ShieldBridgeSDK({ * client: tezos, * saplingViewingKey: viewingKey * }); * * // Now you can query balances without spending ability * const balance = await viewOnlySdk.getShieldedBalance(); */ getViewingKey: () => Promise<string>; /** * @description Initialize the sapling pool for the specified token contract and token id * @param {string} contract The token contract address * @param {number} [tokenId] The token id * @returns The confirmation of the initialized sapling pool */ initTokenSaplingPool: (contract: string, tokenId?: number) => Promise<any>; } export {};