Skip to content

Commit

Permalink
SCIL-27: Documentation (#203)
Browse files Browse the repository at this point in the history
* WiP

* Initial documentation

* Adding getting started
  • Loading branch information
troelsfr authored Sep 26, 2023
1 parent dcc6b88 commit 3422172
Show file tree
Hide file tree
Showing 19 changed files with 1,282 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,7 @@ impl AstConverting for IrEmitter {
_mode: TreeTraversalMode,
_node: &NodeMetaIdentifier,
) -> Result<TraversalResult, String> {
// TODO:
Ok(TraversalResult::Continue)
// unimplemented!();
}
fn emit_variable_identifier(
&mut self,
Expand Down
137 changes: 137 additions & 0 deletions products/bluebell/docs/address.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
## `Address` type format

Check notice on line 1 in products/bluebell/docs/address.md

View workflow job for this annotation

GitHub Actions / Trunk Check

markdownlint(MD041)

[new] First line in a file should be a top-level heading

The `Address` data structure in Scilla represents the 20-byte Ethereum-like
address format. It is utilized to identify contracts and external accounts
within the Zilliqa blockchain network.

```text
+--------------------+
| 20 bytes |
| |
| Address Payload |
+--------------------+
```

Addresses are fundamental in various aspects of contract development in Scilla,
such as sending and receiving funds, calling other contracts, or designating
permissions. It is crucial to ensure the correctness of these addresses to
prevent unintentional transactions.

```scilla
(* Example of contract using Scilla address *)
import ListUtils
contract SimpleStorage(owner: ByStr20)
field storedData : Int32 = 0
transition Store(newData : Int32)
is_owner = builtin eq owner _sender;
match is_owner with
| False =>
e = {_eventname : "Unauthorized"; msg : "You are not the contract owner."};
event e
| True =>
storedData := newData;
e = {_eventname : "DataStored"; data : newData};
event e
end
end
```

## Address Verification

To verify the validity of a Scilla address, one typically checks the following:

1. Ensure the address has a length of 20 bytes.
2. Check if the address does not contain non-hexadecimal characters.
3. For contract addresses, confirm that a corresponding contract exists on the
blockchain.

It's also common to employ checksums to further validate addresses, though this
isn't mandated by Scilla or Zilliqa.

## Print `Address`

The new `print` function allows developers to print the `Address` types, which
is especially useful for debugging purposes. The function outputs the address in
its standard hexadecimal format.

```scilla
(* Example of using print to display Address *)
transition PrintAddress()
owner_address = owner; (* Fetch the owner address *)
print owner_address;
end
```

## Using Addresses with `zilliqa-js`

The `zilliqa-js` library provides a comprehensive suite of functions to manage,
validate, and work with addresses in Zilliqa's blockchain. Here's how you can
work with addresses using `zilliqa-js`:

### Initializing the SDK

Before performing any operations, you need to initialize the SDK.

```javascript
const { Zilliqa } = require("@zilliqa-js/zilliqa");
const zilliqa = new Zilliqa("https://api.zilliqa.com/");
```

### **Creating a New Address**

To generate a new keypair and associated address:

```javascript
const { getAddressFromPrivateKey } = require("@zilliqa-js/crypto");
const privateKey = zilliqa.wallet.create();
const address = getAddressFromPrivateKey(privateKey);
console.log(`Address: ${address}`);
```

### Validating an Address

Before any operations involving an address, it's always good practice to
validate it:

```javascript
const { validation } = require("@zilliqa-js/util");
const isValid = validation.isAddress("Your_Address_Here");
console.log(`Is valid address: ${isValid}`);
```

### Converting Between Address and Bech32

Zilliqa uses the Bech32 format for human-readable addresses. Here's how to
convert between a standard address and its Bech32 format:

```javascript
const { toBech32Address, fromBech32Address } = require("@zilliqa-js/crypto");

const bech32 = toBech32Address("Your_Address_Here");
console.log(`Bech32 format: ${bech32}`);

const originalAddress = fromBech32Address(bech32);
console.log(`Original format: ${originalAddress}`);
```

### Using an Address in Transactions

When you're sending a transaction, you'll typically need to specify the
recipient's address:

```javascript
const tx = zilliqa.transactions.new({
toAddr: "Recipient_Address_Here",
amount: zilliqa.utils.units.toQa("1", zilliqa.utils.units.Units.Zil), // 1 ZIL
gasPrice: zilliqa.utils.units.toQa("1000", zilliqa.utils.units.Units.Li), // Gas Price in Li
gasLimit: Long.fromNumber(50),
});
```

Always remember to handle private keys securely. Avoid exposing them in
client-side code or any public space.
57 changes: 57 additions & 0 deletions products/bluebell/docs/balance-transfer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Contract funds

## Getting the balance owned by the contract

You can get the balance owned by the contract using the `_balance` keyword in
Scilla.

```scilla
scilla_version 0
library BalanceChecker
contract BalanceQuery()
transition CheckBalance()
current_balance <- _balance;
e = { _eventname : "ContractBalance"; current_balance : current_balance };
event e
end
```

## Send funds from contract

In Scilla, sending funds from the contract involves using the `send`
instruction:

```scilla
scilla_version 0
library SendFunds
contract SendMoney(owner: ByStr20)
field balance : Uint128 = Uint128 0
transition Send(to: ByStr20, amount: Uint128)
b <- _balance;
can_send = builtin lt amount b;
match can_send with
| False =>
e = { _eventname : "SendFailed"; reason : "InsufficientFunds" };
event e
| True =>
msg = { _tag : ""; _recipient : to; _amount : amount };
value = builtin sub b amount;
balance := value;
(* TODO: send msg; *)
e = { _eventname : "SendSuccess"; recipient : to; sent_amount : amount };
event e
end
end
```

## Advanced example

TODO: Yet to be written
89 changes: 89 additions & 0 deletions products/bluebell/docs/builtin-functions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Builtin functions

## Builtin example usage

The `eq` builtin in Scilla is used to check the equality of two values. In this
example, we demonstrate how to check the equality of two Uint128 values:

```scilla
scilla_version 0
library EqualityCheck
contract EqualityChecker()
transition CheckEquality(a : Uint128, b : Uint128)
(* Use builtin eq to check equality *)
isEqual = builtin eq a b;
e = { _eventname : "CheckEqualityResult"; result : isEqual };
event e
end
```

The `concat` builtin in Scilla is used to concatenate two strings. In the
following example, we demonstrate how to concatenate two strings:

```scilla
scilla_version 0
library StringConcatContract
contract StringConcat()
(* Fields to store the strings and the result *)
field str1 : String = ""
field str2 : String = ""
field result : String = ""
(* Transition to set the strings *)
transition SetStrings(s1: String, s2: String)
str1 := s1;
str2 := s2;
e = { _eventname : "StringsSet"; s1 : s1; s2 : s2 };
event e
end
(* Transition to concatenate the stored strings *)
transition ConcatenateStrings()
s1 <- str1;
s2 <- str2;
concatenated = builtin concat s1 s2;
result := concatenated;
e = { _eventname : "StringsConcatenated"; concatenated : concatenated };
event e
end
```

With the above contracts, users can check the equality of two `Uint128` values
and concatenate two strings, respectively.

## Builtin summary

Below is the summarized table of builtin functions:

| Function name | Inputs | Outputs | Comments |
| -------------------- | ---------------------------------------------------------------- | --------------------- | ---------------------------------------------------------------------------------------- |
| `builtin eq` | `i1: IntX / UintX, i2: IntX / UintX` OR `s1: String, s2: String` | `Bool` | Checks equality between two integers or strings. |
| `builtin add` | `i1: IntX / UintX, i2: IntX / UintX` | `IntX / UintX` | Adds two integer values. |
| `builtin sub` | `i1: IntX / UintX, i2: IntX / UintX` | `IntX / UintX` | Subtracts the second integer from the first. |
| `builtin mul` | `i1: IntX / UintX, i2: IntX / UintX` | `IntX / UintX` | Multiplies two integers. |
| `builtin div` | `i1: IntX / UintX, i2: IntX / UintX` | `IntX / UintX` | Integer division. |
| `builtin rem` | `i1: IntX / UintX, i2: IntX / UintX` | `IntX / UintX` | Provides the remainder after division. |
| `builtin lt` | `i1: IntX / UintX, i2: IntX / UintX` | `Bool` | Checks if the first integer is less than the second. |
| `builtin pow` | `i1: IntX / UintX, i2: Uint32` | `IntX / UintX` | Raises the first integer to the power of the second. |
| `builtin isqrt` | `i: UintX` | `UintX` | Computes the integer square root. |
| `builtin to_nat` | `i1: Uint32` | `Nat` | Converts a Uint32 value to type Nat. |
| `builtin to_(u)intX` | `UintX / IntX or String` | `Option UintX / IntX` | Converts a value to a specified integer type. Can fail in certain cases. |
| `builtin concat` | `s1: String, s2: String` OR `h1: ByStr(X/Y), h2: ByStr(X/Y)` | `String / ByStr` | Concatenates two strings or byte strings. |
| `builtin substr` | `s: String, idx: Uint32, len: Uint32` | `String` | Extracts a substring from a given string. |
| `builtin to_string` | `x: IntX, UintX, ByStrX, ByStr` | `String` | Converts various types to a string literal. |
| `builtin strlen` | `s: String` OR `h: ByStr` | `Uint32` | Calculates the length of a string or byte string. |
| `builtin strrev` | `s: String` | `String` | Returns the reversed version of a string. |
| `builtin to_ascii` | `h: ByStr or ByStrX` | `String` | Converts a byte string to an ASCII string. Raises an error for non-printable characters. |
| `builtin to_bystr` | `h: ByStrX` | `ByStr` | Converts a fixed size byte string to one of arbitrary length. |
| `builtin to_bystrX` | `h: ByStr OR Uint(X)` | `Option ByStrX` | Converts an arbitrary size byte string or unsigned integer to a fixed size byte string. |
| `builtin to_uintX` | `h: ByStrX` | `Uint(X)` | Converts a fixed sized byte string to an equivalent unsigned integer value. |

Note: In the table, "X" and "Y" represent placeholder values, meaning you would
replace them with actual numeric values (32, 64, 128, 256) as appropriate for
the function's usage.
55 changes: 55 additions & 0 deletions products/bluebell/docs/control-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Control flow

## match

The `match` construct is used for pattern matching and in place of `if`
statements. It's especially useful for handling ADTs (Algebraic Data Types) and
Options.

Here's a simple example of using `match` with an ADT:

```scilla
scilla_version 0
library MatchExample
type Animal =
| Dog
| Cat
| Elephant
contract AnimalSound()
transition GetSound(animal: Animal)
sound =
match animal with
| Dog => "Bark"
| Cat => "Meow"
| Elephant => "Trumpet"
end;
e = { _eventname : "AnimalSound"; sound : sound };
event e
end
```

Here's another example of using `match` to handle an Option type:

```scilla
scilla_version 0
library OptionMatchExample
contract HandleOption()
transition GetNumber(opt: Option Uint32)
result =
match opt with
| Some n => n
| None => Uint32 0
end;
e = { _eventname : "NumberResult"; number : result };
event e
end
```
Loading

0 comments on commit 3422172

Please sign in to comment.