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

add user-feedback docs #8

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions docs/user-feedback/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# User Feedback

## Goals

The Algorand Foundation is working on developing tooling to make it easier for developers to build on Algorand. One of the key components of this tooling is smart contract languages. The Algorand Foundation has previously released Algorand Python, which enables developers to write smart contracts in Python. The compiler for Algorand Python is called Puya and can be leveraged by any other language. The next language being developed for Puya is Algorand TypeScript. The goal is Algorand TypeScript is to make it easy for TypeScript develoeprs to start building on Algorand. The full list of guiding principles can be found [here](../README.md#guiding-principals).

This directory contains documents that offer a streamlined walkthrough of the potential options being explored. The goal is to expose users to various experiences without explaining too much rationale up front. This process allows us to distill the experience users want to help guide us on product decisions.

## Users

Profiles of the users that provide feedback will be included in [users.md](./users.md). The users provided feedback can choose to be anonymous or not. Anonymous feedback will be attributed to "User 1", "User 2", etc. Developer numbering will be consistent across all documents, meaning "User 1" in one document is the same person as "User 1" in another document. A user should write and/or approve of their own profile.

## Guided Walkthroughs

Each guided walkthrough will contain the following secions (if applicable)

### Native TypeScript Baseline

This section will contain a TypeScript snippet that demonstrates the feature we are trying to replicate in PuyaTS. There shouldn't be much feedback relevant to this section. It exists to simply set the stage of what we are trying to accomplish.

If not applicable (ie. ABI routing) this section can be omitted.

### Problems

This section will contain a brief explanation of why the TypeScript snippet cannot work in PuyaTS as is. In most cases this will be due to semantic incompatability.

### Proposed Solutions

This section will have one or more proposed solutions to the problem. If there are multiple solutions, we should start with the solution that is most similar to the TypeScript equvalent. Each solution should have a code snippet and perhaps some guided questions, but not detailed rationale. The solutions will come from the [Architecture Decision Records (ADRs)](./../architecture-decisions/) that have been created to explore the full range of solutions in depth. The walkthroughs are meant to be a high-level overview of the solutions.

### Feature Comparison

This section will contain a table comparing the features of each proposed solution. This table should be concise and easy to read. The goal is to help users quickly understand the trade-offs between each solution.

### Code Comparison

This section will contain side-by-side snippets of the proposed solutions. If applicable, there will also be a side-by-side comparison of the TypeScript equivalent and how it would be treated with the proposed solutions.

## Feedback Summaries

Each guided walkthrough will have a corresponding feedback document. The feeback document will contain sub-sections summarizing the feedback from specific users.

Users should not look at the feedback until they've provided feedback themselves.

## Process

The Algorand Foundation team will be reaching out to users for guided sessions where we will be responsible for taking the users through the walkthrough and summarizing their feedback. Feedback summaries MUST be approved by the user.

### Self-Guided Feedback

If you are going through walkthroughs on your own you can provide feedback by making a PR with the following changes

#### User Profile

In [users.md](./users.md) add a new user profile with some bullet points about yourself. In patciular, we are interested in your experience with TypeScript and Algorand. If you wish to be anonymous, you can use "User N" as your identifier, with N being the next available number (for example, if there's a "User 10", but not "User 11", you'd be "User 11").

##### Example

```md
### User N

- 5 years TypeScript experience
- New to blockchain and Algorand
```

#### Feedback

Then for each walkthrough you go through, add a new section in the corresponding feedback document. For example, if you go through the [strings walkthrough](./walkthroughs/strings.md), you would add a new section in [feedback/strings.md](./feedback/strings.md).

Ideally you would provide feedback for each proposed solution and then an overall feedback section. The feedback should be concise and to the point. If you have a lot of feedback, consider breaking it up into bullet points.

##### Example

```md
### User N

#### Option X

- This is how I'd expect it to work
- Reminds of of SomeRandomLibrary

#### Option Y

- I see the value, but seems a little confusing
- I like the error clarity

#### Overall Feedback

- I generally prefer option X, but if we could get feature A from option Y that would make it even better
```
13 changes: 13 additions & 0 deletions docs/user-feedback/feedback/strings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Feedback: Strings
joe-p marked this conversation as resolved.
Show resolved Hide resolved

Feedback for the [strings walkthrough](./../walkthroughs/strings.md).

The corresponding ADR is [here](../../architecture-decisions/2024-05-21_primitive-bytes-and-strings.md).

## Leaving Feedback

Most of the feedback here will be conducted via a session with someone from the Algorand Foundation. If you are going through this walkthrough on your own, however, and want to provide feedback you can follow the process defined [here](../README.md#self-guided-feedback).

## User Feedback

Currently gathering!
3 changes: 3 additions & 0 deletions docs/user-feedback/users.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Users
joe-p marked this conversation as resolved.
Show resolved Hide resolved

Below are profiles of the users that have provided feedback after going through one or more guided walkthroughs. If you are going through walkthroughs on your own, however, and want to provide feedback you can follow the process defined [here](../README.md#self-guided-feedback).
85 changes: 85 additions & 0 deletions docs/user-feedback/walkthroughs/math.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Walkthrough: Math

This walkthrough will cover how strings are handled in Algorand TypeScript.

# Native TypeScript Baseline

```ts
addNumbers(): number {
const a = 1;
const b = 255;

const sum = a + b;

return sum;
}
```

# Problems

In Algorand, there are multiple ways to encode numbers with ARC4. The AVM natively supports `uint64`, but other widths can be encoded as byte arrays. For example, you can define smaller uints such as `uint8` or larger uints such as `uint256`. When developers use these specific-width integers, there may be certain expcetations for overlow checks. For example, ensuring a `uint8` does not exceed 255 (2^8 - 1). Doing these sort of overflow checks within the AVM can be rather expensive, so it's ideal to not do it on every operation. As such, we need to figure out when and how these overflow checks are performed.

# Proposed Solutions

## Overflow Checks at Boundaries

This option allows you to perform math operations directly on any uint variable. Overflow checks, however, will not be performed directly at the time of the operation. Instead, it will only occur when the value is used externally. For example, returned, logged, or stored.

## Explicit Encoding

This option requires developers to explicitly encode and decode the non-`uint64` numbers. Widths > 64 bits will need to be coverted to bytes to perform byte math operations and widths < 64 bits will need to be converted to `uint64` to perform math operations. Eventually, the developer will need to re-encode the value back to the desire width via a constructor or type definition.

# Feature Comparison

| Feature | Benefit | Overflow Check at Boundaries | Explicit Encoding |
| ------------------------ | ---------------------------------------------------------------------------------- | ---------------------------- | ----------------- |
| Direct operation support | Math operations (ie. `+`, `-`, `*`, `/`) can be performed directly on the variable | ✅ | ❌ |
| Number construction | The developer has direct control over when overflow checks are performed | ❌ | ✅ |

# Code Comparison

<table>
<tr>
<th>Extended String Prototype</th>
<th>Custom Class</th>
</tr>

<tr>
<td>

```ts
addNumbers(): uint8 {
const a: uint8 = 1;
const b: uint8 = 255;

const sum = a + b;

// Runtime Error: Overflow
return sum;
}
```

</td>
<td>

```ts
addNumbers(): uint8 {
const a = Uint8(1);
const b = Uint8(255);

// Runtime Error: Overflow
const sum = Uint8(a.uint64() + b.uint64());

return sum;
}
```

</td>

</tr>
</table>

## General Questions

- How significant is potentially having a `uintN` variable being larger than `2^N - 1` during runtime before it's actually used?
- How important is to to be able to do overflow checks prior to the value being used?
94 changes: 94 additions & 0 deletions docs/user-feedback/walkthroughs/routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Walkthrough: Method Routing

This walkthrough will cover how method routing is handled in Algorand TypeScript.

# Problems

The AVM supports multiple "OnComplete" actions when calling a contract. There is also ARC4, which defines an ABI for the AVM which standardizes how to define handle method calling in a contract. Finally, it is common for a contract to behave differently depending on if the contract is being created (app ID === 0) or if a deployed contract is being called. All of these variables can make it difficult for a developer to succinctly describe the exact scenarios in which any given method should be callable.

## Proposed Solutions

In both solutions, by default, every public method will be a callable ARC4 ABI method when app ID > 0 (app is already deployed) and the OnCompelte is "NoOp". The options diverge when it comes to how we define the logic when app ID === 0 and/or the OnComplete is not "NoOp".

### Decorators

This option proposes to use decorators to define the logic for different scenarios. This would allow the developer to describe the exact scenarios in which any given method should be callable.

| Decorator | Action |
| ---------------------------------- | --------------------------------------------------------------------------------------- |
| `@allow.create("NoOp")` | Allow the method to be called when app ID === 0 and the OnComplete is "NoOp" |
| `@allow.call("UpdateApplication")` | Allow the method to be called when app ID > 0 and the OnComplete is "UpdateApplication" |
| `@allow.call("DeleteApplication")` | Allow the method to be called when app ID > 0 and the OnComplete is "DeleteApplication" |

### Special Method Names

Defining the logic for different scenarios, such as create, update, or delete will be done by implementing a method with a special name. For example, `createApplication`, `updateApplicaiton`, or `deleteApplication`.

| Method Name | Action |
| ------------------- | --------------------------------------------------------------------------------------- |
| `createApplication` | Allow the method to be called when app ID === 0 and the OnComplete is "NoOp" |
| `updateApplication` | Allow the method to be called when app ID > 0 and the OnComplete is "UpdateApplication" |
| `deleteApplication` | Allow the method to be called when app ID > 0 and the OnComplete is "DeleteApplication" |

It should be noted that decorators could also be used for more complex scenarios, for example a create method that has a "DeleteApplication" OnComplete.

# Feature Comparison

| Feature | Benefit | Decorators | Special Method Names |
| -------------------------- | --------------------------------------------------------------- | ---------- | -------------------- |
| Required use of decorators | Enforced explicitness of handled actions for every method | ✅ | ❌ |
| Conventional method names | Contracts will use conventional method names for common actions | ❌ | ✅ |

# Code Comparison

<table>
<tr>
<th>Decorators</th>
<th>Special Method Names</th>
</tr>

<tr>
<td>

```ts
@allow.create("NoOp")
myCreateMethod(): void {
log("Application created");
}

@allow.call("UpdateApplication")
myUpdateMethod(): void {
assert(this.txn.sender === this.app.creator)
log("Application updated");
}

@allow.call("DeleteApplication")
myDeleteMethod(): void {
assert(this.txn.sender === this.app.creator)
log("Application deleted");
}
```

</td>
<td>

```ts
createApplication(): void {
log("Application created");
}

updateApplication(): void {
assert(this.txn.sender === this.app.creator)
log("Application updated");
}

deleteApplication(): void {
assert(this.txn.sender === this.app.creator)
log("Application deleted");
}
```

</td>

</tr>
</table>
Loading