Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: client and composer #234

Merged
merged 42 commits into from
Apr 18, 2024
Merged

feat: client and composer #234

merged 42 commits into from
Apr 18, 2024

Conversation

joe-p
Copy link
Contributor

@joe-p joe-p commented Mar 7, 2024

This PR adds two new classes, AlgokitComposer and AlgokitClient. The core idea is to provide a smooth experience for all chain interactions as discussed in #215. In most cases users are not expected to use the composer directly, but rather through the client. The composer, however, is still exported in case someone wants to use it without the client.

Problems Addressed

Mixing of algosdk and algokit-utils

Sending transactions currently requires mixing the usage of algosdk and algokit-utils.

Solution

AlgokitClient eliminates need for algosdk usage for chain interactions. AlgokitComposer is also able to take an algosdk.AtomicTransactionCompsoer and add it to its group.

Confusing interfaces

Currently, a lot of the interface on algokit-utils can be rather confusing. There are many union types and many ways to do the same thing. For example, in some places when passing a tranasction you use {txn, signer}, {tranasction, signer}, or {transaction, from}. signer and from can be many different types, inlcuding but not limited to the types used by signer or from fields in the SDK.

Solution

AlgokitComposer has straight-forward interfaces for all actions. There are no union types and the functions are not clever. There is one way to do a specific action and it is always done that way.

A lot of async functions

Because of suggestedParams, async calls may currently required when forming transactions. This is paticularly annoying when using .compose() on an generated app client. Because the chain of function calls require await in the middle making it a bit annoying to work with.

Solution

Nothing async happens until AlgokitCompose.execute() or AlgokitComposer.buildGroup()

Repetitive or old suggestedParams

Suggested params is currently needed for every transaction formation. A common solution is to just get suggested params once, but its possible that the suggested params could be out of date.

Solution

AlgokitComposer caches suggestedParams and only does the API call after a certain amount of time has elapsed

Repetitive signers

For every transaction, there needs to be a way to sign it. Currently there are many different ways to sign transactions with algokit and often you use a signer function in multiple places.

Solution

AlgokitClient allows you to specify a defaultSigner to use for all transactions (useful for wallet interaction). You can also set a unique signer per address (useful for localnet or custodied accounts). Attaching a unique signer to a tranasction is still possible if necessary.

Improper fee setting

Many dApps currently do not set fees properly. For example, if an app wants to add extra fees to their current transaction it is common practice to do (1 + extra_txns) * MIN_FEE. This is problematic because it does not account for fee scaling.

Solution (Partial)

AlgokitComposer transactions have two fee fields: flatFee for setting the flatFee on the transaction and extraFee for adding additional microAlgos to the suggested fee. This is important because it still takes into account the feePerByte recommended by algod for the given transaction. This means you can simple set extraFee to numInners * MIN_FEE to ensure the fee will always be correct for app calls with inner transactions, even under fee scaling.

TODO

In the future we need to devise a smart way to handle scenarios where one outer transaction might want to cover the fee for another out transaction. If feePerByte is non-zero, then this is hard to calculate.

Differing validity window and wait times

It is currently common practice to use the default validity window (1000 rounds) on transactions but only wait a short amount of rounds for confirmation (typically 3-5). This can lead to a confusing UX and potentially double transactions if the user is not aware of the validty windows of their transactions in the event of longer confirmation times.

Solution

AlgokitComposer.defaultValidityWindow is set to a much more reasonable window (for user-facing dApps) of 10 rounds (~30 seconds). By default, AlgokitComposer.execute() will wait until the last valid round in the transction group has passed to ensure tranasctions are confirmed when the user is not expecting it.

ABI method argument composability

Currently, if an application expects another ABI method call as an argument there is no great way to handle that other than manually building the ATC and deconstructing the group. Even after doing that, the return values for the argument calls will not be availible.

Solution

AlgokitComposer method calls support other method calls as arguments.

src/client.ts Outdated Show resolved Hide resolved
src/composer.ts Outdated Show resolved Hide resolved
src/composer.ts Outdated Show resolved Hide resolved
src/composer.ts Outdated Show resolved Hide resolved
@joe-p
Copy link
Contributor Author

joe-p commented Mar 13, 2024

@robdmoore as we discussed I added the .send and .transaction interface. I also implemented a maxFee mechanism. I know it's duplicating whats done at a lower level, but properly integrating all the fee features at a lower level would require a good amount of refactoring so I think it's just best to leave it as is now and we can refactor later. I just want to get user-facing stuff out the door ASAP.

Only major thing I can think of that we discussed is supporting string on lease and note fields, which shouldn't be too hard. Then testing and docs.

@joe-p
Copy link
Contributor Author

joe-p commented Mar 26, 2024

FYI @robdmoore in b01bd65 I changed the algorand client used in the test fixture to be persistent. This is particularly useful when you want to use an account across multiple tests and preserve the signer.

src/types/composer.ts Outdated Show resolved Hide resolved
src/types/composer.ts Outdated Show resolved Hide resolved
joe-p and others added 21 commits April 17, 2024 11:32
* Tweaks to AlgorandClient:
* Rename AlgoKitClient to AlgorandClient and added static construction methods
* Added fluent with* methods to AlgorandClient to allow for fluent configuration
* Extracted client related stuff to ClientManager and account stuff to AccountManager and added extra functionality to both
* Add transaction and confirmation to the result of sending a single transaction for better ergonomics
* Added ability to specify suggested params and create a copy of suggested params when providing it
* Moved classes to types directory
* Added getAccountInformation to make tests terser (this method should have been added ages ago)
* Incorporated client into testing fixture
* Changed all possible bigint | numbers' to number (where it's impractical for them to hit 2^53)
* Incorporated TransactionSignerAccount with TransactionSigner to allow for terser code
* Rename ID to Id for consistency with rest of algokit utils

* use bigint where applicable

---------

Co-authored-by: Joe Polny <[email protected]>
…lgoKitComposer

test: Fixing indexer intermittent test timeouts with 20s waits for tests that wait for indexer
@joe-p joe-p force-pushed the feat/client_and_composer branch 2 times, most recently from 38cd0ee to 6bb5069 Compare April 18, 2024 12:08
@joe-p joe-p merged commit ad7dc8e into main Apr 18, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants