Skip to content

Commit

Permalink
feat(docs): add more detailed documentation on Transaction Builder (#50)
Browse files Browse the repository at this point in the history
Description
---

Updates documentation with more details regarding `Transaction Builder`.

Motivation and Context
---

The existing documentation was a bit lacking.

How Has This Been Tested?
---

The documentation site was tested locally:

```bash
$ pnpm install
$ moon tari-docs:build
$ moon tari-docs:serve
tari-docs:build | > tari-docs@0.0.1 build /Users/martinserts/Projects/Tari/tari.js.martins/docusaurus/tari-docs
tari-docs:build | > docusaurus build
tari-docs:build | 
tari-docs:build | [INFO] [en] Creating an optimized production build...
tari-docs:build | [webpackbar] ℹ Compiling Client
tari-docs:build | [webpackbar] ℹ Compiling Server
tari-docs:build | [webpackbar] ✔ Server: Compiled successfully in 7.23s
tari-docs:build | [webpackbar] ✔ Client: Compiled successfully in 10.33s
tari-docs:build | [SUCCESS] Generated static files in "build".
tari-docs:build | [INFO] Use `npm run serve` command to test your build locally.
▪▪▪▪ tari-docs:build (cached, ab3370e3)
▪▪▪▪ tari-docs:serve

> tari-docs@0.0.1 start /Users/martinserts/Projects/Tari/tari.js.martins/docusaurus/tari-docs
> docusaurus start

[INFO] Starting the development server...
[SUCCESS] Docusaurus website is running at: http://localhost:3000/tari.js/

✔ Client
  Compiled successfully in 787.16ms

client (webpack 5.98.0) compiled successfully
```

What process can a PR reviewer use to test or verify this change?
---

Start the documentation server as shown above.
Point the browser to: http://localhost:3000/tari.js/

<!-- Checklist -->
<!-- 1. Is the title of your PR in the form that would make nice release
notes? The title, excluding the conventional commit
tag, will be included exactly as is in the CHANGELOG, so please think
about it carefully. -->


Breaking Changes
---

- [x] None
- [ ] Requires data directory on base node to be deleted
- [ ] Requires hard fork
- [ ] Other - Please specify

<!-- Does this include a breaking change? If so, include this line as a
footer -->
<!-- BREAKING CHANGE: Description what the user should do, e.g. delete a
database, resync the chain -->
  • Loading branch information
martinserts authored Feb 20, 2025
1 parent cdb7604 commit d51c477
Show file tree
Hide file tree
Showing 13 changed files with 362 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
sidebar_position: 2
---

# Build and execute a request

## Build a transaction

After constructing an instance of the *Transaction Builder*, you can build a transaction as follows:

```js
const transaction = builder.build();
```

## Build a transaction request

The transaction request has additional parameters. Therefore, you build it using `buildTransactionRequest`:

```js
const isDryRun = false;
const inputRefs = undefined; // Obsolete
const network = Network.LocalNet;
const requiredSubstates = []; // Soon to be retired. Use `builder.withInputs()` instead.
const submitTransactionRequest = buildTransactionRequest(
transaction,
account.account_id,
requiredSubstates,
inputRefs,
isDryRun,
network
);
```

## Execute a transaction

```js
const txResult = await submitAndWaitForTransaction(provider, submitTransactionRequest);
```

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Transaction Builder",
"position": 1,
"link": {
"type": "doc",
"id": "transaction-builder-index"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
sidebar_position: 5
---

# CallFunction

`callFunction` can be used to create instances of components or call other *static* methods.

```js
builder = builder.callFunction(
{
templateAddress,
functionName: "new",
},
[1, 2, 3]
);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
sidebar_position: 5
---

# CallMethod

`callMethod` calls a method on an instance of a template—in other words, on a component.

```js
const amount = 10;
const tokenResource = "resource_217d58767480fbaa48693e11de34baf7fd727e33ee7627f0c4e5b78def378e57";

builder = builder.callMethod({
componentAddress: account.address,
methodName: "withdraw",
}, [tokenResource, amount.toString()]);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
sidebar_position: 4
---

# Fee

Executing a transaction requires a fee. This fee can originate from sources other than the transaction sender's account.

```js
const account = await provider.getAccount();
const fee = new Amount(2000);
builder = builder
.feeTransactionPayFromComponent(account.address, fee.getStringValue());
```

Under the hood, `feeTransactionPayFromComponent` creates an instruction that calls the `pay_fee` method on a component.

```js
builder.addFeeInstruction({
CallMethod: {
component_address: componentAddress,
method: "pay_fee",
args: [maxFee],
},
});
```

You might need to take this explicit route if the fee payment method is named something other than `pay_fee`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
sidebar_position: 1
id: transaction-builder-index
title: Transaction Builder
description: Overview of a transaction builder
---

# Transaction Builder
Expand Down Expand Up @@ -421,3 +423,4 @@ const txResult = await submitAndWaitForTransaction(provider, submitTransactionRe
}
}
```

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
sidebar_position: 6
---

# Inputs

Inputs are required substates for a transaction. Supplying these helps to assign transactions to correct shards in consensus.

A required substate has one of the following types:

- Component
- Resource
- Vault
- UnclaimedConfidentialOutput
- NonFungible
- NonFungibleIndex
- TransactionReceipt
- Template
- ValidatorFeePool


```js
builder = builder.withInputs([{ substateId: { Component: account.address } }]);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
sidebar_position: 3
---

# Instructions

There are nine types of instructions. In most cases, you will not need to create raw instructions yourself but will instead use one of the methods provided by the Transaction Builder.

## CreateAccount

```json
{
"CreateAccount": {
"owner_public_key": string,
"workspace_bucket": string | null
}
}
```

## CallFunction

```json
{
"CallFunction": {
"template_address": string,
"function": string,
"args": any[]
}
}
```

## CallMethod

```json
{
"CallMethod": {
"component_address": string,
"method": string,
"args": any[]
}
}
```

## PutLastInstructionOutputOnWorkspace

```json
{
"PutLastInstructionOutputOnWorkspace": {
"key": number[]
}
}
```

## EmitLog

```json
{
"EmitLog": {
"level": "Error" | "Warn" | "Info" | "Debug",
"message": string
}
}
```

## ClaimBurn


```json
{
"ClaimBurn": {
"claim": {
"publicKey": string,
"outputAddress": string,
"rangeProof": number[],
"proofOfKnowledge": string,
"withdrawProof": ConfidentialWithdrawProof | null,
}
}
}
```

## ClaimValidatorFees

```json
{
"ClaimValidatorFees": {
"epoch": number,
"validator_public_key": string
}
}
```

## DropAllProofsInWorkspace

```json
DropAllProofsInWorkspace
```

## CreateFreeTestCoins

```json
{
"CreateFreeTestCoins": {
"revealed_amount": string,
"output": ConfidentialOutput | null
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
sidebar_position: 7
---

# WithMinEpoch / WithMaxEpoch

In some circumstances, it is important to limit the time window during which a transaction is valid for execution. These bounds can be specified using `withMinEpoch` and `withMaxEpoch`.

## withMinEpoch

```js
builder = builder.withMinEpoch(2);
```

## withMaxEpoch

```js
builder = builder.withMaxEpoch(10000);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
sidebar_position: 8
---

# Raw instructions

Sometimes the functionality of the *Transaction Builder* is insufficient, and you might need to execute one of the raw [instructions](./instruction.md). In that case, use the `addInstruction` method:

```js
builder = builder.addInstruction({
EmitLog: {
level: "Info",
message: "Test log",
},
});
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
sidebar_position: 7
---

# SaveVar / FromWorkspace

## saveVar

```js
builder = builder
.callMethod(
{
componentAddress: account.address,
methodName: "withdraw",
},
[tokenResource, amount.toString()],
)
.saveVar("bucket")
```

This saves the result of the `withdraw` instruction to the intermediate variable `bucket`, which can later be accessed using `fromWorkspace`.

## fromWorkspace

```js
builder = builder
.callMethod(
{
componentAddress: account.address,
methodName: "deposit",
},
[fromWorkspace("bucket")],
);
```

It is important to note that some methods may return *multiple values*, and you might want to access them separately.
In that case, you can address them using `.0`, `.1`, and so on.

```js
builder = builder
.callMethod(
{
componentAddress: poolComponent,
methodName: "remove_liquidity",
},
[fromWorkspace("tokens_lp")]
)
.saveVar("buckets")
.callMethod(
{
componentAddress: account.address,
methodName: "deposit",
},
[fromWorkspace("buckets.0")]
)
.callMethod(
{
componentAddress: account.address,
methodName: "deposit",
},
[fromWorkspace("buckets.1")]
);
```
Loading

0 comments on commit d51c477

Please sign in to comment.