# Sample Txn Executor

In the newly added `account.rs` file we handle the following txns:

* deposit\_for\_task: Pay deposit when taking a task.
* rollback\_deposit: Move the deposit to the owner in case of "reject" operation.
* reward\_owner: The successful worker takes the reward.

All the function code is straightforward and follows the same pattern:

* Input a `mut ctx`.
* Get the amount as well as payer and payee addresses.
* Call the `move` or `cross_move` function to transfer funds.
* **ctx** is mutable, so it contains all state changes. The caller will handle the ctx.

Let's move to the caller, the txn.rs. We use the TakeTask as an example, but all others txns follow the same pattern:

```
Txns::TakeTask {
            subject,
            worker,
            auth_b64,
        } => {
            let task = task_by_subject(subject).await?;
            if task.status != Status::New {
                return Err(TxnErrors::TakeTaskFailed.into());
            }
            if let Some(worker) = task.worker {
                return Err(TxnErrors::TaskInprogress(task.subject, worker).into());
            }
            check_account(auth_b64, *worker).await?;
            let glue_ctx = new_gluedb_context().await?;

            let (tappstore_ctx, ctx) =
                account::deposit_for_task(tsid, base, *worker, task.required_deposit, ctx).await?;
            take_task(tsid, subject, *worker, task.required_deposit).await?;
            CommitContextList {
                ctx_list: vec![
                    CommitContext::new(
                        ctx,
                        glue_ctx,
                        None,
                        None,
                        decode_auth_key(auth_b64)?,
                        txn.to_string(),
                    ),
                    CommitContext::ctx_receipting(tappstore_ctx, txn.to_string()),
                ],
                ..Default::default()
            }
        }
```

First, get the task. If the task status is not "new" then throw an error because only new tasks can be taken.

If the task has a worker, throw an error because the task has someone working on it.

`check_account(auth_b64, *worker).await?;` guard the current login user as the input worker parameter.

`let glue_ctx = new_gluedb_context().await?;` starts an SQL transaction. We should use this preface line everytime we run or process any SQL transactions.

```
let (tappstore_ctx, ctx) =
                account::deposit_for_task(tsid, base, *worker, task.required_deposit, ctx).await?;
```

This function `deposit_for_task` has a `ctx` input and also outputs `tappstore_ctx` and `ctx`. This is very important. `Ctx` is the object that records all the changes the code logic "should" apply to the state. But until commited, the changes are only stored in `ctx` without actually modifying the state. If anything is wrong during the `ctx` execution, the code can simply throw an error and return, and no changes will be applied to the state (i.e. the state remains unchanged).

In order to keep all changes in `ctx` and commit at once to modify `ctx` at a later time, ALL functions will have `ctx` as an input as well as returning `ctx` to the caller.

In this function, the output has another `tappstore_ctx` variable rather than the sole input `ctx`. That's because the tappstore's state will be changed during the execution. We'll need to commit both ctx for this TApp AND the context of TAppStore. Why will we change the state of the TAppStore? It's because the deposit and TEA account balance are stored in the TAppStore state. This is designed for easier TApp development. In most cases, the TApp doesn't need to maintain a TEA token state in their own state. Nor does the user need to topup TEA tokens to all the TApps they're using.

`take_task` is a function to execute sql scripts. The code is in sql.rs:

```
pub(crate) async fn take_task(
    tsid: Tsid,
    subject: &str,
    worker: Account,
    required_deposit: Balance,
) -> Result<()> {
    exec_sql(
        tsid,
        format!(
            r#"
            UPDATE Tasks SET 
                status = '{}',worker = '{worker:?}' 
                WHERE subject = '{subject}';
            INSERT INTO TaskExecution VALUES (
                '{subject}', '{worker:?}', '{required_deposit}'
            );
               "#,
            Status::InProgress
        ),
    )
    .await
}
```

This function is used to change the table to mark that a worker has taken a specific task.

Lastly, at the end of this [txn](/z_glossary/txn.md), return the CommitContextList:

```
            CommitContextList {
                ctx_list: vec![
                    CommitContext::new(
                        ctx,
                        glue_ctx,
                        None,
                        None,
                        decode_auth_key(auth_b64)?,
                        txn.to_string(),
                    ),
                    CommitContext::ctx_receipting(tappstore_ctx, txn.to_string()),
                ],
                ..Default::default()
            }
```

All matching branches in the txn executor will need to return such a `CommitContextList`. This list includes all the changes during the execution. Eventually, these changes will be applied using a Commit function so that the state and SQL database can be permanently changed.

For the details of CommitContextList, please refer to the Developer Documents.

## Other minor changes

In `error.rs`, you can find a few newly added errors that are self-explanatory.

We won't describe `table.sql` because these are all standard SQL scripts, for indexing, table creating etc. SQL is not in the scope of this tutorial.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.teaproject.org/020_tutorial/060_reward_fund_transfer/061_sample_txn_executor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
