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.
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/index.ts +361 -0
- package/lib/mcp-servers.ts +14 -0
- package/lib/x402-fetch.ts +213 -0
- package/memory/algorand-plugin.md +82 -0
- package/openclaw.plugin.json +30 -0
- package/package.json +38 -0
- package/setup.ts +80 -0
- package/skills/algorand-development/SKILL.md +90 -0
- package/skills/algorand-development/references/build-smart-contracts-reference.md +79 -0
- package/skills/algorand-development/references/build-smart-contracts.md +52 -0
- package/skills/algorand-development/references/create-project-reference.md +86 -0
- package/skills/algorand-development/references/create-project.md +89 -0
- package/skills/algorand-development/references/implement-arc-standards-arc32-arc56.md +396 -0
- package/skills/algorand-development/references/implement-arc-standards-arc4.md +265 -0
- package/skills/algorand-development/references/implement-arc-standards.md +92 -0
- package/skills/algorand-development/references/search-algorand-examples-reference.md +119 -0
- package/skills/algorand-development/references/search-algorand-examples.md +89 -0
- package/skills/algorand-development/references/troubleshoot-errors-contract.md +373 -0
- package/skills/algorand-development/references/troubleshoot-errors-transaction.md +599 -0
- package/skills/algorand-development/references/troubleshoot-errors.md +105 -0
- package/skills/algorand-development/references/use-algokit-cli-reference.md +228 -0
- package/skills/algorand-development/references/use-algokit-cli.md +64 -0
- package/skills/algorand-interaction/SKILL.md +223 -0
- package/skills/algorand-interaction/references/algorand-mcp.md +743 -0
- package/skills/algorand-interaction/references/examples-algorand-mcp.md +647 -0
- package/skills/algorand-python/SKILL.md +95 -0
- package/skills/algorand-python/references/build-smart-contracts-decorators.md +413 -0
- package/skills/algorand-python/references/build-smart-contracts-reference.md +55 -0
- package/skills/algorand-python/references/build-smart-contracts-storage.md +452 -0
- package/skills/algorand-python/references/build-smart-contracts-transactions.md +445 -0
- package/skills/algorand-python/references/build-smart-contracts-types.md +438 -0
- package/skills/algorand-python/references/build-smart-contracts.md +82 -0
- package/skills/algorand-python/references/create-project-reference.md +55 -0
- package/skills/algorand-python/references/create-project.md +75 -0
- package/skills/algorand-python/references/implement-arc-standards-arc32-arc56.md +101 -0
- package/skills/algorand-python/references/implement-arc-standards-arc4.md +154 -0
- package/skills/algorand-python/references/implement-arc-standards.md +39 -0
- package/skills/algorand-python/references/troubleshoot-errors-contract.md +355 -0
- package/skills/algorand-python/references/troubleshoot-errors-transaction.md +430 -0
- package/skills/algorand-python/references/troubleshoot-errors.md +46 -0
- package/skills/algorand-python/references/use-algokit-utils-reference.md +350 -0
- package/skills/algorand-python/references/use-algokit-utils.md +76 -0
- package/skills/algorand-typescript/SKILL.md +131 -0
- package/skills/algorand-typescript/references/algorand-ts-migration-from-beta.md +448 -0
- package/skills/algorand-typescript/references/algorand-ts-migration-from-tealscript.md +487 -0
- package/skills/algorand-typescript/references/algorand-ts-migration.md +102 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-methods-and-abi.md +134 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-reference.md +58 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-storage.md +154 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-transactions.md +187 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax-types-and-values.md +150 -0
- package/skills/algorand-typescript/references/algorand-typescript-syntax.md +84 -0
- package/skills/algorand-typescript/references/build-smart-contracts-reference.md +52 -0
- package/skills/algorand-typescript/references/build-smart-contracts.md +74 -0
- package/skills/algorand-typescript/references/call-smart-contracts-reference.md +237 -0
- package/skills/algorand-typescript/references/call-smart-contracts.md +183 -0
- package/skills/algorand-typescript/references/create-project-reference.md +53 -0
- package/skills/algorand-typescript/references/create-project.md +86 -0
- package/skills/algorand-typescript/references/deploy-react-frontend-examples.md +527 -0
- package/skills/algorand-typescript/references/deploy-react-frontend-reference.md +412 -0
- package/skills/algorand-typescript/references/deploy-react-frontend.md +239 -0
- package/skills/algorand-typescript/references/implement-arc-standards-arc32-arc56.md +73 -0
- package/skills/algorand-typescript/references/implement-arc-standards-arc4.md +126 -0
- package/skills/algorand-typescript/references/implement-arc-standards.md +44 -0
- package/skills/algorand-typescript/references/test-smart-contracts-examples.md +245 -0
- package/skills/algorand-typescript/references/test-smart-contracts-unit-tests.md +147 -0
- package/skills/algorand-typescript/references/test-smart-contracts.md +127 -0
- package/skills/algorand-typescript/references/troubleshoot-errors-contract.md +296 -0
- package/skills/algorand-typescript/references/troubleshoot-errors-transaction.md +438 -0
- package/skills/algorand-typescript/references/troubleshoot-errors.md +56 -0
- package/skills/algorand-typescript/references/use-algokit-utils-reference.md +342 -0
- package/skills/algorand-typescript/references/use-algokit-utils.md +74 -0
- package/skills/algorand-x402-python/SKILL.md +113 -0
- package/skills/algorand-x402-python/references/create-python-x402-client-examples.md +469 -0
- package/skills/algorand-x402-python/references/create-python-x402-client-reference.md +313 -0
- package/skills/algorand-x402-python/references/create-python-x402-client.md +207 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator-examples.md +924 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator-reference.md +629 -0
- package/skills/algorand-x402-python/references/create-python-x402-facilitator.md +408 -0
- package/skills/algorand-x402-python/references/create-python-x402-server-examples.md +703 -0
- package/skills/algorand-x402-python/references/create-python-x402-server-reference.md +303 -0
- package/skills/algorand-x402-python/references/create-python-x402-server.md +221 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python-examples.md +605 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python-reference.md +315 -0
- package/skills/algorand-x402-python/references/explain-algorand-x402-python.md +167 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm-examples.md +554 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm-reference.md +278 -0
- package/skills/algorand-x402-python/references/use-python-x402-core-avm.md +166 -0
- package/skills/algorand-x402-typescript/SKILL.md +129 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client-examples.md +879 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client-reference.md +371 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-client.md +236 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-examples.md +875 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator-reference.md +461 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-facilitator.md +270 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-examples.md +1181 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs-reference.md +360 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-nextjs.md +251 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-examples.md +870 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall-reference.md +323 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-paywall.md +281 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server-examples.md +1135 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server-reference.md +382 -0
- package/skills/algorand-x402-typescript/references/create-typescript-x402-server.md +216 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-examples.md +616 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript-reference.md +323 -0
- package/skills/algorand-x402-typescript/references/explain-algorand-x402-typescript.md +232 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-examples.md +1417 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm-reference.md +504 -0
- package/skills/algorand-x402-typescript/references/use-typescript-x402-core-avm.md +158 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# React Frontend Reference
|
|
2
|
+
|
|
3
|
+
Detailed API reference for building Algorand React frontends.
|
|
4
|
+
|
|
5
|
+
## Dependencies
|
|
6
|
+
|
|
7
|
+
Core packages:
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@algorandfoundation/algokit-utils": "^9.0.0",
|
|
12
|
+
"@txnlab/use-wallet-react": "^4.0.0",
|
|
13
|
+
"algosdk": "^3.0.0",
|
|
14
|
+
"react": "^18.2.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Wallet peer dependencies (install only for wallets you're using):
|
|
20
|
+
|
|
21
|
+
| Wallet | Package |
|
|
22
|
+
|--------|---------|
|
|
23
|
+
| Pera | `@perawallet/connect` |
|
|
24
|
+
| Defly | `@blockshake/defly-connect` |
|
|
25
|
+
| Kibisis | `@agoralabs-sh/avm-web-provider` |
|
|
26
|
+
| Lute | `lute-connect` |
|
|
27
|
+
|
|
28
|
+
Example for Pera + Defly:
|
|
29
|
+
```bash
|
|
30
|
+
npm install @perawallet/connect @blockshake/defly-connect
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## WalletManager Configuration
|
|
34
|
+
|
|
35
|
+
Create a `WalletManager` instance to configure available wallets:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { NetworkId, WalletId, WalletManager } from '@txnlab/use-wallet-react'
|
|
39
|
+
|
|
40
|
+
const walletManager = new WalletManager({
|
|
41
|
+
wallets: WalletId[] | WalletConfig[],
|
|
42
|
+
defaultNetwork: NetworkId | string,
|
|
43
|
+
networks?: NetworkConfig,
|
|
44
|
+
options?: ManagerOptions,
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Wallet IDs
|
|
49
|
+
|
|
50
|
+
| Wallet ID | Type | Notes |
|
|
51
|
+
|-----------|------|-------|
|
|
52
|
+
| `WalletId.PERA` | Mobile/Browser | Most popular Algorand wallet |
|
|
53
|
+
| `WalletId.DEFLY` | Mobile/Browser | Feature-rich wallet |
|
|
54
|
+
| `WalletId.EXODUS` | Desktop/Mobile | Multi-chain wallet |
|
|
55
|
+
| `WalletId.KIBISIS` | Browser Extension | AVM standard |
|
|
56
|
+
| `WalletId.LUTE` | Browser | Community wallet |
|
|
57
|
+
| `WalletId.KMD` | LocalNet only | For local development |
|
|
58
|
+
|
|
59
|
+
### Network IDs
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { NetworkId } from '@txnlab/use-wallet-react'
|
|
63
|
+
|
|
64
|
+
NetworkId.MAINNET // 'mainnet'
|
|
65
|
+
NetworkId.TESTNET // 'testnet'
|
|
66
|
+
NetworkId.BETANET // 'betanet'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Basic Configuration
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
// TestNet/MainNet with popular wallets
|
|
73
|
+
const walletManager = new WalletManager({
|
|
74
|
+
wallets: [WalletId.PERA, WalletId.DEFLY, WalletId.EXODUS],
|
|
75
|
+
defaultNetwork: NetworkId.TESTNET,
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Custom Network Configuration
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
const walletManager = new WalletManager({
|
|
83
|
+
wallets: [WalletId.PERA, WalletId.DEFLY],
|
|
84
|
+
defaultNetwork: NetworkId.TESTNET,
|
|
85
|
+
networks: {
|
|
86
|
+
[NetworkId.TESTNET]: {
|
|
87
|
+
algod: {
|
|
88
|
+
baseServer: 'https://testnet-api.algonode.cloud',
|
|
89
|
+
port: '',
|
|
90
|
+
token: '',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### LocalNet Configuration (Development)
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
const walletManager = new WalletManager({
|
|
101
|
+
wallets: [
|
|
102
|
+
{
|
|
103
|
+
id: WalletId.KMD,
|
|
104
|
+
options: {
|
|
105
|
+
baseServer: 'http://localhost',
|
|
106
|
+
port: '4002',
|
|
107
|
+
token: 'a]'.repeat(64),
|
|
108
|
+
wallet: 'unencrypted-default-wallet',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
defaultNetwork: 'localnet',
|
|
113
|
+
networks: {
|
|
114
|
+
localnet: {
|
|
115
|
+
algod: {
|
|
116
|
+
baseServer: 'http://localhost',
|
|
117
|
+
port: '4001',
|
|
118
|
+
token: 'a'.repeat(64),
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## useWallet() Hook
|
|
126
|
+
|
|
127
|
+
The primary hook for wallet interactions:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
131
|
+
|
|
132
|
+
const {
|
|
133
|
+
// Wallet state
|
|
134
|
+
wallets, // Wallet[] - all available wallets
|
|
135
|
+
isReady, // boolean - manager initialized
|
|
136
|
+
|
|
137
|
+
// Active wallet info
|
|
138
|
+
activeWallet, // Wallet | null - current wallet
|
|
139
|
+
activeAddress, // string | null - current address
|
|
140
|
+
activeWalletAccounts, // WalletAccount[] - accounts in active wallet
|
|
141
|
+
|
|
142
|
+
// Signing
|
|
143
|
+
transactionSigner, // TransactionSigner - for signing txns
|
|
144
|
+
signTransactions, // (txns, indexes?) => Promise<Uint8Array[]>
|
|
145
|
+
|
|
146
|
+
// Clients
|
|
147
|
+
algodClient, // Algodv2 - algod client instance
|
|
148
|
+
} = useWallet()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Wallet Object
|
|
152
|
+
|
|
153
|
+
Each wallet in the `wallets` array has:
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
interface Wallet {
|
|
157
|
+
id: WalletId
|
|
158
|
+
metadata: { name: string; icon: string }
|
|
159
|
+
accounts: WalletAccount[]
|
|
160
|
+
activeAccount: WalletAccount | null
|
|
161
|
+
isConnected: boolean
|
|
162
|
+
isActive: boolean
|
|
163
|
+
|
|
164
|
+
// Methods
|
|
165
|
+
connect: () => Promise<WalletAccount[]>
|
|
166
|
+
disconnect: () => Promise<void>
|
|
167
|
+
setActive: () => void
|
|
168
|
+
setActiveAccount: (address: string) => void
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### WalletAccount Object
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
interface WalletAccount {
|
|
176
|
+
name: string
|
|
177
|
+
address: string
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## AlgorandClient Signer Methods
|
|
182
|
+
|
|
183
|
+
Register wallet signers with `AlgorandClient`:
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
187
|
+
|
|
188
|
+
const algorand = AlgorandClient.testNet()
|
|
189
|
+
|
|
190
|
+
// Register signer for specific address
|
|
191
|
+
algorand.setSigner(address: string, signer: TransactionSigner)
|
|
192
|
+
|
|
193
|
+
// Register signer from account object
|
|
194
|
+
algorand.setSignerFromAccount(account: { addr: string; signer: TransactionSigner })
|
|
195
|
+
|
|
196
|
+
// Set default signer for all transactions
|
|
197
|
+
algorand.setDefaultSigner(signer: TransactionSigner)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Signer Resolution Order
|
|
201
|
+
|
|
202
|
+
When sending transactions, AlgorandClient resolves signers in this order:
|
|
203
|
+
|
|
204
|
+
1. Explicit `signer` parameter in the method call
|
|
205
|
+
2. Registered signer for the sender address (via `setSigner()`)
|
|
206
|
+
3. Default signer (via `setDefaultSigner()`)
|
|
207
|
+
|
|
208
|
+
## AlgorandClient Factory Methods
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
// Network presets
|
|
212
|
+
AlgorandClient.mainNet() // MainNet via AlgoNode
|
|
213
|
+
AlgorandClient.testNet() // TestNet via AlgoNode
|
|
214
|
+
AlgorandClient.defaultLocalNet() // LocalNet defaults
|
|
215
|
+
|
|
216
|
+
// From configuration
|
|
217
|
+
AlgorandClient.fromConfig({
|
|
218
|
+
algodConfig: { server: '...', port: '...', token: '...' },
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
// From environment variables
|
|
222
|
+
AlgorandClient.fromEnvironment()
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Typed App Client Methods
|
|
226
|
+
|
|
227
|
+
### Get Client by App ID
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
const appClient = algorand.client.getTypedAppClientById(
|
|
231
|
+
MyContractClient, // Generated client class
|
|
232
|
+
{
|
|
233
|
+
appId: 12345n, // Required: App ID
|
|
234
|
+
defaultSender: activeAddress, // Optional: default sender
|
|
235
|
+
defaultSigner: transactionSigner, // Optional: explicit signer
|
|
236
|
+
}
|
|
237
|
+
)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Get Client by Creator and Name
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
const appClient = await algorand.client.getTypedAppClientByCreatorAndName(
|
|
244
|
+
MyContractClient,
|
|
245
|
+
{
|
|
246
|
+
creatorAddress: 'ABC123...',
|
|
247
|
+
appName: 'MyContract', // Optional: defaults to spec name
|
|
248
|
+
defaultSender: activeAddress,
|
|
249
|
+
}
|
|
250
|
+
)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Get Client by Network (ARC-56)
|
|
254
|
+
|
|
255
|
+
For contracts with network-specific App IDs in their spec:
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
const appClient = await algorand.client.getTypedAppClientByNetwork(
|
|
259
|
+
MyContractClient,
|
|
260
|
+
{
|
|
261
|
+
defaultSender: activeAddress,
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Typed App Factory
|
|
267
|
+
|
|
268
|
+
Use factories to deploy new contracts or manage multiple instances:
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
import { MyContractFactory } from './contracts/MyContractClient'
|
|
272
|
+
|
|
273
|
+
// Create factory
|
|
274
|
+
const factory = new MyContractFactory({
|
|
275
|
+
algorand,
|
|
276
|
+
defaultSender: activeAddress,
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
// Deploy new instance
|
|
280
|
+
const { appClient, result } = await factory.deploy({
|
|
281
|
+
onSchemaBreak: 'append', // 'replace' | 'append' | 'fail'
|
|
282
|
+
onUpdate: 'append', // 'replace' | 'append' | 'fail'
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
// Get client for existing app by ID
|
|
286
|
+
const existingClient = factory.getAppClientById({ appId: 12345n })
|
|
287
|
+
|
|
288
|
+
// Get client by creator and name
|
|
289
|
+
const namedClient = await factory.getAppClientByCreatorAndName({
|
|
290
|
+
creatorAddress: 'ABC123...',
|
|
291
|
+
appName: 'MyContract',
|
|
292
|
+
})
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Calling Contract Methods
|
|
296
|
+
|
|
297
|
+
### Send (Execute Transaction)
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
// Single method call
|
|
301
|
+
const result = await appClient.send.methodName({
|
|
302
|
+
args: { param1: 'value', param2: 42n },
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
console.log(result.return) // Return value
|
|
306
|
+
console.log(result.txIds) // Transaction IDs
|
|
307
|
+
console.log(result.transaction) // Transaction object
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Simulate (Dry Run)
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
// Test without submitting
|
|
314
|
+
const simResult = await appClient.newGroup()
|
|
315
|
+
.methodName({ args: { param1: 'value' } })
|
|
316
|
+
.simulate()
|
|
317
|
+
|
|
318
|
+
console.log(simResult.returns[0]) // Simulated return value
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Chained Calls (Atomic Group)
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
const result = await appClient.newGroup()
|
|
325
|
+
.method1({ args: { ... } })
|
|
326
|
+
.method2({ args: { ... } })
|
|
327
|
+
.send()
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## App Client Properties
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
appClient.appId // bigint - Application ID
|
|
334
|
+
appClient.appAddress // string - Application account address
|
|
335
|
+
appClient.appName // string - Application name
|
|
336
|
+
appClient.appSpec // Arc56Contract - ARC-56 spec
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Payment Transactions
|
|
340
|
+
|
|
341
|
+
Send ALGO payments using the wallet signer:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
import { algo } from '@algorandfoundation/algokit-utils'
|
|
345
|
+
|
|
346
|
+
const result = await algorand.send.payment({
|
|
347
|
+
sender: activeAddress,
|
|
348
|
+
receiver: 'RECIPIENTADDRESS...',
|
|
349
|
+
amount: algo(1), // 1 ALGO
|
|
350
|
+
signer: transactionSigner,
|
|
351
|
+
})
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Error Handling Pattern
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
const callContract = async () => {
|
|
358
|
+
if (!activeAddress || !transactionSigner) {
|
|
359
|
+
throw new Error('Wallet not connected')
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
const algorand = AlgorandClient.testNet()
|
|
364
|
+
algorand.setSigner(activeAddress, transactionSigner)
|
|
365
|
+
|
|
366
|
+
const appClient = algorand.client.getTypedAppClientById(MyContractClient, {
|
|
367
|
+
appId: APP_ID,
|
|
368
|
+
defaultSender: activeAddress,
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
const result = await appClient.send.myMethod({ args: { value: 42n } })
|
|
372
|
+
return result.return
|
|
373
|
+
} catch (error) {
|
|
374
|
+
if (error.message.includes('rejected')) {
|
|
375
|
+
// User cancelled in wallet
|
|
376
|
+
console.log('Transaction cancelled by user')
|
|
377
|
+
} else if (error.message.includes('below min')) {
|
|
378
|
+
// Insufficient funds
|
|
379
|
+
console.log('Insufficient balance')
|
|
380
|
+
} else {
|
|
381
|
+
// Other error
|
|
382
|
+
console.error('Transaction failed:', error)
|
|
383
|
+
}
|
|
384
|
+
throw error
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Type Imports
|
|
390
|
+
|
|
391
|
+
Common imports for TypeScript:
|
|
392
|
+
|
|
393
|
+
```tsx
|
|
394
|
+
// use-wallet
|
|
395
|
+
import {
|
|
396
|
+
NetworkId,
|
|
397
|
+
WalletId,
|
|
398
|
+
WalletManager,
|
|
399
|
+
WalletProvider,
|
|
400
|
+
useWallet,
|
|
401
|
+
} from '@txnlab/use-wallet-react'
|
|
402
|
+
|
|
403
|
+
// AlgoKit Utils
|
|
404
|
+
import {
|
|
405
|
+
AlgorandClient,
|
|
406
|
+
algo,
|
|
407
|
+
microAlgo,
|
|
408
|
+
} from '@algorandfoundation/algokit-utils'
|
|
409
|
+
|
|
410
|
+
// algosdk (rarely needed directly)
|
|
411
|
+
import algosdk from 'algosdk'
|
|
412
|
+
```
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
|
|
2
|
+
# Deploying React Frontends for Algorand
|
|
3
|
+
|
|
4
|
+
Build React applications that connect to Algorand wallets and interact with smart contracts using typed clients.
|
|
5
|
+
|
|
6
|
+
## Prerequisites
|
|
7
|
+
|
|
8
|
+
Before using this skill, ensure:
|
|
9
|
+
|
|
10
|
+
1. **Smart contract is deployed** with a known App ID
|
|
11
|
+
2. **ARC-56/ARC-32 app spec exists** (e.g., `MyContract.arc56.json`)
|
|
12
|
+
3. **React project is set up** (Vite, Next.js, or Create React App)
|
|
13
|
+
|
|
14
|
+
## Core Workflow: The "Signer Handoff" Pattern
|
|
15
|
+
|
|
16
|
+
The key insight is passing the wallet's transaction signer to AlgorandClient, which then provides it to typed app clients:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Wallet (use-wallet) → transactionSigner
|
|
20
|
+
↓
|
|
21
|
+
AlgorandClient.setSigner()
|
|
22
|
+
↓
|
|
23
|
+
Typed App Client (defaultSender)
|
|
24
|
+
↓
|
|
25
|
+
Contract Method Calls (auto-signed)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## How to proceed
|
|
29
|
+
|
|
30
|
+
### Step 1: Generate Typed Client
|
|
31
|
+
|
|
32
|
+
Generate a TypeScript client from your contract's app spec:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
algokit generate client path/to/MyContract.arc56.json --output src/contracts/MyContractClient.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This creates a typed client with full IntelliSense for your contract's methods.
|
|
39
|
+
|
|
40
|
+
### Step 2: Install Dependencies
|
|
41
|
+
|
|
42
|
+
Core packages:
|
|
43
|
+
```bash
|
|
44
|
+
npm install @algorandfoundation/algokit-utils @txnlab/use-wallet-react algosdk
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Wallet peer dependencies (install only for wallets you're using):
|
|
48
|
+
|
|
49
|
+
| Wallet | Package |
|
|
50
|
+
|--------|---------|
|
|
51
|
+
| Pera | `@perawallet/connect` |
|
|
52
|
+
| Defly | `@blockshake/defly-connect` |
|
|
53
|
+
| Kibisis | `@agoralabs-sh/avm-web-provider` |
|
|
54
|
+
| Lute | `lute-connect` |
|
|
55
|
+
|
|
56
|
+
Example for Pera + Defly:
|
|
57
|
+
```bash
|
|
58
|
+
npm install @perawallet/connect @blockshake/defly-connect
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Step 3: Set Up WalletProvider
|
|
62
|
+
|
|
63
|
+
Wrap your app with `WalletProvider` at the root level:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import { NetworkId, WalletId, WalletManager, WalletProvider } from '@txnlab/use-wallet-react'
|
|
67
|
+
|
|
68
|
+
const walletManager = new WalletManager({
|
|
69
|
+
wallets: [WalletId.PERA, WalletId.DEFLY, WalletId.EXODUS],
|
|
70
|
+
defaultNetwork: NetworkId.TESTNET,
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
export default function App() {
|
|
74
|
+
return (
|
|
75
|
+
<WalletProvider manager={walletManager}>
|
|
76
|
+
<YourApp />
|
|
77
|
+
</WalletProvider>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Step 4: Create Wallet Connection UI
|
|
83
|
+
|
|
84
|
+
Use the `useWallet()` hook to display available wallets:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
88
|
+
|
|
89
|
+
function ConnectWallet() {
|
|
90
|
+
const { wallets, activeAddress } = useWallet()
|
|
91
|
+
|
|
92
|
+
if (activeAddress) {
|
|
93
|
+
return <p>Connected: {activeAddress}</p>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div>
|
|
98
|
+
{wallets.map((wallet) => (
|
|
99
|
+
<button key={wallet.id} onClick={() => wallet.connect()}>
|
|
100
|
+
Connect {wallet.metadata.name}
|
|
101
|
+
</button>
|
|
102
|
+
))}
|
|
103
|
+
</div>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Step 5: Integrate Typed Client with Wallet Signer
|
|
109
|
+
|
|
110
|
+
This is the critical integration step. Register the wallet's signer with AlgorandClient:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
114
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
115
|
+
import { MyContractClient } from './contracts/MyContractClient'
|
|
116
|
+
|
|
117
|
+
function ContractInteraction() {
|
|
118
|
+
const { transactionSigner, activeAddress } = useWallet()
|
|
119
|
+
|
|
120
|
+
const callContract = async () => {
|
|
121
|
+
if (!activeAddress || !transactionSigner) {
|
|
122
|
+
alert('Please connect your wallet first')
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 1. Create AlgorandClient for the network
|
|
127
|
+
const algorand = AlgorandClient.testNet()
|
|
128
|
+
|
|
129
|
+
// 2. Register wallet signer with AlgorandClient
|
|
130
|
+
algorand.setSigner(activeAddress, transactionSigner)
|
|
131
|
+
|
|
132
|
+
// 3. Create typed client with wallet as default sender
|
|
133
|
+
const appClient = algorand.client.getTypedAppClientById(MyContractClient, {
|
|
134
|
+
appId: 12345n, // Your deployed App ID
|
|
135
|
+
defaultSender: activeAddress,
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
// 4. Call contract methods - signer is used automatically
|
|
139
|
+
const result = await appClient.send.myMethod({ args: { value: 42n } })
|
|
140
|
+
console.log('Result:', result.return)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return <button onClick={callContract}>Call Contract</button>
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Step 6: Deploy New Contracts (Optional)
|
|
148
|
+
|
|
149
|
+
If deploying from the frontend (less common), use the Factory pattern:
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { MyContractFactory } from './contracts/MyContractClient'
|
|
153
|
+
|
|
154
|
+
const factory = new MyContractFactory({
|
|
155
|
+
algorand,
|
|
156
|
+
defaultSender: activeAddress,
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
const { appClient } = await factory.deploy({
|
|
160
|
+
onSchemaBreak: 'append',
|
|
161
|
+
onUpdate: 'append',
|
|
162
|
+
})
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Important Rules / Guidelines
|
|
166
|
+
|
|
167
|
+
1. **Always call setSigner() before creating clients** - The signer must be registered with AlgorandClient first
|
|
168
|
+
2. **Check for null activeAddress and transactionSigner** - They are null when no wallet is connected
|
|
169
|
+
3. **Use TypeScript** - Typed clients provide full type safety and IntelliSense
|
|
170
|
+
4. **Match networks** - Ensure AlgorandClient network matches WalletManager network
|
|
171
|
+
5. **React only** - This skill covers React; other frameworks have different patterns
|
|
172
|
+
|
|
173
|
+
## Getting the App Client
|
|
174
|
+
|
|
175
|
+
Three ways to get a typed app client:
|
|
176
|
+
|
|
177
|
+
| Method | Use Case |
|
|
178
|
+
|--------|----------|
|
|
179
|
+
| `getTypedAppClientById()` | Known App ID (most common for frontends) |
|
|
180
|
+
| `getTypedAppClientByCreatorAndName()` | Resolve by creator address and app name |
|
|
181
|
+
| `factory.deploy()` | Deploy new instance and get client |
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
// By App ID (recommended for frontends)
|
|
185
|
+
const appClient = algorand.client.getTypedAppClientById(MyContractClient, {
|
|
186
|
+
appId: 12345n,
|
|
187
|
+
defaultSender: activeAddress,
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
// By Creator and Name
|
|
191
|
+
const appClient = await algorand.client.getTypedAppClientByCreatorAndName(
|
|
192
|
+
MyContractClient,
|
|
193
|
+
{
|
|
194
|
+
creatorAddress: 'CREATORADDRESS...',
|
|
195
|
+
appName: 'MyContract',
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Common Errors / Troubleshooting
|
|
201
|
+
|
|
202
|
+
| Error | Cause | Solution |
|
|
203
|
+
|-------|-------|----------|
|
|
204
|
+
| `activeAddress is null` | Wallet not connected | Check wallet connection before contract calls |
|
|
205
|
+
| `transactionSigner is undefined` | No active wallet | Prompt user to connect wallet first |
|
|
206
|
+
| `signer not found for address` | Signer not registered | Call `algorand.setSigner(activeAddress, transactionSigner)` |
|
|
207
|
+
| `app does not exist` | Wrong App ID | Verify App ID matches deployed contract |
|
|
208
|
+
| `Method not found` | Wrong method name or signature | Check typed client API; ensure args match ABI |
|
|
209
|
+
| `Network mismatch` | Different networks | Ensure AlgorandClient and WalletManager use same network |
|
|
210
|
+
| `User rejected transaction` | User cancelled in wallet | Handle rejection gracefully in UI |
|
|
211
|
+
| `global is not defined` | algosdk references `global` in browser | Add to vite.config.ts: `define: { global: 'globalThis' }` |
|
|
212
|
+
| TypeScript errors in generated client | Strict TS mode incompatibility | Set `verbatimModuleSyntax: false` in tsconfig.json |
|
|
213
|
+
|
|
214
|
+
## Wallet Disconnect
|
|
215
|
+
|
|
216
|
+
Handle wallet disconnection:
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
function DisconnectButton() {
|
|
220
|
+
const { wallets } = useWallet()
|
|
221
|
+
|
|
222
|
+
const disconnect = async () => {
|
|
223
|
+
const activeWallet = wallets.find((w) => w.isActive)
|
|
224
|
+
if (activeWallet) {
|
|
225
|
+
await activeWallet.disconnect()
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return <button onClick={disconnect}>Disconnect</button>
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## References / Further Reading
|
|
234
|
+
|
|
235
|
+
- [REFERENCE.md](./deploy-react-frontend-reference.md) - Detailed API reference
|
|
236
|
+
- [EXAMPLES.md](./deploy-react-frontend-examples.md) - Complete code examples
|
|
237
|
+
- [use-wallet Documentation](https://txnlab.gitbook.io/use-wallet)
|
|
238
|
+
- [AlgoKit Utils TypeScript](https://dev.algorand.co/algokit/utils/typescript/algorand-client/)
|
|
239
|
+
- [Typed App Clients](https://dev.algorand.co/algokit/utils/typescript/typed-app-clients/)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# ARC-32/56 Client Usage (TypeScript)
|
|
2
|
+
|
|
3
|
+
This reference covers generating and using ARC-32/ARC-56 application specifications in TypeScript.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Generating App Specs](#generating-app-specs)
|
|
8
|
+
- [TypeScript Client Usage](#typescript-client-usage)
|
|
9
|
+
- [Factory and Deployment](#factory-and-deployment)
|
|
10
|
+
- [Calling Methods](#calling-methods)
|
|
11
|
+
- [State Access](#state-access)
|
|
12
|
+
- [Converting ARC-32 to ARC-56](#converting-arc-32-to-arc-56)
|
|
13
|
+
|
|
14
|
+
## Generating App Specs
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Compile TypeScript contract - generates both .arc32.json and .arc56.json
|
|
18
|
+
npx puya-ts contracts/my_contract.ts
|
|
19
|
+
|
|
20
|
+
# Or via AlgoKit
|
|
21
|
+
algokit project run build
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Output files:
|
|
25
|
+
- `MyContract.arc32.json` - Legacy app spec
|
|
26
|
+
- `MyContract.arc56.json` - Modern app spec
|
|
27
|
+
|
|
28
|
+
## TypeScript Client Usage
|
|
29
|
+
|
|
30
|
+
### Factory and Deployment
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
34
|
+
import { CalculatorFactory } from './clients/Calculator'
|
|
35
|
+
|
|
36
|
+
const algorand = AlgorandClient.defaultLocalNet()
|
|
37
|
+
|
|
38
|
+
// Deploy new contract
|
|
39
|
+
const factory = algorand.client.getTypedAppFactory(CalculatorFactory)
|
|
40
|
+
const { appClient } = await factory.deploy({
|
|
41
|
+
onSchemaBreak: 'replace',
|
|
42
|
+
onUpdate: 'update',
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Calling Methods
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// Call methods with full type safety
|
|
50
|
+
const result = await appClient.send.add({
|
|
51
|
+
args: { a: 10n, b: 20n }
|
|
52
|
+
})
|
|
53
|
+
console.log(result.return) // BigInt: 30n
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### State Access
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// Read state with typed access
|
|
60
|
+
const state = await appClient.state.global.getAll()
|
|
61
|
+
console.log(state.counter) // Typed as bigint
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Converting ARC-32 to ARC-56
|
|
65
|
+
|
|
66
|
+
AlgoKit Utils provides a conversion utility for migrating legacy ARC-32 specs:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { arc32ToArc56 } from '@algorandfoundation/algokit-utils'
|
|
70
|
+
import arc32Spec from './MyContract.arc32.json'
|
|
71
|
+
|
|
72
|
+
const arc56Spec = arc32ToArc56(arc32Spec)
|
|
73
|
+
```
|