UNPKG

@aptos-labs/ts-sdk

Version:
1,213 lines 54.8 kB
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0
import { getAptosFullNode, getPageWithObfuscatedCursor, paginateWithCursor, paginateWithObfuscatedCursor, } from "../client/index.js";
import { anyPublicKeyVariantToString, } from "../types/index.js";
import { AccountAddress } from "../core/accountAddress.js";
import { Account, Ed25519Account, MultiEd25519Account, MultiKeyAccount, SingleKeyAccount } from "../account/index.js";
import { isKeylessSigner } from "../account/keylessSigner.js";
import { AnyPublicKey } from "../core/crypto/singleKey.js";
import { Ed25519PublicKey } from "../core/crypto/ed25519.js";
import { MultiEd25519PublicKey } from "../core/crypto/multiEd25519.js";
import { AbstractMultiKey, MultiKey } from "../core/crypto/multiKey.js";
import { queryIndexer } from "./general.js";
import { getModule as getModuleUtil, getInfo as getInfoUtil } from "./utils/index.js";
import { GetAccountCoinsCount, GetAccountCoinsData, GetAccountCollectionsWithOwnedTokens, GetObjectData, GetAccountOwnedTokens, GetAccountOwnedTokensFromCollection, GetAccountTokensCount, GetAccountTransactionsCount, GetAuthKeysForPublicKey, GetAccountAddressesForAuthKey, } from "../types/generated/queries.js";
import { Secp256k1PrivateKey } from "../core/crypto/secp256k1.js";
import { Ed25519PrivateKey } from "../core/crypto/ed25519.js";
import { AuthenticationKey } from "../core/authenticationKey.js";
import { createObjectAddress } from "../core/account/utils/address.js";
import { Hex } from "../core/hex.js";
import { getTableItem } from "./table.js";
import { APTOS_COIN } from "../utils/index.js";
import { memoizeAsync } from "../utils/memoize.js";
import { AptosApiError } from "../errors/index.js";
import { Deserializer, U8, MoveVector } from "../bcs/index.js";
import { generateTransaction } from "./transactionSubmission.js";
import { RotationProofChallenge, TypeTagU8, TypeTagVector, } from "../transactions/index.js";
import { accountPublicKeyToBaseAccountPublicKey, accountPublicKeyToSigningScheme } from "../core/crypto/utils.js";
/**
 * Retrieves account information for a specified account address.
 *
 * @param args - The arguments for retrieving account information.
 * @param args.aptosConfig - The configuration object for Aptos.
 * @param args.accountAddress - The address of the account to retrieve information for.
 * @group Implementation
 */
export async function getInfo(args) {
    return getInfoUtil(args);
}
/**
 * Retrieves the modules associated with a specified account address.
 *
 * @param args - The arguments for retrieving modules.
 * @param args.aptosConfig - The configuration for connecting to the Aptos blockchain.
 * @param args.accountAddress - The address of the account whose modules are to be retrieved.
 * @param args.options - Optional parameters for pagination and ledger version.
 * @param args.options.limit - The maximum number of modules to retrieve (default is 1000).
 * @param args.options.offset - The starting point for pagination.  Note, this is obfuscated and is not an index.
 * @param args.options.ledgerVersion - The specific ledger version to query.
 * @group Implementation
 */
export async function getModules(args) {
    const { aptosConfig, accountAddress, options } = args;
    return paginateWithObfuscatedCursor({
        aptosConfig,
        originMethod: "getModules",
        path: `accounts/${AccountAddress.from(accountAddress).toString()}/modules`,
        params: {
            ledger_version: options?.ledgerVersion,
            limit: options?.limit ?? 1000,
        },
    });
}
/**
 * Retrieves the modules associated with a specified account address.
 *
 * @param args - The arguments for retrieving modules.
 * @param args.aptosConfig - The configuration for connecting to the Aptos blockchain.
 * @param args.accountAddress - The address of the account whose modules are to be retrieved.
 * @param args.options - Optional parameters for pagination and ledger version.
 * @param args.options.cursor - The starting point for pagination.  Note, this is obfuscated and is not an index.
 * @param args.options.limit - The maximum number of modules to retrieve (default is 100).
 * @param args.options.ledgerVersion - The specific ledger version to query.
 * @group Implementation
 */
export async function getModulesPage(args) {
    const { aptosConfig, accountAddress, options } = args;
    const { response, cursor } = await getPageWithObfuscatedCursor({
        aptosConfig,
        originMethod: "getModulesPage",
        path: `accounts/${AccountAddress.from(accountAddress).toString()}/modules`,
        params: {
            ledger_version: options?.ledgerVersion,
            cursor: options?.cursor,
            limit: options?.limit ?? 100,
        },
    });
    return { modules: response.data, cursor };
}
/**
 * Queries for a move module given an account address and module name.
 * This function can help you retrieve the module's ABI and other relevant information.
 *
 * @param args - The arguments for retrieving the module.
 * @param args.aptosConfig - The configuration for the Aptos client.
 * @param args.accountAddress - The account address in hex-encoded 32 byte format.
 * @param args.moduleName - The name of the module to retrieve.
 * @param args.options - Optional parameters for the request.
 * @param args.options.ledgerVersion - Specifies the ledger version of transactions. By default, the latest version will be used.
 * @returns The move module.
 * @group Implementation
 */
export async function getModule(args) {
    return getModuleUtil(args);
}
/**
 * Retrieves a list of transactions associated with a specific account address.
 * This function allows you to paginate through the transactions for better performance and usability.
 *
 * @param args - The arguments for retrieving transactions.
 * @param args.aptosConfig - The configuration settings for Aptos.
 * @param args.accountAddress - The account address for which to retrieve transactions.
 * @param args.options - Optional pagination parameters.
 * @param args.options.offset - The starting point for pagination.
 * @param args.options.limit - The maximum number of transactions to retrieve.
 * @group Implementation
 */
export async function getTransactions(args) {
    const { aptosConfig, accountAddress, options } = args;
    return paginateWithCursor({
        aptosConfig,
        originMethod: "getTransactions",
        path: `accounts/${AccountAddress.from(accountAddress).toString()}/transactions`,
        params: { start: options?.offset, limit: options?.limit },
    });
}
/**
 * Retrieves a list of resources associated with a specific account address.
 *
 * @param args - The arguments for retrieving resources.
 * @param args.aptosConfig - The configuration settings for Aptos.
 * @param args.accountAddress - The address of the account to fetch resources for.
 * @param args.options - Optional pagination and ledger version parameters.
 * @param args.options.limit - The maximum number of resources to retrieve (default is 999).
 * @param args.options.ledgerVersion - The specific ledger version to query.
 * @group Implementation
 */
export async function getResources(args) {
    const { aptosConfig, accountAddress, options } = args;
    return paginateWithObfuscatedCursor({
        aptosConfig,
        originMethod: "getResources",
        path: `accounts/${AccountAddress.from(accountAddress).toString()}/resources`,
        params: {
            ledger_version: options?.ledgerVersion,
            limit: options?.limit ?? 999,
        },
    });
}
/**
 * Retrieves a page of resources associated with a specific account address.
 *
 * @param args - The arguments for retrieving resources.
 * @param args.aptosConfig - The configuration settings for Aptos.
 * @param args.accountAddress - The address of the account to fetch resources for.
 * @param args.options - Optional pagination and ledger version parameters.
 * @param args.options.cursor - The starting point for pagination.  Note, this is obfuscated and is not an index.
 * @param args.options.limit - The maximum number of resources to retrieve (default is 100).
 * @param args.options.ledgerVersion - The specific ledger version to query.
 * @group Implementation
 */
export async function getResourcesPage(args) {
    const { aptosConfig, accountAddress, options } = args;
    const { response, cursor } = await getPageWithObfuscatedCursor({
        aptosConfig,
        originMethod: "getResourcesPage",
        path: `accounts/${AccountAddress.from(accountAddress).toString()}/resources`,
        params: {
            ledger_version: options?.ledgerVersion,
            cursor: options?.cursor,
            limit: options?.limit ?? 100,
        },
    });
    return { resources: response.data, cursor };
}
/**
 * Retrieves a specific resource of a given type for the specified account address.
 *
 * @param args - The arguments for retrieving the resource.
 * @param args.aptosConfig - The configuration settings for Aptos.
 * @param args.accountAddress - The address of the account from which to retrieve the resource.
 * @param args.resourceType - The type of the resource to retrieve, specified as a MoveStructId.
 * @param args.options - Optional parameters for specifying the ledger version.
 * @group Implementation
 */
export async function getResource(args) {
    const { aptosConfig, accountAddress, resourceType, options } = args;
    const { data } = await getAptosFullNode({
        aptosConfig,
        originMethod: "getResource",
        path: `accounts/${AccountAddress.from(accountAddress).toString()}/resource/${resourceType}`,
        params: { ledger_version: options?.ledgerVersion },
    });
    // TODO: Fix type checking, so cast is unnecessary
    return data.data;
}
export async function getResourceFallible(args) {
    try {
        return await getResource(args);
    }
    catch (error) {
        // explicitly return null if there is no resource
        if (error?.status === 404 && error?.data?.error_code === "resource_not_found") {
            return null;
        }
        throw error;
    }
}
/**
 * Retrieves the original account address associated with a given authentication key, which is useful for handling key rotations.
 *
 * @param args - The arguments for the lookup.
 * @param args.aptosConfig - The configuration for the Aptos client.
 * @param args.authenticationKey - The authentication key for which to look up the original address.
 * @param args.options - Optional parameters for specifying the ledger version.
 * @returns The original account address or the provided authentication key address if not found.
 * @throws Throws an error if the lookup fails for reasons other than the address not being found.
 * @group Implementation
 */
export async function lookupOriginalAccountAddress(args) {
    const { aptosConfig, authenticationKey, options } = args;
    const resource = await getResource({
        aptosConfig,
        accountAddress: "0x1",
        resourceType: "0x1::account::OriginatingAddress",
        options,
    });
    const { address_map: { handle }, } = resource;
    const authKeyAddress = AccountAddress.from(authenticationKey);
    // If the address is not found in the address map, which means its not rotated
    // then return the address as is
    try {
        const originalAddress = await getTableItem({
            aptosConfig,
            handle,
            data: {
                key: authKeyAddress.toString(),
                key_type: "address",
                value_type: "address",
            },
            options,
        });
        return AccountAddress.from(originalAddress);
    }
    catch (err) {
        if (err instanceof AptosApiError && err.data.error_code === "table_item_not_found") {
            return authKeyAddress;
        }
        throw err;
    }
}
/**
 * Fetches the on-chain `authentication_key` for an account address and memoizes it for ~1 hour,
 * keyed by `(network or fullnode URL, address)`. Used by the encrypted-transaction builder to
 * derive auth keys when the caller does not pass them explicitly. Callers that just rotated their
 * key and need an immediate fresh read should pass the auth key explicitly instead of relying on
 * this cache.
 *
 * If the address has no `0x1::account::Account` resource on chain (a brand-new account, or a light
 * account with balance/objects but no explicit resource), returns the address bytes as the
 * authentication key — matching the chain's account-creation convention (see
 * [`doesAccountExistAtAddress`]). This makes encrypted-transaction builds work for not-yet-created
 * signers (e.g., fee-payer sponsorship of an uncreated sender).
 */
export async function fetchAndCacheAuthKeyForAddress(args) {
    const { aptosConfig, accountAddress } = args;
    const address = AccountAddress.from(accountAddress);
    const addr = address.toString();
    const cacheKey = `auth-key-${aptosConfig.fullnode ?? aptosConfig.network}-${addr}`;
    return memoizeAsync(async () => {
        try {
            const info = await getInfoUtil({ aptosConfig, accountAddress: addr });
            return new AuthenticationKey({ data: info.authentication_key });
        }
        catch (err) {
            if (err instanceof AptosApiError && err.data?.error_code === "account_not_found") {
                // Chain convention: with no Account resource the auth key is the address itself.
                return new AuthenticationKey({ data: address.toUint8Array() });
            }
            throw err;
        }
    }, cacheKey, 60 * 60 * 1000)();
}
/**
 * Retrieves the count of tokens owned by a specific account address.
 *
 * @param args - The arguments for retrieving the account tokens count.
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.accountAddress - The address of the account for which to count the tokens.
 * @returns The count of tokens owned by the specified account.
 * @group Implementation
 */
export async function getAccountTokensCount(args) {
    const { aptosConfig, accountAddress } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const whereCondition = {
        owner_address: { _eq: address },
        amount: { _gt: 0 },
    };
    const graphqlQuery = {
        query: GetAccountTokensCount,
        variables: { where_condition: whereCondition },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountTokensCount",
    });
    // commonjs (aka cjs) doesn't handle Nullish Coalescing for some reason
    // might be because of how ts infer the graphql generated scheme type
    return data.current_token_ownerships_v2_aggregate.aggregate
        ? data.current_token_ownerships_v2_aggregate.aggregate.count
        : 0;
}
/**
 * Retrieves the tokens owned by a specified account address.
 *
 * @param args - The arguments for retrieving the account's tokens.
 * @param args.aptosConfig - The configuration for the Aptos client.
 * @param args.accountAddress - The address of the account whose tokens are being queried.
 * @param args.options - Optional parameters for filtering and pagination.
 * @param args.options.tokenStandard - The specific token standard to filter the results.
 * @param args.options.offset - The number of records to skip before starting to collect the result set.
 * @param args.options.limit - The maximum number of records to return.
 * @param args.options.orderBy - The criteria for ordering the results.
 * @returns A promise that resolves to the current token ownerships of the specified account.
 * @group Implementation
 */
export async function getAccountOwnedTokens(args) {
    const { aptosConfig, accountAddress, options } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const whereCondition = {
        owner_address: { _eq: address },
        amount: { _gt: 0 },
    };
    if (options?.tokenStandard) {
        whereCondition.token_standard = { _eq: options?.tokenStandard };
    }
    const graphqlQuery = {
        query: GetAccountOwnedTokens,
        variables: {
            where_condition: whereCondition,
            offset: options?.offset,
            limit: options?.limit,
            order_by: options?.orderBy,
        },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountOwnedTokens",
    });
    return data.current_token_ownerships_v2;
}
/**
 * Retrieves the tokens owned by a specific account from a particular collection address.
 *
 * @param args - The parameters required to fetch the owned tokens.
 * @param args.aptosConfig - The Aptos configuration object.
 * @param args.accountAddress - The address of the account whose tokens are being queried.
 * @param args.collectionAddress - The address of the collection from which tokens are being retrieved.
 * @param args.options - Optional parameters for filtering and pagination, including token standard, pagination arguments, and
 * order by options.
 * @group Implementation
 */
export async function getAccountOwnedTokensFromCollectionAddress(args) {
    const { aptosConfig, accountAddress, collectionAddress, options } = args;
    const ownerAddress = AccountAddress.from(accountAddress).toStringLong();
    const collAddress = AccountAddress.from(collectionAddress).toStringLong();
    const whereCondition = {
        owner_address: { _eq: ownerAddress },
        current_token_data: { collection_id: { _eq: collAddress } },
        amount: { _gt: 0 },
    };
    if (options?.tokenStandard) {
        whereCondition.token_standard = { _eq: options?.tokenStandard };
    }
    const graphqlQuery = {
        query: GetAccountOwnedTokensFromCollection,
        variables: {
            where_condition: whereCondition,
            offset: options?.offset,
            limit: options?.limit,
            order_by: options?.orderBy,
        },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountOwnedTokensFromCollectionAddress",
    });
    return data.current_token_ownerships_v2;
}
/**
 * Retrieves the collections owned by a specified account along with the tokens in those collections.
 *
 * @param args - The arguments for the function.
 * @param args.aptosConfig - The configuration for the Aptos client.
 * @param args.accountAddress - The address of the account whose collections are being queried.
 * @param args.options - Optional parameters for filtering and pagination.
 * @param args.options.tokenStandard - An optional token standard to filter the collections.
 * @param args.options.offset - An optional offset for pagination.
 * @param args.options.limit - An optional limit for the number of results returned.
 * @param args.options.orderBy - An optional parameter to specify the order of the results.
 * @group Implementation
 */
export async function getAccountCollectionsWithOwnedTokens(args) {
    const { aptosConfig, accountAddress, options } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const whereCondition = {
        owner_address: { _eq: address },
    };
    if (options?.tokenStandard) {
        whereCondition.current_collection = {
            token_standard: { _eq: options?.tokenStandard },
        };
    }
    const graphqlQuery = {
        query: GetAccountCollectionsWithOwnedTokens,
        variables: {
            where_condition: whereCondition,
            offset: options?.offset,
            limit: options?.limit,
            order_by: options?.orderBy,
        },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountCollectionsWithOwnedTokens",
    });
    return data.current_collection_ownership_v2_view;
}
/**
 * Retrieves the count of transactions associated with a specified account.
 *
 * @param args - The arguments for the function.
 * @param args.aptosConfig - The configuration settings for Aptos.
 * @param args.accountAddress - The address of the account for which to retrieve the transaction count.
 * @returns The number of transactions associated with the specified account.
 * @group Implementation
 */
export async function getAccountTransactionsCount(args) {
    const { aptosConfig, accountAddress } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const graphqlQuery = {
        query: GetAccountTransactionsCount,
        variables: { address },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountTransactionsCount",
    });
    // commonjs (aka cjs) doesn't handle Nullish Coalescing for some reason
    // might be because of how ts infer the graphql generated scheme type
    return data.account_transactions_aggregate.aggregate ? data.account_transactions_aggregate.aggregate.count : 0;
}
/**
 * Retrieves the amount of a specific coin held by an account.
 *
 * @param args - The parameters for the request.
 * @param args.aptosConfig - The Aptos configuration object.
 * @param args.accountAddress - The address of the account to query.
 * @param args.coinType - Optional; the type of coin to check the amount for.
 * @param args.faMetadataAddress - Optional; the address of the fungible asset metadata.
 * @returns The amount of the specified coin held by the account, or 0 if none is found.
 * @throws Error if neither coinType nor faMetadataAddress is provided.
 * @group Implementation
 */
export async function getAccountCoinAmount(args) {
    const { aptosConfig, accountAddress, coinType, faMetadataAddress } = args;
    let coinAssetType = coinType;
    let faAddress;
    if (coinType !== undefined && faMetadataAddress !== undefined) {
        faAddress = AccountAddress.from(faMetadataAddress).toStringLong();
    }
    else if (coinType !== undefined && faMetadataAddress === undefined) {
        // TODO Move to a separate function as defined in the AIP for coin migration
        if (coinType === APTOS_COIN) {
            faAddress = AccountAddress.A.toStringLong();
        }
        else {
            faAddress = createObjectAddress(AccountAddress.A, coinType).toStringLong();
        }
    }
    else if (coinType === undefined && faMetadataAddress !== undefined) {
        const addr = AccountAddress.from(faMetadataAddress);
        faAddress = addr.toStringLong();
        if (addr === AccountAddress.A) {
            coinAssetType = APTOS_COIN;
        }
        // The paired CoinType should be populated outside of this function in another
        // async call. We cannot do this internally due to dependency cycles issue.
    }
    else {
        throw new Error("Either coinType, fungibleAssetAddress, or both must be provided");
    }
    const address = AccountAddress.from(accountAddress).toStringLong();
    // Search by fungible asset address, unless it has a coin it migrated from
    let where = { asset_type: { _eq: faAddress } };
    if (coinAssetType !== undefined) {
        where = { asset_type: { _in: [coinAssetType, faAddress] } };
    }
    const data = await getAccountCoinsData({
        aptosConfig,
        accountAddress: address,
        options: {
            where,
        },
    });
    // commonjs (aka cjs) doesn't handle Nullish Coalescing for some reason
    // might be because of how ts infer the graphql generated scheme type
    return data[0] ? data[0].amount : 0;
}
/**
 * Retrieves the current fungible asset balances for a specified account.
 *
 * @param args - The arguments for retrieving account coins data.
 * @param args.aptosConfig - The configuration for connecting to the Aptos network.
 * @param args.accountAddress - The address of the account for which to retrieve coin data.
 * @param args.options - Optional parameters for pagination and filtering the results.
 * @param args.options.offset - The number of items to skip before starting to collect the result set.
 * @param args.options.limit - The maximum number of items to return.
 * @param args.options.orderBy - The criteria for ordering the results.
 * @param args.options.where - Conditions to filter the results based on the current fungible asset balances.
 * @group Implementation
 */
export async function getAccountCoinsData(args) {
    const { aptosConfig, accountAddress, options } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const whereCondition = {
        ...options?.where,
        owner_address: { _eq: address },
    };
    const graphqlQuery = {
        query: GetAccountCoinsData,
        variables: {
            where_condition: whereCondition,
            offset: options?.offset,
            limit: options?.limit,
            order_by: options?.orderBy,
        },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountCoinsData",
    });
    return data.current_fungible_asset_balances;
}
/**
 * Retrieves the count of fungible asset coins held by a specified account.
 *
 * @param args - The arguments for the function.
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.accountAddress - The address of the account for which to retrieve the coin count.
 * @throws Error if the count of account coins cannot be retrieved.
 * @group Implementation
 */
export async function getAccountCoinsCount(args) {
    const { aptosConfig, accountAddress } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const graphqlQuery = {
        query: GetAccountCoinsCount,
        variables: { address },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountCoinsCount",
    });
    if (!data.current_fungible_asset_balances_aggregate.aggregate) {
        throw new Error("Failed to get the count of account coins");
    }
    return data.current_fungible_asset_balances_aggregate.aggregate.count;
}
/**
 * Retrieves an account's balance for the given asset via the fullnode REST API.
 *
 * - `asset` may be a coin type (Move struct ID, e.g. `0x1::aptos_coin::AptosCoin`) or an FA metadata address.
 * - Calls: `GET /accounts/{accountAddress}/balance/{asset}` and returns the numeric balance.
 *
 * @param args - The parameters for the request.
 * @param args.aptosConfig - The Aptos configuration object.
 * @param args.accountAddress - The account address to query.
 * @param args.asset - The asset identifier (coin type or FA metadata address).
 * @returns The balance as a number.
 * @group Implementation
 */
export async function getBalance(args) {
    const { aptosConfig, accountAddress, asset } = args;
    const response = await getAptosFullNode({
        aptosConfig,
        originMethod: "getBalance",
        path: `accounts/${accountAddress}/balance/${asset}`,
        params: {
            accountAddress: accountAddress.toString(),
            asset: asset instanceof Uint8Array ? AccountAddress.from(asset).toString() : asset.toString(),
        },
    });
    return parseInt(response.data.toString(), 10);
}
/**
 * Retrieves the objects owned by a specified account.
 *
 * @param args - The parameters for the request.
 * @param args.aptosConfig - The configuration for the Aptos client.
 * @param args.accountAddress - The address of the account whose owned objects are to be retrieved.
 * @param args.options - Optional parameters for pagination and ordering of the results.
 * @param args.options.offset - The number of items to skip before starting to collect the result set.
 * @param args.options.limit - The maximum number of items to return.
 * @param args.options.orderBy - The criteria to order the results by.
 * @returns A promise that resolves to the current objects owned by the specified account.
 * @group Implementation
 */
export async function getAccountOwnedObjects(args) {
    const { aptosConfig, accountAddress, options } = args;
    const address = AccountAddress.from(accountAddress).toStringLong();
    const whereCondition = {
        owner_address: { _eq: address },
    };
    const graphqlQuery = {
        query: GetObjectData,
        variables: {
            where_condition: whereCondition,
            offset: options?.offset,
            limit: options?.limit,
            order_by: options?.orderBy,
        },
    };
    const data = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountOwnedObjects",
    });
    return data.current_objects;
}
/**
 * Derives an account from the provided private key and Aptos configuration.
 *
 * This function queries all owned accounts for the provided private key and returns the most
 * recently used account. If no account is found, it will throw an error unless `throwIfNoAccountFound` is set to false.
 *
 * If `throwIfNoAccountFound` is set to false, the function will return the default account for the private key via `Account.fromPrivateKey`.
 *
 * NOTE: There is a potential issue once the unified single signer scheme is adopted by the community.
 * Because one could create two accounts with the same private key with this new authenticator type,
 * we'll need to determine the order in which we look up the accounts: first unified scheme and then legacy scheme,
 * or first legacy scheme and then unified scheme.
 *
 * @param args - The arguments for deriving the account.
 * @param args.aptosConfig - The Aptos configuration used for account lookup.
 * @param args.privateKey - The private key used to derive the account.
 * @param args.options.throwIfNoAccountFound - If true, throw an error if no existing account is found on chain. Default is false.
 * @throws Error if the account cannot be derived from the private key.
 * @group Implementation
 * @deprecated Note that more inspection is needed by the user to determine which account exists on-chain
 */
export async function deriveAccountFromPrivateKey(args) {
    const { aptosConfig, privateKey, options } = args;
    const throwIfNoAccountFound = options?.throwIfNoAccountFound ?? false;
    const accounts = await deriveOwnedAccountsFromPrivateKey({ aptosConfig, privateKey });
    if (accounts.length === 0) {
        if (throwIfNoAccountFound) {
            throw new Error(`No existing account found for private key.`);
        }
        // If no account is found, return the default account. This is a legacy account for Ed25519 private keys.
        return Account.fromPrivateKey({ privateKey });
    }
    return accounts[0];
}
/**
 * Checks if an account exists by verifying its information against the Aptos blockchain.
 *
 * @param args - The arguments for the function.
 * @param args.aptosConfig - The configuration for connecting to the Aptos blockchain.
 * @param args.authKey - The authentication key used to derive the account address.
 * @returns A promise that resolves to a boolean indicating whether the account exists.
 *
 * @throws Throws an Error if there is an issue while looking for account information.
 * @group Implementation
 */
export async function isAccountExist(args) {
    const { aptosConfig, authKey } = args;
    const accountAddress = await lookupOriginalAccountAddress({
        aptosConfig,
        authenticationKey: authKey.derivedAddress(),
    });
    return doesAccountExistAtAddress({ aptosConfig, accountAddress });
}
/**
 * Checks if an account exists at a given address.
 *
 * @param args - The arguments for checking account existence.
 * @param args.aptosConfig - The configuration for the Aptos client.
 * @param args.accountAddress - The address of the account to check.
 * @param args.options.withAuthKey - An optional authentication key which will also be checked against if provided.
 * @returns A promise that resolves to a boolean indicating whether the account exists.
 * @group Implementation
 */
async function doesAccountExistAtAddress(args) {
    const { aptosConfig, accountAddress, options } = args;
    try {
        // Get the account resources and the balance of the account.  We need to check both because
        // an account resource can exist with 0 balance and a balance can exist without an account resource (light accounts).
        const [accountResource, ownedObjects] = await Promise.all([
            getResourceFallible({
                aptosConfig,
                accountAddress,
                resourceType: "0x1::account::Account",
            }),
            getAccountOwnedObjects({
                aptosConfig,
                accountAddress,
                options: {
                    limit: 1,
                },
            }),
        ]);
        // If the account resource is not found and the balance is 0, then the account does not exist.
        if (!accountResource && ownedObjects.length === 0) {
            return false;
        }
        // If no auth key is provided as an argument, return true.
        if (!options?.withAuthKey) {
            return true;
        }
        // Get the auth key from the account resource if it exists. If the account resource does not exist,
        // then the auth key is the account address by default.
        let authKey;
        if (accountResource) {
            authKey = accountResource.authentication_key;
        }
        else {
            authKey = accountAddress.toStringLong();
        }
        if (authKey !== options.withAuthKey.toString()) {
            return false;
        }
        // Else the account exists and the auth key matches.
        return true;
    }
    catch (error) {
        throw new Error(`Error while checking if account exists at ${accountAddress.toString()}: ${error}`);
    }
}
// Lazy: instantiating TypeTagU8 at module-init time creates an ESM circular
// import (structEnumParser → internal/account → transactions/index → typeTag)
// where TypeTagU8 may not yet be a constructor when this file evaluates.
// Building the ABI on first use sidesteps the order dependency.
let _rotateAuthKeyAbi;
function rotateAuthKeyAbi() {
    if (!_rotateAuthKeyAbi) {
        _rotateAuthKeyAbi = {
            typeParameters: [],
            parameters: [
                new TypeTagU8(),
                TypeTagVector.u8(),
                new TypeTagU8(),
                TypeTagVector.u8(),
                TypeTagVector.u8(),
                TypeTagVector.u8(),
            ],
        };
    }
    return _rotateAuthKeyAbi;
}
/**
 * Rotates the authentication key for a given account.
 *
 * @param args - The arguments for rotating the authentication key.
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.fromAccount - The account from which the authentication key will be rotated.
 * @param args.toAccount - (Optional) The target account to rotate to. Required if not using toNewPrivateKey.
 * @param args.toNewPrivateKey - (Optional) The new private key to rotate to. Required if not using toAccount.
 *
 * @remarks
 * This function supports three modes of rotation:
 * 1. Using a target Account object (toAccount)
 * 2. Using a new private key (toNewPrivateKey)
 *
 * @returns A simple transaction object that can be submitted to the network.
 * @throws Error if the rotation fails or verification fails.
 *
 * @group Implementation
 */
export async function rotateAuthKey(args) {
    const { aptosConfig, fromAccount, options } = args;
    if ("toNewPrivateKey" in args) {
        return rotateAuthKeyWithChallenge({
            aptosConfig,
            fromAccount,
            toNewPrivateKey: args.toNewPrivateKey,
            options,
        });
    }
    if ("toAccount" in args) {
        if (args.toAccount instanceof Ed25519Account) {
            return rotateAuthKeyWithChallenge({
                aptosConfig,
                fromAccount,
                toNewPrivateKey: args.toAccount.privateKey,
                options,
            });
        }
        return rotateAuthKeyWithChallenge({ aptosConfig, fromAccount, toAccount: args.toAccount, options });
    }
    throw new Error("Invalid arguments");
}
async function rotateAuthKeyWithChallenge(args) {
    const { aptosConfig, fromAccount, options } = args;
    const accountInfo = await getInfo({
        aptosConfig,
        accountAddress: fromAccount.accountAddress,
    });
    let newAccount;
    if ("toNewPrivateKey" in args) {
        newAccount = Account.fromPrivateKey({ privateKey: args.toNewPrivateKey, legacy: true });
    }
    else {
        newAccount = args.toAccount;
    }
    const challenge = new RotationProofChallenge({
        sequenceNumber: BigInt(accountInfo.sequence_number),
        originator: fromAccount.accountAddress,
        currentAuthKey: AccountAddress.from(accountInfo.authentication_key),
        newPublicKey: newAccount.publicKey,
    });
    // Sign the challenge
    const challengeHex = challenge.bcsToBytes();
    const proofSignedByCurrentKey = fromAccount.sign(challengeHex);
    const proofSignedByNewKey = newAccount.sign(challengeHex);
    // Generate transaction
    return generateTransaction({
        aptosConfig,
        sender: fromAccount.accountAddress,
        data: {
            function: "0x1::account::rotate_authentication_key",
            functionArguments: [
                new U8(fromAccount.signingScheme), // from scheme
                MoveVector.U8(fromAccount.publicKey.toUint8Array()),
                new U8(newAccount.signingScheme), // to scheme
                MoveVector.U8(newAccount.publicKey.toUint8Array()),
                MoveVector.U8(proofSignedByCurrentKey.toUint8Array()),
                MoveVector.U8(proofSignedByNewKey.toUint8Array()),
            ],
            abi: rotateAuthKeyAbi(),
        },
        options,
    });
}
let _rotateAuthKeyUnverifiedAbi;
function rotateAuthKeyUnverifiedAbi() {
    if (!_rotateAuthKeyUnverifiedAbi) {
        _rotateAuthKeyUnverifiedAbi = {
            typeParameters: [],
            parameters: [new TypeTagU8(), TypeTagVector.u8()],
        };
    }
    return _rotateAuthKeyUnverifiedAbi;
}
/**
 * Rotates the authentication key for a given account without verifying the new key.
 *
 * @param args - The arguments for rotating the authentication key.
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.fromAccount - The account from which the authentication key will be rotated.
 * @param args.toNewPublicKey - The new public key to rotate to.
 * @returns A simple transaction object that can be submitted to the network.
 * @throws Error if the rotation fails or verification fails.
 *
 * @group Implementation
 */
export async function rotateAuthKeyUnverified(args) {
    const { aptosConfig, fromAccount, toNewPublicKey, options } = args;
    return generateTransaction({
        aptosConfig,
        sender: fromAccount.accountAddress,
        data: {
            function: "0x1::account::rotate_authentication_key_from_public_key",
            functionArguments: [
                new U8(accountPublicKeyToSigningScheme(toNewPublicKey)), // to scheme
                MoveVector.U8(accountPublicKeyToBaseAccountPublicKey(toNewPublicKey).toUint8Array()),
            ],
            abi: rotateAuthKeyUnverifiedAbi(),
        },
        options,
    });
}
export async function getAccountsForPublicKey(args) {
    const { aptosConfig, publicKey, options } = args;
    const noMultiKey = options?.noMultiKey ?? false;
    if (noMultiKey && publicKey instanceof AbstractMultiKey) {
        throw new Error("Multi-key accounts are not supported when noMultiKey is true.");
    }
    const allPublicKeys = [publicKey];
    // For Ed25519, we add the both the legacy Ed25519PublicKey and the new AnyPublicKey form.
    if (publicKey instanceof AnyPublicKey && publicKey.publicKey instanceof Ed25519PublicKey) {
        allPublicKeys.push(publicKey.publicKey);
    }
    else if (publicKey instanceof Ed25519PublicKey) {
        allPublicKeys.push(new AnyPublicKey(publicKey));
    }
    // Run both operations in parallel
    const [defaultAccountData, multiPublicKeys] = await Promise.all([
        // Check the provided public key for the default account. In the case of Ed25519, this will check both the legacy Ed25519PublicKey
        // and the AnyPublicKey form and may an existing account for each.
        Promise.all(allPublicKeys.map(async (publicKey) => {
            const addressAndLastTxnVersion = await getDefaultAccountInfoForPublicKey({ aptosConfig, publicKey });
            if (addressAndLastTxnVersion) {
                return { ...addressAndLastTxnVersion, publicKey };
            }
            return undefined;
        })),
        // Get multi-keys for the provided public key if not already a multi-key.
        !(publicKey instanceof AbstractMultiKey) && !noMultiKey
            ? getMultiKeysForPublicKey({ aptosConfig, publicKey, options })
            : Promise.resolve([]),
    ]);
    const result = [];
    // Add any default accounts that exist to the result.
    for (const data of defaultAccountData) {
        if (data) {
            result.push(data);
        }
    }
    // Add any multi-keys to allPublicKeys
    allPublicKeys.push(...multiPublicKeys);
    // Get a map of the auth key to the public key for all public keys.
    const authKeyToPublicKey = new Map(allPublicKeys.map((key) => [key.authKey().toString(), key]));
    // Get the account addresses for the auth keys.
    const authKeyAccountAddressPairs = await getAccountAddressesForAuthKeys({
        aptosConfig,
        authKeys: allPublicKeys.map((key) => key.authKey()),
        options,
    });
    for (const authKeyAccountAddressPair of authKeyAccountAddressPairs) {
        // Skip if the account address is already in the result.
        // This can happen in the rare edge case where the default account has been rotated but has been rotated back to the original auth key.
        if (result.find((r) => r.accountAddress === authKeyAccountAddressPair.accountAddress)) {
            continue;
        }
        // Get the public key for the auth key using the map we created earlier.
        const publicKey = authKeyToPublicKey.get(authKeyAccountAddressPair.authKey.toString());
        if (!publicKey) {
            throw new Error(`No publicKey found for authentication key ${authKeyAccountAddressPair.authKey}. This should never happen.`);
        }
        result.push({
            accountAddress: authKeyAccountAddressPair.accountAddress,
            publicKey,
            lastTransactionVersion: authKeyAccountAddressPair.lastTransactionVersion,
        });
    }
    // Sort the result by the last transaction version in descending order (most recent first).
    return result.sort((a, b) => b.lastTransactionVersion - a.lastTransactionVersion);
}
export async function deriveOwnedAccountsFromSigner(args) {
    const { aptosConfig, signer, options } = args;
    if (signer instanceof Ed25519PrivateKey || signer instanceof Secp256k1PrivateKey) {
        return deriveOwnedAccountsFromPrivateKey({ aptosConfig, privateKey: signer, options });
    }
    if (signer instanceof Ed25519Account || signer instanceof SingleKeyAccount) {
        return deriveOwnedAccountsFromPrivateKey({ aptosConfig, privateKey: signer.privateKey, options });
    }
    if (isKeylessSigner(signer)) {
        return deriveOwnedAccountsFromKeylessSigner({
            aptosConfig,
            keylessAccount: signer,
            options,
        });
    }
    if (signer instanceof MultiKeyAccount) {
        if (signer.signers.length === 1) {
            return deriveOwnedAccountsFromSigner({ aptosConfig, signer: signer.signers[0], options });
        }
    }
    if (signer instanceof MultiEd25519Account) {
        if (signer.signers.length === 1) {
            return deriveOwnedAccountsFromPrivateKey({ aptosConfig, privateKey: signer.signers[0], options });
        }
    }
    throw new Error("Unknown signer type");
}
async function deriveOwnedAccountsFromKeylessSigner(args) {
    const { aptosConfig, keylessAccount, options } = args;
    const addressesAndPublicKeys = await getAccountsForPublicKey({
        aptosConfig,
        publicKey: keylessAccount.getAnyPublicKey(),
        options,
    });
    const keylessAccountParams = {
        proof: keylessAccount.proofOrPromise,
        jwt: keylessAccount.jwt,
        ephemeralKeyPair: keylessAccount.ephemeralKeyPair,
        pepper: keylessAccount.pepper,
        verificationKeyHash: keylessAccount.verificationKeyHash,
    };
    // Structural discriminator: `FederatedKeylessPublicKey` has a `jwkAddress`
    // field; plain `KeylessPublicKey` does not. Avoids pulling the concrete
    // keyless account classes (and poseidon-lite) into the static import graph.
    const isFederated = "jwkAddress" in keylessAccount.publicKey;
    const accounts = [];
    for (const { accountAddress, publicKey } of addressesAndPublicKeys) {
        if (publicKey instanceof AbstractMultiKey) {
            if (publicKey.getSignaturesRequired() > 1) {
                continue;
            }
            if (publicKey instanceof MultiEd25519PublicKey) {
                throw new Error("Keyless authentication cannot be used for multi-ed25519 accounts. This should never happen.");
            }
            else if (publicKey instanceof MultiKey) {
                accounts.push(new MultiKeyAccount({ multiKey: publicKey, signers: [keylessAccount], address: accountAddress }));
            }
        }
        else if (isFederated) {
            // Dynamic import to avoid pulling poseidon-lite into the `/account` sub-path bundle.
            const { FederatedKeylessAccount } = await import("../account/FederatedKeylessAccount.js");
            accounts.push(FederatedKeylessAccount.create({
                ...keylessAccountParams,
                address: accountAddress,
                jwkAddress: keylessAccount.publicKey.jwkAddress,
            }));
        }
        else {
            // Dynamic import to avoid pulling poseidon-lite into the `/account` sub-path bundle.
            const { KeylessAccount } = await import("../account/KeylessAccount.js");
            accounts.push(KeylessAccount.create({
                ...keylessAccountParams,
                address: accountAddress,
            }));
        }
    }
    return accounts;
}
async function deriveOwnedAccountsFromPrivateKey(args) {
    const { aptosConfig, privateKey, options } = args;
    const singleKeyAccount = Account.fromPrivateKey({ privateKey, legacy: false });
    const addressesAndPublicKeys = await getAccountsForPublicKey({
        aptosConfig,
        publicKey: new AnyPublicKey(privateKey.publicKey()),
        options,
    });
    const accounts = [];
    // Iterate through the addressesAndPublicKeys and construct the accounts.
    for (const { accountAddress, publicKey } of addressesAndPublicKeys) {
        if (publicKey instanceof AbstractMultiKey) {
            // Skip multi-key accounts with more than 1 signature required as the user does not have full ownership with just 1 private key.
            if (publicKey.getSignaturesRequired() > 1) {
                continue;
            }
            // Construct the appropriate multi-key type.
            if (publicKey instanceof MultiEd25519PublicKey) {
                if (!(privateKey instanceof Ed25519PrivateKey)) {
                    throw new Error("Private key not Ed25519 for MultiEd25519 signature");
                }
                accounts.push(new MultiEd25519Account({ publicKey, signers: [privateKey], address: accountAddress }));
            }
            else if (publicKey instanceof MultiKey) {
                accounts.push(new MultiKeyAccount({ multiKey: publicKey, signers: [singleKeyAccount], address: accountAddress }));
            }
        }
        else {
            // Check if the public key is a legacy Ed25519PublicKey, if so, we need to use the legacy account constructor.
            const isLegacy = publicKey instanceof Ed25519PublicKey;
            accounts.push(Account.fromPrivateKey({ privateKey, address: accountAddress, legacy: isLegacy }));
        }
    }
    return accounts;
}
/**
 * Gets the multi-keys for a given public key.
 *
 * This function retrieves the multi-keys that contain the provided public key.
 * It performs the following steps:
 * 1. Constructs a where condition for the public key where the public key matches the provided public key.
 * 2. Queries the indexer for the multi-keys.
 * 3. Returns the multi-keys.
 *
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.publicKey - The public key to get the multi-keys for. This public key cannot itself be a multi-key.
 * @returns The multi-keys (MultiKey or MultiEd25519PublicKey) that contain the given public key.
 */
async function getMultiKeysForPublicKey(args) {
    const { aptosConfig, publicKey, options } = args;
    if (publicKey instanceof AbstractMultiKey) {
        throw new Error("Public key is a multi-key.");
    }
    const includeUnverified = options?.includeUnverified ?? false;
    const anyPublicKey = publicKey instanceof AnyPublicKey ? publicKey : new AnyPublicKey(publicKey);
    const baseKey = anyPublicKey.publicKey;
    const variant = anyPublicKeyVariantToString(anyPublicKey.variant);
    const whereCondition = {
        public_key: { _eq: baseKey.toString() },
        public_key_type: { _eq: variant },
        account_public_key: { _is_null: false },
        ...(includeUnverified ? {} : { is_public_key_used: { _eq: true } }),
    };
    const graphqlQuery = {
        query: GetAuthKeysForPublicKey,
        variables: {
            where_condition: whereCondition,
        },
    };
    const { public_key_auth_keys: data } = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getMultiKeysForPublicKey",
    });
    const authKeys = data
        .filter((entry) => entry.account_public_key !== null)
        .map((entry) => {
        switch (entry.signature_type) {
            case "multi_ed25519_signature":
                return MultiEd25519PublicKey.deserializeWithoutLength(Deserializer.fromHex(entry.account_public_key));
            case "multi_key_signature":
                return MultiKey.deserialize(Deserializer.fromHex(entry.account_public_key));
            default:
                throw new Error(`Unknown multi-signature type: ${entry.signature_type}`);
        }
    });
    return authKeys;
}
/**
 * Gets the account addresses for the given authentication keys.
 *
 * This function retrieves the account addresses that are associated with the provided authentication keys.
 * It performs the following steps:
 * 1. Constructs a where condition for the authentication keys where auth key matches any of the provided auth keys.
 * 2. Queries the indexer for the account addresses and gets the results ordered by the last transaction version (most recent first).
 * 3. Returns the account addresses.
 *
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.authKeys - The authentication keys to get the account addresses for.
 * @param args.options.includeUnverified - Whether to include unverified accounts in the results. Unverified accounts
 * are accounts that can be authenticated with the signer, but there is no history of the signer using the account.
 * Default is false.
 * @returns The account addresses associated with the given authentication keys.
 */
async function getAccountAddressesForAuthKeys(args) {
    const { aptosConfig, authKeys, options } = args;
    const includeUnverified = options?.includeUnverified ?? false;
    if (authKeys.length === 0) {
        throw new Error("No authentication keys provided");
    }
    const whereCondition = {
        auth_key: { _in: authKeys.map((authKey) => authKey.toString()) },
        ...(includeUnverified ? {} : { is_auth_key_used: { _eq: true } }),
    };
    const graphqlQuery = {
        query: GetAccountAddressesForAuthKey,
        variables: {
            where_condition: whereCondition,
            order_by: [{ last_transaction_version: "desc" }],
        },
    };
    const { auth_key_account_addresses: data } = await queryIndexer({
        aptosConfig,
        query: graphqlQuery,
        originMethod: "getAccountAddressesForAuthKeys",
    });
    return data.map((entry) => ({
        authKey: new AuthenticationKey({ data: entry.auth_key }),
        accountAddress: new AccountAddress(Hex.hexInputToUint8Array(entry.account_address)),
        lastTransactionVersion: Number(entry.last_transaction_version),
    }));
}
/**
 * Returns the last transaction version that was signed by an account.
 *
 * If an account was created but has not signed any transactions, the last transaction version will be 0.
 *
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.accountAddress - The account address to get the latest transaction version for.
 * @returns The last transaction version that was signed by the account.
 */
async function getLatestTransactionVersionForAddress(args) {
    const { aptosConfig, accountAddress } = args;
    const transactions = await getTransactions({ aptosConfig, accountAddress, options: { limit: 1 } });
    if (transactions.length === 0) {
        return 0;
    }
    return Number(transactions[0].version);
}
/**
 * Gets the default account info for a given public key. 'Default account' means the account
 * is address is the same as the auth key derived from the public key and the account auth key has
 * not been rotated.
 *
 * @param args - The arguments for getting the default account info for a given public key.
 * @param args.aptosConfig - The configuration settings for the Aptos network.
 * @param args.publicKey - The public key to use to derive the address.
 * @returns An object containing the account address and the last transaction version, or undefined if the account does not exist.
 */
async function getDefaultAccountInfoForPublicKey(args) {
    const { aptosConfig, publicKey } = args;
    const derivedAddress = publicKey.authKey().derivedAddress();
    const [lastTransactionVersion, exists] = await Promise.all([
        getLatestTransactionVersionForAddress({
            aptosConfig,
            accountAddress: derivedAddress,
        }),
        doesAccountExistAtAddress({
            aptosConfig,
            accountAddress: derivedAddress,
            options: { withAuthKey: publicKey.authKey() },
        }),
    ]);
    if (exists) {
        return { accountAddress: derivedAddress, lastTransactionVersion };
    }
    return undefined;
}
//# sourceMappingURL=account.js.map