Skip to content

Commit

Permalink
feat: app client deprecation (#311)
Browse files Browse the repository at this point in the history
* feat: Deprecated methods in transaction module

BREAKING CHANGE: `ExecuteParams` has been moved from `types/composer` to `types/transaction`

* feat: Added `AppClient` as an ARC-56 compatible non-typed application client

* feat: Added `AppFactory` as an ARC-32/ARC-56 compatible mechanism to create and deploy apps and create app clients
test: Added test coverage of AppClient and AppFactory

BREAKING CHANGE: `persistSourceMaps` takes `appManager` rather than `client` now

* docs: Added migration guide and app-client documentation
feat: Added appClient.params.fundAppAccount and appClient.transactions.fundAppAccount
fix: Allow extraProgramPages to be passed into create and deploy call as override

* feat: Proper ARC-56 struct support
feat: Added a number of methods and types to ARC-56 to make interacting with it easier

* Linting and PR review

* feat: ARC-56 Typed client support

* feat: Added logging when sending app calls

* fix: Fixing minor bugs

* fixes

* feat: Finalised typed app client construction methods

* PR feedback

* feat: AlgoAmount microAlgo/s property now returns a bigint

BREAKING CHANGE: microAlgo/s property in AlgoAmount now returns a bigint
  • Loading branch information
robdmoore authored Sep 19, 2024
1 parent 5e63c0e commit 0cd0743
Show file tree
Hide file tree
Showing 152 changed files with 9,457 additions and 2,187 deletions.
12 changes: 0 additions & 12 deletions .github/workflows/issue_closed.yml

This file was deleted.

12 changes: 0 additions & 12 deletions .github/workflows/issue_commented.yml

This file was deleted.

12 changes: 0 additions & 12 deletions .github/workflows/issue_labelled.yml

This file was deleted.

11 changes: 0 additions & 11 deletions .github/workflows/zendesk_github_add_comment.yml

This file was deleted.

11 changes: 0 additions & 11 deletions .github/workflows/zendesk_github_close_issue.yml

This file was deleted.

16 changes: 9 additions & 7 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ To use this library simply include the following at the top of your file:
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).
As well as `AlgorandClient` and `Config`, you can use intellisense to auto-complete the various types that you can import within 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 algokit`):
Expand All @@ -45,7 +45,9 @@ As well as `AlgorandClient` and `Config`, you can use intellisense to auto-compl
> 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.
> This version will still work until the next major version bump, but it exposes an older, function-based interface to the functionality that is deprecated. The new way to use AlgoKit Utils is via the `AlgorandClient` class, which is easier, simpler and more convenient to use and has powerful new features.
>
> If you are migrating from the old functions to the new ones then you can follow the [migration guide](v7-migration.md).
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.:
Expand Down Expand Up @@ -138,15 +140,15 @@ To turn on debug mode you can use the following:
Config.configure({ debug: true })
```
To retrieve the current debug state you can use [`algokit.Config.debug`](./code/interfaces/types_config.Config.md).
To retrieve the current debug state you can use [`Config.debug`](./code/interfaces/types_config.Config.md).
This will turn on things like automatic tracing, more verbose logging and [advanced debugging](./capabilities/debugging.md). It's likely this option will result in extra HTTP calls to algod so worth being careful when it's turned on.
If you want to temporarily turn it on you can use the [`withDebug`](./code/classes/types_config.UpdatableConfig.md#withdebug) function:
```typescript
Config.withDebug(() => {
// Do stuff with algokit.Config.debug set to true
// Do stuff with Config.debug set to true
})
```
Expand All @@ -159,11 +161,11 @@ The library helps you interact with and develop against the Algorand blockchain
- [**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
- [**Transaction management**](./capabilities/transaction.md) - Ability to construct, simulate and send 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
- [**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-56 or ARC-32 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-56 / ARC-32 App client and App factory**](./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-56 and ARC-32 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
Expand Down
52 changes: 37 additions & 15 deletions docs/capabilities/account.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,41 @@ const accountManager = new AccountManager(clientManager)

The core internal type that holds information about a signer/sender pair for a transaction is [`TransactionSignerAccount`](../code/interfaces/types_account.TransactionSignerAccount.md), which represents an `algosdk.TransactionSigner` (`signer`) along with a sender address (`addr`) as the encoded string address.

Many methods in `AccountManager` expose a `TransactionSignerAccount`.
Many methods in `AccountManager` expose a `TransactionSignerAccount`. `TransactionSignerAccount` can be used with `AtomicTransactionComposer`, [`AlgoKitComposer`](./algokit-composer.md) and [useWallet](https://github.com/TxnLab/use-wallet).

### `SendTransactionFrom`
## Registering a signer

> [!NOTE]
> The [legacy functions](../README.md#usage) within AlgoKit Utils make use of a [`SendTransactionFrom`](../code/modules/types_transaction.md#sendtransactionfrom) union type that is slowly being phased out in favour of the simpler `TransactionSignerAccount`. This `SendTransactionFrom` type is still prevalent within the legacy functions though.
The `AccountManager` keeps track of which signer is associated with a given sender address. This is used by [`AlgorandClient`](./algorand-client.md) to automatically sign transactions by that sender. Any of the [methods](#accounts) within `AccountManager` that return an account will automatically register the signer with the sender. If however, you are creating a signer external to the `AccountManager`, for instance when using the use-wallet library in a dApp, then you need to register the signer with the `AccountManager` if you want it to be able to automatically sign transactions from that sender.

`SendTransactionFrom` is a union of the following types that each represent an account that can both sign a transaction and represent a sender address:
There are two methods that can be used for this, `setSignerFromAccount`, which takes any number of [account based objects](#underlying-account-classes) that combine signer and sender (`TransactionSignerAccount` | `algosdk.Account` | `algosdk.LogicSigAccount` | `SigningAccount` | `MultisigAccount`), or `setSigner` which takes the sender address and the `TransactionSigner`:

- `Account` - An in-built algosdk `Account` object
- [`SigningAccount`](../code/classes/types_account.SigningAccount.md) - An abstraction around `algosdk.Account` that supports rekeyed accounts
- `LogicSigAccount` - An in-built algosdk `algosdk.LogicSigAccount` object
- [`MultisigAccount`](../code/classes/types_account.MultisigAccount.md) - An abstraction around `algosdk.MultisigMetadata`, `algosdk.makeMultiSigAccountTransactionSigner`, `algosdk.multisigAddress`, `algosdk.signMultisigTransaction` and `algosdk.appendSignMultisigTransaction` that supports multisig accounts with one or more signers present
- [`TransactionSignerAccount`](../code/interfaces/types_account.TransactionSignerAccount.md) - An interface that provides a sender address alongside a transaction signer (e.g. for use with `AtomicTransactionComposer` or [useWallet](https://github.com/TxnLab/use-wallet))
```typescript
algorand.account
.setSignerFromAccount(algosdk.generateAccount())
.setSignerFromAccount(new algosdk.LogicSigAccount(program, args))
.setSignerFromAccount(new SigningAccount(mnemonic, sender))
.setSignerFromAccount(new MultisigAccount({ version: 1, threshold: 1, addrs: ['ADDRESS1...', 'ADDRESS2...'] }, [account1, account2]))
.setSignerFromAccount({ addr: 'SENDERADDRESS', signer: transactionSigner })
.setSigner('SENDERADDRESS', transactionSigner)
```

The use of in-built algosdk types like `Account`, `LogicSigAccount` and `TransactionSigner` is aligned to the [Modularity](../README.md#core-principles) principle. Allowing you to co-exist non AlgoKit Utils code with AlgoKit Utils functions.
## Default signer

AlgoKit Utils provides a few helper methods to take one of these `SendTransactionFrom` objects (that to reiterate uses the [legacy imports](../README.md#usage) to access):
If you want to have a default signer that is used to sign transactions without a registered signer (rather than throwing an exception) then you can [register a default signer](../code/classes/types_account_manager.AccountManager.md#setdefaultsigner):

- [`algokit.getSenderAddress`](../code/modules/index.md#getsenderaddress) - Returns the public address of the sender the account represents
- [`algokit.getSenderTransactionSigner`](../code/modules/index.md#getsendertransactionsigner) - Returns a `TransactionSigner` to represent the signer of the account' note: this is memoized so multiple calls to this for the same account will safely return the same `TransactionSigner` instance; this works nicely with `AtomicTransactionComposer`
- [`algokit.signTransaction`](../code/modules/index.md#signtransaction) - Signs a single `algosdk.Transaction` object with the given account
```typescript
algorand.account.setDefaultSigner(myDefaultSigner)
```

## Get a signer

[`AlgorandClient`](./algorand-client.md) will automatically retrieve a signer when signing a transaction, but if you need to get a `TransactionSigner` externally to do something more custom then you can [retrieve the signer](../code/classes//types_account_manager.AccountManager.md#getsigner) for a given sender address:

```typescript
const signer = algorand.account.getSigner('SENDER_ADDRESS')
```

If there is no signer registered for that sender address it will either return the default signer ([if registered](#default-signer)) or throw an exception.

## Accounts

Expand All @@ -55,6 +68,15 @@ In order to get/register accounts for signing operations you can use the followi
- [`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

### Underlying account classes

While `TransactionSignerAccount` is the main class used to represent an account that can sign, there are underlying account classes that can underpin the signer within the transaction signer account.

- `Account` - An in-built `algosdk.Account` object that has an address and private signing key, this can be created
- [`SigningAccount`](../code/classes/types_account.SigningAccount.md) - An abstraction around `algosdk.Account` that supports rekeyed accounts
- `LogicSigAccount` - An in-built algosdk `algosdk.LogicSigAccount` object
- [`MultisigAccount`](../code/classes/types_account.MultisigAccount.md) - An abstraction around `algosdk.MultisigMetadata`, `algosdk.makeMultiSigAccountTransactionSigner`, `algosdk.multisigAddress`, `algosdk.signMultisigTransaction` and `algosdk.appendSignMultisigTransaction` that supports multisig accounts with one or more signers present

### Dispenser

- [`algorand.account.dispenserFromEnvironment()`](../code/classes/types_account_manager.AccountManager.md#dispenserfromenvironment) - Returns an account (with private key loaded) that can act as a dispenser from environment variables, or against default LocalNet if no environment variables present
Expand Down
41 changes: 40 additions & 1 deletion docs/capabilities/algokit-composer.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
# AlgoKit composer

TODO
The `AlgoKitComposer` class allows you to easily compose one or more compliant Algorand transactions and execute and/or simulate them.

It's the core of how the [`AlgorandClient`](./algorand-client.md) class composes and sends transactions.

To get an instance of `AlgoKitComposer` you can either get it from an [app client](./app-client.md), from an [`AlgorandClient`](./algorand-client.md), or by new-ing up via the constructor.

```typescript
const composerFromAlgorand = algorand.newGroup()
const composerFromAppClient = appClient.newGroup()
const composerFromConstructor = new AlgoKitComposer({
algod,
/* Return the algosdk.TransactionSigner for this address*/
getSigner: (address: string) => signer,
})
const composerFromConstructorWithOptionalParams = new AlgoKitComposer({
algod,
/* Return the algosdk.TransactionSigner for this address*/
getSigner: (address: string) => signer,
getSuggestedParams: () => algod.getTransactionParams().do(),
defaultValidityWindow: 1000,
appManager: new AppManager(algod),
})
```

## Constructing a transaction

To construct a transaction you need to add it to the composer, passing in the relevant [params object](../code/modules/types_composer.md#type-aliases) for that transaction. Params are normal JavaScript objects and all of them extend the [common call parameters](./algorand-client.md#transaction-parameters).

The [methods to construct a transaction](../code/classes/types_composer.default.md#methods) are all named `add{TransactionType}` and return an instance of the composer so they can be chained together fluently to construct a transaction group.

For example:

```typescript
const result = algorand.addPayment({ sender: 'SENDER', receiver: 'RECEIVER', amount: (100).microAlgo() }).addAppCallMethodCall({
sender: 'SENDER',
appId: 123n,
method: abiMethod,
args: [1, 2, 3],
}).
```
Loading

0 comments on commit 0cd0743

Please sign in to comment.