Add a taco-shop tutorial & launch blog post
@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
id: first-smart-contract
|
|
||||||
title: My first LIGO smart contract
|
|
||||||
---
|
|
||||||
|
|
||||||
TODO
|
|
@ -0,0 +1,23 @@
|
|||||||
|
type taco_supply is record
|
||||||
|
current_stock : nat;
|
||||||
|
max_price : tez;
|
||||||
|
end
|
||||||
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
|
||||||
|
function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
||||||
|
begin
|
||||||
|
// Retrieve the taco_kind from the contract's storage
|
||||||
|
const taco_kind : taco_supply = get_force(taco_kind_index, taco_shop_storage);
|
||||||
|
|
||||||
|
const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock;
|
||||||
|
|
||||||
|
if amount =/= current_purchase_price then
|
||||||
|
// we won't sell tacos if the amount isn't correct
|
||||||
|
fail("Sorry, the taco you're trying to purchase has a different price");
|
||||||
|
else
|
||||||
|
// Decrease the stock by 1n, because we've just sold one
|
||||||
|
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||||
|
|
||||||
|
// Update the storage with the refreshed taco_kind
|
||||||
|
taco_shop_storage[taco_kind_index] := taco_kind;
|
||||||
|
end with ((nil : list(operation)), taco_shop_storage)
|
@ -0,0 +1,335 @@
|
|||||||
|
---
|
||||||
|
id: tezos-taco-shop-smart-contract
|
||||||
|
title: Taco shop smart-contract
|
||||||
|
---
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
Meet **Pedro**, our *artisan taco chef* who has decided to open a Taco shop on the Tezos blockchain, using a smart-contract. He sells two different kinds of tacos, the **el clásico** and the **especial del chef**.
|
||||||
|
|
||||||
|
To help Pedro open his dream taco shop, we'll implement a smart-contract, that will manage supply, pricing & sales of his tacos to the consumers.
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/taco-stand.svg" width="50%" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 10px;">Made by <a href="https://www.flaticon.com/authors/smashicons" title="Smashicons">Smashicons</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pricing
|
||||||
|
|
||||||
|
Pedro's tacos are a rare delicatese, so their **price goes up**, as the **stock for the day begins to deplete**.
|
||||||
|
|
||||||
|
Each taco kind, has it's own `max_price` that it sells for, and a finite supply for the current sales lifecycle.
|
||||||
|
|
||||||
|
> For the sake of simplicity, we won't implement replenishing of the supply after it runs out.
|
||||||
|
|
||||||
|
### Daily offer
|
||||||
|
|
||||||
|
|**kind** |id |**available_stock**| **max_price**|
|
||||||
|
|---|---|---|---|
|
||||||
|
|el clásico | `1n` | `50n` | `50000000mtz` |
|
||||||
|
|especial del chef | `2n` | `20n` | `75000000mtz` |
|
||||||
|
|
||||||
|
### Calculating the current purchase price
|
||||||
|
|
||||||
|
Current purchase price is calculated with the following equation:
|
||||||
|
|
||||||
|
```
|
||||||
|
current_purchase_price = max_price / available_stock
|
||||||
|
```
|
||||||
|
|
||||||
|
#### El clásico
|
||||||
|
|**available_stock**|**max_price**|**current_purchase_price**|
|
||||||
|
|---|---|---|
|
||||||
|
| `50n` | `50000000mtz` | `1tz`|
|
||||||
|
| `20n` | `50000000mtz` | `2.5tz` |
|
||||||
|
| `5n` | `50000000mtz` | `10tz` |
|
||||||
|
|
||||||
|
#### Especial del chef
|
||||||
|
|**available_stock**|**max_price**|**current_purchase_price**|
|
||||||
|
|---|---|---|
|
||||||
|
| `20n` | `75000000mtz` | `3.75tz` |
|
||||||
|
| `10n` | `75000000mtz` | `7.5tz`|
|
||||||
|
| `5n` | `75000000mtz` | `15tz` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installing LIGO
|
||||||
|
|
||||||
|
In this tutorial, we'll use LIGO's dockerized version for the sake of simplicity. You can find the installation instructions [here](setup/installation.md#dockerized-installation-recommended).
|
||||||
|
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/install-ligo.png" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 12px; margin-top:-24px;">Installing the <b>next</b> version of LIGO's CLI</div>
|
||||||
|
|
||||||
|
## Implementing our first entry point
|
||||||
|
|
||||||
|
> From now on we'll get a bit more technical. If you run into something we have not covered yet - please try checking out the [LIGO cheat sheet](language-basics/cheat-sheet.md) for some extra tips & tricks.
|
||||||
|
|
||||||
|
To begin implementing our smart contract, we need an entry point. We'll call it `main` and it'll specify our contract's storage (`int`) and input parameter (`int`). Of course this is not the final storage/parameter of our contract, but it's something to get us started and test our LIGO installation as well.
|
||||||
|
|
||||||
|
### `taco-shop.ligo`
|
||||||
|
```Pascal
|
||||||
|
function main (const parameter : int; const contractStorage : int) : (list(operation) * int) is
|
||||||
|
block {skip} with ((nil : list(operation)), contractStorage + parameter)
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's brake down the contract above to make sure we understand each bit of the LIGO syntax:
|
||||||
|
|
||||||
|
- **`function main`** - definition of a function that serves as an entry point
|
||||||
|
- **`(const parameter : int; const contractStorage : int)`** - parameters passed to the function
|
||||||
|
- **`const parameter : int`** - parameter provided by a transaction that invokes our contract
|
||||||
|
- **`const contractStorage : int`** - definition of our storage (`int`)
|
||||||
|
- **`(list(operation) * int)`** - return type of our function, in our case a touple with a list of operations, and an int
|
||||||
|
- **`block {skip}`** - our function has no body, so we instruct LIGO to `skip` it
|
||||||
|
- **`with ((nil : list(operation)), contractStorage + parameter)`** - essentially a return statement
|
||||||
|
- **`(nil : list(operation))`** - a `nil` value annotated as a list of operations, because that's required by our return type specified above
|
||||||
|
- **`contractStorage + parameter`** - a new storage value for our contract, sum of previous storage and a transaction parameter
|
||||||
|
### Running LIGO for the first time
|
||||||
|
|
||||||
|
To test that we've installed LIGO correctly, and that `taco-shop.ligo` is a valid contract, we'll dry-run it.
|
||||||
|
|
||||||
|
> Dry-running is a simulated execution of the smart contract, based on a mock storage value and a parameter.
|
||||||
|
|
||||||
|
Our contract has a storage of `int` and accepts a parameter that is also an `int`.
|
||||||
|
|
||||||
|
The `dry-run` command requires a few parameters:
|
||||||
|
- **contract** *(file path)*
|
||||||
|
- **entrypoint** *(name of the entrypoint function in the contract)*
|
||||||
|
- **parameter** *(parameter to execute our contract with)*
|
||||||
|
- **storage** *(starting storage before our contract's code is executed)*
|
||||||
|
|
||||||
|
|
||||||
|
And outputs what's returned from our entrypoint - in our case a touple containing an empty list (of operations to apply) and the new storage value - which in our case is the sum of the previous storage and the parameter we've used.
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
# Contract: taco-shop.ligo
|
||||||
|
# Entry point: main
|
||||||
|
# Parameter: 4
|
||||||
|
# Storage: 3
|
||||||
|
ligo dry-run taco-shop.ligo --syntax pascaligo main 4 3
|
||||||
|
# tuple[ list[]
|
||||||
|
# 7
|
||||||
|
# ]
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-1.png" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 12px; margin-top:-24px;">Simulating contract execution with the CLI</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
*`3 + 4 = 7` yay! Our CLI & contract work as expected, we can move onto fulfilling Pedro's on-chain dream.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Designing Taco shop's contract storage
|
||||||
|
|
||||||
|
We know that Pedro's Taco Shop serves two kinds of tacos, so we'll need to manage stock individually, per kind. Let's define a type, that will keep the `stock` & `max_price` per kind - in a record with two fields. Additionally, we'll want to combine our `taco_supply` type into a map, consisting of the entire offer of Pedro's shop.
|
||||||
|
|
||||||
|
**Taco shop's storage**
|
||||||
|
```Pascal
|
||||||
|
type taco_supply is record
|
||||||
|
current_stock : nat;
|
||||||
|
max_price : tez;
|
||||||
|
end
|
||||||
|
|
||||||
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
```
|
||||||
|
|
||||||
|
Next step is to update the `main` entry point to include `taco_shop_storage` as it's storage - while doing that let's set the `parameter` to `unit` as well to clear things up.
|
||||||
|
|
||||||
|
**`taco-shop.ligo`**
|
||||||
|
```Pascal
|
||||||
|
type taco_supply is record
|
||||||
|
current_stock : nat;
|
||||||
|
max_price : tez;
|
||||||
|
end
|
||||||
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
|
||||||
|
function main (const parameter: unit ; const taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
||||||
|
block {skip} with ((nil : list(operation)), taco_shop_storage)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Populating our storage in a dry-run
|
||||||
|
|
||||||
|
When dry-running a contract, it's crucial to provide a correct initial storage value - in our case the storage is type-checked as `taco_shop_storage`. Reflecting [Pedro's daily offer](tutorials/get-started/tezos-taco-shop-smart-contract.md#daily-offer), our storage's value will be defined as following:
|
||||||
|
|
||||||
|
**Storage value**
|
||||||
|
```zsh
|
||||||
|
map
|
||||||
|
1n -> record
|
||||||
|
current_stock = 50n;
|
||||||
|
max_price = 50000000mtz;
|
||||||
|
end;
|
||||||
|
2n -> record
|
||||||
|
current_stock = 20n;
|
||||||
|
max_price = 75000000mtz;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
> Storage value is a map, with two items in it, both items are records identified by natural numbers `1n` & `2n`.
|
||||||
|
|
||||||
|
**Dry run command with a multi-line storage value**
|
||||||
|
```zsh
|
||||||
|
ligo dry-run taco-shop.ligo --syntax pascaligo main unit "map
|
||||||
|
1n -> record
|
||||||
|
current_stock = 50n;
|
||||||
|
max_price = 50000000mtz;
|
||||||
|
end;
|
||||||
|
2n -> record
|
||||||
|
current_stock = 20n;
|
||||||
|
max_price = 75000000mtz;
|
||||||
|
end;
|
||||||
|
end"
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-2.png" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 12px; margin-top:-24px;">Dry-run with a complex storage value</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
*If everything went as expected, the `dry-run` command will return the contract's current storage, which is the map of products we've defined based on the daily offer of Pedro's taco shop.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Providing an entrypoint for buying tacos
|
||||||
|
|
||||||
|
Now that we have our stock well defined in form of storage, we can move on to the actual sales. We'll replace the `main` entrypoint with `buy_taco`, that takes an `id` - effectively a key from our `taco_shop_storage` map. This will allow us to calculate pricing, and if the sale is successful - then we can reduce our stock - because we have sold a taco!
|
||||||
|
|
||||||
|
### Selling the tacos for free
|
||||||
|
|
||||||
|
Let's start by customizing our contract a bit, we will:
|
||||||
|
|
||||||
|
- rename the entrypoint from `main` to `buy_taco`
|
||||||
|
- rename `parameter` to `taco_kind_index`
|
||||||
|
- change `taco_shop_storage` to a `var` instead of a `const`, because we'll want to modify it
|
||||||
|
|
||||||
|
**`taco-shop.ligo`**
|
||||||
|
```Pascal
|
||||||
|
type taco_supply is record
|
||||||
|
current_stock : nat;
|
||||||
|
max_price : tez;
|
||||||
|
end
|
||||||
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
|
||||||
|
|
||||||
|
function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
||||||
|
block { skip } with ((nil : list(operation)), taco_shop_storage)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Decreasing `current_stock` when a taco is sold
|
||||||
|
|
||||||
|
In order to decrease the stock in our contract's storage for a specific taco kind, a few things needs to happen:
|
||||||
|
|
||||||
|
- retrieve the `taco_kind` from our storage, based on the `taco_kind_index` provided
|
||||||
|
- subtract the `taco_kind.current_stock` by `1n`
|
||||||
|
- we can find the absolute (`nat`) value of the subtraction above by using `abs`, otherwise we'd be left with an `int`
|
||||||
|
- update the storage, and return it
|
||||||
|
|
||||||
|
**`taco-shop.ligo`**
|
||||||
|
|
||||||
|
```Pascal
|
||||||
|
type taco_supply is record
|
||||||
|
current_stock : nat;
|
||||||
|
max_price : tez;
|
||||||
|
end
|
||||||
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
|
||||||
|
function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
||||||
|
begin
|
||||||
|
// Retrieve the taco_kind from the contract's storage
|
||||||
|
const taco_kind : taco_supply = get_force(taco_kind_index, taco_shop_storage);
|
||||||
|
// Decrease the stock by 1n, because we've just sold one
|
||||||
|
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||||
|
// Update the storage with the refreshed taco_kind
|
||||||
|
taco_shop_storage[taco_kind_index] := taco_kind;
|
||||||
|
end with ((nil : list(operation)), taco_shop_storage)
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-3.png" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 12px; margin-top:-24px;">Stock decreases after selling a taco</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
### Making sure we get paid for our tacos
|
||||||
|
|
||||||
|
In order to make Pedro's taco shop profitable, he needs to stop giving away tacos for free. When a contract is invoked via a transaction, an amount of tezzies to be sent can be specified as well. This amount is accessible within LIGO as `amount`.
|
||||||
|
|
||||||
|
To make sure we get paid, we will:
|
||||||
|
|
||||||
|
- calculate a `current_purchase_price` based on the [equation specified earlier](tutorials/get-started/tezos-taco-shop-smart-contract.md#calculating-the-current-purchase-price)
|
||||||
|
- check if the sent `amount` matches the `current_purchase_price`
|
||||||
|
- if not, then our contract will `fail` and stop executing
|
||||||
|
- if yes, stock for the given `taco_kind` will be decreased and the payment accepted
|
||||||
|
|
||||||
|
**`taco-shop.ligo`**
|
||||||
|
```Pascal
|
||||||
|
type taco_supply is record
|
||||||
|
current_stock : nat;
|
||||||
|
max_price : tez;
|
||||||
|
end
|
||||||
|
type taco_shop_storage is map(nat, taco_supply);
|
||||||
|
|
||||||
|
function buy_taco (const taco_kind_index: nat ; var taco_shop_storage : taco_shop_storage) : (list(operation) * taco_shop_storage) is
|
||||||
|
begin
|
||||||
|
// Retrieve the taco_kind from the contract's storage
|
||||||
|
const taco_kind : taco_supply = get_force(taco_kind_index, taco_shop_storage);
|
||||||
|
|
||||||
|
const current_purchase_price : tez = taco_kind.max_price / taco_kind.current_stock;
|
||||||
|
|
||||||
|
if amount =/= current_purchase_price then
|
||||||
|
// we won't sell tacos if the amount isn't correct
|
||||||
|
fail("Sorry, the taco you're trying to purchase has a different price");
|
||||||
|
else
|
||||||
|
// Decrease the stock by 1n, because we've just sold one
|
||||||
|
taco_kind.current_stock := abs(taco_kind.current_stock - 1n);
|
||||||
|
|
||||||
|
// Update the storage with the refreshed taco_kind
|
||||||
|
taco_shop_storage[taco_kind_index] := taco_kind;
|
||||||
|
end with ((nil : list(operation)), taco_shop_storage)
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to test the `amount` sent, we'll use the `--amount` option of `dry-run`:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
ligo dry-run taco-shop.ligo--syntax pascaligo --amount 1 buy_taco 1n "map
|
||||||
|
1n -> record
|
||||||
|
current_stock = 50n;
|
||||||
|
max_price = 50000000mtz;
|
||||||
|
end;
|
||||||
|
2n -> record
|
||||||
|
current_stock = 20n;
|
||||||
|
max_price = 75000000mtz;
|
||||||
|
end;
|
||||||
|
end"
|
||||||
|
```
|
||||||
|
**Purchasing a taco with 1.0tz**
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-4.png" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 12px; margin-top:-24px;">Stock decreases after selling a taco, if the right amount of tezzies is provided</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
**Attempting to purchase a taco with 0.7tz**
|
||||||
|
<img src="/img/tutorials/get-started/tezos-taco-shop-smart-contract/dry-run-5.png" />
|
||||||
|
<div style="opacity: 0.7; text-align: center; font-size: 12px; margin-top:-24px;">Stock does not decrease after a purchase attempt with a lower than required amount.</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
**That's it - Pedro can now sell tacos on-chain, thanks to Tezos & LIGO.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💰 Bonus: *Accepting tips above the taco purchase price*
|
||||||
|
|
||||||
|
If you'd like to accept tips in your contract as well, simply change the following line, depending on which behavior do you prefer.
|
||||||
|
|
||||||
|
**Without tips**
|
||||||
|
```Pascal
|
||||||
|
if amount =/= current_purchase_price then
|
||||||
|
```
|
||||||
|
|
||||||
|
**With tips**
|
||||||
|
```Pascal
|
||||||
|
if amount >= current_purchase_price then
|
||||||
|
```
|
@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
title: Introducing LIGO
|
|
||||||
author: Matej Sima
|
|
||||||
---
|
|
||||||
|
|
||||||
Hello LIGO
|
|
103
gitlab-pages/website/blog/2019-06-13-public-launch-of-ligo.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: Public Launch of LIGO
|
||||||
|
author: Gabriel Alfour
|
||||||
|
---
|
||||||
|
|
||||||
|
# Public Launch of [LIGO](https://ligolang.org/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## A Refresher: What is LIGO?
|
||||||
|
LIGO is a statically typed high-level smart-contract language that compiles down to Michelson. It seeks to be easy to use, extensible and safe.
|
||||||
|
|
||||||
|
The core language is being developed by The Marigold Project. George Dupéron and Christian Rinderknecht of Nomadic Labs help on the core language, and tooling for LIGO is being developed by Stove Labs (Granary, docs and infrastructure) and Brice Aldrich (syntax highlighting).
|
||||||
|
|
||||||
|
Our previous Medium posts about LIGO can be found [here](https://medium.com/tezos/introducing-ligo-a-new-smart-contract-language-for-tezos-233fa17f21c7) and [here](https://medium.com/tezos/ligo-becomes-polyglot-a474e2cb0c24).
|
||||||
|
|
||||||
|
## The State of LIGO
|
||||||
|
Today, we are publicly releasing LIGO in beta\*. We've focused on making the onboarding process for LIGO as painless as possible and encourage you to check out our [tutorials](/docs/tutorials/get-started/tezos-taco-shop-smart-contract) and [documentation](https://ligolang.org/docs/next/setup/installation).
|
||||||
|
|
||||||
|
We are fixing bugs and adding features to LIGO (e.g. some Michelson primitives like iterators are missing) by the day. Please submit issues about bugs and missing features you need when you encounter them, and you just might find those solved in the following week.
|
||||||
|
|
||||||
|
We have been also working to extend the capabilities of Michelson, benefitting all languages (e.g. SmartPy) in the Tezos ecosystem. These proposed changes include adding multiple entrypoints, partial application (enabling cheap closures) and new operators for fast stack access to Michelson. We will submit these improvements with Nomadic Labs and Cryptium in an amendment planned for the next proposal period.
|
||||||
|
|
||||||
|
## Sample Contract
|
||||||
|
|
||||||
|
Here are two samples equivalent contracts written in two different syntaxes. They add or substract an amount to the storage depending on the parameter.
|
||||||
|
|
||||||
|
```pascal
|
||||||
|
// Pascaligo syntax
|
||||||
|
type action is
|
||||||
|
| Increment of int
|
||||||
|
| Decrement of int
|
||||||
|
|
||||||
|
function main (const p : action ; const s : int) : (list(operation) * int) is
|
||||||
|
block {skip} with ((nil : list(operation)),
|
||||||
|
case p of
|
||||||
|
| Increment n -> s + n
|
||||||
|
| Decrement n -> s - n
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
|
```ocaml
|
||||||
|
(* Cameligo syntax *)
|
||||||
|
type action =
|
||||||
|
| Increment of int
|
||||||
|
| Decrement of int
|
||||||
|
|
||||||
|
let main (p : action) (s : int) : (operation list * int) =
|
||||||
|
let storage =
|
||||||
|
match p with
|
||||||
|
| Increment n -> s + n
|
||||||
|
| Decrement n -> s - n in
|
||||||
|
(([] : operation list) , storage)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
### Short-Term
|
||||||
|
#### June 2019
|
||||||
|
✓ First public release (hi)
|
||||||
|
✓ PascaLIGO and CameLIGO
|
||||||
|
✓ Docs
|
||||||
|
✓ Tutorials
|
||||||
|
\- Integration testing in JS/Reason with [Granary](https://stove-labs.github.io/granary/)
|
||||||
|
|
||||||
|
#### July 2019
|
||||||
|
\- Try ligo online
|
||||||
|
\- Unit testing in LIGO
|
||||||
|
\- ReasonLIGO (ReasonML syntax)
|
||||||
|
\- Design Pattern repository
|
||||||
|
|
||||||
|
### Mid-Term
|
||||||
|
We are currently planning 3 big projects on the core language (excluding tooling).
|
||||||
|
|
||||||
|
#### Generic Front End (GFE)
|
||||||
|
The PascaLIGO and CameLIGO parsers, pretty-printers and highlighters were written by hand. The same will be done for the ReasonML syntax in July.
|
||||||
|
The Generic Front End is a project to alleviate the need to do this manually for future syntaxes. The idea of the GFE is to develop a system that can take in a syntax description, and then generate:
|
||||||
|
- A parser
|
||||||
|
- A displayer
|
||||||
|
- A transpiler between syntaxes
|
||||||
|
- A syntax highlighter
|
||||||
|
- Some documentation
|
||||||
|
|
||||||
|
(A prototoype can be found in the code base that generated a PrettyPrinter, a Parser and an AST.)
|
||||||
|
|
||||||
|
#### Super Type System (STS)
|
||||||
|
The current type system is very basic: it is structural, non-polymorphic, without subtyping, names, references, advanced inference or effects. We are planning to change that.
|
||||||
|
We are looking to develop a Super Type System that has the following features:
|
||||||
|
- A rich type system. We are planning to integrate standard features (polymorphism, names), clear error messages and intuitive type inference.
|
||||||
|
- An effect system. This is important to capture failure cases, write effects in an idiomatic yet safe style (rather than passing around the storage through function calls) or capture which contracts can be called.
|
||||||
|
- An easy-to-use API. We want people to easily build static analysis tools on top of LIGO.
|
||||||
|
|
||||||
|
#### Real-time Benchmark
|
||||||
|
|
||||||
|
The current version explicitly excludes non-essential features which can produce unexpected explosions in gas costs. To alleviate this constraint, we plan to integrate gas benchmarks on all top-level declarations with some fuzzing. This will allow developers and users to estimate the cost of their contracts in real time.
|
||||||
|
|
||||||
|
## Getting Started and Contact
|
||||||
|
Come visit [our website](ligolang.org)! You can also join our [Discord](https://discord.gg/CmTwFM), Riot (*#ligo-public:matrix.org*) or Telegram Chat (Ligo Public channel).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\* Following software release cycle conventions, it should be called a pre-alpha. But most people don't know the difference.
|
||||||
|
Get started page in docs, Matej's tutorials, contributor docs, etc.
|
@ -56,7 +56,7 @@ class Footer extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<h5>More</h5>
|
<h5>More</h5>
|
||||||
<a href={`${this.props.config.baseUrl}blog`}>Blog</a>
|
<a href={`${this.props.config.baseUrl}blog`}>Blog</a>
|
||||||
<a href={this.docUrl('tutorials/first-smart-contract.html', this.props.language)}>Tutorials</a>
|
<a href={this.docUrl('tutorials/get-started/tezos-taco-shop-smart-contract.html', this.props.language)}>Tutorials</a>
|
||||||
<a href={`${this.props.config.repoUrl}`}>Gitlab</a>
|
<a href={`${this.props.config.repoUrl}`}>Gitlab</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -16,6 +16,6 @@
|
|||||||
"Road Map": ["contributors/road-map/short-term", "contributors/road-map/long-term"]
|
"Road Map": ["contributors/road-map/short-term", "contributors/road-map/long-term"]
|
||||||
},
|
},
|
||||||
"tutorials": {
|
"tutorials": {
|
||||||
"Get Started": ["tutorials/first-smart-contract"]
|
"Get Started": ["tutorials/get-started/tezos-taco-shop-smart-contract"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,10 +98,10 @@ const siteConfig = {
|
|||||||
// For no header links in the top nav bar -> headerLinks: [],
|
// For no header links in the top nav bar -> headerLinks: [],
|
||||||
headerLinks: [
|
headerLinks: [
|
||||||
{doc: 'setup/installation', label: 'Docs'},
|
{doc: 'setup/installation', label: 'Docs'},
|
||||||
{doc: 'api-cli-commands', label: 'CLI'},
|
{doc: 'tutorials/get-started/tezos-taco-shop-smart-contract', label: 'Tutorials'},
|
||||||
{doc: 'tutorials/first-smart-contract', label: 'Tutorials'},
|
|
||||||
{ blog: true, label: 'Blog' },
|
{ blog: true, label: 'Blog' },
|
||||||
{doc: 'contributors/origin', label: 'Contribute'},
|
{doc: 'contributors/origin', label: 'Contribute'},
|
||||||
|
{href: 'https://discord.gg/9rhYaEt', label: ''}
|
||||||
],
|
],
|
||||||
|
|
||||||
// If you have users set above, you add it here:
|
// If you have users set above, you add it here:
|
||||||
|
@ -86,7 +86,7 @@ blockquote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
blockquote code {
|
blockquote code {
|
||||||
opacity: 0.7;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
blockquote a {
|
blockquote a {
|
||||||
@ -211,6 +211,23 @@ code {
|
|||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body > div.fixedHeaderContainer > div > header > div > nav > ul > li:nth-child(5) {
|
||||||
|
background: url('/img/discord.svg');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
min-width: 50px;
|
||||||
|
padding-top: 5px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
body > div.fixedHeaderContainer > div > header > div > nav > ul > li:nth-child(5):hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
body > div.fixedHeaderContainer > div > header > div > nav > ul > li:nth-child(5) > a:hover {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (min-device-width: 360px) and (max-device-width: 736px) {
|
@media only screen and (min-device-width: 360px) and (max-device-width: 736px) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
gitlab-pages/website/static/img/discord.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 245 240"><style>.st0{fill:#FFFFFF;}</style><path class="st0" d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z"/><path class="st0" d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 257 KiB |
After Width: | Height: | Size: 560 KiB |
After Width: | Height: | Size: 512 KiB |
After Width: | Height: | Size: 567 KiB |
After Width: | Height: | Size: 734 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 15 KiB |
@ -37,7 +37,7 @@
|
|||||||
},
|
},
|
||||||
"version-next-tutorials": {
|
"version-next-tutorials": {
|
||||||
"Get Started": [
|
"Get Started": [
|
||||||
"version-next-tutorials/first-smart-contract"
|
"version-next-tutorials/get-started/tezos-taco-shop-smart-contract"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|