import type { Address, ContractRunner, Profile, AdvancedTransferOptions, FindPathParams, AvatarRow, TokenBalanceRow, AggregatedTrustRelation } from '@aboutcircles/sdk-types'; import type { TransactionReceipt } from 'viem'; import type { Core } from '@aboutcircles/sdk-core'; import type { CirclesEvent, Observable } from '@aboutcircles/sdk-rpc'; import { CirclesRpc } from '@aboutcircles/sdk-rpc'; import { Profiles } from '@aboutcircles/sdk-profiles'; import { TransferBuilder } from '@aboutcircles/sdk-transfers'; /** * Advanced pathfinding options (reuses FindPathParams optional fields) */ export type PathfindingOptions = Omit; /** * Forward reference to Sdk type to avoid circular imports * The actual Sdk instance is set via setSdk() after avatar creation */ interface SdkReference { readonly rpc: CirclesRpc; readonly circlesConfig: any; } /** * CommonAvatar abstract class * Provides common functionality shared across all avatar types (Human, Organisation, Group) * * This class extracts common logic for: * - Profile management (get, update, metadata) * - Balance queries * - Trust relationships * - Transaction history * - Event subscriptions */ export declare abstract class CommonAvatar { readonly address: Address; readonly avatarInfo: AvatarRow | undefined; readonly core: Core; readonly contractRunner?: ContractRunner; events: Observable; /** * Reference to the parent SDK instance. * Set automatically when avatar is created via Sdk.getAvatar(). * Provides access to SDK-level RPC methods like getTransactionHistoryEnriched. */ private _sdk?; /** * Get the parent SDK instance. * Throws if the avatar was not created via Sdk.getAvatar(). */ get sdk(): SdkReference; /** * Set the parent SDK reference. * Called internally by Sdk.getAvatar(). * @internal */ setSdk(sdk: SdkReference): void; protected readonly runner: ContractRunner; protected readonly profiles: Profiles; protected readonly rpc: CirclesRpc; protected readonly transferBuilder: TransferBuilder; protected _cachedProfile?: Profile; protected _cachedProfileCid?: string; protected _eventSubscription?: () => void; private _hasSubscribed; constructor(address: Address, core: Core, contractRunner?: ContractRunner, avatarInfo?: AvatarRow); readonly balances: { /** * Get total balance across all tokens */ getTotal: () => Promise; /** * Get detailed token balances */ getTokenBalances: () => Promise; /** * Get total supply of this avatar's token * Override this in subclasses if needed */ getTotalSupply: () => Promise; }; readonly trust: { /** * Trust another avatar or multiple avatars * * When using Safe runner, all trust operations are executed atomically in a single transaction. * When using EOA runner, only single avatars are supported (pass array length 1). * * @param avatar Single avatar address or array of avatar addresses * @param expiry Trust expiry timestamp (in seconds since epoch). Defaults to max uint96 for indefinite trust * @returns Transaction response * * @example * ```typescript * // Trust single avatar indefinitely * await avatar.trust.add('0x123...'); * * // Trust with custom expiry * const oneYear = BigInt(Date.now() / 1000 + 31536000); * await avatar.trust.add('0x123...', oneYear); * * // Trust multiple avatars (Safe only - throws error with EOA) * await avatar.trust.add(['0x123...', '0x456...', '0x789...']); * ``` */ add: (avatar: Address | Address[], expiry?: bigint) => Promise; /** * Remove trust from another avatar or multiple avatars * This is done by setting the trust expiry to 0 * * When using Safe runner, all operations are batched atomically. * When using EOA runner, only single avatars are supported (pass array length 1). * * @param avatar Single avatar address or array of avatar addresses * @returns Transaction response * * @example * ```typescript * // Remove trust from single avatar * await avatar.trust.remove('0x123...'); * * // Remove trust from multiple avatars (Safe only) * await avatar.trust.remove(['0x123...', '0x456...', '0x789...']); * ``` */ remove: (avatar: Address | Address[]) => Promise; /** * Check if this avatar trusts another avatar * @param otherAvatar The avatar address to check * @returns True if this avatar trusts the other avatar * * @example * ```typescript * const trusting = await avatar.trust.isTrusting('0x123...'); * if (trusting) { * console.log('You trust this avatar'); * } * ``` */ isTrusting: (otherAvatar: Address) => Promise; /** * Check if another avatar trusts this avatar * @param otherAvatar The avatar address to check * @returns True if the other avatar trusts this avatar * * @example * ```typescript * const trustedBy = await avatar.trust.isTrustedBy('0x123...'); * if (trustedBy) { * console.log('This avatar trusts you'); * } * ``` */ isTrustedBy: (otherAvatar: Address) => Promise; /** * Get all trust relations for this avatar */ getAll: () => Promise; }; readonly profile: { /** * Get the profile for this avatar from IPFS * Uses caching to avoid redundant fetches for the same CID * * @returns The profile data, or undefined if no profile is set or fetch fails * * @example * ```typescript * const profile = await avatar.profile.get(); * if (profile) { * console.log('Name:', profile.name); * console.log('Description:', profile.description); * } * ``` */ get: () => Promise; /** * Update the profile for this avatar * This will: * 1. Pin the new profile data to IPFS via the profile service * 2. Update the metadata digest in the name registry contract * * @param profile The profile data to update * @returns The CID of the newly pinned profile * * @example * ```typescript * const profile = { * name: 'Alice', * description: 'Hello, Circles!', * avatarUrl: 'https://example.com/avatar.png' * }; * * const cid = await avatar.profile.update(profile); * console.log('Profile updated with CID:', cid); * ``` */ update: (profile: Profile) => Promise; /** * Update the metadata digest (CID) in the name registry * This updates the on-chain pointer to the profile data stored on IPFS * * @param cid The IPFS CIDv0 to set as the metadata digest (e.g., "QmXxxx...") * @returns Transaction receipt * * @example * ```typescript * const receipt = await avatar.profile.updateMetadata('QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG'); * console.log('Metadata updated, tx hash:', receipt.hash); * ``` */ updateMetadata: (cid: string) => Promise; /** * Register a short name for this avatar using a specific nonce * Short names are numeric identifiers that can be used instead of addresses * * @param nonce The nonce to use for generating the short name * @returns Transaction receipt * * @example * ```typescript * // Find available nonce first * const [shortName, nonce] = await core.nameRegistry.searchShortName(avatar.address); * console.log('Available short name:', shortName.toString()); * * // Register it * const receipt = await avatar.profile.registerShortName(Number(nonce)); * console.log('Short name registered, tx hash:', receipt.hash); * ``` */ registerShortName: (nonce: number) => Promise; }; readonly history: { /** * Get transaction history for this avatar using cursor-based pagination * Returns incoming/outgoing transactions and minting events * * @param limit Number of transactions per page (default: 50) * @param sortOrder Sort order for results (default: 'DESC') * @returns PagedQuery instance for iterating through transactions * * @example * ```typescript * const query = avatar.history.getTransactions(20); * * // Get first page * await query.queryNextPage(); * query.currentPage.results.forEach(tx => { * console.log(`${tx.from} -> ${tx.to}: ${tx.circles} CRC`); * }); * * // Get next page if available * if (query.currentPage.hasMore) { * await query.queryNextPage(); * } * ``` */ getTransactions: (limit?: number) => Promise>; }; readonly transfer: { /** * Send Circles tokens directly to another address * This is a simple direct transfer without pathfinding * * Supports both ERC1155 (personal/group tokens) and ERC20 (wrapped tokens) transfers. * The token type is automatically detected and the appropriate transfer method is used. * * For transfers using pathfinding (which can use trust network and multiple token types), * use transfer.advanced() instead. * * @param to Recipient address * @param amount Amount to transfer (in atto-circles) * @param tokenAddress Token address to transfer (defaults to sender's personal token) * @param txData Optional transaction data (only used for ERC1155 transfers) * @returns Transaction receipt * * @example * ```typescript * // Send 100 of your personal CRC directly * const receipt = await avatar.transfer.direct('0x123...', BigInt(100e18)); * * // Send wrapped tokens * const receipt = await avatar.transfer.direct('0x123...', BigInt(100e18), '0xWrappedTokenAddress...'); * ``` */ direct: (to: Address, amount: bigint, tokenAddress?: Address, txData?: Uint8Array) => Promise; /** * Send tokens using pathfinding through the trust network * This enables transfers even when you don't have the recipient's token * * @param to Recipient address * @param amount Amount to transfer (in atto-circles or CRC) * @param options Advanced transfer options (pathfinding parameters) * @returns Transaction receipt * * @example * ```typescript * // Send 100 CRC using pathfinding * await avatar.transfer.advanced('0x123...', BigInt(100e18)); * * // With custom options * await avatar.transfer.advanced('0x123...', 100, { * maxTransfers: 5, * maxDistance: 3 * }); * ``` */ advanced: (to: Address, amount: number | bigint, options?: AdvancedTransferOptions) => Promise; /** * Get the maximum amount that can be transferred to an address using pathfinding * * @param to Recipient address * @returns Maximum transferable amount (in atto-circles) * * @example * ```typescript * const maxAmount = await avatar.transfer.getMaxAmount('0x123...'); * console.log(`Can transfer up to: ${maxAmount}`); * ``` */ getMaxAmount: (to: Address) => Promise; /** * Get the maximum amount that can be transferred with custom pathfinding options * * @param to Recipient address * @param options Pathfinding options (maxTransfers, maxDistance, etc.) * @returns Maximum transferable amount (in atto-circles) * * @example * ```typescript * const maxAmount = await avatar.transfer.getMaxAmountAdvanced('0x123...', { * maxTransfers: 3, * maxDistance: 2 * }); * ``` */ getMaxAmountAdvanced: (to: Address, options?: PathfindingOptions) => Promise; }; readonly wrap: { /** * Wrap personal CRC tokens as demurraged ERC20 tokens * * @param avatarAddress The avatar whose tokens to wrap * @param amount Amount to wrap (in atto-circles) * @returns Transaction receipt * * @example * ```typescript * // Wrap 100 CRC as demurraged ERC20 * const receipt = await avatar.wrap.asDemurraged(avatar.address, BigInt(100e18)); * ``` */ asDemurraged: (avatarAddress: Address, amount: bigint) => Promise; /** * Wrap personal CRC tokens as inflationary ERC20 tokens * * @param avatarAddress The avatar whose tokens to wrap * @param amount Amount to wrap (in atto-circles) * @returns Transaction receipt * * @example * ```typescript * // Wrap 100 CRC as inflationary ERC20 * const receipt = await avatar.wrap.asInflationary(avatar.address, BigInt(100e18)); * ``` */ asInflationary: (avatarAddress: Address, amount: bigint) => Promise; /** * Unwrap demurraged ERC20 tokens back to personal CRC * * @param tokenAddress The demurraged token address to unwrap * @param amount Amount to unwrap (in atto-circles) * @returns Transaction receipt * * @example * ```typescript * const receipt = await avatar.wrap.unwrapDemurraged('0xTokenAddress...', BigInt(100e18)); * ``` */ unwrapDemurraged: (tokenAddress: Address, amount: bigint) => Promise; /** * Unwrap inflationary ERC20 tokens back to personal CRC * * @param tokenAddress The inflationary token address to unwrap * @param amount Amount to unwrap (in atto-circles) * @returns Transaction receipt * * @example * ```typescript * const receipt = await avatar.wrap.unwrapInflationary('0xTokenAddress...', BigInt(100e18)); * ``` */ unwrapInflationary: (tokenAddress: Address, amount: bigint) => Promise; }; /** * Subscribe to Circles events for this avatar * Events are filtered to only include events related to this avatar's address * This method is idempotent - calling it multiple times will not create duplicate subscriptions * * @returns Promise that resolves when subscription is established * * @example * ```typescript * await avatar.subscribeToEvents(); * * // Listen for events * avatar.events.subscribe((event) => { * console.log('Event received:', event.$event, event); * * if (event.$event === 'CrcV2_PersonalMint') { * console.log('Minted:', event.amount); * } * }); * ``` */ subscribeToEvents(): Promise; /** * Unsubscribe from events * Cleans up the WebSocket connection and event listeners */ unsubscribeFromEvents(): void; /** * Transfer ERC1155 tokens using safeTransferFrom * @protected */ protected _transferErc1155(tokenAddress: Address, to: Address, amount: bigint, txData?: Uint8Array): Promise; /** * Transfer ERC20 tokens using the standard transfer function * @protected */ protected _transferErc20(to: Address, amount: bigint, tokenAddress: Address): Promise; } export {}; //# sourceMappingURL=CommonAvatar.d.ts.map