Skip to content

Commit 6922aac

Browse files
Merge pull request #130 from StabilityNexus/feat/example-composite-keys
add example contract
2 parents 187eb71 + 58a2714 commit 6922aac

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

examples/user_profile.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# =============================================================================
2+
# MiniChain Storage Paradigms Example: Grouped Values vs Composite Keys
3+
# =============================================================================
4+
#
5+
# Problem Statement:
6+
# Unlike Solidity, which allows multiple distinct `mapping` variables,
7+
# MiniChain provides a single global `storage` dictionary per contract.
8+
# If you naively try to save an age and a name to the same address key:
9+
# storage[sender] = age
10+
# storage[sender] = name <-- This overwrites the age!
11+
#
12+
# This contract demonstrates two paradigms to solve this key collision.
13+
#
14+
# Valid Payloads:
15+
# - 'set_grouped:<age>:<name>'
16+
# - 'update_age_grouped:<new_age>'
17+
#
18+
# - 'set_composite:<age>:<name>'
19+
# - 'update_age_composite:<new_age>'
20+
# =============================================================================
21+
22+
payload = msg['data']
23+
sender = msg['sender']
24+
25+
# -----------------------------------------------------------------------------
26+
# Paradigm 1: Grouped Values
27+
# -----------------------------------------------------------------------------
28+
# We store a Python dictionary as the value for the sender's address.
29+
# Pros: Keeps all user data neatly organized in one object.
30+
# Cons: To update a single field, we must read the whole dict and write it back.
31+
32+
if payload.startswith('set_grouped:'):
33+
parts = payload.split(':')
34+
if len(parts) != 3:
35+
raise Exception("Invalid format. Use set_grouped:<age>:<name>")
36+
37+
age = int(parts[1])
38+
name = parts[2]
39+
40+
# Store the entire profile as a single dictionary
41+
storage[sender] = {
42+
"age": age,
43+
"name": name
44+
}
45+
46+
elif payload.startswith('update_age_grouped:'):
47+
parts = payload.split(':')
48+
if len(parts) != 2:
49+
raise Exception("Invalid format. Use update_age_grouped:<new_age>")
50+
51+
new_age = int(parts[1])
52+
53+
# Notice the inefficiency here: we must load the entire profile,
54+
# modify one field, and then re-save the entire profile to storage.
55+
profile = storage.get(sender, {})
56+
if not profile:
57+
raise Exception("Profile not found")
58+
59+
profile["age"] = new_age
60+
storage[sender] = profile # Re-saving the whole profile
61+
62+
# -----------------------------------------------------------------------------
63+
# Paradigm 2: Composite Keys
64+
# -----------------------------------------------------------------------------
65+
# We namespace the keys using a string prefix (e.g., "age:0x123").
66+
# Pros: We can update individual fields independently without fetching everything.
67+
# Cons: Data is slightly fragmented across the storage dictionary.
68+
69+
elif payload.startswith('set_composite:'):
70+
parts = payload.split(':')
71+
if len(parts) != 3:
72+
raise Exception("Invalid format. Use set_composite:<age>:<name>")
73+
74+
age = int(parts[1])
75+
name = parts[2]
76+
77+
# Store each field independently using namespaced keys
78+
storage[f"age:{sender}"] = age
79+
storage[f"name:{sender}"] = name
80+
81+
elif payload.startswith('update_age_composite:'):
82+
parts = payload.split(':')
83+
if len(parts) != 2:
84+
raise Exception("Invalid format. Use update_age_composite:<new_age>")
85+
86+
new_age = int(parts[1])
87+
88+
# Notice the efficiency here: we only interact with the exact
89+
# piece of data we want to change, without touching the name at all.
90+
if f"age:{sender}" not in storage:
91+
raise Exception("Profile not found")
92+
93+
storage[f"age:{sender}"] = new_age
94+
95+
else:
96+
raise Exception("Unknown command. Valid commands: set_grouped, update_age_grouped, set_composite, update_age_composite")

0 commit comments

Comments
 (0)