Yumeville

Hello Meチュートリアル

Hello Me

Holochainチュートリアルシリーズへお帰りなさい!

これまでに作成したアプリは定数値を返していますが、より複雑なアプリケーションの場合は、データを保存できると便利ですよね。

今回は、読者のZomeにエントリタイプを追加することでデータをどのように保存するかを学びます。エントリとは、検証済みのソースチェーン内のデータを指します。

子のチュートリアルでは以下のものを追加します。

  1. ユーザー情報を保存するpersonという名のエントリタイプを追加します。
  2. UIにパブリック関数create_personを公開して、personエントリを作成および保存できるようにします。
  3. personエントリを取得するために、UIに対してパブリック関数retrieve_personを公開します。
  4. 最後に、これらの関数とやり取りができるようなUIコンポーネントを追加します。

このチュートリアルは、前回のチュートリアルに基づいて進めていくため、前回のチュートリアルを終えていない場合はまずそこから始めましょう。

まずはテストから

アプリの動作を簡単に確認できるように、テストを作成することからまず始めます。

cc_tuts/test/index.jsをまず開きましょう。

現時点では、Hello Testチュートリアルで作ったテストシナリオのままになっています。

diorama.registerScenario(“Test hello holo”, async (s, t, { alice }) => {
    const result = await alice.call(“hello”, “hello_holo”, {});
    t.ok(result.Ok);
    t.deepEqual(result, { Ok: ‘Hello Holo’ })
// <—- ここに新たなテストを追加しましょう

新しく作るテストシナリオは、t.deepEqual(result, { Ok: 'Hello Holo' })の真下に作ります。

下記のテストでは、「Alice」という名前のエントリを作成し、その同じエントリを取得して、名前が「Alice」であることを確認します。

Aliceという名前でcreate_person関数への呼び出しを追加しましょう。

const create_result = await alice.call(“hello”, “create_person”, {“person”: { “name” : “Alice”}});

次の行で、関数を呼び出した際の返り値がOkであることを確認します。

t.ok(create_result .Ok);

次の行で、最後の関数の呼び出しから返された値(アドレス)を使用して、retrieve_person関数を呼び出しましょう。

const retrieve_result = await alice.call(“hello”, “retrieve_person”, {“address”: create_result .Ok});

次の行で、この呼び出しの返り値OKであることを確認します。

t.ok(retrieve_result.Ok);

次の行が、実際にテスト終了時に望む返り値で、アドレスのエントリが実際にAliceという名前であることを確認します。

t.deepEqual(result, { Ok: {“name” : “Alice”} })

テストを実行しよう

これで、テストのコードが次のようになるはずです。

コードのチェック

const path = require(‘path’);
const tape = require(‘tape’);

const { Diorama, tapeExecutor, backwardCompatibilityMiddleware } = require(‘@holochain/diorama’);

process.on(‘unhandledRejection’, error => {
  console.error(‘got unhandledRejection:’, error);
});

const dnaPath = path.join(__dirname, “../dist/cc_tuts.dna.json”);
const dna = Diorama.dna(dnaPath, ‘cc_tuts’);

const diorama = new Diorama({
  instances: {
    alice: dna,
    bob: dna,
},
  bridges: [],
  debugLog: false,
  executor: tapeExecutor(require(‘tape’)),
  middleware: backwardCompatibilityMiddleware,
});

diorama.registerScenario(“Test hello holo”, async (s, t, { alice }) => {
  // “hello_holo” Zome関数を呼び出す
  // 引数無し.
  const result = await alice.call(“hello”, “hello_holo”, {});
  // resultがOkであることを確認.
  t.ok(result.Ok);
  t.deepEqual(result, { Ok: ‘Hello Holo’ });

  const create_result = await alice.call(“hello”, “create_person”, {“person”: { “name” : “Alice”}});
  t.ok(create_result .Ok);

  const retrieve_result = await alice.call(“hello”, “retrieve_person”, {“address”: create_result .Ok});
  t.ok(retrieve_result.Ok);
  t.deepEqual(result, { Ok: {“name” : “Alice”} });

})

diorama.run();

もちろん、これらのテストは失敗します。最初のエラーがどうなるか推測してみてください。

さあ、実際にどのようなエラーなのかみてみましょう。

nix-shellをまだ開いていない場合はnix-shellにまず入ります。

nix-shell https://github.com/holochain/holonix/archive/v0.0.31.tar.gz

テストを実行してみてください。

nix-shellで実行

hc test

create_person関数はまだ存在しないため、テストは失敗します。

"Holochain Instance Error: Zome function 'create_person' not found in Zome 'hello'"

注:テストに必要な関数をまだ作成していないので、このテストは実際に行き詰まるかもしれないことに注意してください。行き詰った場合は、 ctrl-cを押して、テストを終了しましょう。

エントリを追加

zomes/hello/code/src/lib.rsファイルを開いてください。

ローカルのソースチェーンにエントリを追加するには、Holochainフレームワークにどのようなエントリが存在するのかを伝えることから始めます。

最初に、データの形状を定義するRustのstruct(構造体)を作成します。

Personというstruct(構造体)は、ここに配置します。

// <—- ここにperson structを追加しましょう.

#[zome]
mod hello_zome {

次の行を追加しましょう。

このPerson struct(構造体)をJSONへと簡単に変換できるようにします。

#[derive(Serialize, Deserialize, Debug, DefaultJson, Clone)]

そして、Personという名でstructを宣言しましょう。

pub struct Person {

この、Person structにkey: valueスタイルでnameを加えます。

    name: String,
}

次に、hello_zome mod内で次の行を探してください。

#[zome]
mod hello_zome {

/* — 省略– */
#[zome_fn(“hc_public”)]
fn hello_holo() -> ZomeApiResult<String> {
Ok(“Hello Holo”.into())
}

// <—- ここに次のコードを追加しましょう。

次に、person_entry_defという関数を追加します。この関数は、Holochainに「personというエントリタイプがありますよ」と伝える関数です。

#[entry_def]
fn person_entry_def() -> ValidatingEntryType {

ValidatingEntryTypeを簡単に作成できるentry!マクロを次に追加してください。

        entry!(

一貫性を保つために、Person struct(構造体)と同じ名前を付けましょう。通常、エントリタイプのnameは小文字になります。

エントリの名前と一緒にそのエントリについての簡単な説明も追加しましょう。

name: “person”,
description: “Person to say hello to”,

このタイプのエントリはこのエントリの所有者であるエージェント(ユーザー)のためだけのものであるため、エントリの共有タイプをプライベートに設定します。

sharing: Sharing::Private,

このエントリを検証するために必要な情報を指定するvalidation_package関数を次に追加します。

            validation_package: || {

                hdk::ValidationPackageDefinition::Entry
            },

このエントリを検証するvalidation関数を次に追加します。

Person struct(構造体)の形状に適合する限り、このエントリは常にOkであることを返します。

            validation: | _validation_data: hdk::EntryValidationData<Person>| {

                Ok(())
            }
        )
    }

これで、実際のPersonエントリを作成し、ソースチェーンに保存できるようになりました!

検証ルールに関する注意:検証ルールは非常に重要なものです。これは、Holochainアプリの言わば「ゲームのルール」です。現在は、単にOk(())を返していますが、これでもデータ型がStringを含むnameプロパティを持つPerson struct(構造体)であることを検証していることは理解するべきです。基本的に、このvalidation関数では、PersonというエントリはこのPerson structに基づいた形式でなければならないということを示しています。

Useステートメントを付け足しましょう

上記のコードでは、まだuseステートメントで定義されていないいくつかのタイプとマクロを使用しました。これにより、Rustサーバはこれらを見つけることができていません。

なので、次のuseステートメントを追加しましょう。

#![feature(proc_macro_hygiene)]
+#[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
+#[macro_use]
extern crate holochain_json_derive;

use hdk::{
+    entry_definition::ValidatingEntryType,
error::ZomeApiResult,
};

+use hdk::holochain_core_types::{
+    entry::Entry,
+    dna::entry_types::Sharing,
+};
+
+use hdk::holochain_json_api::{
+    json::JsonString,
+    error::JsonError,
+};
+
+ use hdk::holochain_persistence_api::{
+    cas::content::Address
+};

use hdk_proc_macros::zome;

これでコードがこのようになります。

コードのチェック

#![feature(proc_macro_hygiene)] #[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]

extern crate holochain_json_derive;
use hdk::{
    entry_definition::ValidatingEntryType,

    error::ZomeApiResult,
};

use hdk::holochain_core_types::{

    entry::Entry,
    dna::entry_types::Sharing,
};

use hdk::holochain_json_api::{
    json::JsonString,
    error::JsonError,
};

use hdk::holochain_persistence_api::{
    cas::content::Address
};

use hdk_proc_macros::zome;

#[derive(Serialize, Deserialize, Debug, DefaultJson, Clone)]
pub struct Person {
    name: String,
}

#[zome]
mod hello_zome {
    #[init]
    fn init() {
        Ok(())
}
    #[validate_agent]     pub fn validate_agent(validation_data: EntryValidationData<AgentId>) {
        Ok(())
    }
    #[zome_fn(“hc_public”)]
    fn hello_holo() -> ZomeApiResult<String> {
        Ok(“Hello Holo”.into())
    }

    #[entry_def]
    fn person_entry_def() -> ValidatingEntryType {

        entry!(

            name: “person”,

            description: “Person to say hello to”,

            sharing: Sharing::Private,

            validation_package: || {

                hdk::ValidationPackageDefinition::Entry

            },

            validation: | _validation_data: hdk::EntryValidationData<Person>| {

                Ok(())

            }

        )

    }

}

Personエントリを作ろう

次に、UI側で実際にPersonエントリを作成する方法が必要です。Holochainにはhc_publicと呼ばれる概念があります。これは、hc_publicで定義されたZome関数をZome外部から呼び出せるようにランタイムに伝える役目を持っています。

上記のperson_entry_def関数の下に次の行を追加します。

Personを引数として受け取り、Addressの結果を返すパブリック関数を追加しましょう。

#[zome_fn(“hc_public”)]
pub fn create_person(person: Person) -> ZomeApiResult<Address> {

person引数からエントリを次の行で作成します。

let entry = Entry::App(“person”.into(), person.into());

次に、エントリをローカルソースチェーンにコミットします。

let address = hdk::commit_entry(&entry)?;

最後に、コミットされたPersonエントリのアドレスとともにResult型のOk値を返します。

    Ok(address)
}

これでコードがこのようになります。

コードのチェック

#![feature(proc_macro_hygiene)] #[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]

extern crate holochain_json_derive;
use hdk::{
    entry_definition::ValidatingEntryType,

    error::ZomeApiResult,
};

use hdk::holochain_core_types::{

    entry::Entry,
    dna::entry_types::Sharing,
};

use hdk::holochain_json_api::{
    json::JsonString,
    error::JsonError,
};

use hdk::holochain_persistence_api::{
    cas::content::Address
};

use hdk_proc_macros::zome;

#[derive(Serialize, Deserialize, Debug, DefaultJson, Clone)]
pub struct Person {
    name: String,
}

#[zome]
mod hello_zome {
    #[init]
    fn init() {
        Ok(())
}
    #[validate_agent]     pub fn validate_agent(validation_data: EntryValidationData<AgentId>) {
        Ok(())
    }
    #[zome_fn(“hc_public”)]
    fn hello_holo() -> ZomeApiResult<String> {
        Ok(“Hello Holo”.into())
    }

    #[entry_def]
    fn person_entry_def() -> ValidatingEntryType {

        entry!(

            name: “person”,

            description: “Person to say hello to”,

            sharing: Sharing::Private,

            validation_package: || {

                hdk::ValidationPackageDefinition::Entry

            },

            validation: | _validation_data: hdk::EntryValidationData<Person>| {

                Ok(())

            }

        )

    }

    #[zome_fn(“hc_public”)]

    pub fn create_person(person: Person) -> ZomeApiResult<Address> {

        let entry = Entry::App(“person”.into(), person.into());

        let address = hdk::commit_entry(&entry)?;

        Ok(address)

    }

}

コンパイル

コンパイル時でエラーがまだあるか確認しましょう。

nix-shellで実行
hc package

Personエントリを取得しよう

最後に、UI側から、ソースチェーンよりPersonエントリを取得する方法が必要になります。

create_person関数の真下に次の行を追加してください。

Addressを引数としてPersonエントリを返すパブリックであるretrieve_person関数です。

pub fn retrieve_person(address: Address) -> ZomeApiResult<Person> {

ローカルストレージからそのエントリのアドレスを使用してエントリを取得し、Personの型であるstruct(構造体)に変換します。

    hdk::utils::get_as_type(address)
}

これでコードがこのようになります。

コードのチェック

#![feature(proc_macro_hygiene)] #[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]

extern crate holochain_json_derive;
use hdk::{
    entry_definition::ValidatingEntryType,

    error::ZomeApiResult,
};

use hdk::holochain_core_types::{

    entry::Entry,
    dna::entry_types::Sharing,
};

use hdk::holochain_json_api::{
    json::JsonString,
    error::JsonError,
};

use hdk::holochain_persistence_api::{
    cas::content::Address
};

use hdk_proc_macros::zome;

#[derive(Serialize, Deserialize, Debug, DefaultJson, Clone)]
pub struct Person {
    name: String,
}

#[zome]
mod hello_zome {
    #[init]
    fn init() {
        Ok(())
}
    #[validate_agent]     pub fn validate_agent(validation_data: EntryValidationData<AgentId>) {
        Ok(())
    }
    #[zome_fn(“hc_public”)]
    fn hello_holo() -> ZomeApiResult<String> {
        Ok(“Hello Holo”.into())
    }

    #[entry_def]
    fn person_entry_def() -> ValidatingEntryType {

        entry!(

            name: “person”,

            description: “Person to say hello to”,

            sharing: Sharing::Private,

            validation_package: || {

                hdk::ValidationPackageDefinition::Entry

            },

            validation: | _validation_data: hdk::EntryValidationData<Person>| {

                Ok(())

            }

        )

    }

    #[zome_fn(“hc_public”)]

    pub fn create_person(person: Person) -> ZomeApiResult<Address> {

        let entry = Entry::App(“person”.into(), person.into());

        let address = hdk::commit_entry(&entry)?;

        Ok(address)

}

    #[zome_fn(“hc_public”)]
    pub fn retrieve_person(address: Address) -> ZomeApiResult<Person> {

        hdk::utils::get_as_type(address)

    }

}

直接コンパイルする代わりに、最初に作成したテストを実行してみましょう(テストは常に実行前にコンパイルします)。

nix-shellで実行
hc test

すべてうまくいった場合は、次のように表示されます:

# tests 5
# pass  5

# ok

UI

バックエンドが上手く機能するようになったので、UIを変更して、作成したzome関数とやり取りしてみましょう。まず最初にコードをきれいにしましょう。まずは、前回のチュートリアルのJavaScriptを独自のファイルに移動しましょう。

Hello GUIチュートリアルで作成したGUIプロジェクトフォルダに移動します。

cd holochain/coreconcepts/gui

新しいhello.jsファイルを作成し、お気に入りのエディターで開き、index.htmlも開きます。

<script>タグ内のすべてのコードをhello.jsに移動します。

— index.html
<script type=”text/javascript” >
– var holochain_connection = holochainclient.connect({ url: “ws://localhost:3401”});

– function hello() {
– holochain_connection.then(({callZome, close}) => {
– callZome(‘test-instance’, ‘hello’, ‘hello_holo’)({“args”: {} }).then((result) => update_span(result))
– })
– }
– function show_output(result) {
– var span = document.getElementById(‘output’);
– var output = JSON.parse(result);
– span.textContent = ” ” + output.Ok;
– }
</script>

+++ hello.js
+var holochain_connection = holochainclient.connect({ url: “ws://localhost:3401”});
+
+function hello() {
+ holochain_connection.then(({callZome, close}) => {
+ callZome(‘test-instance’, ‘hello’, ‘hello_holo’)({“args”: {} }).then((result) => update_span(result))
+ })
+}
+
+function show_output(result) {
+ var span = document.getElementById(‘output’);
+ var output = JSON.parse(result);
+ span.textContent = ” ” + output.Ok;

src属性値を<script>タグに追加します。

<script type=“text/javascript” src=“hello.js”></script>

Person用のUIウィジェットを作ろう

index.htmlで、HTML要素を追加してPersonを作成することから始めます。

前回の「say hello」要素を探してください。

<button onclick=“hello()” type=“button”>Say Hello</button>

<div>Response:</span><span id=“output”></div>

<!– ここに下記のコードを追加してください –>

<div>タグの真下に、セクションに見出しを付けるコードを追加しましょう。

<h3>Create a person</h3>

ユーザーが名前を入力できるようにテキストボックスを次に追加します。

<input type=“text” id=“name” placeholder=“Enter your name :)”>

create_personという(まだ書かれていない)JavaScript関数を呼び出すボタンを次に追加します。

<button onclick=“create_person()” type=“button”>Submit Name</button>

idがaddress_outputであるspanを追加して、create_person()を呼び出した時の結果をレンダリングできるようにします。

<div>Address: <span id=“address_output”></span></div>

これでコードが以下のようになります。インデントされていないので気を付けてください。

index.htmlコードチェック

<!DOCTYPE html>

<html lang=“en”>
<head>
<meta charset=“utf-8” />

<title>Hello GUI</title>
<meta name=“description” content=“GUI for a Holochain app” />
<link
rel=“stylesheet”
href=“https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css”
/>
</head>

<body>
<button onclick=“hello()” type=“button”>Say Hello</button>
<div>Response: <span id=“output”></span></div>
<h3>Create a person</h3>
<input type=“text” id=“name” placeholder=“Enter your name :)”>
<button onclick=“create_person()” type=“button”>Submit Name</button>
<div>Address: <span id=“address_output”></span></div>

<script
type=“text/javascript”
src=“hc-web-client/hc-web-client-0.5.1.browser.min.js”
></script>
<script type=“text/javascript” src=”hello.js”>
</script>
</body>
</html>

hello.jsファイルに移ろう

Zomeを呼び出すcreate_person関数を作りましょう。

まずはcreate_person関数を追加します。

function create_person() {

次に、ID名nameでテキストボックスを取得し、現在のテキスト値をname変数に保存しましょう。

const name = document.getElementById(‘name’).value;

接続完了を待ってから、Zome呼び出しを行います。

holochain_connection.then(({callZome, close}) => {

hello zomeでcreate_personを呼び出し、Person structの一部である、name変数を渡し、結果をコンソールに出力します。

    callZome(‘test-instance’, ‘hello’, ‘create_person’)({
      person: {name: name},
    }).then(result => console.log(result));
  });
}

これでhello.jsが以下のようになります。

hello.jsコードチェック

// 接続

var holochain_connection = holochainclient.connect({
  url: ‘ws://localhost:3401’,
});

// レンダリング関数

function show_output(result) {

  var span = document.getElementById(‘output’);

  var output = JSON.parse(result);

  span.textContent = ‘ ‘ + output.Ok;

}

// Zome呼び出し

function hello() {

  holochain_connection.then(({callZome, close}) => {

    callZome(‘test-instance’, ‘hello’, ‘hello_holo’)({args: {}}).then(result =>

      show_output(result));

  });

}

function create_person() {

  const name = document.getElementById(‘name’).value;

  holochain_connection.then(({callZome, close}) => {

    callZome(‘test-instance’, ‘hello’, ‘create_person’)({

      person: {name: name},

    }).then(result => console.log(result));

  });

}

サーバを実行してブラウザを開こう

さあ、関数の呼び出しをテストしましょう。

新しいターミナルウィンドウを開き、nix-shellに入ってください。

cd holochain/coreconcepts/gui
nix-shell https://holochain.love

サーバを実行します。

nix-shellで実行

python -m SimpleHTTPServer

他のターミナル(バックエンドコードがある方)でパッケージを作成し、zomeを実行します。

nix-shellで実行

hc package

hc run -p 3401

UIサーバとHolochainコンダクターサーバの両方が実行されているので、ブラウザを開いて0.0.0.0:8000に移動します。作成したHTML要素が表示されるはずです。

次に、ブラウザの開発者コンソールを開き、自分の名前を入力して、[Submit Name]ボタンを押します。次のようなものが見えるはずです。

注:もちろん、読者は自分の名前を入力したため、表示されるアドレスはおそらく異なるでしょう。

新しいエントリのアドレスを表示しよう

次に、開発者コンソールではなく、ページにアドレスを表示します。

しかし、最初に、少しコードをリファクタリングしましょう。 show_ouput関数をより汎用的にすると、zome関数の出力を表示する各要素で再利用できます。

関数を再利用できるように、要素のIDを引数として渡します。

-function show_output(result) {
+function show_output(result, id) {

–   var span = document.getElementById(‘output’);

+  var el = document.getElementById(id);

var output = JSON.parse(result);

–   span.textContent = ‘ ‘ + output.Ok;

+  el.textContent = ‘ ‘ + output.Ok;

}

function hello() {

holochain_connection.then(({callZome, close}) => {

callZome(‘test-instance’, ‘hello’, ‘hello_holo’)({args: {}}).then(result =>

    – show_output(result),

+    show_output(result, id),

);

});

}

function create_person() {

  const name = document.getElementById(‘name’).value;

  holochain_connection.then(({callZome, close}) => {

    callZome(‘test-instance’, ‘hello’, ‘create_person’)({

      person: {name: name},
–     }).then(result => console.log(result));
+    }).then(result => show_output(result, id));

  });

}

ブラウザに入ろう

ブラウザに戻り、ページを更新します。今回は、名前を入力して[Submit Name]を押すと、アドレスが表示されるようになったでしょう。

Personエントリを取得してUIに表示する

さて、index.htmlファイルに戻り、create personセクションの下(アドレスが表示されるその下)に、新しいヘッダーを追加します。

<h3>Retrieve Person</h3>

ユーザーがcreate_person関数から返されるアドレスを入力できるようにテキストボックスを追加します。

<input type=“text” id=“address_in” placeholder=“Enter the entry address“>

(まだ記述されていない)retrieve_person JavaScript関数を呼び出すボタンを次に追加します。

<button onclick=“retrieve_person()” type=“button”>Get Person</button>

IDがperson_outputであるspanを追加して、retrieve_person関数から返されるPersonエントリを表示します。

<div>Person: <span id=“person_output”></span></div>

hello.jsに移ろう

次に、hello.jsでretrieve_person関数を追加して、同じretrieve_personという名前のzome関数を呼び出し、そのレスポンスを表示します。

function retrieve_person() {

次の行でaddress_inテキストボックスから値を取得します。

var address = document.getElementById(‘address_in’).value;

次の行で接続完了を待ってから、Zomeの呼び出しを行います。

holochain_connection.then(({callZome, close}) => {

次の行でretrieve_personというパブリックzome関数を呼び出して、そこにテキストインプットからのアドレスを渡します。次に、結果をshow_person関数に渡します。

    callZome(‘test-instance’, ‘hello’, ‘retrieve_person’)({

      address: address,

    }).then(result => show_person(result, ‘person_output’));

  });

}

そして、show_person関数を追加します。nameを表示する以外はshow_outputと非常に似ています。

function show_person(result) {
var person = document.getElementById(‘person_output’);
var output = JSON.parse(result);
person.textContent = ‘ ‘ + output.Ok.name;
}

ブラウザに入ろう

これでindex.htmlはこうなります。

index.htmlコードチェック

<!DOCTYPE html>

<html lang=“en”>
<head>
<meta charset=“utf-8” />

<title>Hello GUI</title>
<meta name=“description” content=“GUI for a Holochain app” />
<link
rel=“stylesheet”
href=“https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css”
/>
</head>

<body>
<button onclick=“hello()” type=“button”>Say Hello</button>
<div>Response: <span id=“output”></span></div>
<h3>Create a person</h3>
<input type=“text” id=“name” placeholder=“Enter your name :)”>
<button onclick=“create_person()” type=“button”>Submit Name</button>
<div>Address: <span id=“address_output”></span></div>
<h3>Retrieve Person</h3>
<input type=“text” id=“address_in” placeholder=“Enter the entry address“>
<button onclick=“retrieve_person()” type=“button”>Get Person</button>
<div>Person: <span id=“person_output”></span></div>
<script
type=“text/javascript”
src=“hc-web-client/hc-web-client-0.5.1.browser.min.js”
></script>
<script type=“text/javascript” src=”hello.js”>
</script>
</body>
</html>

そしてhello.jsはこのようになるはずです。

hello.jsコードチェック

// 接続

var holochain_connection = holochainclient.connect({
  url: ‘ws://localhost:3401’,
});

// レンダリング関数

function show_output(result, id) {

  var el= document.getElementById(id);

  var output = JSON.parse(result);

  el.textContent = ‘ ‘ + output.Ok;

}

// Zome呼び出し

function hello() {

  holochain_connection.then(({callZome, close}) => {

    callZome(‘test-instance’, ‘hello’, ‘hello_holo’)({args: {}}).then(result =>

      show_output(result, “output”));

  });

}

function create_person() {

  const name = document.getElementById(‘name’).value;

  holochain_connection.then(({callZome, close}) => {

    callZome(‘test-instance’, ‘hello’, ‘create_person’)({

      person: {name: name}

    }).then(result => show_output(result, “address_output” ));

  });

}

function retrieve_person() {

  var address= document.getElementById(‘address_in’).value;

  holochain_connection.then(({callZome, close}) => {

    callZome(‘test-instance’, ‘hello’, ‘retrieve_person’)({

      address: address

    }).then(result => show_person(result, “person_output” ));

  });

}

  function show_person(result, id) {

    var person = document.getElementById(id);

    var output = JSON.parse(result);

    person.textContent = ‘ ‘ + output.Ok.name;

}

最後に、0.0.0.0:8000でテストします。

次のように表示されるはずです。

retrieving a person

おめでとうございます! GUIを使用して、プライベートソースチェーンからデータを保存および取得しました!