shield-bridge-sdk
Version:
512 lines (511 loc) • 22.7 kB
TypeScript
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 {};