diff --git a/package.json b/package.json
index 3ea4266..0c36d72 100644
--- a/package.json
+++ b/package.json
@@ -10,13 +10,13 @@
"eject": "react-scripts eject"
},
"dependencies": {
- "@monaco-editor/react": "^3.2.1",
- "@testing-library/jest-dom": "^5.4.0",
- "@testing-library/react": "^10.0.2",
- "@testing-library/user-event": "^10.0.1",
+ "@monaco-editor/react": "3.2.1",
+ "@testing-library/jest-dom": "^5.5.0",
+ "@testing-library/react": "^10.0.3",
+ "@testing-library/user-event": "^10.0.2",
"@types/jest": "^25.2.1",
- "@types/node": "^13.11.1",
- "@types/react": "^16.9.33",
+ "@types/node": "^13.13.2",
+ "@types/react": "^16.9.34",
"@types/react-dom": "^16.9.6",
"connected-react-router": "^6.8.0",
"markdown-to-jsx": "^6.11.1",
@@ -52,9 +52,9 @@
"@types/markdown-to-jsx": "^6.11.0",
"@types/rc-slider": "^8.6.5",
"@types/react-redux": "^7.1.7",
- "@types/react-router-dom": "^5.1.3",
+ "@types/react-router-dom": "^5.1.4",
"@types/react-transition-group": "^4.2.4",
- "@types/styled-components": "^5.0.1",
- "raw-loader": "^4.0.0"
+ "@types/styled-components": "^5.1.0",
+ "raw-loader": "^4.0.1"
}
}
diff --git a/public/elements/alien.png b/public/elements/alien.png
index 4605345..88dc604 100644
Binary files a/public/elements/alien.png and b/public/elements/alien.png differ
diff --git a/public/elements/character-bg-evil.svg b/public/elements/character-bg-evil.svg
index 287cb94..3594aa6 100644
--- a/public/elements/character-bg-evil.svg
+++ b/public/elements/character-bg-evil.svg
@@ -1,26 +1,26 @@
diff --git a/public/elements/dialog-evil.png b/public/elements/dialog-evil.png
new file mode 100644
index 0000000..92c71ce
Binary files /dev/null and b/public/elements/dialog-evil.png differ
diff --git a/public/elements/dialog-mobile-evil.png b/public/elements/dialog-mobile-evil.png
new file mode 100644
index 0000000..ea73184
Binary files /dev/null and b/public/elements/dialog-mobile-evil.png differ
diff --git a/public/elements/traitor.png b/public/elements/traitor.png
index 288c0d3..184376c 100644
Binary files a/public/elements/traitor.png and b/public/elements/traitor.png differ
diff --git a/public/fonts/Modern-vulcan11.woff b/public/fonts/Modern-vulcan11.woff
new file mode 100644
index 0000000..0d6c401
Binary files /dev/null and b/public/fonts/Modern-vulcan11.woff differ
diff --git a/public/fonts/Modern-vulcan11.woff2 b/public/fonts/Modern-vulcan11.woff2
new file mode 100644
index 0000000..d0dd55f
Binary files /dev/null and b/public/fonts/Modern-vulcan11.woff2 differ
diff --git a/public/fonts/vulcan.ttf b/public/fonts/vulcan.ttf
deleted file mode 100644
index e999e55..0000000
Binary files a/public/fonts/vulcan.ttf and /dev/null differ
diff --git a/src/Chapter/Chapter.controller.tsx b/src/Chapter/Chapter.controller.tsx
index 9ad0d42..a9c8e26 100644
--- a/src/Chapter/Chapter.controller.tsx
+++ b/src/Chapter/Chapter.controller.tsx
@@ -8,12 +8,13 @@ import { dataAddresses } from "../Chapters/ChapterAddresses";
import { dataBuiltIns } from "../Chapters/ChapterBuiltIns";
import { dataConditionals } from "../Chapters/ChapterConditionals";
import { dataFunctions } from "../Chapters/ChapterFunctions";
+import { dataInteractions } from "../Chapters/ChapterInteractions";
import { dataLists } from "../Chapters/ChapterLists";
import { dataLoops } from "../Chapters/ChapterLoops";
import { dataMainFunction } from "../Chapters/ChapterMainFunction";
import { dataMaps } from "../Chapters/ChapterMaps";
import { dataMath } from "../Chapters/ChapterMath";
-import { dataPatternMatching } from "../Chapters/ChapterPatternMatching";
+import { dataOption } from "../Chapters/ChapterOption";
import { dataRecords } from "../Chapters/ChapterRecords";
import { dataStrings } from "../Chapters/ChapterStrings";
import { dataTimestamps } from "../Chapters/ChapterTimestamps";
@@ -87,15 +88,15 @@ export const Chapter = () => {
setData({ course: dataTimestamps.course, exercise: dataTimestamps.exercise, solution: dataTimestamps.solution });
if (pathname === "/19")
setData({
- course: dataPatternMatching.course,
- exercise: dataPatternMatching.exercise,
- solution: dataPatternMatching.solution,
+ course: dataOption.course,
+ exercise: dataOption.exercise,
+ solution: dataOption.solution,
});
if (pathname === "/20")
setData({
- course: dataTransactions.course,
- exercise: dataTransactions.exercise,
- solution: dataTransactions.solution,
+ course: dataInteractions.course,
+ exercise: dataInteractions.exercise,
+ solution: dataInteractions.solution,
});
}, [pathname]);
@@ -119,7 +120,6 @@ export const Chapter = () => {
};
const proposedSolutionCallback = (e: string) => {
- console.log({ course: data.course, exercise: e, solution: data.solution });
// @ts-ignore
setData({ ...data, exercise: e });
};
diff --git a/src/Chapter/Chapter.view.tsx b/src/Chapter/Chapter.view.tsx
index 6b1acc7..e913554 100644
--- a/src/Chapter/Chapter.view.tsx
+++ b/src/Chapter/Chapter.view.tsx
@@ -8,6 +8,7 @@ import { PENDING, RIGHT, WRONG } from "../Chapters/ChapterAbout/ChapterAbout.con
//prettier-ignore
import { Button, ButtonBorder, ButtonText, ChapterCourse, ChapterGrid, ChapterH1, ChapterH2, ChapterItalic, ChapterMonaco, ChapterStyled, ChapterValidator, ChapterValidatorContent, ChapterValidatorContentWrapper, ChapterValidatorInside, ChapterValidatorTitle } from "../Chapters/ChapterAbout/ChapterAbout.style";
import { Dialog } from "../Dialog/Dialog.controller";
+import { Light } from "../Light/Light.view";
const MonacoReadOnly = ({ children }: any) => {
const height = children.split("\n").length * 22;
@@ -139,6 +140,9 @@ const Content = ({ course }: any) => (
dialog: {
component: Dialog,
},
+ light: {
+ component: Light,
+ },
},
}}
/>
diff --git a/src/Chapters/ChapterAbout/ChapterAbout.style.tsx b/src/Chapters/ChapterAbout/ChapterAbout.style.tsx
index 2124613..45f6253 100644
--- a/src/Chapters/ChapterAbout/ChapterAbout.style.tsx
+++ b/src/Chapters/ChapterAbout/ChapterAbout.style.tsx
@@ -34,6 +34,7 @@ export const ChapterCourse = styled.div`
font-size: 14px;
white-space: pre-wrap;
overflow: auto;
+ position: relative;
`;
export const ChapterH1 = styled.div`
diff --git a/src/Chapters/ChapterAddresses/solution.ligo b/src/Chapters/ChapterAddresses/solution.ligo
index 19df8f2..992e2bd 100644
--- a/src/Chapters/ChapterAddresses/solution.ligo
+++ b/src/Chapters/ChapterAddresses/solution.ligo
@@ -1,6 +1,6 @@
function purchase (const purchase_price : tez) : bool is
// Type your solution below
const ship_address : address = ("tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV" : address);
- const vendor_address : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);
+ const vendor_address : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)
return True
\ No newline at end of file
diff --git a/src/Chapters/ChapterBuiltIns/solution.ligo b/src/Chapters/ChapterBuiltIns/solution.ligo
index 05210ef..c390c82 100644
--- a/src/Chapters/ChapterBuiltIns/solution.ligo
+++ b/src/Chapters/ChapterBuiltIns/solution.ligo
@@ -3,7 +3,7 @@ function purchase (const purchase_price : tez) : bool is
const vendor_address : address = ("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address);
// Type your solution below
- if Tezos.source =/= ship_address then failwith ("Access denied")
+ if Tezos.source =/= ship_address then failwith ("Access denied");
if Tezos.amount =/= purchase_price then failwith ("Incorrect amount")
return True
\ No newline at end of file
diff --git a/src/Chapters/ChapterTransactions/solution_central.ligo b/src/Chapters/ChapterInteractions/central.ligo
similarity index 100%
rename from src/Chapters/ChapterTransactions/solution_central.ligo
rename to src/Chapters/ChapterInteractions/central.ligo
diff --git a/src/Chapters/ChapterTransactions/central_types.ligo b/src/Chapters/ChapterInteractions/central_types.ligo
similarity index 100%
rename from src/Chapters/ChapterTransactions/central_types.ligo
rename to src/Chapters/ChapterInteractions/central_types.ligo
diff --git a/src/Chapters/ChapterInteractions/course.md b/src/Chapters/ChapterInteractions/course.md
new file mode 100644
index 0000000..18c549b
--- /dev/null
+++ b/src/Chapters/ChapterInteractions/course.md
@@ -0,0 +1,126 @@
+# Chapter 20 : Interactions
+
+
+
+
+
+A contract can invoke another by emiting a transaction operation at the end of an entrypoint.
+
+## Syntax
+
+The keyword _operation_ is a predefined type which model transaction (contract invocation).
+
+The keyword _transaction_ is predefined function which generates an _operation_ from following parameters:
+
+- target contract parameter (entrypoint call to execute on the target contract)
+- amount to transfer
+- the target contract interface (which describes possible entrypoints of targeted contract)
+
+ _transaction_ function follows the syntax:
+
+```
+const : operation = Tezos.transaction(, , );
+```
+
+The contract interface of an already deployed contract can be retrieved with the *get\_contract* function. It takes the address of the target contract and returns a contract interface. The _contract_ type is a template type which dpends on a the type of target contract parameter.
+
+```
+const : contract() = Tezos.get_contract_opt();
+```
+
+Since a contract might be destroyed, the call to *Tezos.get\_contract\_opt* may not find the target contract. For a safer purpose, the function *get\_contract\_opt* is also available to retrieve a contract interface and work as *get\_contract* but returns an option of _contract(parameter)_
+
+## Example
+
+The following example shows how a contract can invoke another by emiting a transaction operation at the end of an entrypoint.
+In our case, we have a counter.ligo contract that accepts an action of type parameter, and we have a proxy.ligo contract that accepts the same parameter type, and forwards the call to the deployed counter contract.
+
+```
+// counter.ligo
+
+type storage is int
+
+type parameter is
+ Increment of int
+| Decrement of int
+| Reset
+
+type return is list (operation) * storage
+
+function main (const action : parameter; const store : storage) : return is
+ ((nil : list (operation)),
+ case action of
+ Increment (n) -> store + n
+ | Decrement (n) -> store - n
+ | Reset -> 0
+ end)
+```
+
+```
+// proxy.ligo
+
+type parameter is
+ Increment of nat
+| Decrement of nat
+| Reset
+
+type storage is unit
+
+type return is list (operation) * storage
+
+const dest : address = ("KT19wgxcuXG9VH4Af5Tpm1vqEKdaMFpznXT3" : address)
+
+function proxy (const action : parameter; const store : storage): return is
+ block {
+ const counter : contract (parameter) =
+ case (Tezos.get_contract_opt (dest) : option (contract (parameter))) of
+ Some (contract) -> contract
+ | None -> (failwith ("Contract not found.") : contract (parameter))
+ end;
+ const mock_param : parameter = Increment (5n);
+ const op : operation = Tezos.transaction (action, 0tez, counter);
+ const ops : list (operation) = list [op]
+ } with (ops, store)
+```
+
+Notice that :
+
+- the _proxy_ function has the specific prototype of a Main function.
+- the _proxy_ function returns a list of operation containing the newly created transaction.
+- the _parameter_ type (counter parameter) has also been defined in proxy contract. The calling contract must know the parameter type of called contract.
+
+## Polymorphism
+
+When sending transactions between contracts, each contract must know the target contract interface and the parameter type of the target contract. This is done basicaly by separating type definition and function implementation and by using inclusion. But a problem arises when creating a new contract which must communicate way and back (two-way communication) with an already deployed contract. The deployed contract cannot know the signature of a contract not yet created!
+
+Hopefully a solution exists to this problem of polymorphism, it is *Tezos.get\_entrypoint\_opt* function.
+
+Let's consider two contracts _A_ and _B_. Contract _A_ ask some information from contract _B_ and they communicate between each other with transactions.
+A sends a request to B, (it means _A_ calls an entrypoint of _B_, so contract _A_ includes type definition of _B_)
+B receives the request, process the request and sends an response back to _A_ (it means _B_ calls an entrypoint of _A_, , so contract _B_ includes type definition of _A_)
+Once they are deployed, we cannot change their includes.
+
+Now let's consider a third smart contract _C_ which will communicate with _B_. (Like _A_)
+Since we can't change _B_ (already deployed) , then _C_ must have same definition of _A_ to be able to receive transactions from _B_.
+
+The problem is coming from the fact that _B_ must know the whole definition of _A_ parameter but it actually only needs one entrypoint used for the transaction. If _C_ implements the same entrypoint than _A_ (for receiving a message from _B_) then transaction will match the entrypoint and problems solved !
+
+For this purpose, the predefined function *Tezos.get\_entrypoint\_opt* can be used to retrieve the definition of a single entrypoint (from the whole variant).
+
+The predefined function *Tezos.get\_entrypoint\_opt* can be used in replacement of the *Tezos.get\_contract\_opt* function to retrieve contract interface but for only one entrypoint. It takes the requested entrypoint as parameter (with a special michelson syntax) and the address of the contract.
+
+```
+const : contract() = Tezos.get_entrypoint_opt(, );
+```
+
+ *entrypoint\_name* is a double-quoted string with first character is % followed by the name of the entrypoint (and its first letter must not be capitalized) exemple: for an entrypoint FooBar the corresponding *entrypoint\_name* is "%fooBar"
+
+## Your mission
+
+1- Consider the following smart contract :
+
+```
+
+```
+
+2-
diff --git a/src/Chapters/ChapterInteractions/exercise.ligo b/src/Chapters/ChapterInteractions/exercise.ligo
new file mode 100644
index 0000000..66125c7
--- /dev/null
+++ b/src/Chapters/ChapterInteractions/exercise.ligo
@@ -0,0 +1 @@
+// Type your solution below
\ No newline at end of file
diff --git a/src/Chapters/ChapterPatternMatching/index.ts b/src/Chapters/ChapterInteractions/index.ts
similarity index 83%
rename from src/Chapters/ChapterPatternMatching/index.ts
rename to src/Chapters/ChapterInteractions/index.ts
index bc54d89..9614858 100644
--- a/src/Chapters/ChapterPatternMatching/index.ts
+++ b/src/Chapters/ChapterInteractions/index.ts
@@ -8,4 +8,4 @@ import exercise from "!raw-loader!./exercise.ligo";
// @ts-ignore
import solution from "!raw-loader!./solution.ligo";
-export const dataPatternMatching = { course, exercise, solution };
+export const dataInteractions = { course, exercise, solution };
diff --git a/src/Chapters/ChapterInteractions/solution.ligo b/src/Chapters/ChapterInteractions/solution.ligo
new file mode 100644
index 0000000..66125c7
--- /dev/null
+++ b/src/Chapters/ChapterInteractions/solution.ligo
@@ -0,0 +1 @@
+// Type your solution below
\ No newline at end of file
diff --git a/src/Chapters/ChapterTransactions/solution_squadron.ligo b/src/Chapters/ChapterInteractions/squadron.ligo
similarity index 100%
rename from src/Chapters/ChapterTransactions/solution_squadron.ligo
rename to src/Chapters/ChapterInteractions/squadron.ligo
diff --git a/src/Chapters/ChapterTransactions/squadron_types.ligo b/src/Chapters/ChapterInteractions/squadron_types.ligo
similarity index 100%
rename from src/Chapters/ChapterTransactions/squadron_types.ligo
rename to src/Chapters/ChapterInteractions/squadron_types.ligo
diff --git a/src/Chapters/ChapterOption/course.md b/src/Chapters/ChapterOption/course.md
new file mode 100644
index 0000000..4c6146e
--- /dev/null
+++ b/src/Chapters/ChapterOption/course.md
@@ -0,0 +1,60 @@
+# Chapter 19 : Option
+
+
+
+The _option_ type is a predefined variant type that is used to express whether there is a value of some type or none. This is especially useful when calling a partial function, that is, a function that is not defined for some inputs. In that case, the value of the option type would be _None_, otherwise _Some_ (_v_), where _v_ is some meaningful value of any type.
+
+An example in arithmetic is the division operation:
+
+```
+function div (const a : nat; const b : nat) : option (nat) is
+ if b = 0n then (None: option (nat)) else Some (a/b)
+```
+
+## Map Access and Option evaluation
+
+Use the postfix [] operator to read a value of the map. When accessing to an element of a map (using [] operator), the returned result is the associated value or _None_ if the given key does not exist. This is the reason why the [] operator returns an _option_ of the expected type (and not just the expected type).
+
+The keyword _Some_ can be used to create an _option_ variable for a given value.
+The keyword _None_ can be used to create an _option_ variable with no given value.
+
+```
+const middleName : option(string) = Some("Foo");
+const middleName : option(string) = None;
+```
+
+## Option in Pattern matching
+
+In the previous chapters, you've seen how to do pattern matching using the _case_ operator.
+The keyword _Some_ can be used in a pattern matching to retrieve the value behind the _option_ variable.
+The keyword _None_ can be used in a pattern matching to verify the _option_ variable has no value.
+
+```
+case of
+| Some() ->
+| None ->
+end
+```
+
+__ can be a single instruction or a _block {}_
+__ is a local variable name. __ which holds the _option_ value and can be used inside the __
+
+Here is an example of [] operator returning an option type :
+
+```
+type expected_type is int
+type balance_type is map(nat, expected_type)
+const user_balances: balance_type = map[ 1n -> 10 ];
+
+const my_balance : option(expected_type) = user_balances[1n];
+case my_balance of
+ Some (val) -> block { skip }
+| None -> failwith ("Unknown user")
+end
+```
+
+## Your mission
+
+ 1- Notice the _weapons_ mapping which maps the name of each weapon to its corresponding input of power. We want to increase the power of the _Main Laser_ but mapping returns optional results as they might not be found in the mapping. Define the constant *main\_laser\_power* as an optional int from selecting _"Main Laser"_ from the _weapons_ mapping.
+
+ 2- Writte a pattern matching for *main\_laser\_power*. If it exixts, increase the power of the _"Main Laser"_ by 1. If it does not exist in the mapping, fail with _"Weapon not found"_
diff --git a/src/Chapters/ChapterOption/exercise.ligo b/src/Chapters/ChapterOption/exercise.ligo
new file mode 100644
index 0000000..5c371e6
--- /dev/null
+++ b/src/Chapters/ChapterOption/exercise.ligo
@@ -0,0 +1,15 @@
+type weapon_power is map (string, int)
+
+function main (const p : unit; const store : unit) : (list(operation) * unit) is
+ block {
+ const weapons : weapon_power =
+ map [
+ "Main Laser" -> 5;
+ "Right Laser" -> 2;
+ "Left Laser" -> 3;
+ ];
+
+ // Type your solution below
+
+
+ } with ((nil: list(operation)), unit)
\ No newline at end of file
diff --git a/src/Chapters/ChapterOption/index.ts b/src/Chapters/ChapterOption/index.ts
new file mode 100644
index 0000000..8ebe201
--- /dev/null
+++ b/src/Chapters/ChapterOption/index.ts
@@ -0,0 +1,11 @@
+/* eslint import/no-webpack-loader-syntax: off */
+// @ts-ignore
+import course from "!raw-loader!./course.md";
+/* eslint import/no-webpack-loader-syntax: off */
+// @ts-ignore
+import exercise from "!raw-loader!./exercise.ligo";
+/* eslint import/no-webpack-loader-syntax: off */
+// @ts-ignore
+import solution from "!raw-loader!./solution.ligo";
+
+export const dataOption = { course, exercise, solution };
diff --git a/src/Chapters/ChapterOption/solution.ligo b/src/Chapters/ChapterOption/solution.ligo
new file mode 100644
index 0000000..9122bb2
--- /dev/null
+++ b/src/Chapters/ChapterOption/solution.ligo
@@ -0,0 +1,19 @@
+type weapon_power is map (string, int)
+
+function main (const p : unit; const store : unit) : (list(operation) * unit) is
+ block {
+ const weapons : weapon_power =
+ map [
+ "Main Laser" -> 5;
+ "Right Laser" -> 2;
+ "Left Laser" -> 3;
+ ];
+
+ // Type your solution below
+ const main_laser_power : option(int) = weapons["Main Laser"];
+ case main_laser_power of
+ Some(i) -> weapons["Main Laser"] := i + 1
+ | None -> failwith("Weapon not found")
+ end
+
+ } with ((nil: list(operation)), unit)
\ No newline at end of file
diff --git a/src/Chapters/ChapterPatternMatching/course.md b/src/Chapters/ChapterPatternMatching/course.md
deleted file mode 100644
index 1c3a368..0000000
--- a/src/Chapters/ChapterPatternMatching/course.md
+++ /dev/null
@@ -1,95 +0,0 @@
-# Chapter 19 : Pattern matching
-
-## Option
-
-The _option_ type is a predefined variant type that is used to express whether there is a value of some type or none. This is especially useful when calling a partial function, that is, a function that is not defined for some inputs. In that case, the value of the option type would be _None_, otherwise _Some_ (_v_), where _v_ is some meaningful value of any type.
-
-An example in arithmetic is the division operation:
-
-```
-function div (const a : nat; const b : nat) : option (nat) is
- if b = 0n then (None: option (nat)) else Some (a/b)
-```
-
-## Map Access and Option evaluation
-
-Use the postfix [] operator to read a value of the map. When accessing to an element of a map (using [] operator), the returned result is the associated value or _None_ if the given key does not exist. This is the reason why the [] operator returns an _option_ of the expected type (and not just the expected type).
-
-the keyword _Some_ can be used to create an _option_ variable for a given value.
-the keyword _None_ can be used to create an _option_ variable with no given value.
-
-```
-const user_balance: option(int) = Some(2);
-const user_balance2: option(int) = None;
-```
-
-## Pattern matching
-
-Pattern matching is similiar to the switch construct in Javascript, and can be used to route the program's control flow based on the value of a variant.
-The keyword _case_ allow to execute different blocks of code depending on a value. It follwos the syntax :
-
-```
-case of
-|