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,58 @@
1
+ # Algorand TypeScript Reference Index
2
+
3
+ This skill includes detailed reference files for specific topics. Consult these when you need in-depth guidance.
4
+
5
+ ## Reference Files
6
+
7
+ | File | Topics Covered |
8
+ |------|----------------|
9
+ | [types-and-values.md](./types-and-values.md) | AVM types, `uint64`, `bytes`, `clone()`, value semantics |
10
+ | [storage.md](./storage.md) | GlobalState, LocalState, BoxMap, Box, MBR funding |
11
+ | [methods-and-abi.md](./methods-and-abi.md) | Decorators, lifecycle methods, visibility, return types |
12
+ | [transactions.md](./transactions.md) | Group transactions (gtxn), inner transactions (itxn) |
13
+
14
+ ## Quick Reference
15
+
16
+ ### Types
17
+
18
+ | AVM Type | TypeScript | Creation |
19
+ |----------|------------|----------|
20
+ | uint64 | `uint64` | `Uint64(n)` |
21
+ | bytes | `bytes` | `Bytes('...')` |
22
+ | string | `string` | Native string |
23
+ | bool | `boolean` | Native boolean |
24
+ | biguint | `biguint` | `BigUint(n)` |
25
+
26
+ ### Storage
27
+
28
+ | Type | Scope | Use Case |
29
+ |------|-------|----------|
30
+ | GlobalState | App-wide | Single values, app config |
31
+ | LocalState | Per-account | User-specific data |
32
+ | BoxMap | App-wide | Key-value storage, large data |
33
+ | Box | App-wide | Single large value |
34
+
35
+ ### Method Decorators
36
+
37
+ | Decorator | Purpose |
38
+ |-----------|---------|
39
+ | `@abimethod()` | ABI-callable method |
40
+ | `@abimethod({ readonly: true })` | Read-only method |
41
+ | `@baremethod({ onCreate: 'require' })` | Create handler |
42
+ | `@baremethod({ onUpdate: 'require' })` | Update handler |
43
+
44
+ ### Clone Rules
45
+
46
+ ```typescript
47
+ // Always clone when:
48
+ const value = clone(this.storage.value) // Reading from storage
49
+ this.storage.value = clone(updated) // Writing to storage
50
+ for (const item of clone(array)) { } // Iterating arrays
51
+ const copy = clone(original) // Copying complex types
52
+ ```
53
+
54
+ ## External Documentation
55
+
56
+ - [Algorand TypeScript Documentation](https://dev.algorand.co/docs/get-started/algokit/typescript)
57
+ - [Puya Compiler](https://github.com/algorandfoundation/puya-ts)
58
+ - [AVM Specification](https://developer.algorand.org/docs/get-details/dapps/avm/)
@@ -0,0 +1,154 @@
1
+ # Storage Patterns
2
+
3
+ ## Storage Types Overview
4
+
5
+ | Storage | Scope | Who Pays MBR | Use Case |
6
+ |---------|-------|--------------|----------|
7
+ | `GlobalState` | App-wide | App account | Shared app data |
8
+ | `LocalState` | Per-user | User (on opt-in) | Per-user data with opt-in |
9
+ | `Box` | App-wide | App account | Large data, single key |
10
+ | `BoxMap` | Per-key | App account | Per-user data without opt-in |
11
+
12
+ ## Storage Access Patterns
13
+
14
+ ### GlobalState
15
+
16
+ ```typescript
17
+ import { GlobalState, clone } from '@algorandfoundation/algorand-typescript'
18
+
19
+ export class MyContract extends Contract {
20
+ appState = GlobalState<MyData>({ key: 'state' })
21
+
22
+ public updateState(amount: uint64): void {
23
+ const state = clone(this.appState.value)
24
+ const updated = clone(state)
25
+ updated.counter = updated.counter + amount
26
+ this.appState.value = clone(updated)
27
+ }
28
+ }
29
+ ```
30
+
31
+ ### LocalState (Requires Opt-in)
32
+
33
+ ```typescript
34
+ import { LocalState, Txn, clone } from '@algorandfoundation/algorand-typescript'
35
+
36
+ export class MyContract extends Contract {
37
+ userData = LocalState<UserData>({ key: 'user' })
38
+
39
+ public optInToApplication(): void {
40
+ const initial: UserData = { balance: Uint64(0) }
41
+ this.userData(Txn.sender).value = clone(initial)
42
+ }
43
+
44
+ public getBalance(): uint64 {
45
+ return clone(this.userData(Txn.sender).value).balance
46
+ }
47
+ }
48
+ ```
49
+
50
+ ### BoxMap (No Opt-in Required)
51
+
52
+ ```typescript
53
+ import { BoxMap, Account, clone } from '@algorandfoundation/algorand-typescript'
54
+
55
+ export class MyContract extends Contract {
56
+ userBoxes = BoxMap<Account, UserData>({ keyPrefix: 'u' })
57
+
58
+ public createUser(user: Account): void {
59
+ const initial: UserData = { balance: Uint64(0) }
60
+ this.userBoxes(user).value = clone(initial)
61
+ }
62
+ }
63
+ ```
64
+
65
+ ## Box Storage MBR (CRITICAL)
66
+
67
+ Box storage increases the app account's Minimum Balance Requirement (MBR). The app account must be funded BEFORE boxes can be created.
68
+
69
+ ### MBR Formula
70
+
71
+ ```
72
+ (2500 per box) + (400 * (box size + key size)) microAlgos per box
73
+ ```
74
+
75
+ ### Funding Pattern in deploy-config.ts
76
+
77
+ ```typescript
78
+ import { AlgorandClient } from '@algorandfoundation/algokit-utils'
79
+ import { MyAppFactory } from '../artifacts/my_app/MyAppClient'
80
+
81
+ export async function deploy() {
82
+ const algorand = AlgorandClient.fromEnvironment()
83
+ const deployer = await algorand.account.fromEnvironment('DEPLOYER')
84
+
85
+ const factory = algorand.client.getTypedAppFactory(MyAppFactory, {
86
+ defaultSender: deployer.addr,
87
+ })
88
+
89
+ const { appClient, result } = await factory.deploy({
90
+ onUpdate: 'append',
91
+ onSchemaBreak: 'append'
92
+ })
93
+
94
+ // MANDATORY: Fund app account if BoxMap is used
95
+ if (['create', 'replace'].includes(result.operationPerformed)) {
96
+ await algorand.send.payment({
97
+ amount: (1).algo(), // Fund app account for box MBR
98
+ sender: deployer.addr,
99
+ receiver: appClient.appAddress,
100
+ })
101
+ }
102
+ }
103
+ ```
104
+
105
+ **Note**: `operationPerformed` values are `'create'`, `'replace'`, `'update'`, or `'append'`. Only fund on `'create'` or `'replace'` to avoid redundant funding.
106
+
107
+ ### Testing with BoxMap
108
+
109
+ E2E tests using BoxMap require app account funding before first box operation:
110
+
111
+ ```typescript
112
+ // Fund immediately after deployment in test setup
113
+ const { client } = await deploy(testAccount)
114
+
115
+ await localnet.algorand.send.payment({
116
+ amount: (1).algo(),
117
+ sender: testAccount,
118
+ receiver: client.appAddress,
119
+ })
120
+
121
+ // Now box operations will work
122
+ await client.send.createUser({ args: [userAccount] })
123
+ ```
124
+
125
+ ## Choosing Storage Type
126
+
127
+ | Scenario | Recommended | Reason |
128
+ |----------|-------------|--------|
129
+ | Per-user data, user pays | `LocalState` | User covers MBR on opt-in |
130
+ | Per-user data, app pays | `BoxMap` | No opt-in needed, app funds MBR |
131
+ | Shared app config | `GlobalState` | Simple, always available |
132
+ | Large data (>128 bytes) | `Box` or `BoxMap` | No size limits like GlobalState |
133
+
134
+ ## Class Properties
135
+
136
+ Cannot define class properties or constants. Only storage proxies allowed on contract classes:
137
+
138
+ ```typescript
139
+ // CORRECT: Module-level constants
140
+ const MAX_ITEMS: uint64 = Uint64(100)
141
+
142
+ class MyContract extends Contract {
143
+ items = GlobalState<ItemList>({ key: 'items' }) // OK: storage proxy
144
+
145
+ public addItem(): void {
146
+ // Use MAX_ITEMS here
147
+ }
148
+ }
149
+
150
+ // INCORRECT: Class properties
151
+ class MyContract extends Contract {
152
+ private readonly MAX_ITEMS: uint64 = Uint64(100) // Compiler error
153
+ }
154
+ ```
@@ -0,0 +1,187 @@
1
+ # Group and Inner Transactions
2
+
3
+ ## Group Transactions (gtxn)
4
+
5
+ Access group transactions using typed `gtxn` functions with `uint64` indices:
6
+
7
+ ```typescript
8
+ import { gtxn, Global, Uint64 } from '@algorandfoundation/algorand-typescript'
9
+
10
+ // Verify group size
11
+ assert(Global.groupSize === Uint64(3), 'Must be group of 3 transactions')
12
+
13
+ // Access group transactions using typed functions
14
+ const assetTransfer = gtxn.AssetTransferTxn(Uint64(0)) // First transaction
15
+ const payment = gtxn.PaymentTxn(Uint64(1)) // Second transaction
16
+
17
+ // Verify transaction properties
18
+ assert(assetTransfer.sender.bytes === sellerBytes, 'Asset must come from seller')
19
+ assert(assetTransfer.assetReceiver.bytes === buyer.bytes, 'Asset must go to buyer')
20
+ assert(assetTransfer.xferAsset === asset, 'Asset ID mismatch')
21
+ assert(payment.amount === listing.price, 'Payment amount mismatch')
22
+ ```
23
+
24
+ **INCORRECT**: `const txn = gtxn[0]` — array indexing doesn't work.
25
+
26
+ ### Available Typed Functions
27
+
28
+ | Function | Transaction Type |
29
+ |----------|------------------|
30
+ | `gtxn.PaymentTxn(n)` | Payment |
31
+ | `gtxn.AssetTransferTxn(n)` | Asset transfer |
32
+ | `gtxn.AssetConfigTxn(n)` | Asset configuration |
33
+ | `gtxn.ApplicationCallTxn(n)` | Application call |
34
+ | `gtxn.AssetFreezeTxn(n)` | Asset freeze |
35
+ | `gtxn.KeyRegistrationTxn(n)` | Key registration |
36
+ | `gtxn.Transaction(n)` | Untyped access |
37
+
38
+ ## Inner Transactions (itxn)
39
+
40
+ ### Method Selector Helper
41
+
42
+ Use `methodSelector` to get the 4-byte ARC-4 method selector for inner app calls:
43
+
44
+ ```typescript
45
+ import { methodSelector } from '@algorandfoundation/algorand-typescript/arc4'
46
+
47
+ // Get selector from method signature
48
+ const selector = methodSelector('transfer(address,uint64)void')
49
+
50
+ // Use in inner app call
51
+ itxn.applicationCall({
52
+ appId: targetApp,
53
+ appArgs: [selector, encodedArg1, encodedArg2],
54
+ fee: Uint64(0),
55
+ }).submit()
56
+ ```
57
+
58
+ ### Method Names
59
+
60
+ Inner transaction methods use **lowercase**:
61
+
62
+ ```typescript
63
+ import { itxn, Global, Uint64 } from '@algorandfoundation/algorand-typescript'
64
+
65
+ // CORRECT - lowercase
66
+ itxn.payment({ ... }).submit()
67
+ itxn.assetTransfer({ ... }).submit()
68
+
69
+ // INCORRECT
70
+ itxn.Payment({ ... }) // Wrong case
71
+ ```
72
+
73
+ ### Application Address
74
+
75
+ Use `Global.currentApplicationAddress`, not `this.appAddress()`:
76
+
77
+ ```typescript
78
+ // CORRECT
79
+ assert(payment.receiver.bytes === Global.currentApplicationAddress.bytes)
80
+
81
+ // INCORRECT
82
+ assert(payment.receiver.bytes === this.appAddress().bytes)
83
+ ```
84
+
85
+ ### Account from Bytes
86
+
87
+ When storing Account as bytes and converting back for inner transactions:
88
+
89
+ ```typescript
90
+ // Store Account as bytes (required for GlobalState/BoxMap)
91
+ const escrow = clone(this.escrow.value)
92
+ const sellerBytes = escrow.seller // bytes stored in state
93
+
94
+ // Convert bytes to Account for inner transaction
95
+ itxn.payment({
96
+ receiver: Account(sellerBytes), // Convert bytes to Account
97
+ amount: escrow.amount,
98
+ fee: Uint64(0),
99
+ }).submit()
100
+ ```
101
+
102
+ ### Fee Pooling (CRITICAL)
103
+
104
+ Always set `fee: Uint64(0)` for inner transactions. The app call sender covers fees through fee pooling:
105
+
106
+ ```typescript
107
+ itxn.payment({
108
+ receiver: Account(sellerBytes),
109
+ amount: escrow.amount,
110
+ fee: Uint64(0), // Caller covers fees
111
+ }).submit()
112
+ ```
113
+
114
+ This prevents app account drain attacks where malicious callers force the app to pay fees.
115
+
116
+ ### Composing Multiple Inner Transactions
117
+
118
+ Use `itxnCompose` for submitting multiple inner transactions atomically:
119
+
120
+ ```typescript
121
+ import { itxn, itxnCompose, Global, Account, Uint64 } from '@algorandfoundation/algorand-typescript'
122
+
123
+ // Submit multiple inner transactions as a group
124
+ itxnCompose.begin()
125
+
126
+ itxnCompose.next(
127
+ itxn.payment({
128
+ receiver: Account(recipientBytes),
129
+ amount: Uint64(100_000),
130
+ fee: Uint64(0),
131
+ })
132
+ )
133
+
134
+ itxnCompose.next(
135
+ itxn.assetTransfer({
136
+ xferAsset: assetId,
137
+ assetReceiver: Account(recipientBytes),
138
+ assetAmount: Uint64(50),
139
+ fee: Uint64(0),
140
+ })
141
+ )
142
+
143
+ itxnCompose.submit()
144
+ ```
145
+
146
+ **Note**: `itxnCompose.begin()` starts a new group, `itxnCompose.next()` adds transactions, and `itxnCompose.submit()` sends them all atomically.
147
+
148
+ ## Asset Type
149
+
150
+ `Asset` constructor takes `uint64` directly:
151
+
152
+ ```typescript
153
+ // CORRECT
154
+ const asset = Asset(assetId) // if assetId is already uint64
155
+ const asset = Asset(Uint64(123))
156
+
157
+ // INCORRECT
158
+ const asset = Asset(123) // number literal
159
+ const asset = Asset({ id: 123 }) // object
160
+ ```
161
+
162
+ ## Complete Example: Escrow Release
163
+
164
+ ```typescript
165
+ import {
166
+ itxn, gtxn, Global, Account, Uint64, assert, clone
167
+ } from '@algorandfoundation/algorand-typescript'
168
+
169
+ public releaseEscrow(): void {
170
+ const escrow = clone(this.escrowData.value)
171
+
172
+ // Verify the payment came to app
173
+ assert(Global.groupSize === Uint64(2), 'Expected 2 txns')
174
+ const payment = gtxn.PaymentTxn(Uint64(0))
175
+ assert(
176
+ payment.receiver.bytes === Global.currentApplicationAddress.bytes,
177
+ 'Payment must go to app'
178
+ )
179
+
180
+ // Send funds to seller via inner transaction
181
+ itxn.payment({
182
+ receiver: Account(escrow.seller),
183
+ amount: escrow.amount,
184
+ fee: Uint64(0), // Fee pooling
185
+ }).submit()
186
+ }
187
+ ```
@@ -0,0 +1,150 @@
1
+ # AVM Types and Value Semantics
2
+
3
+ ## Basic AVM Types
4
+
5
+ | Type | Description | Constructor |
6
+ |------|-------------|-------------|
7
+ | `uint64` | 64-bit unsigned integer | `Uint64()` |
8
+ | `bytes` | Byte array | `Bytes()` |
9
+ | `bigint` | Up to 512-bit unsigned integer | `BigUInt` |
10
+ | `string` | UTF-8 string | Native strings |
11
+ | `bool` | Boolean | `true`/`false` |
12
+
13
+ ## Type Mappings
14
+
15
+ AVM types don't map to JavaScript primitives:
16
+ - JavaScript `number` is signed and unbounded; AVM `uint64` is 64-bit unsigned
17
+ - JavaScript `Uint8Array`/`ArrayBuffer` don't exist; use `bytes`
18
+
19
+ ## Objects and Arrays
20
+
21
+ **Plain TypeScript objects** are supported and mutable:
22
+ ```typescript
23
+ type Point = { x: uint64; y: uint64 }
24
+ ```
25
+
26
+ **Plain TypeScript arrays** are supported and mutable:
27
+ ```typescript
28
+ const values: uint64[] = []
29
+ const items: Array<uint64> = []
30
+ ```
31
+
32
+ **Prefer native types over ARC4**: Plain objects and arrays are more efficient for computations and mutations than `arc4.StaticArray`, `arc4.DynamicArray`, `arc4.Struct`.
33
+
34
+ ## Numbers (CRITICAL)
35
+
36
+ Puya rejects JavaScript `number` entirely:
37
+
38
+ ```typescript
39
+ // CORRECT
40
+ const amount: uint64 = Uint64(20)
41
+ const total: uint64 = amount + Uint64(100)
42
+ return this.counter.value // Safe if already uint64
43
+
44
+ // INCORRECT - Compiler error
45
+ const amount = 20
46
+ const total = amount + 100
47
+ ```
48
+
49
+ **Arithmetic type inference**: Explicitly type results to avoid inference as `number`:
50
+
51
+ ```typescript
52
+ // CORRECT
53
+ const timeout: uint64 = Global.latestTimestamp + timeoutSeconds
54
+
55
+ // INCORRECT - May infer as number
56
+ const timeout = Global.latestTimestamp + timeoutSeconds
57
+ ```
58
+
59
+ ## String Operations
60
+
61
+ `string.length` is NOT supported. Use equality checks:
62
+
63
+ ```typescript
64
+ // CORRECT
65
+ assert(text !== '', 'Text cannot be empty')
66
+
67
+ // INCORRECT - Compiler error
68
+ assert(text.length > 0, 'Text cannot be empty')
69
+ assert(text.length <= 200, 'Text too long')
70
+ ```
71
+
72
+ ## Value Semantics (CRITICAL)
73
+
74
+ AVM uses value semantics only. Use `clone()` for complex types (structs, arrays, objects):
75
+
76
+ ```typescript
77
+ import { clone } from '@algorandfoundation/algorand-typescript'
78
+
79
+ // GlobalState: clone on read, modify, write
80
+ const state = clone(this.appState.value) // Clone on read
81
+ const updated = clone(state) // Clone for modification
82
+ updated.field1 = updated.field1 + amount
83
+ this.appState.value = clone(updated) // Clone on write
84
+
85
+ // Box: reads OK without clone, writes need clone
86
+ const stored = this.someBox.value // Read OK
87
+ const copy = clone(stored) // Clone for modification
88
+ copy.someField = copy.someField + amount
89
+ this.someBox.value = clone(copy) // Clone before write
90
+ ```
91
+
92
+ **When to clone**:
93
+ - ALWAYS when reading from `GlobalState`, `Box`, `BoxMap`, `LocalState` with complex types
94
+ - ALWAYS when assigning structs/arrays to storage
95
+ - Even if already cloned, clone again when assigning to storage
96
+
97
+ **Exception**: Primitive types (`uint64`, `bytes`, `string`, `bool`) stored directly (not in structs) do NOT require `clone()`.
98
+
99
+ ## Union Types (Not Supported)
100
+
101
+ Cannot use union types like `Item | null` or `string | uint64`:
102
+
103
+ ```typescript
104
+ // CORRECT - Use boolean flags
105
+ let found = false
106
+ let foundItem: Item = { /* default values */ }
107
+ for (const item of clone(items)) {
108
+ if (matches(item)) {
109
+ foundItem = clone(item)
110
+ found = true
111
+ break
112
+ }
113
+ }
114
+ assert(found, 'Item not found')
115
+ return foundItem
116
+
117
+ // INCORRECT - Compiler error
118
+ let foundItem: Item | null = null
119
+ let value: string | uint64 = someValue
120
+ ```
121
+
122
+ ## Array Operations
123
+
124
+ - **AVOID**: `forEach` — use `for...of`
125
+ - **AVOID**: `splice` on dynamic arrays — opcode-heavy
126
+ - **PREFER**: `StaticArray<uint64, N>` for fixed-size arrays
127
+ - **AVOID**: Nested dynamic types (`uint64[][]`) — encode as tuples
128
+
129
+ **Critical array rules**:
130
+ - Functions cannot mutate passed arrays
131
+ - Cannot specify array lengths with square brackets (`number[10]` invalid)
132
+ - Arrays in object literals must be cloned: `{ todos: clone(array) }`
133
+ - Clone arrays before iterating: `for (const item of clone(array))`
134
+ - Loop indices must be `uint64`, not `number`:
135
+
136
+ ```typescript
137
+ let index = Uint64(0)
138
+ for (const item of clone(array)) {
139
+ // use index
140
+ index = index + Uint64(1)
141
+ }
142
+ ```
143
+
144
+ ## Unavailable APIs
145
+
146
+ These JavaScript APIs are NOT supported (AVM constraints):
147
+ - `Uint8Array` / `ArrayBuffer`
148
+ - Object methods (`.keys()`, `.values()`, etc.)
149
+ - Array length via square brackets
150
+ - Standard JavaScript APIs
@@ -0,0 +1,84 @@
1
+
2
+ # Algorand TypeScript Rules
3
+
4
+ Critical syntax rules for Algorand TypeScript (PuyaTs) that prevent compiler errors and runtime failures.
5
+
6
+ **File Extension**: Contract files must use `.algo.ts` extension (e.g., `Counter.algo.ts`).
7
+
8
+ ## Overview / Core Workflow
9
+
10
+ 1. Identify the syntax issue or pattern needed
11
+ 2. Apply the correct AVM-compatible pattern
12
+ 3. Use `clone()` for complex types
13
+ 4. Verify no union types or JavaScript `number`
14
+
15
+ ## How to proceed
16
+
17
+ 1. **Check the most critical rules below**
18
+ 2. **Consult detailed reference files** for specific topics
19
+ 3. **Apply the correct pattern** with proper AVM types
20
+ 4. **Build to verify**: `algokit project run build`
21
+
22
+ ## Important Rules / Guidelines
23
+
24
+ ### Numbers: No JavaScript `number`
25
+
26
+ ```typescript
27
+ // CORRECT
28
+ const amount: uint64 = Uint64(20)
29
+ const total: uint64 = amount + Uint64(100)
30
+
31
+ // INCORRECT - Compiler error
32
+ const amount = 20
33
+ ```
34
+
35
+ **Numeric limits**: Algorand TypeScript supports integers up to 2^512. Use `biguint` for values exceeding uint64 (2^64 - 1).
36
+
37
+ ### Value Semantics: Always `clone()`
38
+
39
+ ```typescript
40
+ import { clone } from '@algorandfoundation/algorand-typescript'
41
+
42
+ const state = clone(this.appState.value) // Read: clone
43
+ const updated = clone(state) // Modify: clone
44
+ this.appState.value = clone(updated) // Write: clone
45
+ ```
46
+
47
+ ### No Union Types
48
+
49
+ ```typescript
50
+ // CORRECT - Use boolean flags
51
+ let found = false
52
+ let foundItem: Item = { /* defaults */ }
53
+
54
+ // INCORRECT - Compiler error
55
+ let foundItem: Item | null = null
56
+ ```
57
+
58
+ ### Arrays: Clone Before Iterating
59
+
60
+ ```typescript
61
+ // CORRECT
62
+ for (const item of clone(array)) { }
63
+ ```
64
+
65
+ ## Common Variations / Edge Cases
66
+
67
+ | Topic | Rule |
68
+ |-------|------|
69
+ | Numbers | Use `uint64` + `Uint64()`, never `number` |
70
+ | Strings | No `.length`; use `text !== ''` for empty check |
71
+ | Storage | Clone on read AND write for complex types |
72
+ | Arrays | Clone before iterating; indices must be `uint64` |
73
+ | Classes | No class properties; use module-level constants |
74
+ | Methods | Public = ABI method; private = subroutine |
75
+
76
+ ## References / Further Reading
77
+
78
+ Detailed rules by topic:
79
+
80
+ - [Types and Values](./algorand-typescript-syntax-types-and-values.md) — AVM types, numbers, clone(), value semantics
81
+ - [Storage](./algorand-typescript-syntax-storage.md) — GlobalState, LocalState, BoxMap, MBR funding
82
+ - [Methods and ABI](./algorand-typescript-syntax-methods-and-abi.md) — Decorators, lifecycle methods, visibility
83
+ - [Transactions](./algorand-typescript-syntax-transactions.md) — Group transactions (gtxn), inner transactions (itxn)
84
+ - [Full Reference Index](./algorand-typescript-syntax-reference.md)
@@ -0,0 +1,52 @@
1
+ # TypeScript Smart Contract Repository and Pattern Reference
2
+
3
+ TypeScript-specific repositories, paths, and patterns for building Algorand smart contracts with PuyaTs.
4
+
5
+ ## Priority Repositories
6
+
7
+ ### Priority 1: DevPortal Code Examples (TypeScript)
8
+ **Repository:** `algorandfoundation/devportal-code-examples`
9
+ **Path:** `projects/typescript-examples/contracts/`
10
+
11
+ Common contract patterns available:
12
+ - `BoxStorage/` -- Box, BoxMap, BoxRef patterns
13
+ - State management examples (GlobalState, LocalState)
14
+ - ARC-4 method examples
15
+ - Inner transaction patterns
16
+
17
+ Always retrieve corresponding test files alongside contracts.
18
+
19
+ ### Priority 2: Puya-TS Compiler Examples
20
+ **Repository:** `algorandfoundation/puya-ts`
21
+ **Path:** `examples/`
22
+
23
+ Key examples:
24
+ - `hello_world_arc4/` -- Basic ARC-4 contract structure
25
+ - `voting/` -- State management and complex logic
26
+ - `amm/` -- Advanced patterns (multi-asset, inner transactions)
27
+ - Search for `itxn` patterns for inner transaction examples
28
+
29
+ ### Priority 3: AlgoKit TypeScript Template
30
+ **Repository:** `algorandfoundation/algokit-typescript-template`
31
+
32
+ Provides:
33
+ - Project structure and scaffolding
34
+ - Build and test configuration
35
+ - Integration test patterns with generated clients
36
+
37
+ ## Pattern-Specific Lookups
38
+
39
+ | Pattern | Where to Look |
40
+ |---------|--------------|
41
+ | Box storage | `devportal-code-examples/projects/typescript-examples/contracts/BoxStorage/` |
42
+ | Inner transactions | `puya-ts/examples/` (search for itxn usage) |
43
+ | ARC-4 methods | `puya-ts/examples/hello_world_arc4/` |
44
+ | State management | `devportal-code-examples/projects/typescript-examples/contracts/` |
45
+ | AMM / DeFi | `puya-ts/examples/amm/` |
46
+ | Voting | `puya-ts/examples/voting/` |
47
+
48
+ ## Supporting Repositories
49
+
50
+ - `algorandfoundation/algokit-cli` -- CLI tool reference
51
+ - `algorandfoundation/algokit-client-generator-ts` -- Generated client patterns
52
+ - `algorandfoundation/algokit-utils-ts` -- Utility functions for deployment and testing