Skip to content

Commit

Permalink
feat: Deprecate transfer and asset modules (#291)
Browse files Browse the repository at this point in the history
Breaking changes:
* Renamed `AlgokitComposer` to `AlgoKitComposer` to match AlgoKit naming conventions
* Collapsed the second object in algorand.send.type(params, *executeOptions*) to combine into params and make it easier to use based on devrel feedback
* Order of `algorand.account.rekeyed()` parameters to be `rekeyed(sender, signer)` since it conceptually makes more sense (the sender is rekeyed so should come first)
* All microAlgo return values from `algorand.account.getInformation()` now return an `AlgoAmount`, renamed `amount` to `balance` and `round` to `validAsAtRound` (which is now a `bigint` for broader consistency)
* Renamed `algorand.account.getAssetInformation` to `algorand.asset.getAccountInformation`

Added:
* Return value of `algorand.send.assetCreate` now includes `{ assetId: bigint }`
* Up to date documentation for rekeyAccount, AlgorandClient, asset, dispenser client, indexer, testing, transfer
* Up to date documentation for how to refer to an Algo amount (Algo (not plural) in general and ALGO (not plural) when referring to a specific amount)
* `AssetManager` class and `algorand.asset.getById()`, `algorand.asset.bulkOptIn`, and `algorand.asset.bulkOptOut`
* `indexer` export off of `@algorandfoundation/algokit-utils` as the future home of all indexer methods
* Added `algorand.client.getTestNetDispenserFromEnvironment`
* Added `algorand.account.assetBulkOptIn`
* Added `algorand.account.assetBulkOptOut`
* Added `algorand.account.ensureFunded`
* Added `algorand.account.ensureFundedFromEnvironment`
* Added `algorand.account.ensureFundedFromTestNetDispenserApi`
* Added `algorand.account.rekeyAccount`
* Added `algorand.send/transaction.assetOptOut`
* Added `buildTransactions` method to `AlgoKitComposer` so you can build transactions without needing to register a signer
* Added `.algo` and `.microAlgo` methods/properties in place of the plural version for `AlgoAmount` to reflect the current guidance on how to represent Algo amounts, kept previous versions of those methods for now to avoid the breaking change

Deprecated the following in favour of AlgorandClient functionality:
* `algokit.createAsset`
* `algokit.assetOptIn`
* `algokit.assetOptOut`
* `algokit.assetBulkOptIn`
* `algokit.assetBulkOptOut`
* `algokit.ensureFunded`
* `algokit.transferAsset`
* `algokit.rekeyAccount`
* `algokit.transferAlgos`

---------

Co-authored-by: Neil Campbell <neil.campbell@makerx.com.au>

BREAKING CHANGE: Numerous
  • Loading branch information
robdmoore authored Aug 28, 2024
1 parent 40be39f commit 2aebcfd
Show file tree
Hide file tree
Showing 109 changed files with 7,119 additions and 2,611 deletions.
54 changes: 23 additions & 31 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,35 @@ import { AlgorandClient, Config } from '@algorandfoundation/algokit-utils'
As well as `AlgorandClient` and `Config`, you can use intellisense to auto-complete the various types that you can import withing the {} in your favourite Integrated Development Environment (IDE), or you can refer to the [reference documentation](./code/modules/index.md).

> [!WARNING]
> Previous versions of AlgoKit Utils encouraged you to include an import that looks like this (note the subtle difference of the extra `* as`):
> Previous versions of AlgoKit Utils encouraged you to include an import that looks like this (note the subtle difference of the extra `* as algokit`):
>
> ```typescript
> import * as algokit from '@algorandfoundation/algokit-utils'
> ```
>
> This version will still work, but it exposes an older, function-based interface to the functionality that is in the process of being deprecated. The recommended way to use AlgoKit Utils is via the `AlgorandClient` class mentioned below, which is easier and more convenient to use. Some functionality won't yet be migrated to the new approach and this old approach will be needed, but the documentation pages will indicate when this is the case.
The main entrypoint to the bulk of the functionality is the `AlgorandClient` class, most of the time you can get started by typing `algokit.AlgorandClient.` and choosing one of the static initialisation methods to create an [Algorand client](./capabilities/algorand-client.md), e.g.:
The main entrypoint to the bulk of the functionality is the `AlgorandClient` class, most of the time you can get started by typing `AlgorandClient.` and choosing one of the static initialisation methods to create an [Algorand client](./capabilities/algorand-client.md), e.g.:
```typescript
// Point to the network configured through environment variables or
// if no environment variables it will point to the default LocalNet
// configuration
const algorand = algokit.AlgorandClient.fromEnvironment()
const algorand = AlgorandClient.fromEnvironment()
// Point to default LocalNet configuration
const algorand = algokit.AlgorandClient.defaultLocalNet()
const algorand = AlgorandClient.defaultLocalNet()
// Point to TestNet using AlgoNode free tier
const algorand = algokit.AlgorandClient.testNet()
const algorand = AlgorandClient.testNet()
// Point to MainNet using AlgoNode free tier
const algorand = algokit.AlgorandClient.mainNet()
const algorand = AlgorandClient.mainNet()
// Point to a pre-created algod client
const algorand = algokit.AlgorandClient.fromClients({ algod })
const algorand = AlgorandClient.fromClients({ algod })
// Point to pre-created algod, indexer and kmd clients
const algorand = algokit.AlgorandClient.fromClients({ algod, indexer, kmd })
const algorand = AlgorandClient.fromClients({ algod, indexer, kmd })
// Point to custom configuration for algod
const algorand = algokit.AlgorandClient.fromConfig({ algodConfig })
const algorand = AlgorandClient.fromConfig({ algodConfig })
// Point to custom configuration for algod, indexer and kmd
const algorand = algokit.AlgorandClient.fromConfig({ algodConfig, indexerConfig, kmdConfig })
const algorand = AlgorandClient.fromConfig({ algodConfig, indexerConfig, kmdConfig })
```
## Testing
Expand Down Expand Up @@ -155,29 +155,21 @@ algokit.Config.withDebug(() => {
The library helps you interact with and develop against the Algorand blockchain with a series of end-to-end capabilities as described below:
- [**AlgorandClient**](./capabilities/algorand-client.md) - The key entrypoint to the AlgoKit Utils functionality
- Core capabilities
- [**Client management**](./capabilities/client.md) - Creation of (auto-retry) algod, indexer and kmd clients against various networks resolved from environment or specified configuration
- [**Account management**](./capabilities/account.md) - Creation and use of accounts including mnemonic, rekeyed, multisig, transaction signer ([useWallet](https://github.com/TxnLab/use-wallet) for dApps and Atomic Transaction Composer compatible signers), idempotent KMD accounts and environment variable injected
- [**Algo amount handling**](./capabilities/amount.md) - Reliable and terse specification of microAlgo and Algo amounts and conversion between them
- [**Transaction management**](./capabilities/transaction.md) - Ability to send single, grouped or Atomic Transaction Composer transactions with consistent and highly configurable semantics, including configurable control of transaction notes (including ARC-0002), logging, fees, multiple sender account types, and sending behaviour
- Higher-order use cases
- [**App management**](./capabilities/app.md) - Creation, updating, deleting, calling (ABI and otherwise) smart contract apps and the metadata associated with them (including state and boxes)
- [**App deployment**](./capabilities/app-deploy.md) - Idempotent (safely retryable) deployment of an app, including deploy-time immutability and permanence control and TEAL template substitution
- [**ARC-0032 Application Spec client**](./capabilities/app-client.md) - Builds on top of the App management and App deployment capabilities to provide a high productivity application client that works with ARC-0032 application spec defined smart contracts (e.g. via Beaker)
- [**Algo transfers**](./capabilities/transfer.md) - Ability to easily initiate algo transfers between accounts, including dispenser management and idempotent account funding
- **Core capabilities**
- [**Client management**](./capabilities/client.md) - Creation of (auto-retry) algod, indexer and kmd clients against various networks resolved from environment or specified configuration, and creation of other API clients (e.g. TestNet Dispenser API and app clients)
- [**Account management**](./capabilities/account.md) - Creation, use, and management of accounts including mnemonic, rekeyed, multisig, transaction signer ([useWallet](https://github.com/TxnLab/use-wallet) for dApps and Atomic Transaction Composer compatible signers), idempotent KMD accounts and environment variable injected
- [**Algo amount handling**](./capabilities/amount.md) - Reliable, explicit, and terse specification of microAlgo and Algo amounts and safe conversion between them
- [**Transaction management**](./capabilities/transaction.md) - Ability to construct and send single and atomically grouped transactions with consistent and highly configurable semantics, including configurable control of transaction notes, logging, fees, validity, signing, and sending behaviour
- **Higher-order use cases**
- [**Asset management**](./capabilities/asset.md) - Creation, transfer, destroying, opting in and out and managing Algorand Standard Assets
- [**Typed application clients**](./capabilities/typed-app-clients.md) - Type-safe application clients that are [generated](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/features/generate.md#1-typed-clients) from ARC-0032 application spec files and allow you to intuitively and productively interact with a deployed app, which is the recommended way of interacting with apps and builds on top of the following capabilities:
- [**ARC-0032 Application Spec client**](./capabilities/app-client.md) - Builds on top of the App management and App deployment capabilities (below) to provide a high productivity application client that works with ARC-0032 application spec defined smart contracts
- [**App management**](./capabilities/app.md) - Creation, updating, deleting, calling (ABI and otherwise) smart contract apps and the metadata associated with them (including state and boxes)
- [**App deployment**](./capabilities/app-deploy.md) - Idempotent (safely retryable) deployment of an app, including deploy-time immutability and permanence control and TEAL template substitution
- [**Algo transfers (payments)**](./capabilities/transfer.md) - Ability to easily initiate Algo transfers between accounts, including dispenser management and idempotent account funding
- [**Automated testing**](./capabilities/testing.md) - Terse, robust automated testing primitives that work across any testing framework (including jest and vitest) to facilitate fixture management, quickly generating isolated and funded test accounts, transaction logging, indexer wait management and log capture
- [**Indexer lookups / searching**](./capabilities/indexer.md) - Type-safe indexer API wrappers (no more `Record<string, any>` pain), including automatic pagination control
- [**Indexer lookups / searching**](./capabilities/indexer.md) - Type-safe indexer API wrappers (no `Record<string, any>` pain from the SDK client), including automatic pagination control
# Reference documentation
We have [auto-generated reference documentation for the code](./code/README.md).
# Roadmap
This library will naturally evolve with any logical developer experience improvements needed to facilitate the [AlgoKit](https://github.com/algorandfoundation/algokit-cli) roadmap as it evolves.
Likely future capability additions include:
- Typed application client (similar to [beaker-ts](https://github.com/algorand-devrel/beaker-ts))
- Asset management
- Expanded indexer API wrapper support
76 changes: 49 additions & 27 deletions docs/capabilities/account.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Account management is one of the core capabilities provided by AlgoKit Utils. It

## `AccountManager`

The [`AccountManager`](../code/classes/types_account_manager.AccountManager.md) is a class that is used to get, create, and fund accounts and perform account-related actions such as funding. The `AccountManager` also keeps track of signers for each address so when using the [`AlgokitComposer`](./algokit-composer.md) to send transactions, a signer function does not need to manually be specified for each transaction - instead it can be inferred from the sender address automatically!
The [`AccountManager`](../code/classes/types_account_manager.AccountManager.md) is a class that is used to get, create, and fund accounts and perform account-related actions such as funding. The `AccountManager` also keeps track of signers for each address so when using the [`AlgoKitComposer`](./algokit-composer.md) to send transactions, a signer function does not need to manually be specified for each transaction - instead it can be inferred from the sender address automatically!

To get an instance of `AccountManager`, you can use either [`AlgorandClient`](./algorand-client.md) via `algorand.account` or instantiate it directly (passing in a [`ClientManager`](./client.md)):

Expand Down Expand Up @@ -47,10 +47,10 @@ In order to get/register accounts for signing operations you can use the followi

- [`algorand.account.fromEnvironment(name, fundWith)`](../code/classes/types_account_manager.AccountManager.md#fromenvironment) - Registers and returns an account with private key loaded by convention based on the given name identifier - either by idempotently creating the account in KMD or from environment variable via `process.env['{NAME}_MNEMONIC']` and (optionally) `process.env['{NAME}_SENDER']` (if account is rekeyed)
- This allows you to have powerful code that will automatically create and fund an account by name locally and when deployed against TestNet/MainNet will automatically resolve from environment variables, without having to have different code
- Note: `fundWith` allows you to control how many ALGOs are seeded into an account created in KMD
- Note: `fundWith` allows you to control how many Algo are seeded into an account created in KMD
- [`algorand.account.fromMnemonic(mnemonicSecret, sender?)`](../code/classes/types_account_manager.AccountManager.md#frommnemonic) - Registers and returns an account with secret key loaded by taking the mnemonic secret
- [`algorand.account.multisig(multisigParams, signingAccounts)`](../code/classes/types_account_manager.AccountManager.md#multisig) - Registers and returns a multisig account with one or more signing keys loaded
- [`algorand.account.rekeyed(signer, sender)`](../code/classes/types_account_manager.AccountManager.md#rekeyed) - Registers and returns an account representing the given rekeyed sender/signer combination
- [`algorand.account.rekeyed(sender, signer)`](../code/classes/types_account_manager.AccountManager.md#rekeyed) - Registers and returns an account representing the given rekeyed sender/signer combination
- [`algorand.account.random()`](../code/classes/types_account_manager.AccountManager.md#random) - Returns a new, cryptographically randomly generated account with private key loaded
- [`algorand.account.fromKmd()`](../code/classes/types_account_manager.AccountManager.md#fromkmd) - Returns an account with private key loaded from the given KMD wallet (identified by name)
- [`algorand.account.logicsig(program, args?)`](../code/classes/types_account_manager.AccountManager.md#logicsig) - Returns an account that represents a logic signature
Expand All @@ -62,40 +62,62 @@ In order to get/register accounts for signing operations you can use the followi

## Rekey account

> [!NOTE]
> This method requires the [legacy AlgoKit Utils import method to access them](../README.md#usage).
One of the unique features of Algorand is the ability to change the private key that can authorise transactions for an account. This is called [rekeying](https://developer.algorand.org/docs/get-details/accounts/rekey/).

You can issue a transaction to rekey an account by using the `algokit.rekeyAccount(rekey, algod)` function. The `rekey` parameter is an [`AlgoRekeyParams`](../code/interfaces/types_transfer.AlgoRekeyParams.md) object with the following properties:
> [!WARNING]
> Rekeying should be done with caution as a rekey transaction can result in permanent loss of control of an account.
You can issue a transaction to rekey an account by using the [`algorand.account.rekeyAccount(account, rekeyTo, options)`](../code/classes/types_account_manager.AccountManager.md#rekeyaccount) function:

- All properties in [`SendTransactionParams`](./transaction.md#sendtransactionparams)
- `from: SendTransactionFrom` - The account that will be rekeyed
- `rekeyTo: SendTransactionFrom | string` - The address of the account that will be used to authorise transactions for the rekeyed account going forward
- `transactionParams?: SuggestedParams` - The optional [transaction parameters](./transaction.md#transaction-params)
- `note?: TransactionNote` - The [transaction note](./transaction.md#transaction-notes)
- `lease?: string | Uint8Array`: A [lease](https://developer.algorand.org/articles/leased-transactions-securing-advanced-smart-contract-design/) to assign to the transaction to enforce a mutually exclusive transaction (useful to prevent double-posting and other scenarios)
- `account: string | TransactionSignerAccount` - The account address or signing account of the account that will be rekeyed
- `rekeyTo: string | TransactionSignerAccount` - The account address or signing account of the account that will be used to authorise transactions for the rekeyed account going forward. If a signing account is provided that will now be tracked as the signer for `account` in the `AccountManager` instance.
- An `options` object, which has:
- [Common transaction parameters](./algorand-client.md#transaction-parameters)
- [Execution parameters](./algorand-client.md#sending-a-single-transaction)

You can also pass in `rekeyTo` as a [common transaction parameter](./algorand-client.md#transaction-parameters) to any transaction.

### Examples

```typescript
// Example
await algokit.rekeyAccount(
{
from: account,
rekeyTo: newAccount,
// Optionally specify transactionParams, note, lease and transaction sending parameters
},
algod,
)
// Basic example (with string addresses)

await algorand.account.rekeyAccount({ account: 'ACCOUNTADDRESS', rekeyTo: 'NEWADDRESS' })

// Basic example (with signer accounts)

await algorand.account.rekeyAccount({ account: account1, rekeyTo: newSignerAccount })

// Advanced example

await algorand.account.rekeyAccount({
account: 'ACCOUNTADDRESS',
rekeyTo: 'NEWADDRESS',
lease: 'lease',
note: 'note',
firstValidRound: 1000n,
validityWindow: 10,
extraFee: (1000).microAlgo(),
staticFee: (1000).microAlgo(),
// Max fee doesn't make sense with extraFee AND staticFee
// already specified, but here for completeness
maxFee: (3000).microAlgo(),
maxRoundsToWaitForConfirmation: 5,
suppressLog: true,
})

// Using a rekeyed account

const rekeyedAccount = algokit.rekeyedAccount(newAccount, account.addr)
// Note: if a signing account is passed into `algorand.account.rekeyAccount` then you don't need to call `rekeyedAccount` to register the new signer
const rekeyedAccount = algorand.account.rekeyed(account.addr, newAccount)
// rekeyedAccount can be used to sign transactions on behalf of account...
```

# KMD account management

When running LocalNet, you have an instance of the [Key Management Daemon](https://github.com/algorand/go-algorand/blob/master/daemon/kmd/README.md), which is useful for:

- Accessing the private key of the default accounts that are pre-seeded with algos so that other accounts can be funded and it's possible to use LocalNet
- Accessing the private key of the default accounts that are pre-seeded with Algo so that other accounts can be funded and it's possible to use LocalNet
- Idempotently creating new accounts against a name that will stay intact while the LocalNet instance is running without you needing to store private keys anywhere (i.e. completely automated)

The KMD SDK is fairly low level so to make use of it there is a fair bit of boilerplate code that's needed. This code has been abstracted away into the `KmdAccountManager` class.
Expand Down Expand Up @@ -124,8 +146,8 @@ const defaultDispenserAccount = await kmdAccountManager.getWalletAccount(
// Same as above, but dedicated method call for convenience
const localNetDispenserAccount = await kmdAccountManager.getLocalNetDispenserAccount()
// Idempotently get (if exists) or create (if it doesn't exist yet) an account by name using KMD
// if creating it then fund it with 2 Algos from the default dispenser account
const newAccount = await kmdAccountManager.getOrCreateWalletAccount('account1', (2).algos())
// if creating it then fund it with 2 ALGO from the default dispenser account
const newAccount = await kmdAccountManager.getOrCreateWalletAccount('account1', (2).algo())
// This will return the same account as above since the name matches
const existingAccount = await kmdAccountManager.getOrCreateWalletAccount('account1')
```
Expand All @@ -138,5 +160,5 @@ const localNetDispenser = await algorand.account.localNetDispenser()
// Get and register a dispenser by environment variable, or if not set then LocalNet dispenser via KMD
const dispenser = await algorand.account.dispenserFromEnvironment()
// Get / create and register account from KMD idempotently by name
const account1 = await algorand.account.fromKmd('account1', (2).algos())
const account1 = await algorand.account.fromKmd('account1', (2).algo())
```
Loading

0 comments on commit 2aebcfd

Please sign in to comment.