openclaw-algorand-plugin 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/index.ts +361 -0
  4. package/lib/mcp-servers.ts +14 -0
  5. package/lib/x402-fetch.ts +213 -0
  6. package/memory/algorand-plugin.md +82 -0
  7. package/openclaw.plugin.json +30 -0
  8. package/package.json +38 -0
  9. package/setup.ts +80 -0
  10. package/skills/algorand-development/SKILL.md +90 -0
  11. package/skills/algorand-development/references/build-smart-contracts-reference.md +79 -0
  12. package/skills/algorand-development/references/build-smart-contracts.md +52 -0
  13. package/skills/algorand-development/references/create-project-reference.md +86 -0
  14. package/skills/algorand-development/references/create-project.md +89 -0
  15. package/skills/algorand-development/references/implement-arc-standards-arc32-arc56.md +396 -0
  16. package/skills/algorand-development/references/implement-arc-standards-arc4.md +265 -0
  17. package/skills/algorand-development/references/implement-arc-standards.md +92 -0
  18. package/skills/algorand-development/references/search-algorand-examples-reference.md +119 -0
  19. package/skills/algorand-development/references/search-algorand-examples.md +89 -0
  20. package/skills/algorand-development/references/troubleshoot-errors-contract.md +373 -0
  21. package/skills/algorand-development/references/troubleshoot-errors-transaction.md +599 -0
  22. package/skills/algorand-development/references/troubleshoot-errors.md +105 -0
  23. package/skills/algorand-development/references/use-algokit-cli-reference.md +228 -0
  24. package/skills/algorand-development/references/use-algokit-cli.md +64 -0
  25. package/skills/algorand-interaction/SKILL.md +223 -0
  26. package/skills/algorand-interaction/references/algorand-mcp.md +743 -0
  27. package/skills/algorand-interaction/references/examples-algorand-mcp.md +647 -0
  28. package/skills/algorand-python/SKILL.md +95 -0
  29. package/skills/algorand-python/references/build-smart-contracts-decorators.md +413 -0
  30. package/skills/algorand-python/references/build-smart-contracts-reference.md +55 -0
  31. package/skills/algorand-python/references/build-smart-contracts-storage.md +452 -0
  32. package/skills/algorand-python/references/build-smart-contracts-transactions.md +445 -0
  33. package/skills/algorand-python/references/build-smart-contracts-types.md +438 -0
  34. package/skills/algorand-python/references/build-smart-contracts.md +82 -0
  35. package/skills/algorand-python/references/create-project-reference.md +55 -0
  36. package/skills/algorand-python/references/create-project.md +75 -0
  37. package/skills/algorand-python/references/implement-arc-standards-arc32-arc56.md +101 -0
  38. package/skills/algorand-python/references/implement-arc-standards-arc4.md +154 -0
  39. package/skills/algorand-python/references/implement-arc-standards.md +39 -0
  40. package/skills/algorand-python/references/troubleshoot-errors-contract.md +355 -0
  41. package/skills/algorand-python/references/troubleshoot-errors-transaction.md +430 -0
  42. package/skills/algorand-python/references/troubleshoot-errors.md +46 -0
  43. package/skills/algorand-python/references/use-algokit-utils-reference.md +350 -0
  44. package/skills/algorand-python/references/use-algokit-utils.md +76 -0
  45. package/skills/algorand-typescript/SKILL.md +131 -0
  46. package/skills/algorand-typescript/references/algorand-ts-migration-from-beta.md +448 -0
  47. package/skills/algorand-typescript/references/algorand-ts-migration-from-tealscript.md +487 -0
  48. package/skills/algorand-typescript/references/algorand-ts-migration.md +102 -0
  49. package/skills/algorand-typescript/references/algorand-typescript-syntax-methods-and-abi.md +134 -0
  50. package/skills/algorand-typescript/references/algorand-typescript-syntax-reference.md +58 -0
  51. package/skills/algorand-typescript/references/algorand-typescript-syntax-storage.md +154 -0
  52. package/skills/algorand-typescript/references/algorand-typescript-syntax-transactions.md +187 -0
  53. package/skills/algorand-typescript/references/algorand-typescript-syntax-types-and-values.md +150 -0
  54. package/skills/algorand-typescript/references/algorand-typescript-syntax.md +84 -0
  55. package/skills/algorand-typescript/references/build-smart-contracts-reference.md +52 -0
  56. package/skills/algorand-typescript/references/build-smart-contracts.md +74 -0
  57. package/skills/algorand-typescript/references/call-smart-contracts-reference.md +237 -0
  58. package/skills/algorand-typescript/references/call-smart-contracts.md +183 -0
  59. package/skills/algorand-typescript/references/create-project-reference.md +53 -0
  60. package/skills/algorand-typescript/references/create-project.md +86 -0
  61. package/skills/algorand-typescript/references/deploy-react-frontend-examples.md +527 -0
  62. package/skills/algorand-typescript/references/deploy-react-frontend-reference.md +412 -0
  63. package/skills/algorand-typescript/references/deploy-react-frontend.md +239 -0
  64. package/skills/algorand-typescript/references/implement-arc-standards-arc32-arc56.md +73 -0
  65. package/skills/algorand-typescript/references/implement-arc-standards-arc4.md +126 -0
  66. package/skills/algorand-typescript/references/implement-arc-standards.md +44 -0
  67. package/skills/algorand-typescript/references/test-smart-contracts-examples.md +245 -0
  68. package/skills/algorand-typescript/references/test-smart-contracts-unit-tests.md +147 -0
  69. package/skills/algorand-typescript/references/test-smart-contracts.md +127 -0
  70. package/skills/algorand-typescript/references/troubleshoot-errors-contract.md +296 -0
  71. package/skills/algorand-typescript/references/troubleshoot-errors-transaction.md +438 -0
  72. package/skills/algorand-typescript/references/troubleshoot-errors.md +56 -0
  73. package/skills/algorand-typescript/references/use-algokit-utils-reference.md +342 -0
  74. package/skills/algorand-typescript/references/use-algokit-utils.md +74 -0
  75. package/skills/algorand-x402-python/SKILL.md +113 -0
  76. package/skills/algorand-x402-python/references/create-python-x402-client-examples.md +469 -0
  77. package/skills/algorand-x402-python/references/create-python-x402-client-reference.md +313 -0
  78. package/skills/algorand-x402-python/references/create-python-x402-client.md +207 -0
  79. package/skills/algorand-x402-python/references/create-python-x402-facilitator-examples.md +924 -0
  80. package/skills/algorand-x402-python/references/create-python-x402-facilitator-reference.md +629 -0
  81. package/skills/algorand-x402-python/references/create-python-x402-facilitator.md +408 -0
  82. package/skills/algorand-x402-python/references/create-python-x402-server-examples.md +703 -0
  83. package/skills/algorand-x402-python/references/create-python-x402-server-reference.md +303 -0
  84. package/skills/algorand-x402-python/references/create-python-x402-server.md +221 -0
  85. package/skills/algorand-x402-python/references/explain-algorand-x402-python-examples.md +605 -0
  86. package/skills/algorand-x402-python/references/explain-algorand-x402-python-reference.md +315 -0
  87. package/skills/algorand-x402-python/references/explain-algorand-x402-python.md +167 -0
  88. package/skills/algorand-x402-python/references/use-python-x402-core-avm-examples.md +554 -0
  89. package/skills/algorand-x402-python/references/use-python-x402-core-avm-reference.md +278 -0
  90. package/skills/algorand-x402-python/references/use-python-x402-core-avm.md +166 -0
  91. package/skills/algorand-x402-typescript/SKILL.md +129 -0
  92. package/skills/algorand-x402-typescript/references/create-typescript-x402-client-examples.md +879 -0
  93. package/skills/algorand-x402-typescript/references/create-typescript-x402-client-reference.md +371 -0
  94. package/skills/algorand-x402-typescript/references/create-typescript-x402-client.md +236 -0
  95. package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-examples.md +875 -0
  96. package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-reference.md +461 -0
  97. package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator.md +270 -0
  98. package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-examples.md +1181 -0
  99. package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-reference.md +360 -0
  100. package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs.md +251 -0
  101. package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-examples.md +870 -0
  102. package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-reference.md +323 -0
  103. package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall.md +281 -0
  104. package/skills/algorand-x402-typescript/references/create-typescript-x402-server-examples.md +1135 -0
  105. package/skills/algorand-x402-typescript/references/create-typescript-x402-server-reference.md +382 -0
  106. package/skills/algorand-x402-typescript/references/create-typescript-x402-server.md +216 -0
  107. package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-examples.md +616 -0
  108. package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-reference.md +323 -0
  109. package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript.md +232 -0
  110. package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-examples.md +1417 -0
  111. package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-reference.md +504 -0
  112. package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm.md +158 -0
@@ -0,0 +1,452 @@
1
+ # Algorand Python Storage Patterns
2
+
3
+ Store data on-chain using GlobalState, LocalState, and Box storage in Algorand Python smart contracts.
4
+
5
+ ## When to use this reference
6
+
7
+ Use this reference when:
8
+
9
+ - Choosing between storage types for your contract
10
+ - Implementing global or local state
11
+ - Working with Box storage for larger data
12
+ - Understanding MBR (Minimum Balance Requirement) costs
13
+
14
+ ## Storage Types Overview
15
+
16
+ | Storage | Scope | Who Pays MBR | Max Size | Use Case |
17
+ |---------|-------|--------------|----------|----------|
18
+ | `GlobalState` | App-wide | App creator | 64 keys, 8KB total | Shared app data |
19
+ | `LocalState` | Per-user | User (on opt-in) | 16 keys, 2KB total | Per-user data with opt-in |
20
+ | `Box` | App-wide | App account | 32KB per box | Large single values |
21
+ | `BoxMap` | Per-key | App account | 32KB per box | Per-user data without opt-in |
22
+ | `BoxRef` | App-wide | App account | 32KB | Raw binary data, manual sizing |
23
+
24
+ ## GlobalState
25
+
26
+ Store app-wide data accessible by all users. Two approaches available:
27
+
28
+ ### Simple Assignment (Recommended for Basic Use)
29
+
30
+ ```python
31
+ from algopy import ARC4Contract, UInt64, Bytes, arc4
32
+
33
+ class MyContract(ARC4Contract):
34
+ def __init__(self) -> None:
35
+ # Simple assignment - uses variable name as key
36
+ self.counter = UInt64(0)
37
+ self.name = Bytes(b"MyApp")
38
+ self.active = True
39
+
40
+ @arc4.abimethod
41
+ def increment(self) -> None:
42
+ self.counter += 1
43
+ ```
44
+
45
+ ### GlobalState Wrapper (For Advanced Control)
46
+
47
+ ```python
48
+ from algopy import ARC4Contract, GlobalState, UInt64, Bytes, arc4
49
+
50
+ class MyContract(ARC4Contract):
51
+ def __init__(self) -> None:
52
+ # With custom key and description (for ARC-32/56 app spec)
53
+ self.counter = GlobalState(
54
+ UInt64(0),
55
+ key="cnt",
56
+ description="Transaction counter"
57
+ )
58
+ # No default value - must set before reading
59
+ self.owner = GlobalState(Bytes)
60
+
61
+ @arc4.abimethod
62
+ def increment(self) -> UInt64:
63
+ self.counter.value += 1
64
+ return self.counter.value
65
+
66
+ @arc4.abimethod
67
+ def get_counter_safe(self) -> UInt64:
68
+ # Check if value exists
69
+ if self.counter:
70
+ return self.counter.value
71
+ return UInt64(0)
72
+
73
+ @arc4.abimethod
74
+ def get_with_default(self) -> Bytes:
75
+ # Get with fallback default
76
+ return self.owner.get(default=Bytes(b"unset"))
77
+
78
+ @arc4.abimethod
79
+ def get_maybe(self) -> tuple[UInt64, bool]:
80
+ # Returns (value, exists)
81
+ return self.counter.maybe()
82
+ ```
83
+
84
+ ### GlobalState Methods
85
+
86
+ | Method | Description |
87
+ |--------|-------------|
88
+ | `.value` | Get/set the value (errors if not set) |
89
+ | `.get(default)` | Get value or return default |
90
+ | `.maybe()` | Returns `(value, exists)` tuple |
91
+ | `bool(state)` | `True` if value is set |
92
+ | `.key` | Access raw storage key |
93
+
94
+ ## LocalState
95
+
96
+ Store per-user data. Requires user to opt-in to the application first.
97
+
98
+ ```python
99
+ from algopy import ARC4Contract, LocalState, UInt64, Bytes, Account, Txn, arc4
100
+
101
+ class MyContract(ARC4Contract):
102
+ def __init__(self) -> None:
103
+ self.user_balance = LocalState(UInt64, key="bal")
104
+ self.user_name = LocalState(Bytes)
105
+
106
+ @arc4.abimethod(allow_actions=["OptIn"])
107
+ def opt_in(self) -> None:
108
+ # Initialize local state on opt-in
109
+ self.user_balance[Txn.sender] = UInt64(0)
110
+
111
+ @arc4.abimethod
112
+ def deposit(self, amount: UInt64) -> None:
113
+ self.user_balance[Txn.sender] += amount
114
+
115
+ @arc4.abimethod
116
+ def get_balance(self, account: Account) -> UInt64:
117
+ # Direct access (fails if not opted in)
118
+ return self.user_balance[account]
119
+
120
+ @arc4.abimethod
121
+ def get_balance_safe(self, account: Account) -> UInt64:
122
+ # Check if account has local state
123
+ if account in self.user_balance:
124
+ return self.user_balance[account]
125
+ return UInt64(0)
126
+
127
+ @arc4.abimethod
128
+ def get_balance_default(self, account: Account) -> UInt64:
129
+ # Get with default
130
+ return self.user_balance.get(account, default=UInt64(0))
131
+
132
+ @arc4.abimethod
133
+ def get_balance_maybe(self, account: Account) -> tuple[UInt64, bool]:
134
+ # Returns (value, exists)
135
+ return self.user_balance.maybe(account)
136
+
137
+ @arc4.abimethod
138
+ def clear_balance(self, account: Account) -> None:
139
+ # Delete local state entry
140
+ del self.user_balance[account]
141
+ ```
142
+
143
+ ### LocalState Methods
144
+
145
+ | Method | Description |
146
+ |--------|-------------|
147
+ | `state[account]` | Get/set value for account |
148
+ | `state.get(account, default)` | Get value or return default |
149
+ | `state.maybe(account)` | Returns `(value, exists)` tuple |
150
+ | `account in state` | `True` if account has value |
151
+ | `del state[account]` | Delete value for account |
152
+ | `.key` | Access raw storage key |
153
+
154
+ ## Box Storage
155
+
156
+ Store larger data without user opt-in. App account pays MBR.
157
+
158
+ ### Box (Single Value)
159
+
160
+ ```python
161
+ from algopy import ARC4Contract, Box, UInt64, Bytes, arc4, String
162
+
163
+ class MyContract(ARC4Contract):
164
+ def __init__(self) -> None:
165
+ # Box with compile-time constant key
166
+ self.config = Box(UInt64, key=b"config")
167
+ self.data = Box(Bytes, key=b"data")
168
+
169
+ @arc4.abimethod
170
+ def set_config(self, value: UInt64) -> None:
171
+ # Automatically creates box if needed
172
+ self.config.value = value
173
+
174
+ @arc4.abimethod
175
+ def get_config(self) -> UInt64:
176
+ # Check existence first
177
+ if self.config:
178
+ return self.config.value
179
+ return UInt64(0)
180
+
181
+ @arc4.abimethod
182
+ def get_config_maybe(self) -> tuple[UInt64, bool]:
183
+ return self.config.maybe()
184
+
185
+ @arc4.abimethod
186
+ def delete_config(self) -> None:
187
+ # Delete box to reclaim MBR
188
+ del self.config.value
189
+ ```
190
+
191
+ ### Box with Dynamic Key
192
+
193
+ ```python
194
+ from algopy import ARC4Contract, Box, UInt64, String, arc4
195
+
196
+ class MyContract(ARC4Contract):
197
+ @arc4.abimethod
198
+ def create_named_box(self, name: String) -> None:
199
+ # Create box with dynamic key inside method
200
+ box = Box(UInt64, key=name.bytes)
201
+ box.value = UInt64(100)
202
+
203
+ @arc4.abimethod
204
+ def read_named_box(self, name: String) -> UInt64:
205
+ box = Box(UInt64, key=name.bytes)
206
+ if box:
207
+ return box.value
208
+ return UInt64(0)
209
+ ```
210
+
211
+ ### Box Methods
212
+
213
+ | Method | Description |
214
+ |--------|-------------|
215
+ | `.value` | Get/set the box value |
216
+ | `.get(default=...)` | Get value or return default |
217
+ | `.maybe()` | Returns `(value, exists)` tuple |
218
+ | `bool(box)` | `True` if box exists |
219
+ | `del box.value` | Delete the box |
220
+ | `.create(size=...)` | Create box with specific size |
221
+ | `.length` | Get box length in bytes |
222
+ | `.extract(start, length)` | Extract bytes from box |
223
+ | `.replace(start, value)` | Replace bytes in box |
224
+ | `.splice(start, stop, value)` | Splice bytes in box |
225
+
226
+ ### BoxMap (Per-Key Storage)
227
+
228
+ Best for per-user data when you don't want to require opt-in.
229
+
230
+ ```python
231
+ from algopy import ARC4Contract, BoxMap, UInt64, String, Account, Txn, arc4
232
+
233
+ class MyContract(ARC4Contract):
234
+ def __init__(self) -> None:
235
+ # BoxMap with key type and value type
236
+ self.balances = BoxMap(Account, UInt64, key_prefix="bal_")
237
+ self.names = BoxMap(UInt64, String, key_prefix="name_")
238
+
239
+ @arc4.abimethod
240
+ def deposit(self, amount: UInt64) -> None:
241
+ sender = Txn.sender
242
+ if sender in self.balances:
243
+ self.balances[sender] += amount
244
+ else:
245
+ self.balances[sender] = amount
246
+
247
+ @arc4.abimethod
248
+ def get_balance(self, account: Account) -> UInt64:
249
+ if account in self.balances:
250
+ return self.balances[account]
251
+ return UInt64(0)
252
+
253
+ @arc4.abimethod
254
+ def get_balance_default(self, account: Account) -> UInt64:
255
+ return self.balances.get(account, default=UInt64(0))
256
+
257
+ @arc4.abimethod
258
+ def get_balance_maybe(self, account: Account) -> tuple[UInt64, bool]:
259
+ return self.balances.maybe(account)
260
+
261
+ @arc4.abimethod
262
+ def withdraw_all(self) -> UInt64:
263
+ sender = Txn.sender
264
+ balance = self.balances.get(sender, default=UInt64(0))
265
+ if balance > 0:
266
+ del self.balances[sender] # Delete to reclaim MBR
267
+ return balance
268
+ ```
269
+
270
+ ### BoxMap Methods
271
+
272
+ | Method | Description |
273
+ |--------|-------------|
274
+ | `map[key]` | Get/set value for key |
275
+ | `map.get(key, default=...)` | Get value or return default |
276
+ | `map.maybe(key)` | Returns `(value, exists)` tuple |
277
+ | `key in map` | `True` if key exists |
278
+ | `del map[key]` | Delete the box |
279
+ | `.length(key)` | Get box length for key |
280
+ | `.key_prefix` | Access raw key prefix |
281
+ | `.box(key)` | Get Box proxy for key |
282
+
283
+ ### BoxRef (Raw Binary Data)
284
+
285
+ For manual control over large binary data.
286
+
287
+ ```python
288
+ from algopy import ARC4Contract, BoxRef, Bytes, UInt64, Txn, Global, arc4
289
+
290
+ class MyContract(ARC4Contract):
291
+ def __init__(self) -> None:
292
+ self.blob = BoxRef(key=b"blob")
293
+
294
+ @arc4.abimethod
295
+ def create_blob(self, size: UInt64) -> bool:
296
+ # Manually create box with specific size
297
+ return self.blob.create(size=size)
298
+
299
+ @arc4.abimethod
300
+ def write_to_blob(self, offset: UInt64, data: Bytes) -> None:
301
+ self.blob.replace(offset, data)
302
+
303
+ @arc4.abimethod
304
+ def read_from_blob(self, offset: UInt64, length: UInt64) -> Bytes:
305
+ return self.blob.extract(offset, length)
306
+
307
+ @arc4.abimethod
308
+ def delete_blob(self) -> bool:
309
+ return self.blob.delete()
310
+ ```
311
+
312
+ ## Minimum Balance Requirement (MBR)
313
+
314
+ ### MBR Formulas
315
+
316
+ **Global State:**
317
+ ```
318
+ 100,000 + (28,500 * NumUint) + (50,000 * NumByteSlice) microAlgos
319
+ ```
320
+
321
+ **Local State (per opt-in):**
322
+ ```
323
+ 100,000 + (28,500 * NumUint) + (50,000 * NumByteSlice) microAlgos
324
+ ```
325
+
326
+ **Box Storage:**
327
+ ```
328
+ 2,500 + (400 * (key_length + value_length)) microAlgos per box
329
+ ```
330
+
331
+ ### Box MBR Examples
332
+
333
+ | Box Name | Size | MBR Cost |
334
+ |----------|------|----------|
335
+ | "a" (1 byte) | 100 bytes | 2,500 + 400×101 = 42,900 µAlgo |
336
+ | "user" (4 bytes) | 1024 bytes | 2,500 + 400×1028 = 413,700 µAlgo |
337
+ | 32-byte key | 8 bytes | 2,500 + 400×40 = 18,500 µAlgo |
338
+
339
+ ### Funding App Account for Boxes (CRITICAL)
340
+
341
+ The app account must be funded BEFORE creating boxes.
342
+
343
+ ```python
344
+ # In your deploy script or test setup:
345
+ from algokit_utils import AlgorandClient
346
+
347
+ algorand = AlgorandClient.from_environment()
348
+ deployer = algorand.account.from_environment("DEPLOYER")
349
+
350
+ # Deploy the contract
351
+ factory = algorand.client.get_typed_app_factory(MyAppFactory)
352
+ result = factory.deploy()
353
+
354
+ # Fund app account for box MBR
355
+ if result.operation_performed in ["create", "replace"]:
356
+ algorand.send.payment(
357
+ sender=deployer.address,
358
+ receiver=result.app_client.app_address,
359
+ amount=1_000_000 # 1 Algo for box storage
360
+ )
361
+ ```
362
+
363
+ ### Calculating MBR in Contract
364
+
365
+ ```python
366
+ from algopy import ARC4Contract, UInt64, arc4
367
+
368
+ class MyContract(ARC4Contract):
369
+ @arc4.abimethod
370
+ def calculate_box_mbr(self, key_length: UInt64, value_length: UInt64) -> UInt64:
371
+ return UInt64(2500) + (key_length + value_length) * UInt64(400)
372
+ ```
373
+
374
+ ## Choosing Storage Type
375
+
376
+ | Scenario | Recommended | Reason |
377
+ |----------|-------------|--------|
378
+ | App configuration | `GlobalState` | Simple, always available |
379
+ | Per-user data, user pays | `LocalState` | User covers MBR on opt-in |
380
+ | Per-user data, app pays | `BoxMap` | No opt-in needed |
381
+ | Large single value | `Box` | Up to 32KB per box |
382
+ | Large binary blob | `BoxRef` | Manual size control |
383
+ | Dynamic key-value store | `BoxMap` | Flexible key types |
384
+
385
+ ## Common Mistakes
386
+
387
+ ### Forgetting to Fund App Account for Boxes
388
+
389
+ ```python
390
+ # INCORRECT - Box creation fails if app not funded
391
+ @arc4.abimethod
392
+ def create_user(self, account: Account) -> None:
393
+ self.users[account] = UInt64(0) # Fails: insufficient MBR
394
+
395
+ # CORRECT - Fund app account before creating boxes
396
+ # (Done externally via payment transaction)
397
+ ```
398
+
399
+ ### Not Checking Box Existence
400
+
401
+ ```python
402
+ # INCORRECT - Fails if box doesn't exist
403
+ @arc4.abimethod
404
+ def get_value(self) -> UInt64:
405
+ return self.my_box.value # Error if not set
406
+
407
+ # CORRECT - Check first or use get/maybe
408
+ @arc4.abimethod
409
+ def get_value_safe(self) -> UInt64:
410
+ if self.my_box:
411
+ return self.my_box.value
412
+ return UInt64(0)
413
+
414
+ # OR
415
+ @arc4.abimethod
416
+ def get_value_default(self) -> UInt64:
417
+ return self.my_box.get(default=UInt64(0))
418
+ ```
419
+
420
+ ### Not Deleting Boxes to Reclaim MBR
421
+
422
+ ```python
423
+ # CORRECT - Delete boxes when no longer needed
424
+ @arc4.abimethod
425
+ def cleanup_user(self, account: Account) -> None:
426
+ if account in self.users:
427
+ del self.users[account] # Reclaims MBR
428
+ ```
429
+
430
+ ### Using LocalState Without Opt-in Check
431
+
432
+ ```python
433
+ # INCORRECT - Fails if user not opted in
434
+ @arc4.abimethod
435
+ def get_user_data(self, account: Account) -> UInt64:
436
+ return self.user_data[account] # Error if not opted in
437
+
438
+ # CORRECT - Check opt-in status
439
+ @arc4.abimethod
440
+ def get_user_data_safe(self, account: Account) -> UInt64:
441
+ if account in self.user_data:
442
+ return self.user_data[account]
443
+ return UInt64(0)
444
+ ```
445
+
446
+ ## References
447
+
448
+ - [Algorand Python Storage Documentation](https://dev.algorand.co/algokit/languages/python/lg-storage/)
449
+ - [Box Storage Concepts](https://dev.algorand.co/concepts/smart-contracts/storage/box/)
450
+ - [Global Storage Concepts](https://dev.algorand.co/concepts/smart-contracts/storage/global/)
451
+ - [Local Storage Concepts](https://dev.algorand.co/concepts/smart-contracts/storage/local/)
452
+ - [Protocol Parameters (MBR)](https://dev.algorand.co/concepts/protocol/protocol-parameters/)