---
# System prepended metadata

title: NOTAS Junio 13

---

# NOTAS Junio 13

## App architecture

The first app had this architecture.
We storage the questions in a static json.

```sequence
User -> FE: Load page
FE -> FE: Get questions
FE --> User: Page files (static)
User -> FE: Submit responses
FE --> User: Display results
```

Then we add swarm to storage the questions:

```sequence
User -> FE: Load page
FE -> DS: Get questions
DS --> FE: Questions JSON
FE --> User: Page files (static)

User -> FE: Submit responses
FE --> User: Display results
```

## Pre-requisites

* Install swarm.
* Install Metamask add-on in your browser.
* Truffle.
* Install an add-on to enable CORS.
* Node and git.

## Uploading questions on swarm

Run `swarm` in a new terminal

```bash=
swarm
```

Then run:

```bash=
swarm --defaultpath js/questions.json --manifest=true up js/questions.json

8be54696f73724a8d956c35ddb3351a664115ba53c1ccde8cfbb798c2f01205a

```

To see the upload info, copy and paste the hash and make a request using `curl`:

```bash=
curl -s http://localhost:8500/bzz-raw:/8be54696f73724a8d956c35ddb3351a664115ba53c1ccde8cfbb798c2f01205a | jq
{
  "entries": [
    {
      "hash": "9cab4c9198ea0e1ed8bccaa44d3830218ae2e3fa5ba03d828b33f83e6e94532e",
      "contentType": "application/json",
      "mode": 436,
      "size": 1546,
      "mod_time": "2020-06-15T20:36:06-05:00"
    }
  ]
}


```

To get the file content, copy and paste the new hash:


```bash=
curl -s http://localhost:8500/bzz-raw:/9cab4c9198ea0e1ed8bccaa44d3830218ae2e3fa5ba03d828b33f83e6e94532e | jq


{
    "questions": [
    ]
    ...
```


### Getting the questions from swarm

**Important:** You need to get CORS disabled!

Add the new data source in `app.js`:

Before:

```javascript=
mounted: () {
    axios.get('js/questions.json')
    ...
}

```

After: 

```javascript=
mounted: () {
    axios.get('http://localhost:8500/bzz-raw:/9cab4c9198ea0e1ed8bccaa44d3830218ae2e3fa5ba03d828b33f83e6e94532e')
}

```

---


## Setup the project

You will create the truffle files and folder in the root folder, so you must to say "yes" when truffle warns you

```bash=
truffle init
```

It will create the contract's folder, migrations, and truffle config

## Creating the contract

### Specify the soldity compiler version

In the `truffle-config.js` file, in the `compilers` section, we need to change the solidity compiler version

```javascript=
compilers: {
    solc: {
      version: "^0.4.14",    // Fetch exact version from solc-bin (default: truffle's version)
    }
  }
```



### Contract boiler plate:

In the `contracts` folder, create a new file named `Quiz.sol`

Copy and paste the following code:

```
pragma solidity ^0.4.14;

contract Quiz {

    string[] rightAnswers = ["c", "a", "a", "b"];
    address[] public players;
    uint8[] public playerHits;

    constructor() public {
    }

    function getPlayerHits() public view returns (uint8[] memory) {
        return playerHits;
    }

    function getPlayers() public view returns (address[] memory) {
        return players;
    }

    function answerQuestions (string playerAnswers) public returns (string memory) {
    }
}


```

In the terminal run the `compile` command

```bash=
truffle compile
```

### Before migrate

If you are using `testnet`, `mainnet`, or `regtest` with rskj you should edit the `truffle-config` file to setup the networks:

Also you need to install the `hdwallet provider`:

```bash=
npm install @truffle/hdwallet-provider --save
```

then, add the network data in the `networks` sections in the `truffle-config` file.

### Migration

Add a new file named `2_deploy_contracts.js` in the `migrations` folder and write the following code:

```javascript=
var Quiz = artifacts.require('Quiz');

module.exports = function (deployer) {
  deployer.deploy(Quiz)
}

```

### Run migrations

For `ganache`:

Uncomment the `developer` network and edit the port:

```javascript=
networks: {
    development: {
     host: "127.0.0.1",     // Localhost
     port: 7545,            // Ganache port
     network_id: "*",       // Any network
    }
}
```

Open ganache, and click on the `add workplace`, navigate to your app folder and select the `truffle-config.js` file.

Run the migrations:

```bash=
truffle migrate --network development
```

### Adding web3.js

Add the `web3` CDN in the `index.html` file and the `truffle-contract.js` script.

I copy the `truffle-contract.js` file from the [pet-shop tutorial github](https://github.com/truffle-box/pet-shop-box/blob/master/src/js/truffle-contract.js).

Note: I recommend that the `truffle-contract` be the first script in the 'script' section in `index.html` file.

```htmlembedded=
<script src="js/truffle-contract.js"></script> 

<!-- -->

<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>

```

So, at the end, the scripts order will be:

1. `truffle-contract.js` <- truffle contracts library
2. `vue.js` <- Vue CDN library
3. `bulma-steps.min.js` <- Bulma steps (used to render the questions in a step by step form).
4. `axios.min.js` <- The axios library. (used to get the questions data from DS).
5. `web3.min.js` <- Web3 library
6. `app.js` <- our app script

```htmlmixed=
<script src="js/truffle-contract.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bulma-steps@2.2.1/dist/js/bulma-steps.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
  <script src="js/app.js"></script>
```

### Getting the questions Second part.

In the `app.js` file, clear the `mounted` method and add this new lines:

```javascript=
mounted () {
    this.initWeb3()
      .then(() => {
        console.log('App initialized')
      })
},
```

Add a new method `initWeb3` in the beggining of the `method` section:

Note: the `initWeb3` method has the word `async`!

> [name=Hiram E. Pérez] You must to have installed the `Metamask` add-on in your browser. 

```javascript=
methods: {
    async initWeb3() {
        await axios.get('http://localhost:8500/bzz-raw:/07f1112168025f4c309b652fb364b9ea126728e7b0959338b0bf9f5187d474d0')
        .then(response => {
          this.questions = response.data.questions
        })

      if (window.ethereum) {
        this.web3Provider = window.ethereum
        try {
          // request account access
          await window.ethereum.enable()
        } catch (error) {
          console.error("user denied account access")
        }
      } else if (window.web3) {
        this.web3Provider = window.web3.currentProvider
      } else {
        this.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545')
      }
      web3 = new Web3(this.web3Provider)

      return this.initContract()
    },
    // more methods
}
```

### Init the contract

Add the `initContract` method just below of the `initWeb3` function:

> [name=Hiram E. Pérez] It initializes the contract, I mean, load the contract logic (everything in the `Quiz.sol` contract).
> *TruffleContract()* create an instance of our contract, then we set its web3 provider using our `web3Provider`.

```javascript=
initContract: function (params) {
    return axios.get('../build/contracts/Quiz.json')
        .then(response => {
          const QuizArtifact = response.data
          this.contracts.Quiz = TruffleContract(QuizArtifact)
          // Set the provider for our contract
          this.contracts.Quiz.setProvider(this.web3Provider)
        })
},
```




### Add sendQuestions method

Add a new method just below the `selectOption` function:

```javascript=
sendQuestions: function () {
    // ...
},
```

This method handles the click event on the `ok` button in the modal window. This modal appears when you answer all the questions.

Add the following code in the `sendQuestions` function.

```javascript=
const contract = this.contracts.Quiz
web3.eth.getAccounts((error, accounts) => {
    if (error) {
      console.error(error)
    }

    const account = accounts[0]

    this.contracts.Quiz.deployed()
        .then(instance => {
            const quizInstance = instance

            return quizInstance.answerQuestions(this.answers.join("."), { from: account })
        })
        .then(result => {
            document.querySelector('div.modal').classList.remove('is-active')
        })
        .catch(err => {
            console.error("=======================")
            console.error(err)
            console.error(err.message)
            console.error(err.stack)
            console.error('=======================')
        })
})
```

**Important:** The next line calls the `answerQuestions` function on the smart contract Quiz.sol It will open a `Metamask` window asking if you want sign the contract.

```javascript=
return quizInstance.answerQuestions(this.answers.join("."), { from: account })
```

> [name=Hiram E. Pérez] Solidity don't accept arrays of strings as paramenters in functions, so we need the array of answers as string.
> 

### Answer question method in contract

Add the following method just below of `getPlayers` function in the `Quiz.sol`

```
function answerQuestions (string playerAnswers) public returns (string memory) {
    uint hits = 0;
    var s = playerAnswers.toSlice();
    var delim = ".".toSlice();
    var parts = new string[](s.count(delim) + 1);

    for (uint i = 0; i < parts.length; i++) {
        parts[i] = s.split(delim).toString();
        if (parts[i] == rightAnswers[i]) {
            hits++;
        }
    }
    players.push(msg.sender);
    hits.push(hits);

    return playerAnswers;
}
```

This function compares the rigth answers with the user's ones.

### Add the string solidity contract

Solidity doesn't accept arrays of string as function parameters.

Create a new file named `Strings.sol` in the `contracts` folder.

Open [this repo](https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol), copy and paste it in the `string.sol` file.

In Quiz.sol, please add this line just below of `pragma solidity ^0.4.14;` line.

```
import "./strings.sol";
```

Then add the line `using strings for *;` below of `contract Quiz {` line:

```
pragma solidity ^0.4.14;

import "./strings.sol";

contract Quiz {
    using strings for *;
    // the rest of the code ...
```

Add [this script](https://github.com/ethereum/dapp-bin/blob/master/library/stringUtils.sol)


Run the migrations:

```bash=
truffle migrate --reset --network development  
```