1010Traditional blockchain applications face a fundamental challenge:
1111
1212```
13- Decentralized
13+ Web3
1414 /\
1515 / \
1616 / \
@@ -23,10 +23,10 @@ Traditional blockchain applications face a fundamental challenge:
2323Affordable Queryable
2424```
2525
26- ** Without Arkiv** , you pick 2 :
26+ ** Without Arkiv** , you loose at least one :
2727- ** Ethereum Storage** : Decentralized + Queryable, but $1000s per MB
28- - ** IPFS + Centralized DB** : Affordable + Queryable, but centralized
2928- ** Pure IPFS** : Decentralized + Affordable, but no queries
29+ - ** Web2 DB** : Affordable + Queryable, but centralized
3030
3131** With Arkiv** : All three! 🎯
3232
@@ -51,18 +51,16 @@ Entity:
5151 - key: EntityKey # Unique 256-bit identifier (auto-generated)
5252 - payload: bytes # Binary data (up to MBs)
5353 - content_type: str # MIME type (e.g., "application/json")
54- - attributes: dict # Queryable metadata
55- - string_attrs: {str : str } # Text values
56- - numeric_attrs: {str : int } # Integer values (>= 0)
54+ - attributes: dict # Queryable attrs, text and ints >= 0
5755 - owner: Address # Ethereum address with control
58- - expiration : int # Block number when entity expires
56+ - expires_at : int # Block number when entity expires
5957 - created_at: int # Block number of creation
6058 - last_modified_at: int # Block number of last update
6159```
6260
6361#### 3. ** Storage Economics**
6462
65- - ** Cost Model** : Pay for storage duration, not just write
63+ - ** Cost Model** : Pay for storage size and duration
6664- ** Expiration** : Entities automatically expire after specified time
6765- ** Extension** : Owners can extend lifetime before expiration
6866- ** Deletion** : Manual deletion possible, may offer gas refunds
@@ -71,31 +69,31 @@ Entity:
7169
7270### Arkiv vs Alternatives: Technical Comparison
7371
74- | Aspect | Ethereum | IPFS | Arweave | ** Arkiv** |
75- | --------| ----------| ------| ---------| -----------|
76- | Storage Cost (1MB/day) | $10-100 | ~ Free | $0.005 (permanent) | ~ $0.001 |
77- | Query Support | Events only | No | No | SQL-like |
78- | Mutable Data | Yes | No | No | Yes |
79- | Expiration | Manual | No | No | Built-in |
80- | Real-time Events | Yes | No | No | Yes |
81- | EVM Compatible | Yes | No | No | Yes |
72+
73+ | Feature | ** Arkiv** | Ethereum | IPFS | Web2 DB |
74+ | ---------| -----------| ----------| ------| ---------|
75+ | Web3 Data | ✅ | ✅ | ✅ | ❌ |
76+ | Affordable | ✅ | ❌ | ✅ | ✅ |
77+ | SQL-like Queries | ✅ | ❌ | ❌ | ✅ |
78+ | Real-time Events | ✅ | ✅ | ❌ | ✅ |
8279
8380---
8481
8582## Part 2: SDK Architecture & Setup (10 minutes)
8683
8784### Design Philosophy
8885
89- ** "Web3.py + Entities"**
86+ ** "Web3 Library + Entities"**
9087
91- The Arkiv SDK is built on Web3.py and feels like a natural extension :
88+ Python: Arkiv SDK is built on Web3.py with an "arkiv" extensino :
9289
9390``` python
9491from arkiv import Arkiv
9592
9693client = Arkiv()
9794
9895# Standard Web3.py functionality
96+ account = client.eth.default_account
9997balance = client.eth.get_balance(address)
10098block = client.eth.get_block(' latest' )
10199tx = client.eth.send_transaction({... })
@@ -114,6 +112,7 @@ results = client.arkiv.query_entities(query)
114112``` bash
115113# Install SDK
116114pip install arkiv-sdk
115+ pip install testcontainers, websockets
117116
118117# Run with auto-managed local node (requires Docker)
119118from arkiv import Arkiv
@@ -126,20 +125,20 @@ from arkiv import Arkiv
126125from arkiv.provider import ProviderBuilder
127126from arkiv.account import NamedAccount
128127
129- # Load your account
128+ MENDOZA_RPC = " https://mendoza.hoodi.arkiv.network/rpc"
129+
130+ # Load your account from wallet
130131with open (' wallet.json' , ' r' ) as f:
131132 wallet = f.read()
132- account = NamedAccount.from_wallet(' MyAccount ' , wallet, ' password' )
133+ account = NamedAccount.from_wallet(' alice ' , wallet, ' password' )
133134
134- # Connect to Kaolin testnet
135- provider = ProviderBuilder().kaolin().build()
136- client = Arkiv(provider, account = account)
137- ```
135+ # Load your account from private key
136+ account = NamedAccount.from_private_key(" alice" , " 0x..." )
138137
139- #### Option 3: Custom Network
140- ``` python
141- provider = ProviderBuilder().custom(" https://your-arkiv-node.com/rpc " ).build()
142- client = Arkiv(provider, account = account )
138+ # Lock
139+ # Connect to Kaolin testnet
140+ provider = ProviderBuilder().custom(MENDOZA_RPC ).build()
141+ client = Arkiv(provider, account)
143142```
144143
145144---
@@ -168,21 +167,6 @@ bob = NamedAccount.from_key('Bob', private_key)
168167client = Arkiv(provider, account = alice)
169168```
170169
171- #### Multi-Account Workflows
172- ``` python
173- alice = NamedAccount.from_wallet(' Alice' , alice_wallet, ' pass1' )
174- bob = NamedAccount.from_wallet(' Bob' , bob_wallet, ' pass2' )
175-
176- client = Arkiv(provider, account = alice)
177-
178- # Switch accounts dynamically
179- client.switch_to(bob)
180- entity_key, _ = client.arkiv.create_entity(... ) # Created by Bob
181-
182- client.switch_to(alice)
183- # Now operating as Alice
184- ```
185-
186170---
187171
188172## Part 3: Core Entity Operations (10 minutes)
@@ -192,14 +176,14 @@ client.switch_to(alice)
192176#### Basic Creation
193177``` python
194178entity_key, receipt = client.arkiv.create_entity(
195- payload = b " Hello, Arkiv!" ,
196- content_type = " text/plain" ,
197- attributes = {
179+ payload = b " Hello, Arkiv!" ,
180+ content_type = " text/plain" ,
181+ attributes = {
198182 " type" : " greeting" ,
199183 " language" : " en" ,
200184 " version" : 1
201185 },
202- expires_in = 86400 # 24 hours in seconds
186+ expires_in = client.arkiv.to_seconds( hours = 24 )
203187)
204188
205189print (f " Entity created: { entity_key} " )
@@ -221,14 +205,14 @@ data = {
221205}
222206
223207entity_key, _ = client.arkiv.create_entity(
224- payload = json.dumps(data).encode(),
225- content_type = " application/json" ,
226- attributes = {
208+ payload = json.dumps(data).encode(),
209+ content_type = " application/json" ,
210+ attributes = {
227211 " type" : " user_profile" ,
228212 " user_id" : " alice" ,
229213 " verified" : 1 # Use 1 for true, 0 for false
230214 },
231- expires_in = client.arkiv.to_seconds(days = 30 ) # 30 days
215+ expires_in = client.arkiv.to_seconds(days = 30 ) # 30 days
232216)
233217```
234218
@@ -239,14 +223,14 @@ with open('avatar.png', 'rb') as f:
239223 image_data = f.read()
240224
241225entity_key, _ = client.arkiv.create_entity(
242- payload = image_data,
243- content_type = " image/png" ,
226+ payload = image_data,
227+ content_type = " image/png" ,
244228 attributes = {
245229 " type" : " avatar" ,
246230 " user" : " alice" ,
247231 " size" : len (image_data)
248232 },
249- expires_in = client.arkiv.to_seconds(days = 365 ) # 1 year
233+ expires_in = client.arkiv.to_seconds(days = 365 ) # 1 year
250234)
251235```
252236
@@ -261,7 +245,7 @@ entity = client.arkiv.get_entity(entity_key)
261245print (entity.payload)
262246print (entity.attributes)
263247print (entity.owner)
264- print (entity.expiration )
248+ print (entity.expires_at_block )
265249```
266250
267251#### Selective Field Loading
@@ -292,6 +276,7 @@ else:
292276receipt = client.arkiv.update_entity(
293277 entity_key,
294278 payload = b " Updated content" ,
279+ content_type = " text/plain" ,
295280 attributes = {
296281 " type" : " greeting" ,
297282 " language" : " en" ,
0 commit comments