My First Node

Install docker images

  • Install a Weavechain node locally if not done already, the easiest way is by starting it as a docker
  • Install a local jupyter jupyter server to connect to the node (if not done already)

Run the notebook

  • make sure both the node and jupyter server dockers are running
  • connect to the local jupyter server http://127.0.0.1:18888/notebooks/hello-world.ipynb
  • use the token taken from the weave_jupyter_public docker logs
  • OR, if you're not using the provided docker server, download the notebook from here and run it in your locally configured jupyter server
  • run the cells one by one, in case of errors check for the docker images running properly and without errors in their logs and for the ports being open
  • contact us on Telegram or via email support@weavechain.com
  • see below a non-interactive output of how the notebook should look like

Sample of expected notebook:


In this demo notebook we will showcase a self-sovereign data scenario:

  • we will create a table in a shared data collection, that can be read by anyone in the network
  • mark some fields as personal information that is not to be shared
  • write a record
  • read it locally (and be able to see all fields)
  • read all records from a remote server

The default Weavechain node installation is preconfigured to support this scenario (by connecting to a public weave, having a shared data collection defined and mapped to a in-process SQLite instance and read rights for that collection already given).

1. Create an API session

import pandas as pd

from weaveapi.records import *
from weaveapi.options import *
from weaveapi.filter import *
from weaveapi.weaveh import *

WEAVE_CONFIG = "config/demo_client_local.config"
nodeApi, session = connect_weave_api(WEAVE_CONFIG)

scope = "shared"
table = "directory"
{"res":"ok","data":"pong 1674668207181"}

2. Create a local table

  • we drop the existing table if already existing and re-create it from scratch
  • a weavechain node can also connect to existing tables, reading their structure, but in this case we create it via the API
layout = { 
    "columns": { 
        "id": { "type": "LONG", "isIndexed": True, "isUnique": True, "isNullable": False },
        "name_nickname": { "type": "STRING" },
        "name_last": { "type": "STRING" },
        "name_first": { "type": "STRING" },
        "birthday": { "type": "STRING" },
        "email_personal": { "type": "STRING" },
        "phone_number": { "type": "STRING" },
        "address_country": { "type": "STRING" },
        "address_summary": { "type": "STRING" },
        "address_timezone": { "type": "STRING" },
        "linkedin_url": { "type": "STRING" },
        "discord_username": { "type": "STRING" },
        "telegram_username": { "type": "STRING" },
        "ethereum_wallet_address": { "type": "STRING" }
    }, 
    "idColumnIndex": 0, 
    "isLocal": False,
    "applyReadTransformations": True
}

nodeApi.dropTable(session, scope, table).get()
reply = nodeApi.createTable(session, scope, table, CreateOptions(False, False, layout)).get()
print(reply)
{'res': 'ok', 'target': {'operationType': 'CREATE_TABLE', 'organization': 'weavedemo', 'account': 'weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg', 'scope': 'shared', 'table': 'directory'}}

3. Mark some fields for erasure

  • the purpose is to protect certain fields when shared
reply = nodeApi.getTableDefinition(session, scope, table).get()
#print(reply)
layout = json.loads(reply["data"])["layout"]
layout["columns"]

newLayout = layout.copy()
del newLayout["layout"]
del newLayout["indexes"]
del newLayout["columnNames"]
newLayout["columns"] = { i["columnName"]: i for i in layout["columns"]}

newLayout["columns"]["phone_number"]["readTransform"] = "ERASURE"
newLayout["columns"]["address_summary"]["readTransform"] = "ERASURE"
newLayout["columns"]["ethereum_wallet_address"]["readTransform"] = "ERASURE"
newLayout["columns"]["birthday"]["readTransform"] = "ERASURE"

reply = nodeApi.updateLayout(session, scope, table, newLayout).get()
print(reply)
{'res': 'ok', 'target': {'operationType': 'UPDATE_LAYOUT', 'organization': 'weavedemo', 'account': 'weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg', 'scope': 'shared', 'table': 'directory'}}

4. Write a record in the local storage

records = Records(table, [ 
    [ 1, 'Nickname', 'Last Name', 'First name', '1980-01-01', 'email@gmail.com', '+40712345678', 'US', 'Secret', 'EST', 'https://www.linkedin.com/in/linkedin/', 'discord#1234', '@telegram', '0xwallet' ]
])
reply = nodeApi.write(session, scope, records, WRITE_DEFAULT).get()
print(reply)
{'res': 'ok', 'target': {'operationType': 'WRITE', 'organization': 'weavedemo', 'account': 'weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg', 'scope': 'shared', 'table': 'directory'}, 'data': 'weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg,USr/yA9isOGMQ3/gNenSpZLi2VhwIP9x6UacGTkuBVc=,4YjeYJpUrcrpCf4oTEvuAspeJYiQYEy1AvTgbLsTo8UNzYbHKbNiV6jZihb7si5yc8MbXcr16kmGrieJgNW8s75e'}

5. Read the local record, from the local storage

  • since we read with the owner key and from the local node, we expect the records to have all fields visible
scope = "shared"
table = "directory"

reply = nodeApi.read(session, scope, table, None, READ_DEFAULT_NO_CHAIN).get()
#print(reply)
df = pd.DataFrame(reply["data"])

df.head()
id name_nickname name_last name_first birthday email_personal phone_number address_country address_summary address_timezone linkedin_url discord_username telegram_username ethereum_wallet_address
0 1 Nickname Last Name First name 1980-01-01 email@gmail.com +40712345678 US Secret EST https://www.linkedin.com/in/linkedin/ discord#1234 @telegram 0xwallet

5. Connect to proxy server

WEAVE_CONFIG_REMOTE = "config/demo_client_remote.config"
nodeApi2, session2 = connect_weave_api(WEAVE_CONFIG_REMOTE)
{"res":"ok","data":"pong 1674668209764"}

6. Read all shared records

  • we expect the records that we don't own to have certain fields erased for privacy
scope = "shared"
table = "directory"

reply = nodeApi2.read(session2, scope, table, None, READ_DEFAULT_MUX_NO_CHAIN).get()
#print(reply)
df = pd.DataFrame(reply["data"].get("result"))

df.head()
id name_nickname name_last name_first birthday email_personal phone_number address_country address_summary address_timezone linkedin_url discord_username telegram_username ethereum_wallet_address _nodeKey
0 1.0 Nickname Last Name First name email@gmail.com US EST https://www.linkedin.com/in/linkedin/ discord#1234 @telegram weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg

7. Check the local node for all operations on the shared data

reply = nodeApi.history(session, scope, table, None, HISTORY_DEFAULT).get()
#print(reply)
df = pd.DataFrame(reply["data"]).transpose()
#display(df)
pd.DataFrame(df.iloc[0]["history"])
account operation timestamp ip apiKey
0 weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg write 1674668207300999936 127.0.0.1 d2f86331322b497fb644e09862b681fdc2a9aa5180d0011c
1 weaveyh5R1ytoUCZnr3JjqMDfhUrXwqWC2EWnZX3q7krKLPcg read 1674668207315000064 127.0.0.1 d2f86331322b497fb644e09862b681fdc2a9aa5180d0011c
2 weavexUTKAe7J5faqmiq94DXXWntyRBA8bPwmrUbCtebxWd3f read 1674668211353999872 34.28.85.136 1e2f9e5e7c9f406081256bf5709dd1eae5ccf2e324469e1c