@algorandfoundation/algokit-utils 10.0.0-alpha.44 → 10.0.0-alpha.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -174,7 +174,7 @@ var AccountManager = class {
174
174
  */
175
175
  getSigner(sender) {
176
176
  const signer = this._accounts[require_address.getAddress(sender).toString()]?.signer ?? this._defaultSigner;
177
- if (!signer) throw new Error(`No signer found for address ${sender}`);
177
+ if (!signer) throw new Error(`No signer found for address ${require_address.getAddress(sender)}`);
178
178
  return signer;
179
179
  }
180
180
  /**
@@ -193,7 +193,7 @@ var AccountManager = class {
193
193
  */
194
194
  getAccount(sender) {
195
195
  const account = this._accounts[require_address.getAddress(sender).toString()];
196
- if (!account) throw new Error(`No signer found for address ${sender}`);
196
+ if (!account) throw new Error(`No signer found for address ${require_address.getAddress(sender)}`);
197
197
  return account;
198
198
  }
199
199
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"account-manager.js","names":["memoize","KmdAccountManager","TransactionComposer","Address","getAddress","AlgoAmount","seedFromMnemonic","generateAddressWithSigners","getOptionalAddress","MultisigAccount","LogicSigAccount","nacl","DISPENSER_ACCOUNT","calculateFundAmount"],"sources":["../src/account-manager.ts"],"sourcesContent":["import { seedFromMnemonic } from '@algorandfoundation/algokit-algo25'\nimport { SuggestedParams } from '@algorandfoundation/algokit-algod-client'\nimport { Address, ReadableAddress, getAddress, getOptionalAddress } from '@algorandfoundation/algokit-common'\nimport {\n AddressWithSigners,\n AddressWithTransactionSigner,\n LogicSigAccount,\n MultisigAccount,\n MultisigMetadata,\n TransactionSigner,\n generateAddressWithSigners,\n} from '@algorandfoundation/algokit-transact'\nimport nacl from 'tweetnacl'\nimport { AccountInformation, DISPENSER_ACCOUNT } from './account'\nimport { AlgoAmount } from './amount'\nimport { ClientManager } from './client-manager'\nimport { CommonTransactionParams, TransactionComposer } from './composer'\nimport { Config } from './config'\nimport { TestNetDispenserApiClient } from './dispenser-client'\nimport { KmdAccountManager } from './kmd-account-manager'\nimport { SendParams, SendSingleTransactionResult } from './transaction/types'\nimport { calculateFundAmount, memoize } from './util'\nimport { Ed25519Generator } from '@algorandfoundation/algokit-crypto'\n\n/** Result from performing an ensureFunded call. */\nexport interface EnsureFundedResult {\n /** The transaction ID of the transaction that funded the account. */\n transactionId: string\n /** The amount that was sent to the account. */\n amountFunded: AlgoAmount\n}\n\nexport const getAccountTransactionSigner = memoize(function (\n account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount,\n): TransactionSigner {\n return account.signer\n})\n\nexport interface AccountManagerConfig {\n ed25519Generator: Ed25519Generator\n}\n\n/**\n * Creates and keeps track of signing accounts that can sign transactions for a sending address.\n * @see {@link KmdAccountManager} for KMD-specific account management\n * @see {@link AlgorandClient} for the main entry point that provides access to this manager\n */\nexport class AccountManager {\n private _clientManager: ClientManager\n private _kmdAccountManager: KmdAccountManager\n private _accounts: { [address: string]: AddressWithTransactionSigner } = {}\n private _defaultSigner?: TransactionSigner\n private _ed25519Generator: Ed25519Generator\n\n /**\n * Create a new account manager.\n * @param clientManager The ClientManager client to use for algod and kmd clients\n * @example Create a new account manager\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * ```\n */\n constructor(clientManager: ClientManager, config: AccountManagerConfig) {\n this._clientManager = clientManager\n this._kmdAccountManager = new KmdAccountManager(clientManager)\n this._ed25519Generator = config.ed25519Generator\n }\n\n private _getComposer(getSuggestedParams?: () => Promise<SuggestedParams>) {\n return new TransactionComposer({\n algod: this._clientManager.algod,\n getSigner: this.getSigner.bind(this),\n getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.suggestedParams()),\n })\n }\n\n /**\n * KMD account manager that allows you to easily get and create accounts using KMD.\n * @returns The `KmdAccountManager` instance.\n * @example\n * ```typescript\n * const kmdManager = accountManager.kmd;\n * ```\n */\n public get kmd() {\n return this._kmdAccountManager\n }\n\n /**\n * Sets the default signer to use if no other signer is specified.\n *\n * If this isn't set an a transaction needs signing for a given sender\n * then an error will be thrown from `getSigner` / `getAccount`.\n * @param signer The signer to use, either a `TransactionSigner` or a `AddressWithSigner`\n * @example\n * ```typescript\n * const signer = accountManager.random() // Can be anything that returns a `TransactionSigner` or `AddressWithSigner`\n * accountManager.setDefaultSigner(signer)\n *\n * // When signing a transaction, if there is no signer registered for the sender then the default signer will be used\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `AccountManager` so method calls can be chained\n */\n public setDefaultSigner(signer: TransactionSigner | AddressWithTransactionSigner): AccountManager {\n this._defaultSigner = 'signer' in signer ? signer.signer : signer\n return this\n }\n\n /**\n * Records the given account (that can sign) against the address of the provided account for later\n * retrieval and returns a `AddressWithTransactionSigner` along with the original account in an `account` property.\n */\n private signerAccount<T extends AddressWithTransactionSigner | LogicSigAccount | MultisigAccount>(\n account: T,\n ): Address &\n AddressWithTransactionSigner & {\n /* The underlying account that specified this address. */ account: T\n } {\n const signer = getAccountTransactionSigner(account)\n const acc: AddressWithTransactionSigner = {\n addr: account.addr,\n signer: signer,\n }\n this._accounts[acc.addr.toString()] = acc\n\n const addressWithAccount = Address.fromString(acc.addr.toString()) as Address & AddressWithTransactionSigner & { account: T }\n addressWithAccount.account = account\n addressWithAccount.addr = acc.addr\n addressWithAccount.signer = signer\n return addressWithAccount\n }\n\n /**\n * Tracks the given account for later signing.\n *\n * Note: If you are generating accounts via the various methods on `AccountManager`\n * (like `random`, `fromMnemonic`, `logicsig`, etc.) then they automatically get tracked.\n * @param account The account to register, which can be a `AddressWithSigner` or\n * a `algosdk.Account`, `algosdk.LogicSigAccount`, `SigningAccount` or `MultisigAccount`\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSignerFromAccount(algosdk.generateAccount())\n * .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))\n * .setSignerFromAccount(new SigningAccount(mnemonic, sender))\n * .setSignerFromAccount(new MultisigAccount({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]}, [account1, account2]))\n * .setSignerFromAccount({addr: \"SENDERADDRESS\", signer: transactionSigner})\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSignerFromAccount(account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount) {\n this.signerAccount(account)\n return this\n }\n\n /**\n * Tracks the given `TransactionSigner` against the given sender address for later signing.\n * @param sender The sender address to use this signer for\n * @param signer The `TransactionSigner` to sign transactions with for the given sender\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSigner(\"SENDERADDRESS\", transactionSigner)\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSigner(sender: string | Address, signer: TransactionSigner) {\n this._accounts[getAddress(sender).toString()] = { addr: getAddress(sender), signer }\n return this\n }\n\n /**\n * Takes all registered signers from the given `AccountManager` and adds them to this `AccountManager`.\n *\n * This is useful for situations where you have multiple contexts you are building accounts in such as unit tests.\n * @param anotherAccountManager Another account manager with signers registered\n * @param overwriteExisting Whether or not to overwrite any signers that have the same sender address with the ones in the other account manager or not (default: true)\n * @returns The `AccountManager` instance for method chaining\n * @example\n * ```typescript\n * accountManager2.setSigners(accountManager1);\n * ```\n */\n public setSigners(anotherAccountManager: AccountManager, overwriteExisting = true) {\n this._accounts = overwriteExisting\n ? { ...this._accounts, ...anotherAccountManager._accounts }\n : { ...anotherAccountManager._accounts, ...this._accounts }\n return this\n }\n\n /**\n * Returns the `TransactionSigner` for the given sender address, ready to sign a transaction for that sender.\n *\n * If no signer has been registered for that address then the default signer is used if registered and\n * if not then an error is thrown.\n *\n * @param sender The sender address\n * @example\n * ```typescript\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `TransactionSigner` or throws an error if not found and no default signer is set\n */\n public getSigner(sender: ReadableAddress): TransactionSigner {\n const signer = this._accounts[getAddress(sender).toString()]?.signer ?? this._defaultSigner\n if (!signer) throw new Error(`No signer found for address ${sender}`)\n return signer\n }\n\n /**\n * Returns the `AddressWithSigner` for the given sender address.\n *\n * If no signer has been registered for that address then an error is thrown.\n * @param sender The sender address\n * @example\n * ```typescript\n * const sender = accountManager.random()\n * // ...\n * // Returns the `AddressWithSigner` for `sender` that has previously been registered\n * const account = accountManager.getAccount(sender)\n * ```\n * @returns The `AddressWithSigner` or throws an error if not found\n */\n public getAccount(sender: ReadableAddress): AddressWithTransactionSigner {\n const account = this._accounts[getAddress(sender).toString()]\n if (!account) throw new Error(`No signer found for address ${sender}`)\n return account\n }\n\n /**\n * Returns the given sender account's current status, balance and spendable amounts.\n *\n * [Response data schema details](https://dev.algorand.co/reference/rest-apis/algod/#accountinformation)\n * @example\n * ```typescript\n * const address = \"XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA\";\n * const accountInfo = await accountManager.getInformation(address);\n * ```\n *\n * @param sender The account / address to look up\n * @returns The account information\n */\n public async getInformation(sender: ReadableAddress): Promise<AccountInformation> {\n const senderAddress = getAddress(sender).toString()\n const {\n round,\n lastHeartbeat = undefined,\n lastProposed = undefined,\n address,\n ...account\n } = await this._clientManager.algod.accountInformation(senderAddress)\n\n return {\n ...account,\n authAddr: account.authAddr,\n address,\n balance: AlgoAmount.MicroAlgo(Number(account.amount)),\n amountWithoutPendingRewards: AlgoAmount.MicroAlgo(Number(account.amountWithoutPendingRewards)),\n minBalance: AlgoAmount.MicroAlgo(Number(account.minBalance)),\n pendingRewards: AlgoAmount.MicroAlgo(Number(account.pendingRewards)),\n rewards: AlgoAmount.MicroAlgo(Number(account.rewards)),\n validAsOfRound: BigInt(round),\n totalAppsOptedIn: Number(account.totalAppsOptedIn),\n totalAssetsOptedIn: Number(account.totalAssetsOptedIn),\n totalCreatedApps: Number(account.totalCreatedApps),\n totalCreatedAssets: Number(account.totalCreatedAssets),\n appsTotalExtraPages: account.appsTotalExtraPages !== undefined ? Number(account.appsTotalExtraPages) : undefined,\n rewardBase: account.rewardBase !== undefined ? Number(account.rewardBase) : undefined,\n totalBoxBytes: account.totalBoxBytes !== undefined ? Number(account.totalBoxBytes) : undefined,\n totalBoxes: account.totalBoxes !== undefined ? Number(account.totalBoxes) : undefined,\n lastHeartbeatRound: lastHeartbeat !== undefined ? BigInt(lastHeartbeat) : undefined,\n lastProposedRound: lastProposed !== undefined ? BigInt(lastProposed) : undefined,\n }\n }\n\n /**\n * Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.fromMnemonic(\"mnemonic secret ...\", \"SENDERADDRESS...\")\n * ```\n * @param mnemonicSecret The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @returns The account\n */\n public fromMnemonic(mnemonicSecret: string, sender?: string | Address): AddressWithTransactionSigner {\n const seed = seedFromMnemonic(mnemonicSecret)\n\n const generated = this._ed25519Generator(seed)\n\n const addrWithSigners = generateAddressWithSigners({\n ed25519Pubkey: generated.ed25519Pubkey,\n rawEd25519Signer: generated.rawEd25519Signer,\n sendingAddress: getOptionalAddress(sender),\n })\n\n return this.signerAccount(addrWithSigners)\n }\n\n /**\n * Tracks and returns an Algorand account that is a rekeyed version of the given account to a new sender.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.rekeyed(account, \"SENDERADDRESS...\")\n * ```\n * @param account The account to use as the signer for this new rekeyed account\n * @param sender The sender address to use as the new sender\n * @returns The account\n */\n public rekeyed(sender: string | Address, account: AddressWithTransactionSigner) {\n return this.signerAccount({ addr: getAddress(sender), signer: account.signer })\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded by convention from environment variables based on the given name identifier.\n *\n * Note: This function expects to run in a Node.js environment.\n *\n * ## Convention:\n * * **Non-LocalNet:** will load process.env['\\{NAME\\}_MNEMONIC'] as a mnemonic secret; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it via a secret storage service rather than the file system.\n * If process.env['\\{NAME\\}_SENDER'] is defined then it will use that for the sender address (i.e. to support rekeyed accounts)\n * * **LocalNet:** will load the account from a KMD wallet called \\{NAME\\} and if that wallet doesn't exist it will create it and fund the account for you\n *\n * This allows you to write code that will work seamlessly in production and local development (LocalNet) without manual config locally (including when you reset the LocalNet).\n *\n * @example Default\n *\n * If you have a mnemonic secret loaded into `process.env.MY_ACCOUNT_MNEMONIC` then you can call the following to get that private key loaded into an account object:\n * ```typescript\n * const account = await accountManager.fromEnvironment('MY_ACCOUNT')\n * ```\n *\n * If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created with an account that is automatically funded with 1000 (default) ALGO from the default LocalNet dispenser.\n * If not running against LocalNet then it will use proces.env.MY_ACCOUNT_MNEMONIC as the private key and (if present) process.env.MY_ACCOUNT_SENDER as the sender address.\n *\n * @param name The name identifier of the account\n * @param fundWith The optional amount to fund the account with when it gets created (when targeting LocalNet), if not specified then 1000 ALGO will be funded from the dispenser account\n * @returns The account\n */\n public async fromEnvironment(name: string, fundWith?: AlgoAmount) {\n if (!process || !process.env) {\n throw new Error('Attempt to get account with private key from a non Node.js context; this is not supported!')\n }\n\n const accountMnemonic = process.env[`${name.toUpperCase()}_MNEMONIC`]\n const sender = process.env[`${name.toUpperCase()}_SENDER`]\n\n if (accountMnemonic) {\n return this.fromMnemonic(accountMnemonic, sender)\n }\n\n if (await this._clientManager.isLocalNet()) {\n const account = await this._kmdAccountManager.getOrCreateWalletAccount(name, fundWith)\n return this.signerAccount(account)\n }\n\n throw new Error(`Missing environment variable ${name.toUpperCase()}_MNEMONIC when looking for account ${name}`)\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).\n *\n * @param name The name of the wallet to retrieve an account from\n * @param predicate An optional filter to use to find the account (otherwise it will return a random account from the wallet)\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @example Get default funded account in a LocalNet\n *\n * ```typescript\n * const defaultDispenserAccount = await accountManager.fromKmd('unencrypted-default-wallet',\n * a => a.status !== 'Offline' && a.amount > 1_000_000_000\n * )\n * ```\n * @returns The account\n */\n public async fromKmd(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n predicate?: (account: Record<string, any>) => boolean,\n sender?: string | Address,\n ) {\n const account = await this._kmdAccountManager.getWalletAccount(name, predicate, sender)\n if (!account) throw new Error(`Unable to find KMD account ${name}${predicate ? ' with predicate' : ''}`)\n return this.signerAccount(account)\n }\n\n /**\n * Tracks and returns an account that supports partial or full multisig signing.\n *\n * @example\n * ```typescript\n * const account = accountManager.multisig({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]},\n * [(await accountManager.fromEnvironment('ACCOUNT1')).account])\n * ```\n * @param multisigParams The parameters that define the multisig account\n * @param subSigners The signers that are currently present\n * @returns A multisig account wrapper\n */\n public multisig(multisigParams: MultisigMetadata, subSigners: AddressWithSigners[]) {\n return this.signerAccount(new MultisigAccount(multisigParams, subSigners))\n }\n\n /**\n * Tracks and returns an account that represents a logic signature.\n *\n * @example\n * ```typescript\n * const account = accountManager.logicsig(program, [new Uint8Array(3, ...)])\n * ```\n * @param program The bytes that make up the compiled logic signature\n * @param args The (binary) arguments to pass into the logic signature\n * @returns A logic signature account wrapper\n */\n public logicsig(program: Uint8Array, args?: Array<Uint8Array>) {\n return this.signerAccount(new LogicSigAccount(program, args))\n }\n\n /**\n * Tracks and returns a new, random Algorand account with secret key loaded.\n *\n * @example\n * ```typescript\n * const account = accountManager.random()\n * ```\n * @returns The account\n */\n public random() {\n const keypair = nacl.sign.keyPair()\n const rawSigner = async (bytesToSign: Uint8Array): Promise<Uint8Array> => {\n return nacl.sign.detached(bytesToSign, keypair.secretKey)\n }\n\n const addrWithSigners = generateAddressWithSigners({ ed25519Pubkey: keypair.publicKey, rawEd25519Signer: rawSigner })\n\n this._accounts[addrWithSigners.addr.toString()] = addrWithSigners\n\n const acct = addrWithSigners.addr as Address & AddressWithSigners\n\n for (const prop in addrWithSigners) {\n // Create a new Address instance for avoid circular references\n if (prop === 'addr') {\n acct.addr = new Address(addrWithSigners.addr.publicKey)\n continue\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(acct as any)[prop] = (addrWithSigners as any)[prop]\n }\n\n return acct\n }\n\n /**\n * Returns an account (with private key loaded) that can act as a dispenser from\n * environment variables, or against default LocalNet if no environment variables present.\n *\n * Note: requires a Node.js environment to execute.\n *\n * If present, it will load the account mnemonic stored in process.env.DISPENSER_MNEMONIC and optionally\n * process.env.DISPENSER_SENDER if it's a rekeyed account.\n *\n * @example\n * ```typescript\n * const account = await accountManager.dispenserFromEnvironment()\n * ```\n *\n * @returns The account\n */\n public async dispenserFromEnvironment() {\n if (!process || !process.env) {\n throw new Error('Attempt to get dispenser from environment from a non Node.js context; this is not supported!')\n }\n\n return process.env[`${DISPENSER_ACCOUNT.toUpperCase()}_MNEMONIC`]\n ? await this.fromEnvironment(DISPENSER_ACCOUNT)\n : await this.localNetDispenser()\n }\n\n /**\n * Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).\n *\n * @example\n * ```typescript\n * const account = await accountManager.localNetDispenser()\n * ```\n * @returns The account\n */\n public async localNetDispenser() {\n const dispenser = await this._kmdAccountManager.getLocalNetDispenserAccount()\n return this.signerAccount(dispenser)\n }\n\n /**\n * Rekey an account to a new address.\n *\n * **Note:** Please be careful with this function and be sure to read the [official rekey guidance](https://dev.algorand.co/concepts/accounts/rekeying).\n *\n * @param account The account to rekey\n * @param rekeyTo The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward.\n * If a signing account is provided that will now be tracked as the signer for `account` in this `AccountManager`\n * @param options Any parameters to control the transaction or execution of the transaction\n *\n * @example Basic example (with string addresses)\n * ```typescript\n * await accountManager.rekeyAccount({account: \"ACCOUNTADDRESS\", rekeyTo: \"NEWADDRESS\"})\n * ```\n * @example Basic example (with signer accounts)\n * ```typescript\n * await accountManager.rekeyAccount({account: account1, rekeyTo: newSignerAccount})\n * ```\n * @example Advanced example\n * ```typescript\n * await accountManager.rekeyAccount({\n * account: \"ACCOUNTADDRESS\",\n * rekeyTo: \"NEWADDRESS\",\n * lease: 'lease',\n * note: 'note',\n * firstValidRound: 1000n,\n * validityWindow: 10,\n * extraFee: (1000).microAlgo(),\n * staticFee: (1000).microAlgo(),\n * // Max fee doesn't make sense with extraFee AND staticFee\n * // already specified, but here for completeness\n * maxFee: (3000).microAlgo(),\n * maxRoundsToWaitForConfirmation: 5,\n * suppressLog: true,\n * })\n * ```\n * @returns The result of the transaction and the transaction that was sent\n */\n async rekeyAccount(\n account: string | Address,\n rekeyTo: string | Address | AddressWithTransactionSigner,\n options?: Omit<CommonTransactionParams, 'sender'> & SendParams,\n ): Promise<SendSingleTransactionResult> {\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(account),\n receiver: getAddress(account),\n amount: AlgoAmount.MicroAlgo(0),\n rekeyTo: getAddress(rekeyTo),\n })\n .send(options)\n\n // If the rekey is a signing account set it as the signer for this account\n if (typeof rekeyTo === 'object' && 'addr' in rekeyTo) {\n this.rekeyed(account, rekeyTo)\n }\n\n Config.getLogger(options?.suppressLog).info(`Rekeyed ${account} to ${rekeyTo} via transaction ${result.txIds.at(-1)}`)\n\n return { ...result, transaction: result.transactions.at(-1)!, confirmation: result.confirmations.at(-1)! }\n }\n\n private async _getEnsureFundedAmount(sender: Address, minSpendingBalance: AlgoAmount, minFundingIncrement?: AlgoAmount) {\n const accountInfo = await this.getInformation(sender)\n const currentSpendingBalance = accountInfo.balance.microAlgo - accountInfo.minBalance.microAlgo\n\n const amountFunded = calculateFundAmount(minSpendingBalance.microAlgo, currentSpendingBalance, minFundingIncrement?.microAlgo ?? 0n)\n\n return amountFunded === null ? undefined : AlgoAmount.MicroAlgo(amountFunded)\n }\n\n /**\n * Funds a given account using a dispenser account as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserAccount The account to use as a dispenser funding source\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFunded(\n accountToFund: string | Address,\n dispenserAccount: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(dispenserAccount),\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using a dispenser account retrieved from the environment,\n * per the `dispenserFromEnvironment` method, as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * **Note:** requires a Node.js environment to execute.\n *\n * The dispenser account is retrieved from the account mnemonic stored in\n * process.env.DISPENSER_MNEMONIC and optionally process.env.DISPENSER_SENDER\n * if it's a rekeyed account, or against default LocalNet if no environment variables present.\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromEnvironment(\n accountToFund: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n const dispenserAccount = await this.dispenserFromEnvironment()\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: dispenserAccount,\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using the TestNet Dispenser API as a funding source such that\n * the account has a certain amount of Algo free to spend (accounting for Algo locked\n * in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserClient The TestNet dispenser funding client\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2) }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromTestNetDispenserApi(\n accountToFund: string | Address,\n dispenserClient: TestNetDispenserApiClient,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n },\n ): Promise<EnsureFundedResult | undefined> {\n if (!(await this._clientManager.isTestNet())) {\n throw new Error('Attempt to fund using TestNet dispenser API on non TestNet network.')\n }\n\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await dispenserClient.fund(addressToFund, amountFunded.microAlgo)\n return {\n amountFunded: AlgoAmount.MicroAlgo(result.amount),\n transactionId: result.txId,\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"account-manager.js","names":["memoize","KmdAccountManager","TransactionComposer","Address","getAddress","AlgoAmount","seedFromMnemonic","generateAddressWithSigners","getOptionalAddress","MultisigAccount","LogicSigAccount","nacl","DISPENSER_ACCOUNT","calculateFundAmount"],"sources":["../src/account-manager.ts"],"sourcesContent":["import { seedFromMnemonic } from '@algorandfoundation/algokit-algo25'\nimport { SuggestedParams } from '@algorandfoundation/algokit-algod-client'\nimport { Address, ReadableAddress, getAddress, getOptionalAddress } from '@algorandfoundation/algokit-common'\nimport {\n AddressWithSigners,\n AddressWithTransactionSigner,\n LogicSigAccount,\n MultisigAccount,\n MultisigMetadata,\n TransactionSigner,\n generateAddressWithSigners,\n} from '@algorandfoundation/algokit-transact'\nimport nacl from 'tweetnacl'\nimport { AccountInformation, DISPENSER_ACCOUNT } from './account'\nimport { AlgoAmount } from './amount'\nimport { ClientManager } from './client-manager'\nimport { CommonTransactionParams, TransactionComposer } from './composer'\nimport { Config } from './config'\nimport { TestNetDispenserApiClient } from './dispenser-client'\nimport { KmdAccountManager } from './kmd-account-manager'\nimport { SendParams, SendSingleTransactionResult } from './transaction/types'\nimport { calculateFundAmount, memoize } from './util'\nimport { Ed25519Generator } from '@algorandfoundation/algokit-crypto'\n\n/** Result from performing an ensureFunded call. */\nexport interface EnsureFundedResult {\n /** The transaction ID of the transaction that funded the account. */\n transactionId: string\n /** The amount that was sent to the account. */\n amountFunded: AlgoAmount\n}\n\nexport const getAccountTransactionSigner = memoize(function (\n account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount,\n): TransactionSigner {\n return account.signer\n})\n\nexport interface AccountManagerConfig {\n ed25519Generator: Ed25519Generator\n}\n\n/**\n * Creates and keeps track of signing accounts that can sign transactions for a sending address.\n * @see {@link KmdAccountManager} for KMD-specific account management\n * @see {@link AlgorandClient} for the main entry point that provides access to this manager\n */\nexport class AccountManager {\n private _clientManager: ClientManager\n private _kmdAccountManager: KmdAccountManager\n private _accounts: { [address: string]: AddressWithTransactionSigner } = {}\n private _defaultSigner?: TransactionSigner\n private _ed25519Generator: Ed25519Generator\n\n /**\n * Create a new account manager.\n * @param clientManager The ClientManager client to use for algod and kmd clients\n * @example Create a new account manager\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * ```\n */\n constructor(clientManager: ClientManager, config: AccountManagerConfig) {\n this._clientManager = clientManager\n this._kmdAccountManager = new KmdAccountManager(clientManager)\n this._ed25519Generator = config.ed25519Generator\n }\n\n private _getComposer(getSuggestedParams?: () => Promise<SuggestedParams>) {\n return new TransactionComposer({\n algod: this._clientManager.algod,\n getSigner: this.getSigner.bind(this),\n getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.suggestedParams()),\n })\n }\n\n /**\n * KMD account manager that allows you to easily get and create accounts using KMD.\n * @returns The `KmdAccountManager` instance.\n * @example\n * ```typescript\n * const kmdManager = accountManager.kmd;\n * ```\n */\n public get kmd() {\n return this._kmdAccountManager\n }\n\n /**\n * Sets the default signer to use if no other signer is specified.\n *\n * If this isn't set an a transaction needs signing for a given sender\n * then an error will be thrown from `getSigner` / `getAccount`.\n * @param signer The signer to use, either a `TransactionSigner` or a `AddressWithSigner`\n * @example\n * ```typescript\n * const signer = accountManager.random() // Can be anything that returns a `TransactionSigner` or `AddressWithSigner`\n * accountManager.setDefaultSigner(signer)\n *\n * // When signing a transaction, if there is no signer registered for the sender then the default signer will be used\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `AccountManager` so method calls can be chained\n */\n public setDefaultSigner(signer: TransactionSigner | AddressWithTransactionSigner): AccountManager {\n this._defaultSigner = 'signer' in signer ? signer.signer : signer\n return this\n }\n\n /**\n * Records the given account (that can sign) against the address of the provided account for later\n * retrieval and returns a `AddressWithTransactionSigner` along with the original account in an `account` property.\n */\n private signerAccount<T extends AddressWithTransactionSigner | LogicSigAccount | MultisigAccount>(\n account: T,\n ): Address &\n AddressWithTransactionSigner & {\n /* The underlying account that specified this address. */ account: T\n } {\n const signer = getAccountTransactionSigner(account)\n const acc: AddressWithTransactionSigner = {\n addr: account.addr,\n signer: signer,\n }\n this._accounts[acc.addr.toString()] = acc\n\n const addressWithAccount = Address.fromString(acc.addr.toString()) as Address & AddressWithTransactionSigner & { account: T }\n addressWithAccount.account = account\n addressWithAccount.addr = acc.addr\n addressWithAccount.signer = signer\n return addressWithAccount\n }\n\n /**\n * Tracks the given account for later signing.\n *\n * Note: If you are generating accounts via the various methods on `AccountManager`\n * (like `random`, `fromMnemonic`, `logicsig`, etc.) then they automatically get tracked.\n * @param account The account to register, which can be a `AddressWithSigner` or\n * a `algosdk.Account`, `algosdk.LogicSigAccount`, `SigningAccount` or `MultisigAccount`\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSignerFromAccount(algosdk.generateAccount())\n * .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))\n * .setSignerFromAccount(new SigningAccount(mnemonic, sender))\n * .setSignerFromAccount(new MultisigAccount({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]}, [account1, account2]))\n * .setSignerFromAccount({addr: \"SENDERADDRESS\", signer: transactionSigner})\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSignerFromAccount(account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount) {\n this.signerAccount(account)\n return this\n }\n\n /**\n * Tracks the given `TransactionSigner` against the given sender address for later signing.\n * @param sender The sender address to use this signer for\n * @param signer The `TransactionSigner` to sign transactions with for the given sender\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSigner(\"SENDERADDRESS\", transactionSigner)\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSigner(sender: string | Address, signer: TransactionSigner) {\n this._accounts[getAddress(sender).toString()] = { addr: getAddress(sender), signer }\n return this\n }\n\n /**\n * Takes all registered signers from the given `AccountManager` and adds them to this `AccountManager`.\n *\n * This is useful for situations where you have multiple contexts you are building accounts in such as unit tests.\n * @param anotherAccountManager Another account manager with signers registered\n * @param overwriteExisting Whether or not to overwrite any signers that have the same sender address with the ones in the other account manager or not (default: true)\n * @returns The `AccountManager` instance for method chaining\n * @example\n * ```typescript\n * accountManager2.setSigners(accountManager1);\n * ```\n */\n public setSigners(anotherAccountManager: AccountManager, overwriteExisting = true) {\n this._accounts = overwriteExisting\n ? { ...this._accounts, ...anotherAccountManager._accounts }\n : { ...anotherAccountManager._accounts, ...this._accounts }\n return this\n }\n\n /**\n * Returns the `TransactionSigner` for the given sender address, ready to sign a transaction for that sender.\n *\n * If no signer has been registered for that address then the default signer is used if registered and\n * if not then an error is thrown.\n *\n * @param sender The sender address\n * @example\n * ```typescript\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `TransactionSigner` or throws an error if not found and no default signer is set\n */\n public getSigner(sender: ReadableAddress): TransactionSigner {\n const signer = this._accounts[getAddress(sender).toString()]?.signer ?? this._defaultSigner\n if (!signer) throw new Error(`No signer found for address ${getAddress(sender)}`)\n return signer\n }\n\n /**\n * Returns the `AddressWithSigner` for the given sender address.\n *\n * If no signer has been registered for that address then an error is thrown.\n * @param sender The sender address\n * @example\n * ```typescript\n * const sender = accountManager.random()\n * // ...\n * // Returns the `AddressWithSigner` for `sender` that has previously been registered\n * const account = accountManager.getAccount(sender)\n * ```\n * @returns The `AddressWithSigner` or throws an error if not found\n */\n public getAccount(sender: ReadableAddress): AddressWithTransactionSigner {\n const account = this._accounts[getAddress(sender).toString()]\n if (!account) throw new Error(`No signer found for address ${getAddress(sender)}`)\n return account\n }\n\n /**\n * Returns the given sender account's current status, balance and spendable amounts.\n *\n * [Response data schema details](https://dev.algorand.co/reference/rest-apis/algod/#accountinformation)\n * @example\n * ```typescript\n * const address = \"XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA\";\n * const accountInfo = await accountManager.getInformation(address);\n * ```\n *\n * @param sender The account / address to look up\n * @returns The account information\n */\n public async getInformation(sender: ReadableAddress): Promise<AccountInformation> {\n const senderAddress = getAddress(sender).toString()\n const {\n round,\n lastHeartbeat = undefined,\n lastProposed = undefined,\n address,\n ...account\n } = await this._clientManager.algod.accountInformation(senderAddress)\n\n return {\n ...account,\n authAddr: account.authAddr,\n address,\n balance: AlgoAmount.MicroAlgo(Number(account.amount)),\n amountWithoutPendingRewards: AlgoAmount.MicroAlgo(Number(account.amountWithoutPendingRewards)),\n minBalance: AlgoAmount.MicroAlgo(Number(account.minBalance)),\n pendingRewards: AlgoAmount.MicroAlgo(Number(account.pendingRewards)),\n rewards: AlgoAmount.MicroAlgo(Number(account.rewards)),\n validAsOfRound: BigInt(round),\n totalAppsOptedIn: Number(account.totalAppsOptedIn),\n totalAssetsOptedIn: Number(account.totalAssetsOptedIn),\n totalCreatedApps: Number(account.totalCreatedApps),\n totalCreatedAssets: Number(account.totalCreatedAssets),\n appsTotalExtraPages: account.appsTotalExtraPages !== undefined ? Number(account.appsTotalExtraPages) : undefined,\n rewardBase: account.rewardBase !== undefined ? Number(account.rewardBase) : undefined,\n totalBoxBytes: account.totalBoxBytes !== undefined ? Number(account.totalBoxBytes) : undefined,\n totalBoxes: account.totalBoxes !== undefined ? Number(account.totalBoxes) : undefined,\n lastHeartbeatRound: lastHeartbeat !== undefined ? BigInt(lastHeartbeat) : undefined,\n lastProposedRound: lastProposed !== undefined ? BigInt(lastProposed) : undefined,\n }\n }\n\n /**\n * Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.fromMnemonic(\"mnemonic secret ...\", \"SENDERADDRESS...\")\n * ```\n * @param mnemonicSecret The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @returns The account\n */\n public fromMnemonic(mnemonicSecret: string, sender?: string | Address): AddressWithTransactionSigner {\n const seed = seedFromMnemonic(mnemonicSecret)\n\n const generated = this._ed25519Generator(seed)\n\n const addrWithSigners = generateAddressWithSigners({\n ed25519Pubkey: generated.ed25519Pubkey,\n rawEd25519Signer: generated.rawEd25519Signer,\n sendingAddress: getOptionalAddress(sender),\n })\n\n return this.signerAccount(addrWithSigners)\n }\n\n /**\n * Tracks and returns an Algorand account that is a rekeyed version of the given account to a new sender.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.rekeyed(account, \"SENDERADDRESS...\")\n * ```\n * @param account The account to use as the signer for this new rekeyed account\n * @param sender The sender address to use as the new sender\n * @returns The account\n */\n public rekeyed(sender: string | Address, account: AddressWithTransactionSigner) {\n return this.signerAccount({ addr: getAddress(sender), signer: account.signer })\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded by convention from environment variables based on the given name identifier.\n *\n * Note: This function expects to run in a Node.js environment.\n *\n * ## Convention:\n * * **Non-LocalNet:** will load process.env['\\{NAME\\}_MNEMONIC'] as a mnemonic secret; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it via a secret storage service rather than the file system.\n * If process.env['\\{NAME\\}_SENDER'] is defined then it will use that for the sender address (i.e. to support rekeyed accounts)\n * * **LocalNet:** will load the account from a KMD wallet called \\{NAME\\} and if that wallet doesn't exist it will create it and fund the account for you\n *\n * This allows you to write code that will work seamlessly in production and local development (LocalNet) without manual config locally (including when you reset the LocalNet).\n *\n * @example Default\n *\n * If you have a mnemonic secret loaded into `process.env.MY_ACCOUNT_MNEMONIC` then you can call the following to get that private key loaded into an account object:\n * ```typescript\n * const account = await accountManager.fromEnvironment('MY_ACCOUNT')\n * ```\n *\n * If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created with an account that is automatically funded with 1000 (default) ALGO from the default LocalNet dispenser.\n * If not running against LocalNet then it will use proces.env.MY_ACCOUNT_MNEMONIC as the private key and (if present) process.env.MY_ACCOUNT_SENDER as the sender address.\n *\n * @param name The name identifier of the account\n * @param fundWith The optional amount to fund the account with when it gets created (when targeting LocalNet), if not specified then 1000 ALGO will be funded from the dispenser account\n * @returns The account\n */\n public async fromEnvironment(name: string, fundWith?: AlgoAmount) {\n if (!process || !process.env) {\n throw new Error('Attempt to get account with private key from a non Node.js context; this is not supported!')\n }\n\n const accountMnemonic = process.env[`${name.toUpperCase()}_MNEMONIC`]\n const sender = process.env[`${name.toUpperCase()}_SENDER`]\n\n if (accountMnemonic) {\n return this.fromMnemonic(accountMnemonic, sender)\n }\n\n if (await this._clientManager.isLocalNet()) {\n const account = await this._kmdAccountManager.getOrCreateWalletAccount(name, fundWith)\n return this.signerAccount(account)\n }\n\n throw new Error(`Missing environment variable ${name.toUpperCase()}_MNEMONIC when looking for account ${name}`)\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).\n *\n * @param name The name of the wallet to retrieve an account from\n * @param predicate An optional filter to use to find the account (otherwise it will return a random account from the wallet)\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @example Get default funded account in a LocalNet\n *\n * ```typescript\n * const defaultDispenserAccount = await accountManager.fromKmd('unencrypted-default-wallet',\n * a => a.status !== 'Offline' && a.amount > 1_000_000_000\n * )\n * ```\n * @returns The account\n */\n public async fromKmd(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n predicate?: (account: Record<string, any>) => boolean,\n sender?: string | Address,\n ) {\n const account = await this._kmdAccountManager.getWalletAccount(name, predicate, sender)\n if (!account) throw new Error(`Unable to find KMD account ${name}${predicate ? ' with predicate' : ''}`)\n return this.signerAccount(account)\n }\n\n /**\n * Tracks and returns an account that supports partial or full multisig signing.\n *\n * @example\n * ```typescript\n * const account = accountManager.multisig({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]},\n * [(await accountManager.fromEnvironment('ACCOUNT1')).account])\n * ```\n * @param multisigParams The parameters that define the multisig account\n * @param subSigners The signers that are currently present\n * @returns A multisig account wrapper\n */\n public multisig(multisigParams: MultisigMetadata, subSigners: AddressWithSigners[]) {\n return this.signerAccount(new MultisigAccount(multisigParams, subSigners))\n }\n\n /**\n * Tracks and returns an account that represents a logic signature.\n *\n * @example\n * ```typescript\n * const account = accountManager.logicsig(program, [new Uint8Array(3, ...)])\n * ```\n * @param program The bytes that make up the compiled logic signature\n * @param args The (binary) arguments to pass into the logic signature\n * @returns A logic signature account wrapper\n */\n public logicsig(program: Uint8Array, args?: Array<Uint8Array>) {\n return this.signerAccount(new LogicSigAccount(program, args))\n }\n\n /**\n * Tracks and returns a new, random Algorand account with secret key loaded.\n *\n * @example\n * ```typescript\n * const account = accountManager.random()\n * ```\n * @returns The account\n */\n public random() {\n const keypair = nacl.sign.keyPair()\n const rawSigner = async (bytesToSign: Uint8Array): Promise<Uint8Array> => {\n return nacl.sign.detached(bytesToSign, keypair.secretKey)\n }\n\n const addrWithSigners = generateAddressWithSigners({ ed25519Pubkey: keypair.publicKey, rawEd25519Signer: rawSigner })\n\n this._accounts[addrWithSigners.addr.toString()] = addrWithSigners\n\n const acct = addrWithSigners.addr as Address & AddressWithSigners\n\n for (const prop in addrWithSigners) {\n // Create a new Address instance for avoid circular references\n if (prop === 'addr') {\n acct.addr = new Address(addrWithSigners.addr.publicKey)\n continue\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(acct as any)[prop] = (addrWithSigners as any)[prop]\n }\n\n return acct\n }\n\n /**\n * Returns an account (with private key loaded) that can act as a dispenser from\n * environment variables, or against default LocalNet if no environment variables present.\n *\n * Note: requires a Node.js environment to execute.\n *\n * If present, it will load the account mnemonic stored in process.env.DISPENSER_MNEMONIC and optionally\n * process.env.DISPENSER_SENDER if it's a rekeyed account.\n *\n * @example\n * ```typescript\n * const account = await accountManager.dispenserFromEnvironment()\n * ```\n *\n * @returns The account\n */\n public async dispenserFromEnvironment() {\n if (!process || !process.env) {\n throw new Error('Attempt to get dispenser from environment from a non Node.js context; this is not supported!')\n }\n\n return process.env[`${DISPENSER_ACCOUNT.toUpperCase()}_MNEMONIC`]\n ? await this.fromEnvironment(DISPENSER_ACCOUNT)\n : await this.localNetDispenser()\n }\n\n /**\n * Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).\n *\n * @example\n * ```typescript\n * const account = await accountManager.localNetDispenser()\n * ```\n * @returns The account\n */\n public async localNetDispenser() {\n const dispenser = await this._kmdAccountManager.getLocalNetDispenserAccount()\n return this.signerAccount(dispenser)\n }\n\n /**\n * Rekey an account to a new address.\n *\n * **Note:** Please be careful with this function and be sure to read the [official rekey guidance](https://dev.algorand.co/concepts/accounts/rekeying).\n *\n * @param account The account to rekey\n * @param rekeyTo The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward.\n * If a signing account is provided that will now be tracked as the signer for `account` in this `AccountManager`\n * @param options Any parameters to control the transaction or execution of the transaction\n *\n * @example Basic example (with string addresses)\n * ```typescript\n * await accountManager.rekeyAccount({account: \"ACCOUNTADDRESS\", rekeyTo: \"NEWADDRESS\"})\n * ```\n * @example Basic example (with signer accounts)\n * ```typescript\n * await accountManager.rekeyAccount({account: account1, rekeyTo: newSignerAccount})\n * ```\n * @example Advanced example\n * ```typescript\n * await accountManager.rekeyAccount({\n * account: \"ACCOUNTADDRESS\",\n * rekeyTo: \"NEWADDRESS\",\n * lease: 'lease',\n * note: 'note',\n * firstValidRound: 1000n,\n * validityWindow: 10,\n * extraFee: (1000).microAlgo(),\n * staticFee: (1000).microAlgo(),\n * // Max fee doesn't make sense with extraFee AND staticFee\n * // already specified, but here for completeness\n * maxFee: (3000).microAlgo(),\n * maxRoundsToWaitForConfirmation: 5,\n * suppressLog: true,\n * })\n * ```\n * @returns The result of the transaction and the transaction that was sent\n */\n async rekeyAccount(\n account: string | Address,\n rekeyTo: string | Address | AddressWithTransactionSigner,\n options?: Omit<CommonTransactionParams, 'sender'> & SendParams,\n ): Promise<SendSingleTransactionResult> {\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(account),\n receiver: getAddress(account),\n amount: AlgoAmount.MicroAlgo(0),\n rekeyTo: getAddress(rekeyTo),\n })\n .send(options)\n\n // If the rekey is a signing account set it as the signer for this account\n if (typeof rekeyTo === 'object' && 'addr' in rekeyTo) {\n this.rekeyed(account, rekeyTo)\n }\n\n Config.getLogger(options?.suppressLog).info(`Rekeyed ${account} to ${rekeyTo} via transaction ${result.txIds.at(-1)}`)\n\n return { ...result, transaction: result.transactions.at(-1)!, confirmation: result.confirmations.at(-1)! }\n }\n\n private async _getEnsureFundedAmount(sender: Address, minSpendingBalance: AlgoAmount, minFundingIncrement?: AlgoAmount) {\n const accountInfo = await this.getInformation(sender)\n const currentSpendingBalance = accountInfo.balance.microAlgo - accountInfo.minBalance.microAlgo\n\n const amountFunded = calculateFundAmount(minSpendingBalance.microAlgo, currentSpendingBalance, minFundingIncrement?.microAlgo ?? 0n)\n\n return amountFunded === null ? undefined : AlgoAmount.MicroAlgo(amountFunded)\n }\n\n /**\n * Funds a given account using a dispenser account as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserAccount The account to use as a dispenser funding source\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFunded(\n accountToFund: string | Address,\n dispenserAccount: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(dispenserAccount),\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using a dispenser account retrieved from the environment,\n * per the `dispenserFromEnvironment` method, as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * **Note:** requires a Node.js environment to execute.\n *\n * The dispenser account is retrieved from the account mnemonic stored in\n * process.env.DISPENSER_MNEMONIC and optionally process.env.DISPENSER_SENDER\n * if it's a rekeyed account, or against default LocalNet if no environment variables present.\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromEnvironment(\n accountToFund: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n const dispenserAccount = await this.dispenserFromEnvironment()\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: dispenserAccount,\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using the TestNet Dispenser API as a funding source such that\n * the account has a certain amount of Algo free to spend (accounting for Algo locked\n * in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserClient The TestNet dispenser funding client\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2) }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromTestNetDispenserApi(\n accountToFund: string | Address,\n dispenserClient: TestNetDispenserApiClient,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n },\n ): Promise<EnsureFundedResult | undefined> {\n if (!(await this._clientManager.isTestNet())) {\n throw new Error('Attempt to fund using TestNet dispenser API on non TestNet network.')\n }\n\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await dispenserClient.fund(addressToFund, amountFunded.microAlgo)\n return {\n amountFunded: AlgoAmount.MicroAlgo(result.amount),\n transactionId: result.txId,\n }\n }\n}\n"],"mappings":"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"}
@@ -171,7 +171,7 @@ var AccountManager = class {
171
171
  */
172
172
  getSigner(sender) {
173
173
  const signer = this._accounts[getAddress(sender).toString()]?.signer ?? this._defaultSigner;
174
- if (!signer) throw new Error(`No signer found for address ${sender}`);
174
+ if (!signer) throw new Error(`No signer found for address ${getAddress(sender)}`);
175
175
  return signer;
176
176
  }
177
177
  /**
@@ -190,7 +190,7 @@ var AccountManager = class {
190
190
  */
191
191
  getAccount(sender) {
192
192
  const account = this._accounts[getAddress(sender).toString()];
193
- if (!account) throw new Error(`No signer found for address ${sender}`);
193
+ if (!account) throw new Error(`No signer found for address ${getAddress(sender)}`);
194
194
  return account;
195
195
  }
196
196
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"account-manager.mjs","names":[],"sources":["../src/account-manager.ts"],"sourcesContent":["import { seedFromMnemonic } from '@algorandfoundation/algokit-algo25'\nimport { SuggestedParams } from '@algorandfoundation/algokit-algod-client'\nimport { Address, ReadableAddress, getAddress, getOptionalAddress } from '@algorandfoundation/algokit-common'\nimport {\n AddressWithSigners,\n AddressWithTransactionSigner,\n LogicSigAccount,\n MultisigAccount,\n MultisigMetadata,\n TransactionSigner,\n generateAddressWithSigners,\n} from '@algorandfoundation/algokit-transact'\nimport nacl from 'tweetnacl'\nimport { AccountInformation, DISPENSER_ACCOUNT } from './account'\nimport { AlgoAmount } from './amount'\nimport { ClientManager } from './client-manager'\nimport { CommonTransactionParams, TransactionComposer } from './composer'\nimport { Config } from './config'\nimport { TestNetDispenserApiClient } from './dispenser-client'\nimport { KmdAccountManager } from './kmd-account-manager'\nimport { SendParams, SendSingleTransactionResult } from './transaction/types'\nimport { calculateFundAmount, memoize } from './util'\nimport { Ed25519Generator } from '@algorandfoundation/algokit-crypto'\n\n/** Result from performing an ensureFunded call. */\nexport interface EnsureFundedResult {\n /** The transaction ID of the transaction that funded the account. */\n transactionId: string\n /** The amount that was sent to the account. */\n amountFunded: AlgoAmount\n}\n\nexport const getAccountTransactionSigner = memoize(function (\n account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount,\n): TransactionSigner {\n return account.signer\n})\n\nexport interface AccountManagerConfig {\n ed25519Generator: Ed25519Generator\n}\n\n/**\n * Creates and keeps track of signing accounts that can sign transactions for a sending address.\n * @see {@link KmdAccountManager} for KMD-specific account management\n * @see {@link AlgorandClient} for the main entry point that provides access to this manager\n */\nexport class AccountManager {\n private _clientManager: ClientManager\n private _kmdAccountManager: KmdAccountManager\n private _accounts: { [address: string]: AddressWithTransactionSigner } = {}\n private _defaultSigner?: TransactionSigner\n private _ed25519Generator: Ed25519Generator\n\n /**\n * Create a new account manager.\n * @param clientManager The ClientManager client to use for algod and kmd clients\n * @example Create a new account manager\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * ```\n */\n constructor(clientManager: ClientManager, config: AccountManagerConfig) {\n this._clientManager = clientManager\n this._kmdAccountManager = new KmdAccountManager(clientManager)\n this._ed25519Generator = config.ed25519Generator\n }\n\n private _getComposer(getSuggestedParams?: () => Promise<SuggestedParams>) {\n return new TransactionComposer({\n algod: this._clientManager.algod,\n getSigner: this.getSigner.bind(this),\n getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.suggestedParams()),\n })\n }\n\n /**\n * KMD account manager that allows you to easily get and create accounts using KMD.\n * @returns The `KmdAccountManager` instance.\n * @example\n * ```typescript\n * const kmdManager = accountManager.kmd;\n * ```\n */\n public get kmd() {\n return this._kmdAccountManager\n }\n\n /**\n * Sets the default signer to use if no other signer is specified.\n *\n * If this isn't set an a transaction needs signing for a given sender\n * then an error will be thrown from `getSigner` / `getAccount`.\n * @param signer The signer to use, either a `TransactionSigner` or a `AddressWithSigner`\n * @example\n * ```typescript\n * const signer = accountManager.random() // Can be anything that returns a `TransactionSigner` or `AddressWithSigner`\n * accountManager.setDefaultSigner(signer)\n *\n * // When signing a transaction, if there is no signer registered for the sender then the default signer will be used\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `AccountManager` so method calls can be chained\n */\n public setDefaultSigner(signer: TransactionSigner | AddressWithTransactionSigner): AccountManager {\n this._defaultSigner = 'signer' in signer ? signer.signer : signer\n return this\n }\n\n /**\n * Records the given account (that can sign) against the address of the provided account for later\n * retrieval and returns a `AddressWithTransactionSigner` along with the original account in an `account` property.\n */\n private signerAccount<T extends AddressWithTransactionSigner | LogicSigAccount | MultisigAccount>(\n account: T,\n ): Address &\n AddressWithTransactionSigner & {\n /* The underlying account that specified this address. */ account: T\n } {\n const signer = getAccountTransactionSigner(account)\n const acc: AddressWithTransactionSigner = {\n addr: account.addr,\n signer: signer,\n }\n this._accounts[acc.addr.toString()] = acc\n\n const addressWithAccount = Address.fromString(acc.addr.toString()) as Address & AddressWithTransactionSigner & { account: T }\n addressWithAccount.account = account\n addressWithAccount.addr = acc.addr\n addressWithAccount.signer = signer\n return addressWithAccount\n }\n\n /**\n * Tracks the given account for later signing.\n *\n * Note: If you are generating accounts via the various methods on `AccountManager`\n * (like `random`, `fromMnemonic`, `logicsig`, etc.) then they automatically get tracked.\n * @param account The account to register, which can be a `AddressWithSigner` or\n * a `algosdk.Account`, `algosdk.LogicSigAccount`, `SigningAccount` or `MultisigAccount`\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSignerFromAccount(algosdk.generateAccount())\n * .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))\n * .setSignerFromAccount(new SigningAccount(mnemonic, sender))\n * .setSignerFromAccount(new MultisigAccount({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]}, [account1, account2]))\n * .setSignerFromAccount({addr: \"SENDERADDRESS\", signer: transactionSigner})\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSignerFromAccount(account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount) {\n this.signerAccount(account)\n return this\n }\n\n /**\n * Tracks the given `TransactionSigner` against the given sender address for later signing.\n * @param sender The sender address to use this signer for\n * @param signer The `TransactionSigner` to sign transactions with for the given sender\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSigner(\"SENDERADDRESS\", transactionSigner)\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSigner(sender: string | Address, signer: TransactionSigner) {\n this._accounts[getAddress(sender).toString()] = { addr: getAddress(sender), signer }\n return this\n }\n\n /**\n * Takes all registered signers from the given `AccountManager` and adds them to this `AccountManager`.\n *\n * This is useful for situations where you have multiple contexts you are building accounts in such as unit tests.\n * @param anotherAccountManager Another account manager with signers registered\n * @param overwriteExisting Whether or not to overwrite any signers that have the same sender address with the ones in the other account manager or not (default: true)\n * @returns The `AccountManager` instance for method chaining\n * @example\n * ```typescript\n * accountManager2.setSigners(accountManager1);\n * ```\n */\n public setSigners(anotherAccountManager: AccountManager, overwriteExisting = true) {\n this._accounts = overwriteExisting\n ? { ...this._accounts, ...anotherAccountManager._accounts }\n : { ...anotherAccountManager._accounts, ...this._accounts }\n return this\n }\n\n /**\n * Returns the `TransactionSigner` for the given sender address, ready to sign a transaction for that sender.\n *\n * If no signer has been registered for that address then the default signer is used if registered and\n * if not then an error is thrown.\n *\n * @param sender The sender address\n * @example\n * ```typescript\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `TransactionSigner` or throws an error if not found and no default signer is set\n */\n public getSigner(sender: ReadableAddress): TransactionSigner {\n const signer = this._accounts[getAddress(sender).toString()]?.signer ?? this._defaultSigner\n if (!signer) throw new Error(`No signer found for address ${sender}`)\n return signer\n }\n\n /**\n * Returns the `AddressWithSigner` for the given sender address.\n *\n * If no signer has been registered for that address then an error is thrown.\n * @param sender The sender address\n * @example\n * ```typescript\n * const sender = accountManager.random()\n * // ...\n * // Returns the `AddressWithSigner` for `sender` that has previously been registered\n * const account = accountManager.getAccount(sender)\n * ```\n * @returns The `AddressWithSigner` or throws an error if not found\n */\n public getAccount(sender: ReadableAddress): AddressWithTransactionSigner {\n const account = this._accounts[getAddress(sender).toString()]\n if (!account) throw new Error(`No signer found for address ${sender}`)\n return account\n }\n\n /**\n * Returns the given sender account's current status, balance and spendable amounts.\n *\n * [Response data schema details](https://dev.algorand.co/reference/rest-apis/algod/#accountinformation)\n * @example\n * ```typescript\n * const address = \"XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA\";\n * const accountInfo = await accountManager.getInformation(address);\n * ```\n *\n * @param sender The account / address to look up\n * @returns The account information\n */\n public async getInformation(sender: ReadableAddress): Promise<AccountInformation> {\n const senderAddress = getAddress(sender).toString()\n const {\n round,\n lastHeartbeat = undefined,\n lastProposed = undefined,\n address,\n ...account\n } = await this._clientManager.algod.accountInformation(senderAddress)\n\n return {\n ...account,\n authAddr: account.authAddr,\n address,\n balance: AlgoAmount.MicroAlgo(Number(account.amount)),\n amountWithoutPendingRewards: AlgoAmount.MicroAlgo(Number(account.amountWithoutPendingRewards)),\n minBalance: AlgoAmount.MicroAlgo(Number(account.minBalance)),\n pendingRewards: AlgoAmount.MicroAlgo(Number(account.pendingRewards)),\n rewards: AlgoAmount.MicroAlgo(Number(account.rewards)),\n validAsOfRound: BigInt(round),\n totalAppsOptedIn: Number(account.totalAppsOptedIn),\n totalAssetsOptedIn: Number(account.totalAssetsOptedIn),\n totalCreatedApps: Number(account.totalCreatedApps),\n totalCreatedAssets: Number(account.totalCreatedAssets),\n appsTotalExtraPages: account.appsTotalExtraPages !== undefined ? Number(account.appsTotalExtraPages) : undefined,\n rewardBase: account.rewardBase !== undefined ? Number(account.rewardBase) : undefined,\n totalBoxBytes: account.totalBoxBytes !== undefined ? Number(account.totalBoxBytes) : undefined,\n totalBoxes: account.totalBoxes !== undefined ? Number(account.totalBoxes) : undefined,\n lastHeartbeatRound: lastHeartbeat !== undefined ? BigInt(lastHeartbeat) : undefined,\n lastProposedRound: lastProposed !== undefined ? BigInt(lastProposed) : undefined,\n }\n }\n\n /**\n * Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.fromMnemonic(\"mnemonic secret ...\", \"SENDERADDRESS...\")\n * ```\n * @param mnemonicSecret The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @returns The account\n */\n public fromMnemonic(mnemonicSecret: string, sender?: string | Address): AddressWithTransactionSigner {\n const seed = seedFromMnemonic(mnemonicSecret)\n\n const generated = this._ed25519Generator(seed)\n\n const addrWithSigners = generateAddressWithSigners({\n ed25519Pubkey: generated.ed25519Pubkey,\n rawEd25519Signer: generated.rawEd25519Signer,\n sendingAddress: getOptionalAddress(sender),\n })\n\n return this.signerAccount(addrWithSigners)\n }\n\n /**\n * Tracks and returns an Algorand account that is a rekeyed version of the given account to a new sender.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.rekeyed(account, \"SENDERADDRESS...\")\n * ```\n * @param account The account to use as the signer for this new rekeyed account\n * @param sender The sender address to use as the new sender\n * @returns The account\n */\n public rekeyed(sender: string | Address, account: AddressWithTransactionSigner) {\n return this.signerAccount({ addr: getAddress(sender), signer: account.signer })\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded by convention from environment variables based on the given name identifier.\n *\n * Note: This function expects to run in a Node.js environment.\n *\n * ## Convention:\n * * **Non-LocalNet:** will load process.env['\\{NAME\\}_MNEMONIC'] as a mnemonic secret; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it via a secret storage service rather than the file system.\n * If process.env['\\{NAME\\}_SENDER'] is defined then it will use that for the sender address (i.e. to support rekeyed accounts)\n * * **LocalNet:** will load the account from a KMD wallet called \\{NAME\\} and if that wallet doesn't exist it will create it and fund the account for you\n *\n * This allows you to write code that will work seamlessly in production and local development (LocalNet) without manual config locally (including when you reset the LocalNet).\n *\n * @example Default\n *\n * If you have a mnemonic secret loaded into `process.env.MY_ACCOUNT_MNEMONIC` then you can call the following to get that private key loaded into an account object:\n * ```typescript\n * const account = await accountManager.fromEnvironment('MY_ACCOUNT')\n * ```\n *\n * If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created with an account that is automatically funded with 1000 (default) ALGO from the default LocalNet dispenser.\n * If not running against LocalNet then it will use proces.env.MY_ACCOUNT_MNEMONIC as the private key and (if present) process.env.MY_ACCOUNT_SENDER as the sender address.\n *\n * @param name The name identifier of the account\n * @param fundWith The optional amount to fund the account with when it gets created (when targeting LocalNet), if not specified then 1000 ALGO will be funded from the dispenser account\n * @returns The account\n */\n public async fromEnvironment(name: string, fundWith?: AlgoAmount) {\n if (!process || !process.env) {\n throw new Error('Attempt to get account with private key from a non Node.js context; this is not supported!')\n }\n\n const accountMnemonic = process.env[`${name.toUpperCase()}_MNEMONIC`]\n const sender = process.env[`${name.toUpperCase()}_SENDER`]\n\n if (accountMnemonic) {\n return this.fromMnemonic(accountMnemonic, sender)\n }\n\n if (await this._clientManager.isLocalNet()) {\n const account = await this._kmdAccountManager.getOrCreateWalletAccount(name, fundWith)\n return this.signerAccount(account)\n }\n\n throw new Error(`Missing environment variable ${name.toUpperCase()}_MNEMONIC when looking for account ${name}`)\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).\n *\n * @param name The name of the wallet to retrieve an account from\n * @param predicate An optional filter to use to find the account (otherwise it will return a random account from the wallet)\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @example Get default funded account in a LocalNet\n *\n * ```typescript\n * const defaultDispenserAccount = await accountManager.fromKmd('unencrypted-default-wallet',\n * a => a.status !== 'Offline' && a.amount > 1_000_000_000\n * )\n * ```\n * @returns The account\n */\n public async fromKmd(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n predicate?: (account: Record<string, any>) => boolean,\n sender?: string | Address,\n ) {\n const account = await this._kmdAccountManager.getWalletAccount(name, predicate, sender)\n if (!account) throw new Error(`Unable to find KMD account ${name}${predicate ? ' with predicate' : ''}`)\n return this.signerAccount(account)\n }\n\n /**\n * Tracks and returns an account that supports partial or full multisig signing.\n *\n * @example\n * ```typescript\n * const account = accountManager.multisig({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]},\n * [(await accountManager.fromEnvironment('ACCOUNT1')).account])\n * ```\n * @param multisigParams The parameters that define the multisig account\n * @param subSigners The signers that are currently present\n * @returns A multisig account wrapper\n */\n public multisig(multisigParams: MultisigMetadata, subSigners: AddressWithSigners[]) {\n return this.signerAccount(new MultisigAccount(multisigParams, subSigners))\n }\n\n /**\n * Tracks and returns an account that represents a logic signature.\n *\n * @example\n * ```typescript\n * const account = accountManager.logicsig(program, [new Uint8Array(3, ...)])\n * ```\n * @param program The bytes that make up the compiled logic signature\n * @param args The (binary) arguments to pass into the logic signature\n * @returns A logic signature account wrapper\n */\n public logicsig(program: Uint8Array, args?: Array<Uint8Array>) {\n return this.signerAccount(new LogicSigAccount(program, args))\n }\n\n /**\n * Tracks and returns a new, random Algorand account with secret key loaded.\n *\n * @example\n * ```typescript\n * const account = accountManager.random()\n * ```\n * @returns The account\n */\n public random() {\n const keypair = nacl.sign.keyPair()\n const rawSigner = async (bytesToSign: Uint8Array): Promise<Uint8Array> => {\n return nacl.sign.detached(bytesToSign, keypair.secretKey)\n }\n\n const addrWithSigners = generateAddressWithSigners({ ed25519Pubkey: keypair.publicKey, rawEd25519Signer: rawSigner })\n\n this._accounts[addrWithSigners.addr.toString()] = addrWithSigners\n\n const acct = addrWithSigners.addr as Address & AddressWithSigners\n\n for (const prop in addrWithSigners) {\n // Create a new Address instance for avoid circular references\n if (prop === 'addr') {\n acct.addr = new Address(addrWithSigners.addr.publicKey)\n continue\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(acct as any)[prop] = (addrWithSigners as any)[prop]\n }\n\n return acct\n }\n\n /**\n * Returns an account (with private key loaded) that can act as a dispenser from\n * environment variables, or against default LocalNet if no environment variables present.\n *\n * Note: requires a Node.js environment to execute.\n *\n * If present, it will load the account mnemonic stored in process.env.DISPENSER_MNEMONIC and optionally\n * process.env.DISPENSER_SENDER if it's a rekeyed account.\n *\n * @example\n * ```typescript\n * const account = await accountManager.dispenserFromEnvironment()\n * ```\n *\n * @returns The account\n */\n public async dispenserFromEnvironment() {\n if (!process || !process.env) {\n throw new Error('Attempt to get dispenser from environment from a non Node.js context; this is not supported!')\n }\n\n return process.env[`${DISPENSER_ACCOUNT.toUpperCase()}_MNEMONIC`]\n ? await this.fromEnvironment(DISPENSER_ACCOUNT)\n : await this.localNetDispenser()\n }\n\n /**\n * Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).\n *\n * @example\n * ```typescript\n * const account = await accountManager.localNetDispenser()\n * ```\n * @returns The account\n */\n public async localNetDispenser() {\n const dispenser = await this._kmdAccountManager.getLocalNetDispenserAccount()\n return this.signerAccount(dispenser)\n }\n\n /**\n * Rekey an account to a new address.\n *\n * **Note:** Please be careful with this function and be sure to read the [official rekey guidance](https://dev.algorand.co/concepts/accounts/rekeying).\n *\n * @param account The account to rekey\n * @param rekeyTo The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward.\n * If a signing account is provided that will now be tracked as the signer for `account` in this `AccountManager`\n * @param options Any parameters to control the transaction or execution of the transaction\n *\n * @example Basic example (with string addresses)\n * ```typescript\n * await accountManager.rekeyAccount({account: \"ACCOUNTADDRESS\", rekeyTo: \"NEWADDRESS\"})\n * ```\n * @example Basic example (with signer accounts)\n * ```typescript\n * await accountManager.rekeyAccount({account: account1, rekeyTo: newSignerAccount})\n * ```\n * @example Advanced example\n * ```typescript\n * await accountManager.rekeyAccount({\n * account: \"ACCOUNTADDRESS\",\n * rekeyTo: \"NEWADDRESS\",\n * lease: 'lease',\n * note: 'note',\n * firstValidRound: 1000n,\n * validityWindow: 10,\n * extraFee: (1000).microAlgo(),\n * staticFee: (1000).microAlgo(),\n * // Max fee doesn't make sense with extraFee AND staticFee\n * // already specified, but here for completeness\n * maxFee: (3000).microAlgo(),\n * maxRoundsToWaitForConfirmation: 5,\n * suppressLog: true,\n * })\n * ```\n * @returns The result of the transaction and the transaction that was sent\n */\n async rekeyAccount(\n account: string | Address,\n rekeyTo: string | Address | AddressWithTransactionSigner,\n options?: Omit<CommonTransactionParams, 'sender'> & SendParams,\n ): Promise<SendSingleTransactionResult> {\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(account),\n receiver: getAddress(account),\n amount: AlgoAmount.MicroAlgo(0),\n rekeyTo: getAddress(rekeyTo),\n })\n .send(options)\n\n // If the rekey is a signing account set it as the signer for this account\n if (typeof rekeyTo === 'object' && 'addr' in rekeyTo) {\n this.rekeyed(account, rekeyTo)\n }\n\n Config.getLogger(options?.suppressLog).info(`Rekeyed ${account} to ${rekeyTo} via transaction ${result.txIds.at(-1)}`)\n\n return { ...result, transaction: result.transactions.at(-1)!, confirmation: result.confirmations.at(-1)! }\n }\n\n private async _getEnsureFundedAmount(sender: Address, minSpendingBalance: AlgoAmount, minFundingIncrement?: AlgoAmount) {\n const accountInfo = await this.getInformation(sender)\n const currentSpendingBalance = accountInfo.balance.microAlgo - accountInfo.minBalance.microAlgo\n\n const amountFunded = calculateFundAmount(minSpendingBalance.microAlgo, currentSpendingBalance, minFundingIncrement?.microAlgo ?? 0n)\n\n return amountFunded === null ? undefined : AlgoAmount.MicroAlgo(amountFunded)\n }\n\n /**\n * Funds a given account using a dispenser account as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserAccount The account to use as a dispenser funding source\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFunded(\n accountToFund: string | Address,\n dispenserAccount: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(dispenserAccount),\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using a dispenser account retrieved from the environment,\n * per the `dispenserFromEnvironment` method, as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * **Note:** requires a Node.js environment to execute.\n *\n * The dispenser account is retrieved from the account mnemonic stored in\n * process.env.DISPENSER_MNEMONIC and optionally process.env.DISPENSER_SENDER\n * if it's a rekeyed account, or against default LocalNet if no environment variables present.\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromEnvironment(\n accountToFund: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n const dispenserAccount = await this.dispenserFromEnvironment()\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: dispenserAccount,\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using the TestNet Dispenser API as a funding source such that\n * the account has a certain amount of Algo free to spend (accounting for Algo locked\n * in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserClient The TestNet dispenser funding client\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2) }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromTestNetDispenserApi(\n accountToFund: string | Address,\n dispenserClient: TestNetDispenserApiClient,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n },\n ): Promise<EnsureFundedResult | undefined> {\n if (!(await this._clientManager.isTestNet())) {\n throw new Error('Attempt to fund using TestNet dispenser API on non TestNet network.')\n }\n\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await dispenserClient.fund(addressToFund, amountFunded.microAlgo)\n return {\n amountFunded: AlgoAmount.MicroAlgo(result.amount),\n transactionId: result.txId,\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"account-manager.mjs","names":[],"sources":["../src/account-manager.ts"],"sourcesContent":["import { seedFromMnemonic } from '@algorandfoundation/algokit-algo25'\nimport { SuggestedParams } from '@algorandfoundation/algokit-algod-client'\nimport { Address, ReadableAddress, getAddress, getOptionalAddress } from '@algorandfoundation/algokit-common'\nimport {\n AddressWithSigners,\n AddressWithTransactionSigner,\n LogicSigAccount,\n MultisigAccount,\n MultisigMetadata,\n TransactionSigner,\n generateAddressWithSigners,\n} from '@algorandfoundation/algokit-transact'\nimport nacl from 'tweetnacl'\nimport { AccountInformation, DISPENSER_ACCOUNT } from './account'\nimport { AlgoAmount } from './amount'\nimport { ClientManager } from './client-manager'\nimport { CommonTransactionParams, TransactionComposer } from './composer'\nimport { Config } from './config'\nimport { TestNetDispenserApiClient } from './dispenser-client'\nimport { KmdAccountManager } from './kmd-account-manager'\nimport { SendParams, SendSingleTransactionResult } from './transaction/types'\nimport { calculateFundAmount, memoize } from './util'\nimport { Ed25519Generator } from '@algorandfoundation/algokit-crypto'\n\n/** Result from performing an ensureFunded call. */\nexport interface EnsureFundedResult {\n /** The transaction ID of the transaction that funded the account. */\n transactionId: string\n /** The amount that was sent to the account. */\n amountFunded: AlgoAmount\n}\n\nexport const getAccountTransactionSigner = memoize(function (\n account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount,\n): TransactionSigner {\n return account.signer\n})\n\nexport interface AccountManagerConfig {\n ed25519Generator: Ed25519Generator\n}\n\n/**\n * Creates and keeps track of signing accounts that can sign transactions for a sending address.\n * @see {@link KmdAccountManager} for KMD-specific account management\n * @see {@link AlgorandClient} for the main entry point that provides access to this manager\n */\nexport class AccountManager {\n private _clientManager: ClientManager\n private _kmdAccountManager: KmdAccountManager\n private _accounts: { [address: string]: AddressWithTransactionSigner } = {}\n private _defaultSigner?: TransactionSigner\n private _ed25519Generator: Ed25519Generator\n\n /**\n * Create a new account manager.\n * @param clientManager The ClientManager client to use for algod and kmd clients\n * @example Create a new account manager\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * ```\n */\n constructor(clientManager: ClientManager, config: AccountManagerConfig) {\n this._clientManager = clientManager\n this._kmdAccountManager = new KmdAccountManager(clientManager)\n this._ed25519Generator = config.ed25519Generator\n }\n\n private _getComposer(getSuggestedParams?: () => Promise<SuggestedParams>) {\n return new TransactionComposer({\n algod: this._clientManager.algod,\n getSigner: this.getSigner.bind(this),\n getSuggestedParams: getSuggestedParams ?? (() => this._clientManager.algod.suggestedParams()),\n })\n }\n\n /**\n * KMD account manager that allows you to easily get and create accounts using KMD.\n * @returns The `KmdAccountManager` instance.\n * @example\n * ```typescript\n * const kmdManager = accountManager.kmd;\n * ```\n */\n public get kmd() {\n return this._kmdAccountManager\n }\n\n /**\n * Sets the default signer to use if no other signer is specified.\n *\n * If this isn't set an a transaction needs signing for a given sender\n * then an error will be thrown from `getSigner` / `getAccount`.\n * @param signer The signer to use, either a `TransactionSigner` or a `AddressWithSigner`\n * @example\n * ```typescript\n * const signer = accountManager.random() // Can be anything that returns a `TransactionSigner` or `AddressWithSigner`\n * accountManager.setDefaultSigner(signer)\n *\n * // When signing a transaction, if there is no signer registered for the sender then the default signer will be used\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `AccountManager` so method calls can be chained\n */\n public setDefaultSigner(signer: TransactionSigner | AddressWithTransactionSigner): AccountManager {\n this._defaultSigner = 'signer' in signer ? signer.signer : signer\n return this\n }\n\n /**\n * Records the given account (that can sign) against the address of the provided account for later\n * retrieval and returns a `AddressWithTransactionSigner` along with the original account in an `account` property.\n */\n private signerAccount<T extends AddressWithTransactionSigner | LogicSigAccount | MultisigAccount>(\n account: T,\n ): Address &\n AddressWithTransactionSigner & {\n /* The underlying account that specified this address. */ account: T\n } {\n const signer = getAccountTransactionSigner(account)\n const acc: AddressWithTransactionSigner = {\n addr: account.addr,\n signer: signer,\n }\n this._accounts[acc.addr.toString()] = acc\n\n const addressWithAccount = Address.fromString(acc.addr.toString()) as Address & AddressWithTransactionSigner & { account: T }\n addressWithAccount.account = account\n addressWithAccount.addr = acc.addr\n addressWithAccount.signer = signer\n return addressWithAccount\n }\n\n /**\n * Tracks the given account for later signing.\n *\n * Note: If you are generating accounts via the various methods on `AccountManager`\n * (like `random`, `fromMnemonic`, `logicsig`, etc.) then they automatically get tracked.\n * @param account The account to register, which can be a `AddressWithSigner` or\n * a `algosdk.Account`, `algosdk.LogicSigAccount`, `SigningAccount` or `MultisigAccount`\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSignerFromAccount(algosdk.generateAccount())\n * .setSignerFromAccount(new algosdk.LogicSigAccount(program, args))\n * .setSignerFromAccount(new SigningAccount(mnemonic, sender))\n * .setSignerFromAccount(new MultisigAccount({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]}, [account1, account2]))\n * .setSignerFromAccount({addr: \"SENDERADDRESS\", signer: transactionSigner})\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSignerFromAccount(account: AddressWithTransactionSigner | LogicSigAccount | MultisigAccount) {\n this.signerAccount(account)\n return this\n }\n\n /**\n * Tracks the given `TransactionSigner` against the given sender address for later signing.\n * @param sender The sender address to use this signer for\n * @param signer The `TransactionSigner` to sign transactions with for the given sender\n * @example\n * ```typescript\n * const accountManager = new AccountManager(clientManager)\n * .setSigner(\"SENDERADDRESS\", transactionSigner)\n * ```\n * @returns The `AccountManager` instance for method chaining\n */\n public setSigner(sender: string | Address, signer: TransactionSigner) {\n this._accounts[getAddress(sender).toString()] = { addr: getAddress(sender), signer }\n return this\n }\n\n /**\n * Takes all registered signers from the given `AccountManager` and adds them to this `AccountManager`.\n *\n * This is useful for situations where you have multiple contexts you are building accounts in such as unit tests.\n * @param anotherAccountManager Another account manager with signers registered\n * @param overwriteExisting Whether or not to overwrite any signers that have the same sender address with the ones in the other account manager or not (default: true)\n * @returns The `AccountManager` instance for method chaining\n * @example\n * ```typescript\n * accountManager2.setSigners(accountManager1);\n * ```\n */\n public setSigners(anotherAccountManager: AccountManager, overwriteExisting = true) {\n this._accounts = overwriteExisting\n ? { ...this._accounts, ...anotherAccountManager._accounts }\n : { ...anotherAccountManager._accounts, ...this._accounts }\n return this\n }\n\n /**\n * Returns the `TransactionSigner` for the given sender address, ready to sign a transaction for that sender.\n *\n * If no signer has been registered for that address then the default signer is used if registered and\n * if not then an error is thrown.\n *\n * @param sender The sender address\n * @example\n * ```typescript\n * const signer = accountManager.getSigner(\"SENDERADDRESS\")\n * ```\n * @returns The `TransactionSigner` or throws an error if not found and no default signer is set\n */\n public getSigner(sender: ReadableAddress): TransactionSigner {\n const signer = this._accounts[getAddress(sender).toString()]?.signer ?? this._defaultSigner\n if (!signer) throw new Error(`No signer found for address ${getAddress(sender)}`)\n return signer\n }\n\n /**\n * Returns the `AddressWithSigner` for the given sender address.\n *\n * If no signer has been registered for that address then an error is thrown.\n * @param sender The sender address\n * @example\n * ```typescript\n * const sender = accountManager.random()\n * // ...\n * // Returns the `AddressWithSigner` for `sender` that has previously been registered\n * const account = accountManager.getAccount(sender)\n * ```\n * @returns The `AddressWithSigner` or throws an error if not found\n */\n public getAccount(sender: ReadableAddress): AddressWithTransactionSigner {\n const account = this._accounts[getAddress(sender).toString()]\n if (!account) throw new Error(`No signer found for address ${getAddress(sender)}`)\n return account\n }\n\n /**\n * Returns the given sender account's current status, balance and spendable amounts.\n *\n * [Response data schema details](https://dev.algorand.co/reference/rest-apis/algod/#accountinformation)\n * @example\n * ```typescript\n * const address = \"XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA\";\n * const accountInfo = await accountManager.getInformation(address);\n * ```\n *\n * @param sender The account / address to look up\n * @returns The account information\n */\n public async getInformation(sender: ReadableAddress): Promise<AccountInformation> {\n const senderAddress = getAddress(sender).toString()\n const {\n round,\n lastHeartbeat = undefined,\n lastProposed = undefined,\n address,\n ...account\n } = await this._clientManager.algod.accountInformation(senderAddress)\n\n return {\n ...account,\n authAddr: account.authAddr,\n address,\n balance: AlgoAmount.MicroAlgo(Number(account.amount)),\n amountWithoutPendingRewards: AlgoAmount.MicroAlgo(Number(account.amountWithoutPendingRewards)),\n minBalance: AlgoAmount.MicroAlgo(Number(account.minBalance)),\n pendingRewards: AlgoAmount.MicroAlgo(Number(account.pendingRewards)),\n rewards: AlgoAmount.MicroAlgo(Number(account.rewards)),\n validAsOfRound: BigInt(round),\n totalAppsOptedIn: Number(account.totalAppsOptedIn),\n totalAssetsOptedIn: Number(account.totalAssetsOptedIn),\n totalCreatedApps: Number(account.totalCreatedApps),\n totalCreatedAssets: Number(account.totalCreatedAssets),\n appsTotalExtraPages: account.appsTotalExtraPages !== undefined ? Number(account.appsTotalExtraPages) : undefined,\n rewardBase: account.rewardBase !== undefined ? Number(account.rewardBase) : undefined,\n totalBoxBytes: account.totalBoxBytes !== undefined ? Number(account.totalBoxBytes) : undefined,\n totalBoxes: account.totalBoxes !== undefined ? Number(account.totalBoxes) : undefined,\n lastHeartbeatRound: lastHeartbeat !== undefined ? BigInt(lastHeartbeat) : undefined,\n lastProposedRound: lastProposed !== undefined ? BigInt(lastProposed) : undefined,\n }\n }\n\n /**\n * Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.fromMnemonic(\"mnemonic secret ...\", \"SENDERADDRESS...\")\n * ```\n * @param mnemonicSecret The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @returns The account\n */\n public fromMnemonic(mnemonicSecret: string, sender?: string | Address): AddressWithTransactionSigner {\n const seed = seedFromMnemonic(mnemonicSecret)\n\n const generated = this._ed25519Generator(seed)\n\n const addrWithSigners = generateAddressWithSigners({\n ed25519Pubkey: generated.ed25519Pubkey,\n rawEd25519Signer: generated.rawEd25519Signer,\n sendingAddress: getOptionalAddress(sender),\n })\n\n return this.signerAccount(addrWithSigners)\n }\n\n /**\n * Tracks and returns an Algorand account that is a rekeyed version of the given account to a new sender.\n *\n * @example\n * ```typescript\n * const account = accountManager.fromMnemonic(\"mnemonic secret ...\")\n * const rekeyedAccount = accountManager.rekeyed(account, \"SENDERADDRESS...\")\n * ```\n * @param account The account to use as the signer for this new rekeyed account\n * @param sender The sender address to use as the new sender\n * @returns The account\n */\n public rekeyed(sender: string | Address, account: AddressWithTransactionSigner) {\n return this.signerAccount({ addr: getAddress(sender), signer: account.signer })\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded by convention from environment variables based on the given name identifier.\n *\n * Note: This function expects to run in a Node.js environment.\n *\n * ## Convention:\n * * **Non-LocalNet:** will load process.env['\\{NAME\\}_MNEMONIC'] as a mnemonic secret; **Note: Be careful how the mnemonic is handled**,\n * never commit it into source control and ideally load it via a secret storage service rather than the file system.\n * If process.env['\\{NAME\\}_SENDER'] is defined then it will use that for the sender address (i.e. to support rekeyed accounts)\n * * **LocalNet:** will load the account from a KMD wallet called \\{NAME\\} and if that wallet doesn't exist it will create it and fund the account for you\n *\n * This allows you to write code that will work seamlessly in production and local development (LocalNet) without manual config locally (including when you reset the LocalNet).\n *\n * @example Default\n *\n * If you have a mnemonic secret loaded into `process.env.MY_ACCOUNT_MNEMONIC` then you can call the following to get that private key loaded into an account object:\n * ```typescript\n * const account = await accountManager.fromEnvironment('MY_ACCOUNT')\n * ```\n *\n * If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created with an account that is automatically funded with 1000 (default) ALGO from the default LocalNet dispenser.\n * If not running against LocalNet then it will use proces.env.MY_ACCOUNT_MNEMONIC as the private key and (if present) process.env.MY_ACCOUNT_SENDER as the sender address.\n *\n * @param name The name identifier of the account\n * @param fundWith The optional amount to fund the account with when it gets created (when targeting LocalNet), if not specified then 1000 ALGO will be funded from the dispenser account\n * @returns The account\n */\n public async fromEnvironment(name: string, fundWith?: AlgoAmount) {\n if (!process || !process.env) {\n throw new Error('Attempt to get account with private key from a non Node.js context; this is not supported!')\n }\n\n const accountMnemonic = process.env[`${name.toUpperCase()}_MNEMONIC`]\n const sender = process.env[`${name.toUpperCase()}_SENDER`]\n\n if (accountMnemonic) {\n return this.fromMnemonic(accountMnemonic, sender)\n }\n\n if (await this._clientManager.isLocalNet()) {\n const account = await this._kmdAccountManager.getOrCreateWalletAccount(name, fundWith)\n return this.signerAccount(account)\n }\n\n throw new Error(`Missing environment variable ${name.toUpperCase()}_MNEMONIC when looking for account ${name}`)\n }\n\n /**\n * Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).\n *\n * @param name The name of the wallet to retrieve an account from\n * @param predicate An optional filter to use to find the account (otherwise it will return a random account from the wallet)\n * @param sender The optional sender address to use this signer for (aka a rekeyed account)\n * @example Get default funded account in a LocalNet\n *\n * ```typescript\n * const defaultDispenserAccount = await accountManager.fromKmd('unencrypted-default-wallet',\n * a => a.status !== 'Offline' && a.amount > 1_000_000_000\n * )\n * ```\n * @returns The account\n */\n public async fromKmd(\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n predicate?: (account: Record<string, any>) => boolean,\n sender?: string | Address,\n ) {\n const account = await this._kmdAccountManager.getWalletAccount(name, predicate, sender)\n if (!account) throw new Error(`Unable to find KMD account ${name}${predicate ? ' with predicate' : ''}`)\n return this.signerAccount(account)\n }\n\n /**\n * Tracks and returns an account that supports partial or full multisig signing.\n *\n * @example\n * ```typescript\n * const account = accountManager.multisig({version: 1, threshold: 1, addrs: [\"ADDRESS1...\", \"ADDRESS2...\"]},\n * [(await accountManager.fromEnvironment('ACCOUNT1')).account])\n * ```\n * @param multisigParams The parameters that define the multisig account\n * @param subSigners The signers that are currently present\n * @returns A multisig account wrapper\n */\n public multisig(multisigParams: MultisigMetadata, subSigners: AddressWithSigners[]) {\n return this.signerAccount(new MultisigAccount(multisigParams, subSigners))\n }\n\n /**\n * Tracks and returns an account that represents a logic signature.\n *\n * @example\n * ```typescript\n * const account = accountManager.logicsig(program, [new Uint8Array(3, ...)])\n * ```\n * @param program The bytes that make up the compiled logic signature\n * @param args The (binary) arguments to pass into the logic signature\n * @returns A logic signature account wrapper\n */\n public logicsig(program: Uint8Array, args?: Array<Uint8Array>) {\n return this.signerAccount(new LogicSigAccount(program, args))\n }\n\n /**\n * Tracks and returns a new, random Algorand account with secret key loaded.\n *\n * @example\n * ```typescript\n * const account = accountManager.random()\n * ```\n * @returns The account\n */\n public random() {\n const keypair = nacl.sign.keyPair()\n const rawSigner = async (bytesToSign: Uint8Array): Promise<Uint8Array> => {\n return nacl.sign.detached(bytesToSign, keypair.secretKey)\n }\n\n const addrWithSigners = generateAddressWithSigners({ ed25519Pubkey: keypair.publicKey, rawEd25519Signer: rawSigner })\n\n this._accounts[addrWithSigners.addr.toString()] = addrWithSigners\n\n const acct = addrWithSigners.addr as Address & AddressWithSigners\n\n for (const prop in addrWithSigners) {\n // Create a new Address instance for avoid circular references\n if (prop === 'addr') {\n acct.addr = new Address(addrWithSigners.addr.publicKey)\n continue\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(acct as any)[prop] = (addrWithSigners as any)[prop]\n }\n\n return acct\n }\n\n /**\n * Returns an account (with private key loaded) that can act as a dispenser from\n * environment variables, or against default LocalNet if no environment variables present.\n *\n * Note: requires a Node.js environment to execute.\n *\n * If present, it will load the account mnemonic stored in process.env.DISPENSER_MNEMONIC and optionally\n * process.env.DISPENSER_SENDER if it's a rekeyed account.\n *\n * @example\n * ```typescript\n * const account = await accountManager.dispenserFromEnvironment()\n * ```\n *\n * @returns The account\n */\n public async dispenserFromEnvironment() {\n if (!process || !process.env) {\n throw new Error('Attempt to get dispenser from environment from a non Node.js context; this is not supported!')\n }\n\n return process.env[`${DISPENSER_ACCOUNT.toUpperCase()}_MNEMONIC`]\n ? await this.fromEnvironment(DISPENSER_ACCOUNT)\n : await this.localNetDispenser()\n }\n\n /**\n * Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).\n *\n * @example\n * ```typescript\n * const account = await accountManager.localNetDispenser()\n * ```\n * @returns The account\n */\n public async localNetDispenser() {\n const dispenser = await this._kmdAccountManager.getLocalNetDispenserAccount()\n return this.signerAccount(dispenser)\n }\n\n /**\n * Rekey an account to a new address.\n *\n * **Note:** Please be careful with this function and be sure to read the [official rekey guidance](https://dev.algorand.co/concepts/accounts/rekeying).\n *\n * @param account The account to rekey\n * @param rekeyTo The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward.\n * If a signing account is provided that will now be tracked as the signer for `account` in this `AccountManager`\n * @param options Any parameters to control the transaction or execution of the transaction\n *\n * @example Basic example (with string addresses)\n * ```typescript\n * await accountManager.rekeyAccount({account: \"ACCOUNTADDRESS\", rekeyTo: \"NEWADDRESS\"})\n * ```\n * @example Basic example (with signer accounts)\n * ```typescript\n * await accountManager.rekeyAccount({account: account1, rekeyTo: newSignerAccount})\n * ```\n * @example Advanced example\n * ```typescript\n * await accountManager.rekeyAccount({\n * account: \"ACCOUNTADDRESS\",\n * rekeyTo: \"NEWADDRESS\",\n * lease: 'lease',\n * note: 'note',\n * firstValidRound: 1000n,\n * validityWindow: 10,\n * extraFee: (1000).microAlgo(),\n * staticFee: (1000).microAlgo(),\n * // Max fee doesn't make sense with extraFee AND staticFee\n * // already specified, but here for completeness\n * maxFee: (3000).microAlgo(),\n * maxRoundsToWaitForConfirmation: 5,\n * suppressLog: true,\n * })\n * ```\n * @returns The result of the transaction and the transaction that was sent\n */\n async rekeyAccount(\n account: string | Address,\n rekeyTo: string | Address | AddressWithTransactionSigner,\n options?: Omit<CommonTransactionParams, 'sender'> & SendParams,\n ): Promise<SendSingleTransactionResult> {\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(account),\n receiver: getAddress(account),\n amount: AlgoAmount.MicroAlgo(0),\n rekeyTo: getAddress(rekeyTo),\n })\n .send(options)\n\n // If the rekey is a signing account set it as the signer for this account\n if (typeof rekeyTo === 'object' && 'addr' in rekeyTo) {\n this.rekeyed(account, rekeyTo)\n }\n\n Config.getLogger(options?.suppressLog).info(`Rekeyed ${account} to ${rekeyTo} via transaction ${result.txIds.at(-1)}`)\n\n return { ...result, transaction: result.transactions.at(-1)!, confirmation: result.confirmations.at(-1)! }\n }\n\n private async _getEnsureFundedAmount(sender: Address, minSpendingBalance: AlgoAmount, minFundingIncrement?: AlgoAmount) {\n const accountInfo = await this.getInformation(sender)\n const currentSpendingBalance = accountInfo.balance.microAlgo - accountInfo.minBalance.microAlgo\n\n const amountFunded = calculateFundAmount(minSpendingBalance.microAlgo, currentSpendingBalance, minFundingIncrement?.microAlgo ?? 0n)\n\n return amountFunded === null ? undefined : AlgoAmount.MicroAlgo(amountFunded)\n }\n\n /**\n * Funds a given account using a dispenser account as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserAccount The account to use as a dispenser funding source\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFunded(\"ACCOUNTADDRESS\", \"DISPENSERADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFunded(\n accountToFund: string | Address,\n dispenserAccount: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: getAddress(dispenserAccount),\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using a dispenser account retrieved from the environment,\n * per the `dispenserFromEnvironment` method, as a funding source such that\n * the given account has a certain amount of Algo free to spend (accounting for\n * Algo locked in minimum balance requirement).\n *\n * **Note:** requires a Node.js environment to execute.\n *\n * The dispenser account is retrieved from the account mnemonic stored in\n * process.env.DISPENSER_MNEMONIC and optionally process.env.DISPENSER_SENDER\n * if it's a rekeyed account, or against default LocalNet if no environment variables present.\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromEnvironment(\"ACCOUNTADDRESS\", algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2), fee: (1000).microAlgo(), suppressLog: true }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromEnvironment(\n accountToFund: string | Address,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n } & SendParams &\n Omit<CommonTransactionParams, 'sender'>,\n ): Promise<(SendSingleTransactionResult & EnsureFundedResult) | undefined> {\n const addressToFund = getAddress(accountToFund)\n const dispenserAccount = await this.dispenserFromEnvironment()\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await this._getComposer()\n .addPayment({\n ...options,\n sender: dispenserAccount,\n receiver: addressToFund,\n amount: amountFunded,\n })\n .send(options)\n\n return {\n ...result,\n transaction: result.transactions[0],\n confirmation: result.confirmations[0],\n transactionId: result.txIds[0],\n amountFunded: amountFunded,\n }\n }\n\n /**\n * Funds a given account using the TestNet Dispenser API as a funding source such that\n * the account has a certain amount of Algo free to spend (accounting for Algo locked\n * in minimum balance requirement).\n *\n * https://dev.algorand.co/concepts/smart-contracts/costs-constraints#mbr\n *\n * @param accountToFund The account to fund\n * @param dispenserClient The TestNet dispenser funding client\n * @param minSpendingBalance The minimum balance of Algo that the account should have available to spend (i.e. on top of minimum balance requirement)\n * @param options Optional parameters to control the funding increment, transaction or execution of the transaction\n * @example Example using AlgorandClient\n * ```typescript\n * // Basic example\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1))\n * // With configuration\n * await accountManager.ensureFundedFromTestNetDispenserApi(\"ACCOUNTADDRESS\", algorand.client.getTestNetDispenserFromEnvironment(), algokit.algo(1),\n * { minFundingIncrement: algokit.algo(2) }\n * )\n * ```\n * @returns\n * - The result of executing the dispensing transaction and the `amountFunded` if funds were needed.\n * - `undefined` if no funds were needed.\n */\n async ensureFundedFromTestNetDispenserApi(\n accountToFund: string | Address,\n dispenserClient: TestNetDispenserApiClient,\n minSpendingBalance: AlgoAmount,\n options?: {\n minFundingIncrement?: AlgoAmount\n },\n ): Promise<EnsureFundedResult | undefined> {\n if (!(await this._clientManager.isTestNet())) {\n throw new Error('Attempt to fund using TestNet dispenser API on non TestNet network.')\n }\n\n const addressToFund = getAddress(accountToFund)\n\n const amountFunded = await this._getEnsureFundedAmount(addressToFund, minSpendingBalance, options?.minFundingIncrement)\n if (!amountFunded) return undefined\n\n const result = await dispenserClient.fund(addressToFund, amountFunded.microAlgo)\n return {\n amountFunded: AlgoAmount.MicroAlgo(result.amount),\n transactionId: result.txId,\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAgCA,MAAa,8BAA8B,QAAQ,SACjD,SACmB;AACnB,QAAO,QAAQ;EACf;;;;;;AAWF,IAAa,iBAAb,MAA4B;CAC1B,AAAQ;CACR,AAAQ;CACR,AAAQ,YAAiE,EAAE;CAC3E,AAAQ;CACR,AAAQ;;;;;;;;;CAUR,YAAY,eAA8B,QAA8B;AACtE,OAAK,iBAAiB;AACtB,OAAK,qBAAqB,IAAI,kBAAkB,cAAc;AAC9D,OAAK,oBAAoB,OAAO;;CAGlC,AAAQ,aAAa,oBAAqD;AACxE,SAAO,IAAI,oBAAoB;GAC7B,OAAO,KAAK,eAAe;GAC3B,WAAW,KAAK,UAAU,KAAK,KAAK;GACpC,oBAAoB,6BAA6B,KAAK,eAAe,MAAM,iBAAiB;GAC7F,CAAC;;;;;;;;;;CAWJ,IAAW,MAAM;AACf,SAAO,KAAK;;;;;;;;;;;;;;;;;;CAmBd,AAAO,iBAAiB,QAA0E;AAChG,OAAK,iBAAiB,YAAY,SAAS,OAAO,SAAS;AAC3D,SAAO;;;;;;CAOT,AAAQ,cACN,SAIE;EACF,MAAM,SAAS,4BAA4B,QAAQ;EACnD,MAAM,MAAoC;GACxC,MAAM,QAAQ;GACN;GACT;AACD,OAAK,UAAU,IAAI,KAAK,UAAU,IAAI;EAEtC,MAAM,qBAAqB,QAAQ,WAAW,IAAI,KAAK,UAAU,CAAC;AAClE,qBAAmB,UAAU;AAC7B,qBAAmB,OAAO,IAAI;AAC9B,qBAAmB,SAAS;AAC5B,SAAO;;;;;;;;;;;;;;;;;;;;CAqBT,AAAO,qBAAqB,SAA2E;AACrG,OAAK,cAAc,QAAQ;AAC3B,SAAO;;;;;;;;;;;;;CAcT,AAAO,UAAU,QAA0B,QAA2B;AACpE,OAAK,UAAU,WAAW,OAAO,CAAC,UAAU,IAAI;GAAE,MAAM,WAAW,OAAO;GAAE;GAAQ;AACpF,SAAO;;;;;;;;;;;;;;CAeT,AAAO,WAAW,uBAAuC,oBAAoB,MAAM;AACjF,OAAK,YAAY,oBACb;GAAE,GAAG,KAAK;GAAW,GAAG,sBAAsB;GAAW,GACzD;GAAE,GAAG,sBAAsB;GAAW,GAAG,KAAK;GAAW;AAC7D,SAAO;;;;;;;;;;;;;;;CAgBT,AAAO,UAAU,QAA4C;EAC3D,MAAM,SAAS,KAAK,UAAU,WAAW,OAAO,CAAC,UAAU,GAAG,UAAU,KAAK;AAC7E,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,+BAA+B,WAAW,OAAO,GAAG;AACjF,SAAO;;;;;;;;;;;;;;;;CAiBT,AAAO,WAAW,QAAuD;EACvE,MAAM,UAAU,KAAK,UAAU,WAAW,OAAO,CAAC,UAAU;AAC5D,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,+BAA+B,WAAW,OAAO,GAAG;AAClF,SAAO;;;;;;;;;;;;;;;CAgBT,MAAa,eAAe,QAAsD;EAChF,MAAM,gBAAgB,WAAW,OAAO,CAAC,UAAU;EACnD,MAAM,EACJ,OACA,gBAAgB,QAChB,eAAe,QACf,SACA,GAAG,YACD,MAAM,KAAK,eAAe,MAAM,mBAAmB,cAAc;AAErE,SAAO;GACL,GAAG;GACH,UAAU,QAAQ;GAClB;GACA,SAAS,WAAW,UAAU,OAAO,QAAQ,OAAO,CAAC;GACrD,6BAA6B,WAAW,UAAU,OAAO,QAAQ,4BAA4B,CAAC;GAC9F,YAAY,WAAW,UAAU,OAAO,QAAQ,WAAW,CAAC;GAC5D,gBAAgB,WAAW,UAAU,OAAO,QAAQ,eAAe,CAAC;GACpE,SAAS,WAAW,UAAU,OAAO,QAAQ,QAAQ,CAAC;GACtD,gBAAgB,OAAO,MAAM;GAC7B,kBAAkB,OAAO,QAAQ,iBAAiB;GAClD,oBAAoB,OAAO,QAAQ,mBAAmB;GACtD,kBAAkB,OAAO,QAAQ,iBAAiB;GAClD,oBAAoB,OAAO,QAAQ,mBAAmB;GACtD,qBAAqB,QAAQ,wBAAwB,SAAY,OAAO,QAAQ,oBAAoB,GAAG;GACvG,YAAY,QAAQ,eAAe,SAAY,OAAO,QAAQ,WAAW,GAAG;GAC5E,eAAe,QAAQ,kBAAkB,SAAY,OAAO,QAAQ,cAAc,GAAG;GACrF,YAAY,QAAQ,eAAe,SAAY,OAAO,QAAQ,WAAW,GAAG;GAC5E,oBAAoB,kBAAkB,SAAY,OAAO,cAAc,GAAG;GAC1E,mBAAmB,iBAAiB,SAAY,OAAO,aAAa,GAAG;GACxE;;;;;;;;;;;;;;;CAgBH,AAAO,aAAa,gBAAwB,QAAyD;EACnG,MAAM,OAAO,iBAAiB,eAAe;EAE7C,MAAM,YAAY,KAAK,kBAAkB,KAAK;EAE9C,MAAM,kBAAkB,2BAA2B;GACjD,eAAe,UAAU;GACzB,kBAAkB,UAAU;GAC5B,gBAAgB,mBAAmB,OAAO;GAC3C,CAAC;AAEF,SAAO,KAAK,cAAc,gBAAgB;;;;;;;;;;;;;;CAe5C,AAAO,QAAQ,QAA0B,SAAuC;AAC9E,SAAO,KAAK,cAAc;GAAE,MAAM,WAAW,OAAO;GAAE,QAAQ,QAAQ;GAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BjF,MAAa,gBAAgB,MAAc,UAAuB;AAChE,MAAI,CAAC,WAAW,CAAC,QAAQ,IACvB,OAAM,IAAI,MAAM,6FAA6F;EAG/G,MAAM,kBAAkB,QAAQ,IAAI,GAAG,KAAK,aAAa,CAAC;EAC1D,MAAM,SAAS,QAAQ,IAAI,GAAG,KAAK,aAAa,CAAC;AAEjD,MAAI,gBACF,QAAO,KAAK,aAAa,iBAAiB,OAAO;AAGnD,MAAI,MAAM,KAAK,eAAe,YAAY,EAAE;GAC1C,MAAM,UAAU,MAAM,KAAK,mBAAmB,yBAAyB,MAAM,SAAS;AACtF,UAAO,KAAK,cAAc,QAAQ;;AAGpC,QAAM,IAAI,MAAM,gCAAgC,KAAK,aAAa,CAAC,qCAAqC,OAAO;;;;;;;;;;;;;;;;;CAkBjH,MAAa,QACX,MAEA,WACA,QACA;EACA,MAAM,UAAU,MAAM,KAAK,mBAAmB,iBAAiB,MAAM,WAAW,OAAO;AACvF,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,8BAA8B,OAAO,YAAY,oBAAoB,KAAK;AACxG,SAAO,KAAK,cAAc,QAAQ;;;;;;;;;;;;;;CAepC,AAAO,SAAS,gBAAkC,YAAkC;AAClF,SAAO,KAAK,cAAc,IAAI,gBAAgB,gBAAgB,WAAW,CAAC;;;;;;;;;;;;;CAc5E,AAAO,SAAS,SAAqB,MAA0B;AAC7D,SAAO,KAAK,cAAc,IAAI,gBAAgB,SAAS,KAAK,CAAC;;;;;;;;;;;CAY/D,AAAO,SAAS;EACd,MAAM,UAAU,KAAK,KAAK,SAAS;EACnC,MAAM,YAAY,OAAO,gBAAiD;AACxE,UAAO,KAAK,KAAK,SAAS,aAAa,QAAQ,UAAU;;EAG3D,MAAM,kBAAkB,2BAA2B;GAAE,eAAe,QAAQ;GAAW,kBAAkB;GAAW,CAAC;AAErH,OAAK,UAAU,gBAAgB,KAAK,UAAU,IAAI;EAElD,MAAM,OAAO,gBAAgB;AAE7B,OAAK,MAAM,QAAQ,iBAAiB;AAElC,OAAI,SAAS,QAAQ;AACnB,SAAK,OAAO,IAAI,QAAQ,gBAAgB,KAAK,UAAU;AACvD;;AAGD,GAAC,KAAa,QAAS,gBAAwB;;AAGlD,SAAO;;;;;;;;;;;;;;;;;;CAmBT,MAAa,2BAA2B;AACtC,MAAI,CAAC,WAAW,CAAC,QAAQ,IACvB,OAAM,IAAI,MAAM,+FAA+F;AAGjH,SAAO,QAAQ,IAAI,GAAG,kBAAkB,aAAa,CAAC,cAClD,MAAM,KAAK,gBAAgB,kBAAkB,GAC7C,MAAM,KAAK,mBAAmB;;;;;;;;;;;CAYpC,MAAa,oBAAoB;EAC/B,MAAM,YAAY,MAAM,KAAK,mBAAmB,6BAA6B;AAC7E,SAAO,KAAK,cAAc,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCtC,MAAM,aACJ,SACA,SACA,SACsC;EACtC,MAAM,SAAS,MAAM,KAAK,cAAc,CACrC,WAAW;GACV,GAAG;GACH,QAAQ,WAAW,QAAQ;GAC3B,UAAU,WAAW,QAAQ;GAC7B,QAAQ,WAAW,UAAU,EAAE;GAC/B,SAAS,WAAW,QAAQ;GAC7B,CAAC,CACD,KAAK,QAAQ;AAGhB,MAAI,OAAO,YAAY,YAAY,UAAU,QAC3C,MAAK,QAAQ,SAAS,QAAQ;AAGhC,SAAO,UAAU,SAAS,YAAY,CAAC,KAAK,WAAW,QAAQ,MAAM,QAAQ,mBAAmB,OAAO,MAAM,GAAG,GAAG,GAAG;AAEtH,SAAO;GAAE,GAAG;GAAQ,aAAa,OAAO,aAAa,GAAG,GAAG;GAAG,cAAc,OAAO,cAAc,GAAG,GAAG;GAAG;;CAG5G,MAAc,uBAAuB,QAAiB,oBAAgC,qBAAkC;EACtH,MAAM,cAAc,MAAM,KAAK,eAAe,OAAO;EACrD,MAAM,yBAAyB,YAAY,QAAQ,YAAY,YAAY,WAAW;EAEtF,MAAM,eAAe,oBAAoB,mBAAmB,WAAW,wBAAwB,qBAAqB,aAAa,GAAG;AAEpI,SAAO,iBAAiB,OAAO,SAAY,WAAW,UAAU,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;CA2B/E,MAAM,aACJ,eACA,kBACA,oBACA,SAIyE;EACzE,MAAM,gBAAgB,WAAW,cAAc;EAE/C,MAAM,eAAe,MAAM,KAAK,uBAAuB,eAAe,oBAAoB,SAAS,oBAAoB;AACvH,MAAI,CAAC,aAAc,QAAO;EAE1B,MAAM,SAAS,MAAM,KAAK,cAAc,CACrC,WAAW;GACV,GAAG;GACH,QAAQ,WAAW,iBAAiB;GACpC,UAAU;GACV,QAAQ;GACT,CAAC,CACD,KAAK,QAAQ;AAEhB,SAAO;GACL,GAAG;GACH,aAAa,OAAO,aAAa;GACjC,cAAc,OAAO,cAAc;GACnC,eAAe,OAAO,MAAM;GACd;GACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCH,MAAM,4BACJ,eACA,oBACA,SAIyE;EACzE,MAAM,gBAAgB,WAAW,cAAc;EAC/C,MAAM,mBAAmB,MAAM,KAAK,0BAA0B;EAE9D,MAAM,eAAe,MAAM,KAAK,uBAAuB,eAAe,oBAAoB,SAAS,oBAAoB;AACvH,MAAI,CAAC,aAAc,QAAO;EAE1B,MAAM,SAAS,MAAM,KAAK,cAAc,CACrC,WAAW;GACV,GAAG;GACH,QAAQ;GACR,UAAU;GACV,QAAQ;GACT,CAAC,CACD,KAAK,QAAQ;AAEhB,SAAO;GACL,GAAG;GACH,aAAa,OAAO,aAAa;GACjC,cAAc,OAAO,cAAc;GACnC,eAAe,OAAO,MAAM;GACd;GACf;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BH,MAAM,oCACJ,eACA,iBACA,oBACA,SAGyC;AACzC,MAAI,CAAE,MAAM,KAAK,eAAe,WAAW,CACzC,OAAM,IAAI,MAAM,sEAAsE;EAGxF,MAAM,gBAAgB,WAAW,cAAc;EAE/C,MAAM,eAAe,MAAM,KAAK,uBAAuB,eAAe,oBAAoB,SAAS,oBAAoB;AACvH,MAAI,CAAC,aAAc,QAAO;EAE1B,MAAM,SAAS,MAAM,gBAAgB,KAAK,eAAe,aAAa,UAAU;AAChF,SAAO;GACL,cAAc,WAAW,UAAU,OAAO,OAAO;GACjD,eAAe,OAAO;GACvB"}
@@ -569,6 +569,7 @@ declare class AlgorandClientTransactionCreator {
569
569
  */
570
570
  appCreateMethodCall: (params: {
571
571
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
572
+ appId?: 0 | undefined;
572
573
  sender: SendingAddress;
573
574
  rekeyTo?: ReadableAddress | undefined;
574
575
  note?: (Uint8Array | string) | undefined;
@@ -579,7 +580,6 @@ declare class AlgorandClientTransactionCreator {
579
580
  validityWindow?: number | bigint | undefined;
580
581
  firstValidRound?: bigint | undefined;
581
582
  lastValidRound?: bigint | undefined;
582
- appId?: 0 | undefined;
583
583
  onComplete?: OnApplicationComplete.NoOp | OnApplicationComplete.OptIn | OnApplicationComplete.CloseOut | OnApplicationComplete.UpdateApplication | OnApplicationComplete.DeleteApplication | undefined;
584
584
  accountReferences?: ReadableAddress[] | undefined;
585
585
  appReferences?: bigint[] | undefined;
@@ -650,6 +650,7 @@ declare class AlgorandClientTransactionCreator {
650
650
  */
651
651
  appUpdateMethodCall: (params: {
652
652
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
653
+ appId: bigint;
653
654
  sender: SendingAddress;
654
655
  rekeyTo?: ReadableAddress | undefined;
655
656
  note?: (Uint8Array | string) | undefined;
@@ -660,7 +661,6 @@ declare class AlgorandClientTransactionCreator {
660
661
  validityWindow?: number | bigint | undefined;
661
662
  firstValidRound?: bigint | undefined;
662
663
  lastValidRound?: bigint | undefined;
663
- appId: bigint;
664
664
  onComplete?: OnApplicationComplete.UpdateApplication | undefined;
665
665
  accountReferences?: ReadableAddress[] | undefined;
666
666
  appReferences?: bigint[] | undefined;
@@ -722,6 +722,7 @@ declare class AlgorandClientTransactionCreator {
722
722
  */
723
723
  appDeleteMethodCall: (params: {
724
724
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
725
+ appId: bigint;
725
726
  sender: SendingAddress;
726
727
  rekeyTo?: ReadableAddress | undefined;
727
728
  note?: (Uint8Array | string) | undefined;
@@ -732,7 +733,6 @@ declare class AlgorandClientTransactionCreator {
732
733
  validityWindow?: number | bigint | undefined;
733
734
  firstValidRound?: bigint | undefined;
734
735
  lastValidRound?: bigint | undefined;
735
- appId: bigint;
736
736
  onComplete?: OnApplicationComplete.DeleteApplication | undefined;
737
737
  accountReferences?: ReadableAddress[] | undefined;
738
738
  appReferences?: bigint[] | undefined;
@@ -792,6 +792,7 @@ declare class AlgorandClientTransactionCreator {
792
792
  */
793
793
  appCallMethodCall: (params: {
794
794
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
795
+ appId: bigint;
795
796
  sender: SendingAddress;
796
797
  rekeyTo?: ReadableAddress | undefined;
797
798
  note?: (Uint8Array | string) | undefined;
@@ -802,7 +803,6 @@ declare class AlgorandClientTransactionCreator {
802
803
  validityWindow?: number | bigint | undefined;
803
804
  firstValidRound?: bigint | undefined;
804
805
  lastValidRound?: bigint | undefined;
805
- appId: bigint;
806
806
  onComplete?: OnApplicationComplete.NoOp | OnApplicationComplete.OptIn | OnApplicationComplete.CloseOut | OnApplicationComplete.DeleteApplication | undefined;
807
807
  accountReferences?: ReadableAddress[] | undefined;
808
808
  appReferences?: bigint[] | undefined;
@@ -747,6 +747,7 @@ declare class AlgorandClientTransactionSender {
747
747
  */
748
748
  appCreateMethodCall: (params: {
749
749
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
750
+ appId?: 0 | undefined;
750
751
  sender: SendingAddress;
751
752
  rekeyTo?: ReadableAddress | undefined;
752
753
  note?: (Uint8Array | string) | undefined;
@@ -757,7 +758,6 @@ declare class AlgorandClientTransactionSender {
757
758
  validityWindow?: number | bigint | undefined;
758
759
  firstValidRound?: bigint | undefined;
759
760
  lastValidRound?: bigint | undefined;
760
- appId?: 0 | undefined;
761
761
  onComplete?: OnApplicationComplete.NoOp | OnApplicationComplete.OptIn | OnApplicationComplete.CloseOut | OnApplicationComplete.UpdateApplication | OnApplicationComplete.DeleteApplication | undefined;
762
762
  accountReferences?: ReadableAddress[] | undefined;
763
763
  appReferences?: bigint[] | undefined;
@@ -835,6 +835,7 @@ declare class AlgorandClientTransactionSender {
835
835
  */
836
836
  appUpdateMethodCall: (params: {
837
837
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
838
+ appId: bigint;
838
839
  sender: SendingAddress;
839
840
  rekeyTo?: ReadableAddress | undefined;
840
841
  note?: (Uint8Array | string) | undefined;
@@ -845,7 +846,6 @@ declare class AlgorandClientTransactionSender {
845
846
  validityWindow?: number | bigint | undefined;
846
847
  firstValidRound?: bigint | undefined;
847
848
  lastValidRound?: bigint | undefined;
848
- appId: bigint;
849
849
  onComplete?: OnApplicationComplete.UpdateApplication | undefined;
850
850
  accountReferences?: ReadableAddress[] | undefined;
851
851
  appReferences?: bigint[] | undefined;
@@ -914,6 +914,7 @@ declare class AlgorandClientTransactionSender {
914
914
  */
915
915
  appDeleteMethodCall: (params: {
916
916
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
917
+ appId: bigint;
917
918
  sender: SendingAddress;
918
919
  rekeyTo?: ReadableAddress | undefined;
919
920
  note?: (Uint8Array | string) | undefined;
@@ -924,7 +925,6 @@ declare class AlgorandClientTransactionSender {
924
925
  validityWindow?: number | bigint | undefined;
925
926
  firstValidRound?: bigint | undefined;
926
927
  lastValidRound?: bigint | undefined;
927
- appId: bigint;
928
928
  onComplete?: OnApplicationComplete.DeleteApplication | undefined;
929
929
  accountReferences?: ReadableAddress[] | undefined;
930
930
  appReferences?: bigint[] | undefined;
@@ -991,6 +991,7 @@ declare class AlgorandClientTransactionSender {
991
991
  */
992
992
  appCallMethodCall: (params: {
993
993
  signer?: (TransactionSigner | AddressWithTransactionSigner) | undefined;
994
+ appId: bigint;
994
995
  sender: SendingAddress;
995
996
  rekeyTo?: ReadableAddress | undefined;
996
997
  note?: (Uint8Array | string) | undefined;
@@ -1001,7 +1002,6 @@ declare class AlgorandClientTransactionSender {
1001
1002
  validityWindow?: number | bigint | undefined;
1002
1003
  firstValidRound?: bigint | undefined;
1003
1004
  lastValidRound?: bigint | undefined;
1004
- appId: bigint;
1005
1005
  onComplete?: OnApplicationComplete.NoOp | OnApplicationComplete.OptIn | OnApplicationComplete.CloseOut | OnApplicationComplete.DeleteApplication | undefined;
1006
1006
  accountReferences?: ReadableAddress[] | undefined;
1007
1007
  appReferences?: bigint[] | undefined;