Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add missing images in polygon mobile dapp #500

Merged
merged 2 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

`TodoContract.sol`のファイル内に以下のコードを記載します。

```js
```solidity
// TodoContract.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.9;
Expand Down Expand Up @@ -45,7 +45,7 @@ contract TodoContract {

では、コードを詳しく見ていきましょう。

```js
```solidity
// TodoContract.sol
// SPDX-License-Identifier: GPL-3.0
```
Expand All @@ -54,7 +54,7 @@ contract TodoContract {

詳細については、[こちら](https://www.skyarch.net/blog/?p=15940)を参照してみてください。

```js
```solidity
// TodoContract.sol
pragma solidity ^0.8.9;
```
Expand All @@ -63,7 +63,7 @@ pragma solidity ^0.8.9;

上記の場合「このコントラクトを実行するときは、Solidityコンパイラのバージョン0.8.6のみを使用し、それ以下のものは使用しません」という意味です。

```js
```solidity
// TodoContract.sol
contract TodoContract {
...
Expand All @@ -72,14 +72,14 @@ contract TodoContract {

`contract`は、ほかの言語でいうところの「[class](https://wa3.i-3-i.info/word1120.html)」のようなものなのです。

```js
```solidity
// TodoContract.sol
uint256 public taskCount = 0;
```

`taskCount`は、スマートコントラクト内のToDoアイテムの総数を格納する符号なしpublic整数です。

```js
```solidity
// TodoContract.sol
struct Task {
uint256 index;
Expand All @@ -89,18 +89,19 @@ contract TodoContract {
```

`struct Task`は、各ToDoに関する情報(メタデータ)を格納するためのデータ構造です。これには、To-doの`id`、`taskName`、`isComplete`のブール値などが含まれています。

- `id` : To-doを識別するためのid
- `taskName` : To-doのタイトル
- `isComplete` : To-doが完了したかどうかの状態(完了したら`true`、完了してないなら`false`)

```js
```solidity
// TodoContract.sol
mapping(uint256 => Task) public todos;
```

`mapping(uint256 => Task) public todos;`は、すべてのToDoを格納するマッピングで、キーは`id`で、値は上記の`Task`です。

```js
```solidity
// TodoContract.sol
//1.to-doを作成する機能
event TaskCreated(string task, uint256 taskNumber);
Expand All @@ -111,15 +112,14 @@ contract TodoContract {
//4.to-doを削除する機能
event TaskDeleted(uint256 taskNumber);
```
`TaskCreated`、`TaskUpdated`、`TaskIsCompleteToggled`、`TaskDeleted`は、ブロックチェーン上に発生するイベントで、dAppはこれをリスニングし、それに応じて機能することができます。


`TaskCreated`、`TaskUpdated`、`TaskIsCompleteToggled`、`TaskDeleted`は、ブロックチェーン上に発生するイベントで、dAppはこれをリスニングし、それに応じて機能することができます。

次に以下のコードを`TodoContract`内の`event TaskDeleted(uint256 taskNumber);`下に追加してください。

1\. to-doを作成する機能

```js
```solidity
// TodoContract.sol
function createTask(string memory _taskName) public {
todos[taskCount] = Task(taskCount, _taskName, false);
Expand All @@ -130,7 +130,7 @@ contract TodoContract {

では、コードを詳しく見ていきましょう。

```js
```solidity
// TodoContract.sol
function createTask(string memory _taskName) public {
 ...
Expand All @@ -139,21 +139,21 @@ contract TodoContract {

`createTask`関数は、to-doの`_taskName`を受け取ります。

```js
```solidity
// TodoContract.sol
todos[taskCount] = Task(taskCount, _taskName, false);
todos[taskCount] = Task(taskCount, _taskName, false);
```

`taskCount`と`_taskName`で新しい`Task`構造を作成し、`todos`マップの現在の`taskCount`の値に代入することができます。

```js
```solidity
// TodoContract.sol
taskCount++;
taskCount++;
```

to-doが作成されるたびに`taskCount`が1ずつ増えるようにしています。

```js
```solidity
// TodoContract.sol
emit TaskCreated(_taskName, taskCount - 1);
```
Expand All @@ -164,7 +164,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

2\.to-doを更新する機能

```js
```solidity
// TodoContract.sol
function updateTask(uint256 _taskId, string memory _taskName) public {
Task memory currTask = todos[_taskId];
Expand All @@ -175,7 +175,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

では、コードを詳しく見ていきましょう。

```js
```solidity
// TodoContract.sol
function updateTask(uint256 _taskId, string memory _taskName) public {
...
Expand All @@ -184,7 +184,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

`updateTask`関数は、更新されるto-doの`_taskId`と更新された`taskName`を受け取ります。

```js
```solidity
// TodoContract.sol
Task memory currTask = todos[_taskId];
todos[_taskId] = Task(_taskId, _taskName, currTask.isComplete);
Expand All @@ -194,7 +194,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

- 更新中に、そのto-doの`isComplete`の値を保持しておく必要があります。まず、マップから現在のタスクを取得し、それを変数に格納し、その`isComplete`値を新しいタスク・オブジェクトに使用します。

```js
```solidity
// TodoContract.sol
emit TaskUpdated(_taskName, _taskId);
```
Expand All @@ -205,7 +205,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

3\.to-doの完了・未完了を切り替える機能

```js
```solidity
// TodoContract.sol
function toggleComplete(uint256 _taskId) public {
Task memory currTask = todos[_taskId];
Expand All @@ -221,7 +221,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

では、コードを詳しく見ていきましょう。

```js
```solidity
// TodoContract.sol
function toggleComplete(uint256 _taskId) public {
...
Expand All @@ -230,16 +230,17 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

`toggleComplete`関数には、更新するto-doの`_taskId`を受け取ります。

```js
```solidity
// TodoContract.sol
Task memory currTask = todos[_taskId];
todos[_taskId] = Task(_taskId, currTask.taskName, !currTask.isComplete);
```

- `todos`マップから`Task`オブジェクトを取得し、その値で新しい`Task`オブジェクトを作成します。

- `isComplete`を現在の`isComplete`の反対の値として設定します。

```js
```solidity
// TodoContract.sol
emit TaskIsCompleteToggled(
currTask.taskName,
Expand All @@ -254,7 +255,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

4\.to-doを削除する機能

```js
```solidity
// TodoContract.sol
function deleteTask(uint256 _taskId) public {
delete todos[_taskId];
Expand All @@ -264,7 +265,7 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

では、コードを詳しく見ていきましょう。

```js
```solidity
// TodoContract.sol
function deleteTask(uint256 _taskId) public {
...
Expand All @@ -273,20 +274,159 @@ to-doが作成されるたびに`taskCount`が1ずつ増えるようにして

`deleteTask`は、削除するto-doの`_task`をパラメータとして受け取ります。

```js
```solidity
// TodoContract.sol
delete todos[_taskId];
delete todos[_taskId];
```

受け取った`_task`に対応する`todos`マップから`Task`オブジェクトを削除します。

```js
```solidity
// TodoContract.sol
emit TaskDeleted(_taskId);
```

すべてが完了したら、`TaskDeleted`イベントを`emit`する必要があります。

### ✅ 動作確認をする

`TodoContract`に実装した各機能が、期待する動作を行うかを確認するために、テストを作成しましょう。

`packages/contract/test`ディレクトリの中に、`test.js`ファイルを作成して、以下のコードを記載してください。

```js
const hre = require("hardhat");
const { expect } = require("chai");

describe("TodoContract", () => {
// declare contract variable
let contract;

// deploy contract before all of the tests
before(async () => {
const contractFactory = await hre.ethers.getContractFactory("TodoContract");
contract = await contractFactory.deploy();
});

// check creating function
it("create function is working on chain", async () => {
// check if you can create multiple tasks
const receipt = await (await contract.createTask("make lunch")).wait();
await contract.createTask("do the dises");
await contract.createTask("have luch with friends");

// check if you can read tasks
expect((await contract.readTask(0))[1]).to.equal("make lunch");
expect((await contract.readTask(1))[1]).to.equal("do the dises");
expect((await contract.readTask(2))[1]).to.equal("have luch with friends");

// check if event "TaskCreated" works
expect(
receipt.events?.filter((x) => {
return x.event === "TaskCreated";
})[0].args[0]
).to.equal("make lunch");
});

it("update function is working on chain", async () => {
// check if you can update tasks
const receipt = await (await contract.updateTask(0, "make dinner")).wait();
await contract.updateTask(1, "clean up the rooms");
expect((await contract.readTask(0))[1]).to.equal("make dinner");
expect((await contract.readTask(1))[1]).to.equal("clean up the rooms");

// check if event "TaskUpdated" works
expect(
receipt.events?.filter((x) => {
return x.event === "TaskUpdated";
})[0].args[0]
).to.equal("make dinner");
});

// check toggling function
it("toggleComplete function is working on chain", async () => {
// check if you can make a task completed
const formerState = (await contract.readTask(0))[2];
const receipt = await (await contract.toggleComplete(0)).wait();
expect((await contract.readTask(0))[2]).to.equal(!formerState);

// check if event "TaskIsCompleteToggled" works
expect(
receipt.events?.filter((x) => {
return x.event === "TaskIsCompleteToggled";
})[0].args[0]
).to.equal("make dinner");
});

// check deleting function
it("delete function is working on chain", async () => {
// check if you can delete a task
const receipt = await (await contract.deleteTask(0)).wait();
expect((await contract.readTask(0))[1]).to.equal("");

// check if event "TaskDeleted" works
expect(
receipt.events
?.filter((x) => {
return x.event === "TaskDeleted";
})[0]
.args[0].toNumber()
).to.equal(0);
});
});
```

簡単にテストの内容を解説します。
以下の部分でTodoContractのデプロイを行います。`before()`を用いることで、テストの前に一度だけ実行されるようになります。

```js
// deploy contract before all of the tests
before(async () => {
const contractFactory = await hre.ethers.getContractFactory("TodoContract");
contract = await contractFactory.deploy();
});
```

以降のコードで、実際にコントラクトの関数を呼び出して期待する結果となるかどうかを確認しています。
例として、`createTask`関数のテストを見てみましょう。ToDoを3つ作成し、それぞれのToDoが正しく登録されているかを確認しています。

```js
// check creating function
it('create function is working on chain', async () => {
// check if you can create multiple tasks
const receipt = await (await contract.createTask('make lunch')).wait();
await contract.createTask('do the dises');
await contract.createTask('have luch with friends');

// check if you can read tasks
expect((await contract.readTask(0))[1]).to.equal('make lunch');
expect((await contract.readTask(1))[1]).to.equal('do the dises');
expect((await contract.readTask(2))[1]).to.equal('have luch with friends');
```

また、ToDo: `make lunch`を作成した際のイベントが正しく発火しているかも確認しています。

```js
const receipt = await (await contract.createTask('make lunch')).wait();
...
// check if event "TaskCreated" works
expect(
receipt.events?.filter((x) => {
return x.event === 'TaskCreated';
})[0].args[0],
).to.equal('make lunch');
});
```

それでは、以下のコマンドでテストを実行してみましょう。

```
yarn test
```

全てのテストにパスした場合、このように表示されます。
![](/images/Polygon-Mobile-dApp/section-1/1_2_1.png)

スマートコントラクトの開発は以上で完了です。

あとは、コンパイルとデプロイの作業を進めるだけです。頑張っていきましょう!
Expand Down
Loading