- 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)
- 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
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).
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"}
- 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'}}
- 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'}}
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'}
- 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 |
WEAVE_CONFIG_REMOTE = "config/demo_client_remote.config"
nodeApi2, session2 = connect_weave_api(WEAVE_CONFIG_REMOTE)
{"res":"ok","data":"pong 1674668209764"}
- 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 |
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 |