@goplausible/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 +41 -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,527 @@
|
|
|
1
|
+
# React Frontend Examples
|
|
2
|
+
|
|
3
|
+
Complete, minimal examples for Algorand React frontends.
|
|
4
|
+
|
|
5
|
+
## Example 1: Minimal Wallet Connection
|
|
6
|
+
|
|
7
|
+
Basic wallet connection without contract interaction.
|
|
8
|
+
|
|
9
|
+
### App.tsx
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { NetworkId, WalletId, WalletManager, WalletProvider } from '@txnlab/use-wallet-react'
|
|
13
|
+
import { WalletConnect } from './WalletConnect'
|
|
14
|
+
|
|
15
|
+
const walletManager = new WalletManager({
|
|
16
|
+
wallets: [WalletId.PERA, WalletId.DEFLY],
|
|
17
|
+
defaultNetwork: NetworkId.TESTNET,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export default function App() {
|
|
21
|
+
return (
|
|
22
|
+
<WalletProvider manager={walletManager}>
|
|
23
|
+
<WalletConnect />
|
|
24
|
+
</WalletProvider>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### WalletConnect.tsx
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
33
|
+
|
|
34
|
+
export function WalletConnect() {
|
|
35
|
+
const { wallets, activeAddress, activeWallet } = useWallet()
|
|
36
|
+
|
|
37
|
+
if (activeAddress) {
|
|
38
|
+
return (
|
|
39
|
+
<div>
|
|
40
|
+
<p>Connected: {activeAddress.slice(0, 8)}...{activeAddress.slice(-4)}</p>
|
|
41
|
+
<button onClick={() => activeWallet?.disconnect()}>Disconnect</button>
|
|
42
|
+
</div>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div>
|
|
48
|
+
<h2>Connect Wallet</h2>
|
|
49
|
+
{wallets.map((wallet) => (
|
|
50
|
+
<button key={wallet.id} onClick={() => wallet.connect()}>
|
|
51
|
+
{wallet.metadata.name}
|
|
52
|
+
</button>
|
|
53
|
+
))}
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Example 2: Contract Interaction (Existing App)
|
|
62
|
+
|
|
63
|
+
Connect to an already-deployed contract by App ID.
|
|
64
|
+
|
|
65
|
+
### App.tsx
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { NetworkId, WalletId, WalletManager, WalletProvider } from '@txnlab/use-wallet-react'
|
|
69
|
+
import { ContractDemo } from './ContractDemo'
|
|
70
|
+
|
|
71
|
+
const walletManager = new WalletManager({
|
|
72
|
+
wallets: [WalletId.PERA, WalletId.DEFLY],
|
|
73
|
+
defaultNetwork: NetworkId.TESTNET,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
export default function App() {
|
|
77
|
+
return (
|
|
78
|
+
<WalletProvider manager={walletManager}>
|
|
79
|
+
<ContractDemo />
|
|
80
|
+
</WalletProvider>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### ContractDemo.tsx
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { useState } from 'react'
|
|
89
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
90
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
91
|
+
import { HelloWorldClient } from './contracts/HelloWorldClient'
|
|
92
|
+
|
|
93
|
+
const APP_ID = 12345n // Replace with your App ID
|
|
94
|
+
|
|
95
|
+
export function ContractDemo() {
|
|
96
|
+
const { transactionSigner, activeAddress, wallets } = useWallet()
|
|
97
|
+
const [result, setResult] = useState<string>('')
|
|
98
|
+
const [loading, setLoading] = useState(false)
|
|
99
|
+
|
|
100
|
+
const callContract = async () => {
|
|
101
|
+
if (!activeAddress || !transactionSigner) return
|
|
102
|
+
|
|
103
|
+
setLoading(true)
|
|
104
|
+
try {
|
|
105
|
+
const algorand = AlgorandClient.testNet()
|
|
106
|
+
algorand.setSigner(activeAddress, transactionSigner)
|
|
107
|
+
|
|
108
|
+
const appClient = algorand.client.getTypedAppClientById(HelloWorldClient, {
|
|
109
|
+
appId: APP_ID,
|
|
110
|
+
defaultSender: activeAddress,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const response = await appClient.send.hello({ args: { name: 'World' } })
|
|
114
|
+
setResult(response.return ?? 'No return value')
|
|
115
|
+
} catch (error) {
|
|
116
|
+
setResult(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`)
|
|
117
|
+
} finally {
|
|
118
|
+
setLoading(false)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!activeAddress) {
|
|
123
|
+
return (
|
|
124
|
+
<div>
|
|
125
|
+
<h2>Connect Wallet</h2>
|
|
126
|
+
{wallets.map((wallet) => (
|
|
127
|
+
<button key={wallet.id} onClick={() => wallet.connect()}>
|
|
128
|
+
{wallet.metadata.name}
|
|
129
|
+
</button>
|
|
130
|
+
))}
|
|
131
|
+
</div>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<div>
|
|
137
|
+
<p>Connected: {activeAddress.slice(0, 8)}...</p>
|
|
138
|
+
<button onClick={callContract} disabled={loading}>
|
|
139
|
+
{loading ? 'Calling...' : 'Call hello()'}
|
|
140
|
+
</button>
|
|
141
|
+
{result && <p>Result: {result}</p>}
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Example 3: Deploy and Call Contract
|
|
150
|
+
|
|
151
|
+
Deploy a new contract instance from the frontend.
|
|
152
|
+
|
|
153
|
+
### DeployContract.tsx
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import { useState } from 'react'
|
|
157
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
158
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
159
|
+
import { HelloWorldFactory } from './contracts/HelloWorldClient'
|
|
160
|
+
|
|
161
|
+
export function DeployContract() {
|
|
162
|
+
const { transactionSigner, activeAddress } = useWallet()
|
|
163
|
+
const [appId, setAppId] = useState<bigint | null>(null)
|
|
164
|
+
const [loading, setLoading] = useState(false)
|
|
165
|
+
|
|
166
|
+
const deployContract = async () => {
|
|
167
|
+
if (!activeAddress || !transactionSigner) return
|
|
168
|
+
|
|
169
|
+
setLoading(true)
|
|
170
|
+
try {
|
|
171
|
+
const algorand = AlgorandClient.testNet()
|
|
172
|
+
algorand.setSigner(activeAddress, transactionSigner)
|
|
173
|
+
|
|
174
|
+
const factory = new HelloWorldFactory({
|
|
175
|
+
algorand,
|
|
176
|
+
defaultSender: activeAddress,
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const { appClient } = await factory.deploy({
|
|
180
|
+
onSchemaBreak: 'append',
|
|
181
|
+
onUpdate: 'append',
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
setAppId(appClient.appId)
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error('Deploy failed:', error)
|
|
187
|
+
} finally {
|
|
188
|
+
setLoading(false)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!activeAddress) {
|
|
193
|
+
return <p>Please connect your wallet first.</p>
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<div>
|
|
198
|
+
<button onClick={deployContract} disabled={loading}>
|
|
199
|
+
{loading ? 'Deploying...' : 'Deploy Contract'}
|
|
200
|
+
</button>
|
|
201
|
+
{appId && <p>Deployed! App ID: {appId.toString()}</p>}
|
|
202
|
+
</div>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Example 4: Send Payment
|
|
210
|
+
|
|
211
|
+
Send ALGO to another address.
|
|
212
|
+
|
|
213
|
+
### SendPayment.tsx
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import { useState } from 'react'
|
|
217
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
218
|
+
import { AlgorandClient, algo } from '@algorandfoundation/algokit-utils'
|
|
219
|
+
|
|
220
|
+
export function SendPayment() {
|
|
221
|
+
const { transactionSigner, activeAddress } = useWallet()
|
|
222
|
+
const [receiver, setReceiver] = useState('')
|
|
223
|
+
const [loading, setLoading] = useState(false)
|
|
224
|
+
const [txId, setTxId] = useState('')
|
|
225
|
+
|
|
226
|
+
const sendPayment = async () => {
|
|
227
|
+
if (!activeAddress || !transactionSigner || !receiver) return
|
|
228
|
+
|
|
229
|
+
setLoading(true)
|
|
230
|
+
try {
|
|
231
|
+
const algorand = AlgorandClient.testNet()
|
|
232
|
+
|
|
233
|
+
const result = await algorand.send.payment({
|
|
234
|
+
sender: activeAddress,
|
|
235
|
+
receiver: receiver,
|
|
236
|
+
amount: algo(1),
|
|
237
|
+
signer: transactionSigner,
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
setTxId(result.txIds[0])
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error('Payment failed:', error)
|
|
243
|
+
} finally {
|
|
244
|
+
setLoading(false)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!activeAddress) {
|
|
249
|
+
return <p>Please connect your wallet first.</p>
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<div>
|
|
254
|
+
<input
|
|
255
|
+
type="text"
|
|
256
|
+
placeholder="Receiver address"
|
|
257
|
+
value={receiver}
|
|
258
|
+
onChange={(e) => setReceiver(e.target.value)}
|
|
259
|
+
/>
|
|
260
|
+
<button onClick={sendPayment} disabled={loading || receiver.length !== 58}>
|
|
261
|
+
{loading ? 'Sending...' : 'Send 1 ALGO'}
|
|
262
|
+
</button>
|
|
263
|
+
{txId && <p>Sent! TX: {txId}</p>}
|
|
264
|
+
</div>
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Example 5: Multiple Account Selection
|
|
272
|
+
|
|
273
|
+
Handle wallets with multiple accounts.
|
|
274
|
+
|
|
275
|
+
### AccountSelector.tsx
|
|
276
|
+
|
|
277
|
+
```tsx
|
|
278
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
279
|
+
|
|
280
|
+
export function AccountSelector() {
|
|
281
|
+
const { activeWallet, activeWalletAccounts, activeAddress } = useWallet()
|
|
282
|
+
|
|
283
|
+
if (!activeWallet || activeWalletAccounts.length <= 1) {
|
|
284
|
+
return null
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<div>
|
|
289
|
+
<label>Select Account:</label>
|
|
290
|
+
<select
|
|
291
|
+
value={activeAddress ?? ''}
|
|
292
|
+
onChange={(e) => activeWallet.setActiveAccount(e.target.value)}
|
|
293
|
+
>
|
|
294
|
+
{activeWalletAccounts.map((account) => (
|
|
295
|
+
<option key={account.address} value={account.address}>
|
|
296
|
+
{account.name || account.address.slice(0, 8) + '...'}
|
|
297
|
+
</option>
|
|
298
|
+
))}
|
|
299
|
+
</select>
|
|
300
|
+
</div>
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Example 6: Contract with Arguments
|
|
308
|
+
|
|
309
|
+
Call a contract method with typed arguments.
|
|
310
|
+
|
|
311
|
+
### CounterContract.tsx
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import { useState } from 'react'
|
|
315
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
316
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
317
|
+
import { CounterClient } from './contracts/CounterClient'
|
|
318
|
+
|
|
319
|
+
const APP_ID = 12345n
|
|
320
|
+
|
|
321
|
+
export function CounterContract() {
|
|
322
|
+
const { transactionSigner, activeAddress } = useWallet()
|
|
323
|
+
const [count, setCount] = useState<bigint | null>(null)
|
|
324
|
+
|
|
325
|
+
const getClient = () => {
|
|
326
|
+
if (!activeAddress || !transactionSigner) return null
|
|
327
|
+
|
|
328
|
+
const algorand = AlgorandClient.testNet()
|
|
329
|
+
algorand.setSigner(activeAddress, transactionSigner)
|
|
330
|
+
|
|
331
|
+
return algorand.client.getTypedAppClientById(CounterClient, {
|
|
332
|
+
appId: APP_ID,
|
|
333
|
+
defaultSender: activeAddress,
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const increment = async () => {
|
|
338
|
+
const client = getClient()
|
|
339
|
+
if (!client) return
|
|
340
|
+
|
|
341
|
+
const result = await client.send.increment()
|
|
342
|
+
setCount(result.return ?? 0n)
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const add = async (value: bigint) => {
|
|
346
|
+
const client = getClient()
|
|
347
|
+
if (!client) return
|
|
348
|
+
|
|
349
|
+
const result = await client.send.add({ args: { value } })
|
|
350
|
+
setCount(result.return ?? 0n)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const readCount = async () => {
|
|
354
|
+
const client = getClient()
|
|
355
|
+
if (!client) return
|
|
356
|
+
|
|
357
|
+
const result = await client.send.getCount()
|
|
358
|
+
setCount(result.return ?? 0n)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (!activeAddress) {
|
|
362
|
+
return <p>Connect wallet to interact with counter.</p>
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
<div>
|
|
367
|
+
<p>Count: {count?.toString() ?? 'Unknown'}</p>
|
|
368
|
+
<button onClick={readCount}>Read Count</button>
|
|
369
|
+
<button onClick={increment}>Increment</button>
|
|
370
|
+
<button onClick={() => add(5n)}>Add 5</button>
|
|
371
|
+
<button onClick={() => add(10n)}>Add 10</button>
|
|
372
|
+
</div>
|
|
373
|
+
)
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Example 7: Read Global State
|
|
380
|
+
|
|
381
|
+
Read contract global state without sending a transaction.
|
|
382
|
+
|
|
383
|
+
### ReadState.tsx
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
import { useState, useEffect } from 'react'
|
|
387
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
388
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
389
|
+
import { MyContractClient } from './contracts/MyContractClient'
|
|
390
|
+
|
|
391
|
+
const APP_ID = 12345n
|
|
392
|
+
|
|
393
|
+
export function ReadState() {
|
|
394
|
+
const { activeAddress } = useWallet()
|
|
395
|
+
const [globalState, setGlobalState] = useState<Record<string, unknown>>({})
|
|
396
|
+
|
|
397
|
+
useEffect(() => {
|
|
398
|
+
const fetchState = async () => {
|
|
399
|
+
const algorand = AlgorandClient.testNet()
|
|
400
|
+
|
|
401
|
+
// Reading state doesn't require a signer
|
|
402
|
+
const appClient = algorand.client.getTypedAppClientById(MyContractClient, {
|
|
403
|
+
appId: APP_ID,
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
// Access typed state if available
|
|
407
|
+
const state = await appClient.state.global.getAll()
|
|
408
|
+
setGlobalState(state as Record<string, unknown>)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
fetchState()
|
|
412
|
+
}, [])
|
|
413
|
+
|
|
414
|
+
return (
|
|
415
|
+
<div>
|
|
416
|
+
<h3>Global State</h3>
|
|
417
|
+
<pre>{JSON.stringify(globalState, null, 2)}</pre>
|
|
418
|
+
</div>
|
|
419
|
+
)
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## Example 8: Custom Hook for Contract
|
|
426
|
+
|
|
427
|
+
Create a reusable hook for contract interactions.
|
|
428
|
+
|
|
429
|
+
### useContract.ts
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import { useMemo } from 'react'
|
|
433
|
+
import { useWallet } from '@txnlab/use-wallet-react'
|
|
434
|
+
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
|
|
435
|
+
import { MyContractClient } from './contracts/MyContractClient'
|
|
436
|
+
|
|
437
|
+
const APP_ID = 12345n
|
|
438
|
+
|
|
439
|
+
export function useContract() {
|
|
440
|
+
const { transactionSigner, activeAddress, isReady } = useWallet()
|
|
441
|
+
|
|
442
|
+
const client = useMemo(() => {
|
|
443
|
+
if (!activeAddress || !transactionSigner || !isReady) return null
|
|
444
|
+
|
|
445
|
+
const algorand = AlgorandClient.testNet()
|
|
446
|
+
algorand.setSigner(activeAddress, transactionSigner)
|
|
447
|
+
|
|
448
|
+
return algorand.client.getTypedAppClientById(MyContractClient, {
|
|
449
|
+
appId: APP_ID,
|
|
450
|
+
defaultSender: activeAddress,
|
|
451
|
+
})
|
|
452
|
+
}, [activeAddress, transactionSigner, isReady])
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
client,
|
|
456
|
+
isConnected: !!activeAddress,
|
|
457
|
+
address: activeAddress,
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Usage
|
|
463
|
+
|
|
464
|
+
```tsx
|
|
465
|
+
import { useContract } from './useContract'
|
|
466
|
+
|
|
467
|
+
function MyComponent() {
|
|
468
|
+
const { client, isConnected } = useContract()
|
|
469
|
+
|
|
470
|
+
const callMethod = async () => {
|
|
471
|
+
if (!client) return
|
|
472
|
+
const result = await client.send.myMethod({ args: { value: 42n } })
|
|
473
|
+
console.log(result.return)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (!isConnected) return <p>Connect wallet first</p>
|
|
477
|
+
|
|
478
|
+
return <button onClick={callMethod}>Call Method</button>
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Project Structure
|
|
485
|
+
|
|
486
|
+
Recommended file organization:
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
src/
|
|
490
|
+
├── App.tsx # Root with WalletProvider
|
|
491
|
+
├── components/
|
|
492
|
+
│ ├── WalletConnect.tsx # Wallet connection UI
|
|
493
|
+
│ ├── AccountSelector.tsx # Multi-account selection
|
|
494
|
+
│ └── ContractInteraction.tsx
|
|
495
|
+
├── contracts/
|
|
496
|
+
│ └── MyContractClient.ts # Generated typed client
|
|
497
|
+
├── hooks/
|
|
498
|
+
│ └── useContract.ts # Custom contract hook
|
|
499
|
+
└── config/
|
|
500
|
+
└── wallet.ts # WalletManager configuration
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### config/wallet.ts
|
|
504
|
+
|
|
505
|
+
```tsx
|
|
506
|
+
import { NetworkId, WalletId, WalletManager } from '@txnlab/use-wallet-react'
|
|
507
|
+
|
|
508
|
+
export const walletManager = new WalletManager({
|
|
509
|
+
wallets: [WalletId.PERA, WalletId.DEFLY, WalletId.EXODUS],
|
|
510
|
+
defaultNetwork: NetworkId.TESTNET,
|
|
511
|
+
})
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
Then in App.tsx:
|
|
515
|
+
|
|
516
|
+
```tsx
|
|
517
|
+
import { WalletProvider } from '@txnlab/use-wallet-react'
|
|
518
|
+
import { walletManager } from './config/wallet'
|
|
519
|
+
|
|
520
|
+
export default function App() {
|
|
521
|
+
return (
|
|
522
|
+
<WalletProvider manager={walletManager}>
|
|
523
|
+
<YourApp />
|
|
524
|
+
</WalletProvider>
|
|
525
|
+
)
|
|
526
|
+
}
|
|
527
|
+
```
|