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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GoPlausible
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# OpenClaw Algorand Plugin
|
|
2
|
+
|
|
3
|
+
🔷 Algorand blockchain integration for [OpenClaw](https://openclaw.ai) — by [GoPlausible](https://goplausible.com)
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Local MCP Server**: Bundled `algorand-mcp` (99 tools) — wallet, transactions, smart contracts, TEAL, indexer, DEX, NFD, knowledge base
|
|
8
|
+
- **x402 Payment Protocol**: Built-in `x402_fetch` tool for HTTP-native payments on Algorand
|
|
9
|
+
- **Interactive Setup**: Guided wizard for configuration
|
|
10
|
+
- **Skills Included** (6 skills):
|
|
11
|
+
- `algorand-development` — AlgoKit CLI, project creation, general workflows
|
|
12
|
+
- `algorand-typescript` — TypeScript smart contracts (PuyaTs)
|
|
13
|
+
- `algorand-python` — Python smart contracts (PuyaPy)
|
|
14
|
+
- `algorand-interaction` — Blockchain interaction via MCP (wallet, transactions, swaps, NFD)
|
|
15
|
+
- `algorand-x402-typescript` — x402 payments in TypeScript
|
|
16
|
+
- `algorand-x402-python` — x402 payments in Python
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
openclaw plugins install openclaw-algorand-plugin
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or install from local path:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
openclaw plugins install ./path/to/openclaw-algorand-plugin
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Post-Installation Setup
|
|
31
|
+
|
|
32
|
+
After installing, run these commands:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# 1. Initialize plugin (write memory file + configure mcporter)
|
|
36
|
+
openclaw algorand-plugin init
|
|
37
|
+
|
|
38
|
+
# 2. Run interactive setup (configure x402 toggle)
|
|
39
|
+
openclaw algorand-plugin setup
|
|
40
|
+
|
|
41
|
+
# 3. Restart the gateway
|
|
42
|
+
openclaw gateway restart
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
openclaw algorand-plugin init # Write plugin memory + configure mcporter
|
|
49
|
+
openclaw algorand-plugin setup # Run interactive setup wizard
|
|
50
|
+
openclaw algorand-plugin status # Show plugin status (binary, mcporter, config)
|
|
51
|
+
openclaw algorand-plugin mcp-config # Show MCP config snippet for external coding agents
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## MCP Server
|
|
55
|
+
|
|
56
|
+
The plugin bundles [`algorand-mcp`](https://www.npmjs.com/package/algorand-mcp) as an npm dependency. It runs locally via stdio through [mcporter](https://www.npmjs.com/package/mcporter).
|
|
57
|
+
|
|
58
|
+
- **99 tools** across 11 categories (wallet, transactions, algod, indexer, NFD, Tinyman, TEAL, knowledge base, and more)
|
|
59
|
+
- **Multi-network**: `mainnet`, `testnet`, `localnet`
|
|
60
|
+
- **Secure wallet**: Per-transaction and daily spending limits, private keys never exposed to agents
|
|
61
|
+
|
|
62
|
+
## x402 Payment Protocol
|
|
63
|
+
|
|
64
|
+
When `enableX402` is enabled (default), the plugin registers the `x402_fetch` tool — an HTTP fetch with [x402](https://github.com/coinbase/x402) payment protocol support.
|
|
65
|
+
|
|
66
|
+
- Fetches URLs normally; on HTTP 402, returns structured `PaymentRequirements` with step-by-step instructions
|
|
67
|
+
- Agent builds payment using algorand-mcp wallet tools (atomic group with facilitator-sponsored fees)
|
|
68
|
+
- Agent retries with signed `PAYMENT-SIGNATURE` header to complete the payment and access the resource
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
Config is stored in `~/.openclaw/openclaw.json` under `plugins.entries.openclaw-algorand-plugin.config`:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"plugins": {
|
|
77
|
+
"allow": ["openclaw-algorand-plugin"],
|
|
78
|
+
"entries": {
|
|
79
|
+
"openclaw-algorand-plugin": {
|
|
80
|
+
"config": {
|
|
81
|
+
"enableX402": true
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Skills Overview
|
|
90
|
+
|
|
91
|
+
| Skill | Purpose |
|
|
92
|
+
|-------|---------|
|
|
93
|
+
| `algorand-development` | AlgoKit CLI, project creation, general workflows |
|
|
94
|
+
| `algorand-typescript` | TypeScript smart contracts (PuyaTs) |
|
|
95
|
+
| `algorand-python` | Python smart contracts (PuyaPy) |
|
|
96
|
+
| `algorand-interaction` | MCP-based blockchain interaction (wallet, txns, DEX, NFD, x402) |
|
|
97
|
+
| `algorand-x402-typescript` | x402 payments in TypeScript |
|
|
98
|
+
| `algorand-x402-python` | x402 payments in Python |
|
|
99
|
+
|
|
100
|
+
## Links
|
|
101
|
+
|
|
102
|
+
- **GoPlausible**: https://goplausible.com
|
|
103
|
+
- **Algorand**: https://algorand.co
|
|
104
|
+
- **Algorand Developer Docs**: https://dev.algorand.co/
|
|
105
|
+
- **Algorand x402**: https://x402.goplausible.xyz
|
|
106
|
+
- **Algorand x402 test endpoints**: https://example.x402.goplausible.xyz/
|
|
107
|
+
- **Algorand x402 Facilitator**: https://facilitator.goplausible.xyz
|
|
108
|
+
- **OpenClaw**: https://openclaw.ai
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT © [GoPlausible](https://goplausible.com)
|
package/index.ts
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { ALGORAND_MCP, GOPLAUSIBLE_SERVICES } from "./lib/mcp-servers.js";
|
|
2
|
+
import { runSetup, type AlgorandPluginConfig } from "./setup.js";
|
|
3
|
+
import { x402Fetch } from "./lib/x402-fetch.js";
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { execSync } from "node:child_process";
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const PLUGIN_ID = "openclaw-algorand-plugin";
|
|
11
|
+
|
|
12
|
+
interface PluginApi {
|
|
13
|
+
config: {
|
|
14
|
+
plugins?: {
|
|
15
|
+
entries?: {
|
|
16
|
+
"openclaw-algorand-plugin"?: {
|
|
17
|
+
config?: Partial<AlgorandPluginConfig>;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
agents?: {
|
|
22
|
+
defaults?: {
|
|
23
|
+
workspace?: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
logger: {
|
|
28
|
+
info: (msg: string) => void;
|
|
29
|
+
warn: (msg: string) => void;
|
|
30
|
+
error: (msg: string) => void;
|
|
31
|
+
};
|
|
32
|
+
runtime: {
|
|
33
|
+
openUrl: (url: string) => Promise<void>;
|
|
34
|
+
};
|
|
35
|
+
registerTool: (tool: object, options?: object) => void;
|
|
36
|
+
registerCli: (fn: (ctx: { program: any }) => void, options: { commands: string[] }) => void;
|
|
37
|
+
registerHook: (event: string, handler: () => Promise<void>, meta: object) => void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getWorkspacePath(api: PluginApi): string {
|
|
41
|
+
return api.config.agents?.defaults?.workspace ||
|
|
42
|
+
join(process.env.HOME || "~", ".openclaw", "workspace");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getConfigPath(): string {
|
|
46
|
+
return join(process.env.HOME || "~", ".openclaw", "openclaw.json");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getMcpBinaryPath(): string {
|
|
50
|
+
// Check plugin's node_modules first
|
|
51
|
+
const pluginBin = join(__dirname, "node_modules", ".bin", "algorand-mcp");
|
|
52
|
+
if (existsSync(pluginBin)) {
|
|
53
|
+
return pluginBin;
|
|
54
|
+
}
|
|
55
|
+
// Fall back to npx
|
|
56
|
+
return "npx algorand-mcp";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function updatePluginConfig(newConfig: AlgorandPluginConfig): { success: boolean; error?: string } {
|
|
60
|
+
try {
|
|
61
|
+
const configPath = getConfigPath();
|
|
62
|
+
if (!existsSync(configPath)) {
|
|
63
|
+
return { success: false, error: `Config file not found: ${configPath}` };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const rawConfig = readFileSync(configPath, "utf-8");
|
|
67
|
+
const config = JSON.parse(rawConfig);
|
|
68
|
+
|
|
69
|
+
// Ensure plugins structure exists
|
|
70
|
+
if (!config.plugins) config.plugins = {};
|
|
71
|
+
if (!config.plugins.entries) config.plugins.entries = {};
|
|
72
|
+
if (!config.plugins.entries[PLUGIN_ID]) {
|
|
73
|
+
config.plugins.entries[PLUGIN_ID] = {};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Update the plugin config
|
|
77
|
+
config.plugins.entries[PLUGIN_ID].config = newConfig;
|
|
78
|
+
|
|
79
|
+
// Add to plugins.allow if not already there
|
|
80
|
+
if (!config.plugins.allow) config.plugins.allow = [];
|
|
81
|
+
if (!config.plugins.allow.includes(PLUGIN_ID)) {
|
|
82
|
+
config.plugins.allow.push(PLUGIN_ID);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Write back with pretty formatting
|
|
86
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
87
|
+
|
|
88
|
+
return { success: true };
|
|
89
|
+
} catch (err) {
|
|
90
|
+
return { success: false, error: String(err) };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function configureMcporter(): { success: boolean; message: string } {
|
|
95
|
+
const mcpCommand = getMcpBinaryPath();
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
// Check if mcporter is available
|
|
99
|
+
execSync("which mcporter", { encoding: "utf-8" });
|
|
100
|
+
} catch {
|
|
101
|
+
return { success: false, message: "mcporter not installed. Install with: npm install -g mcporter" };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// Check if algorand server already configured
|
|
106
|
+
const listOutput = execSync("mcporter config list 2>/dev/null || echo ''", { encoding: "utf-8" });
|
|
107
|
+
if (listOutput.includes("algorand-mcp")) {
|
|
108
|
+
return { success: true, message: "algorand-mcp server already configured in mcporter" };
|
|
109
|
+
}
|
|
110
|
+
} catch {
|
|
111
|
+
// Continue to add
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
// Add algorand server to mcporter config (home scope for global access)
|
|
116
|
+
const cmd = `mcporter config add algorand-mcp --command "${mcpCommand}" --scope home --description "Algorand blockchain MCP (GoPlausible)"`;
|
|
117
|
+
execSync(cmd, { encoding: "utf-8" });
|
|
118
|
+
return { success: true, message: `algorand server added to mcporter (command: ${mcpCommand})` };
|
|
119
|
+
} catch (err) {
|
|
120
|
+
return { success: false, message: `Failed to configure mcporter: ${err}` };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function writeMemoryFile(workspacePath: string): { success: boolean; message: string } {
|
|
125
|
+
const sourceFile = join(__dirname, "memory", "algorand-plugin.md");
|
|
126
|
+
const memoryDir = join(workspacePath, "memory");
|
|
127
|
+
const targetFile = join(memoryDir, "algorand-plugin.md");
|
|
128
|
+
|
|
129
|
+
if (!existsSync(sourceFile)) {
|
|
130
|
+
return { success: false, message: `Source memory/algorand-plugin.md not found at ${sourceFile}` };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!existsSync(memoryDir)) {
|
|
134
|
+
mkdirSync(memoryDir, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const content = readFileSync(sourceFile, "utf-8");
|
|
138
|
+
writeFileSync(targetFile, content);
|
|
139
|
+
|
|
140
|
+
return { success: true, message: `Plugin memory written to ${targetFile}` };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function checkMcpBinary(): { available: boolean; path?: string } {
|
|
144
|
+
try {
|
|
145
|
+
const path = execSync("which algorand-mcp", { encoding: "utf-8" }).trim();
|
|
146
|
+
return { available: true, path };
|
|
147
|
+
} catch {
|
|
148
|
+
// Check plugin's node_modules
|
|
149
|
+
const pluginBin = join(__dirname, "node_modules", ".bin", "algorand-mcp");
|
|
150
|
+
if (existsSync(pluginBin)) {
|
|
151
|
+
return { available: true, path: pluginBin };
|
|
152
|
+
}
|
|
153
|
+
return { available: false };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default function register(api: PluginApi) {
|
|
158
|
+
const pluginConfig = api.config.plugins?.entries?.[PLUGIN_ID]?.config ?? {};
|
|
159
|
+
|
|
160
|
+
// ─────────────────────────────────────────────────────────────
|
|
161
|
+
// x402 Fetch Tool
|
|
162
|
+
// ─────────────────────────────────────────────────────────────
|
|
163
|
+
if (pluginConfig.enableX402 !== false) {
|
|
164
|
+
api.registerTool(
|
|
165
|
+
{
|
|
166
|
+
name: "x402_fetch",
|
|
167
|
+
description:
|
|
168
|
+
"Fetch a URL with x402 payment protocol support. On HTTP 402, returns structured PaymentRequirements and step-by-step instructions to build payment using algorand-mcp tools. Use paymentHeader to retry with a signed payment.",
|
|
169
|
+
parameters: {
|
|
170
|
+
type: "object",
|
|
171
|
+
properties: {
|
|
172
|
+
url: {
|
|
173
|
+
type: "string",
|
|
174
|
+
description: "The URL to fetch",
|
|
175
|
+
},
|
|
176
|
+
method: {
|
|
177
|
+
type: "string",
|
|
178
|
+
description: "HTTP method (default: GET)",
|
|
179
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
180
|
+
default: "GET",
|
|
181
|
+
},
|
|
182
|
+
headers: {
|
|
183
|
+
type: "object",
|
|
184
|
+
description: "Additional request headers as key-value pairs",
|
|
185
|
+
additionalProperties: { type: "string" },
|
|
186
|
+
},
|
|
187
|
+
body: {
|
|
188
|
+
type: "string",
|
|
189
|
+
description: "Request body (for POST/PUT/PATCH)",
|
|
190
|
+
},
|
|
191
|
+
paymentHeader: {
|
|
192
|
+
type: "string",
|
|
193
|
+
description:
|
|
194
|
+
"JSON string for X-PAYMENT header — the signed payment payload from the x402 payment flow",
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
required: ["url"],
|
|
198
|
+
},
|
|
199
|
+
async execute(_id: string, params: {
|
|
200
|
+
url: string;
|
|
201
|
+
method?: string;
|
|
202
|
+
headers?: Record<string, string>;
|
|
203
|
+
body?: string;
|
|
204
|
+
paymentHeader?: string;
|
|
205
|
+
}) {
|
|
206
|
+
const result = await x402Fetch(params);
|
|
207
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{ scope: "agent" },
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ─────────────────────────────────────────────────────────────
|
|
215
|
+
// CLI Commands
|
|
216
|
+
// ─────────────────────────────────────────────────────────────
|
|
217
|
+
api.registerCli(
|
|
218
|
+
({ program }) => {
|
|
219
|
+
const algorand = program
|
|
220
|
+
.command("algorand-plugin")
|
|
221
|
+
.description("Algorand blockchain integration (GoPlausible)");
|
|
222
|
+
|
|
223
|
+
// Init command - writes plugin memory file AND configures mcporter
|
|
224
|
+
algorand
|
|
225
|
+
.command("init")
|
|
226
|
+
.description("Initialize Algorand plugin (memory file + mcporter config)")
|
|
227
|
+
.action(async () => {
|
|
228
|
+
console.log("\n🔷 Initializing Algorand plugin...\n");
|
|
229
|
+
|
|
230
|
+
const workspacePath = getWorkspacePath(api);
|
|
231
|
+
|
|
232
|
+
// Step 1: Write memory file
|
|
233
|
+
const memResult = writeMemoryFile(workspacePath);
|
|
234
|
+
if (memResult.success) {
|
|
235
|
+
console.log(` ✅ ${memResult.message}`);
|
|
236
|
+
} else {
|
|
237
|
+
console.error(` ❌ ${memResult.message}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Step 2: Configure mcporter
|
|
241
|
+
console.log("");
|
|
242
|
+
const mcpResult = configureMcporter();
|
|
243
|
+
if (mcpResult.success) {
|
|
244
|
+
console.log(` ✅ ${mcpResult.message}`);
|
|
245
|
+
} else {
|
|
246
|
+
console.log(` ⚠️ ${mcpResult.message}`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
console.log("\n Run `openclaw algorand-plugin setup` to configure options.");
|
|
250
|
+
console.log(" Run `mcporter list algorand-mcp --schema` to verify MCP tools.\n");
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Setup wizard
|
|
254
|
+
algorand
|
|
255
|
+
.command("setup")
|
|
256
|
+
.description("Run interactive Algorand plugin setup")
|
|
257
|
+
.action(async () => {
|
|
258
|
+
const newConfig = await runSetup(pluginConfig);
|
|
259
|
+
if (newConfig) {
|
|
260
|
+
const result = updatePluginConfig(newConfig);
|
|
261
|
+
if (result.success) {
|
|
262
|
+
console.log("\n✅ Config saved to ~/.openclaw/openclaw.json");
|
|
263
|
+
console.log(" Plugin added to plugins.allow list.");
|
|
264
|
+
console.log(" Restart gateway to apply changes: openclaw gateway restart\n");
|
|
265
|
+
} else {
|
|
266
|
+
console.error(`\n❌ Failed to save config: ${result.error}`);
|
|
267
|
+
console.log(" You can manually add to ~/.openclaw/openclaw.json:");
|
|
268
|
+
console.log(` "plugins": { "allow": ["${PLUGIN_ID}"], "entries": { "${PLUGIN_ID}": { "config": ${JSON.stringify(newConfig)} } } }\n`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Status command
|
|
274
|
+
algorand
|
|
275
|
+
.command("status")
|
|
276
|
+
.description("Show Algorand plugin status")
|
|
277
|
+
.action(() => {
|
|
278
|
+
const mcp = checkMcpBinary();
|
|
279
|
+
|
|
280
|
+
// Check mcporter config
|
|
281
|
+
let mcporterConfigured = false;
|
|
282
|
+
try {
|
|
283
|
+
const list = execSync("mcporter config list 2>/dev/null || echo ''", { encoding: "utf-8" });
|
|
284
|
+
mcporterConfigured = list.includes("algorand-mcp");
|
|
285
|
+
} catch { }
|
|
286
|
+
|
|
287
|
+
console.log("\n🔷 Algorand Plugin Status\n");
|
|
288
|
+
console.log(" Skills:");
|
|
289
|
+
console.log(" • algorand-development");
|
|
290
|
+
console.log(" • algorand-typescript");
|
|
291
|
+
console.log(" • algorand-python");
|
|
292
|
+
console.log(" • algorand-interaction");
|
|
293
|
+
console.log(" • algorand-x402-typescript");
|
|
294
|
+
console.log(" • algorand-x402-python");
|
|
295
|
+
console.log("");
|
|
296
|
+
console.log(" MCP Server:");
|
|
297
|
+
console.log(` Binary: ${mcp.available ? `✅ ${mcp.path}` : "⚠️ Not found"}`);
|
|
298
|
+
console.log(` mcporter: ${mcporterConfigured ? "✅ Configured" : "⚠️ Not configured (run init)"}`);
|
|
299
|
+
console.log("");
|
|
300
|
+
console.log(" Config:");
|
|
301
|
+
console.log(` x402: ${pluginConfig.enableX402 !== false ? "Enabled" : "Disabled"}`);
|
|
302
|
+
console.log("");
|
|
303
|
+
console.log(" Links:");
|
|
304
|
+
console.log(` GoPlausible: ${GOPLAUSIBLE_SERVICES.website}`);
|
|
305
|
+
console.log(` Algorand x402: ${GOPLAUSIBLE_SERVICES.x402}`);
|
|
306
|
+
console.log(` Algorand x402 Facilitator: ${GOPLAUSIBLE_SERVICES.facilitator}`);
|
|
307
|
+
console.log(` Algorand x402 Test endpoints: ${GOPLAUSIBLE_SERVICES.test}`);
|
|
308
|
+
console.log("");
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// MCP config helper (for external coding agents)
|
|
312
|
+
algorand
|
|
313
|
+
.command("mcp-config")
|
|
314
|
+
.description("Show MCP config snippet for coding agents (Claude Code, Cursor, etc.)")
|
|
315
|
+
.action(() => {
|
|
316
|
+
const mcp = checkMcpBinary();
|
|
317
|
+
const command = mcp.path || "npx algorand-mcp";
|
|
318
|
+
|
|
319
|
+
console.log("\n🔷 Algorand MCP Configuration\n");
|
|
320
|
+
console.log(" For external coding agents, add this to their MCP config:\n");
|
|
321
|
+
console.log(" Claude Code (.mcp.json):");
|
|
322
|
+
console.log(" ─────────────────────────");
|
|
323
|
+
console.log(` {`);
|
|
324
|
+
console.log(` "mcpServers": {`);
|
|
325
|
+
console.log(` "algorand": {`);
|
|
326
|
+
console.log(` "command": "${command}",`);
|
|
327
|
+
console.log(` "args": []`);
|
|
328
|
+
console.log(` }`);
|
|
329
|
+
console.log(` }`);
|
|
330
|
+
console.log(` }\n`);
|
|
331
|
+
console.log(" Cursor (.cursor/mcp.json) — same format\n");
|
|
332
|
+
console.log(" Note: OpenClaw uses mcporter. Run `openclaw algorand-plugin init` to configure.\n");
|
|
333
|
+
});
|
|
334
|
+
},
|
|
335
|
+
{ commands: ["algorand-plugin"] }
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
// ─────────────────────────────────────────────────────────────
|
|
339
|
+
// Post-install hook
|
|
340
|
+
// ─────────────────────────────────────────────────────────────
|
|
341
|
+
api.registerHook(
|
|
342
|
+
"plugin:post-install",
|
|
343
|
+
async () => {
|
|
344
|
+
console.log("\n🔷 Algorand plugin installed!\n");
|
|
345
|
+
console.log(" This plugin provides:");
|
|
346
|
+
console.log(" • 6 Algorand development skills (smart contracts, x402, MCP interaction)");
|
|
347
|
+
console.log(" • algorand-mcp server (99 blockchain tools via mcporter)\n");
|
|
348
|
+
console.log(" Next steps:");
|
|
349
|
+
console.log(" 1. Run `openclaw algorand-plugin init` — configure mcporter + add plugin memory");
|
|
350
|
+
console.log(" 2. Run `openclaw algorand-plugin setup` — configure options & add to allow list");
|
|
351
|
+
console.log(" 3. Restart OpenClaw gateway\n");
|
|
352
|
+
console.log(` Docs: ${GOPLAUSIBLE_SERVICES.website}\n`);
|
|
353
|
+
},
|
|
354
|
+
{ name: "algorand.post-install", description: "Show setup instructions on install" }
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
api.logger.info(`Algorand plugin registered (skills: 6, MCP: ${ALGORAND_MCP.name})`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export const id = PLUGIN_ID;
|
|
361
|
+
export const name = "Algorand Integration";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const ALGORAND_MCP = {
|
|
2
|
+
id: "algorand-mcp",
|
|
3
|
+
name: "Algorand MCP",
|
|
4
|
+
description: "Local Algorand MCP server — 99 tools for blockchain interaction",
|
|
5
|
+
type: "stdio" as const,
|
|
6
|
+
command: "algorand-mcp",
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export const GOPLAUSIBLE_SERVICES = {
|
|
10
|
+
website: "https://goplausible.com",
|
|
11
|
+
x402: "https://x402.goplausible.xyz",
|
|
12
|
+
facilitator: "https://facilitator.goplausible.xyz",
|
|
13
|
+
test: "https://example.x402.goplausible.xyz/",
|
|
14
|
+
} as const;
|