openclaw-arcade-plugin 0.1.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/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # OpenClaw Arcade Plugin
2
+
3
+ A programmatic OpenClaw plugin that enables transaction broadcasting and full lifecycle tracking using the **BSV Arcade** infrastructure.
4
+
5
+ ## Key Features
6
+ - **Broadcasting**: Submit raw transaction hex directly to the network via Teranode-optimized API.
7
+ - **Lifecycle Tracking**: Monitor transactions through states like `RECEIVED`, `SEEN`, and `MINED`.
8
+ - **Merkle Proofs**: Retrieve cryptographically valid proofs for mined transactions.
9
+ - **Sovereignty**: Configure your own local Arcade instance for maximum reliability.
10
+
11
+ ## AI Tool: `arcade`
12
+ Agents can use the `arcade` tool to:
13
+ - `broadcast`: Send signed transactions to the BSV blockchain.
14
+ - `status`: Check if a transaction has been mined or rejected.
15
+ - `proof`: Get binary proofs for SPV validation.
16
+
17
+ ## Architecture
18
+ Built with the **OpenClaw Plugin SDK**, this extension interfaces with the Arcade REST API to provide agents with a reliable "mouth" for the blockchain.
19
+
20
+ ## License
21
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: arcade
3
+ description: >
4
+ Submit and track BSV transactions. Use for broadcasting raw transaction hex,
5
+ checking the status of a payment (SEEN, MINED), or retrieving Merkle proofs.
6
+ metadata: '{"openclaw": {"requires": {"bins": ["node"]}}}'
7
+ ---
8
+
9
+ ## Tool Actions
10
+
11
+ | Action | Description |
12
+ |--------|-------------|
13
+ | `broadcast` | Submit a raw transaction hex to the network |
14
+ | `status` | Check the current state of a transaction ID (RECEIVED, SEEN, MINED) |
15
+ | `proof` | Retrieve the Merkle proof for a mined transaction |
16
+ | `config` | Show current broadcaster URL and network |
17
+
18
+ ## Usage Guidance
19
+
20
+ ### Broadcasting Payments
21
+ When you have built and signed a transaction (e.g., using `simplesv` or `overlay`), use `arcade` to send it to the network.
22
+
23
+ ```javascript
24
+ arcade({
25
+ action: "broadcast",
26
+ txhex: "01000000..."
27
+ })
28
+ ```
29
+
30
+ ### Tracking Confirmation
31
+ If a task requires proof of payment, use `status` to monitor the transaction until it reaches the `MINED` state.
32
+
33
+ ```javascript
34
+ arcade({
35
+ action: "status",
36
+ txid: "a1b2c3d4..."
37
+ })
38
+ ```
39
+
40
+ ### Generating Proofs
41
+ Use `proof` to get the binary Merkle proof needed for BEEF construction or SPV validation.
42
+
43
+ ## Etiquette
44
+ Broadcasting is the final step of any on-chain operation. Only broadcast once you are certain the transaction is complete and signed.
@@ -0,0 +1,6 @@
1
+ /**
2
+ * OpenClaw Arcade Plugin
3
+ * Transaction broadcasting and lifecycle tracking via BSV Arcade.
4
+ */
5
+ export default function register(api: any): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QAmFxC"}
package/dist/index.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * OpenClaw Arcade Plugin
3
+ * Transaction broadcasting and lifecycle tracking via BSV Arcade.
4
+ */
5
+ export default function register(api) {
6
+ const entries = api.getConfig?.()?.plugins?.entries || {};
7
+ const entry = entries['openclaw-arcade']
8
+ || entries['openclaw-arcade-plugin']
9
+ || entries['bsv-arcade']
10
+ || {};
11
+ const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
12
+ const arcadeUrl = (pluginConfig.arcadeUrl || 'https://arcade.bsv.direct').replace(/\/$/, '');
13
+ const network = pluginConfig.network || 'mainnet';
14
+ api.logger.info(`[arcade] Initializing Arcade Plugin (network: ${network}, host: ${arcadeUrl})`);
15
+ // Register the arcade tool
16
+ api.registerTool({
17
+ name: "arcade",
18
+ description: "Submit and track BSV transactions with full lifecycle visibility",
19
+ parameters: {
20
+ type: "object",
21
+ properties: {
22
+ action: {
23
+ type: "string",
24
+ enum: ["broadcast", "status", "proof", "config"],
25
+ description: "Action to perform"
26
+ },
27
+ txhex: {
28
+ type: "string",
29
+ description: "Hex-encoded raw transaction to broadcast"
30
+ },
31
+ txid: {
32
+ type: "string",
33
+ description: "Transaction ID to track or fetch proof for"
34
+ }
35
+ },
36
+ required: ["action"]
37
+ },
38
+ async execute(_id, params) {
39
+ try {
40
+ const { action, txhex, txid } = params;
41
+ switch (action) {
42
+ case "broadcast":
43
+ if (!txhex)
44
+ throw new Error("txhex is required for broadcast");
45
+ const bResp = await fetch(`${arcadeUrl}/v1/tx`, {
46
+ method: 'POST',
47
+ headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify({ rawTx: txhex })
49
+ });
50
+ const bData = await bResp.json();
51
+ if (!bResp.ok)
52
+ throw new Error(`Broadcast failed: ${JSON.stringify(bData)}`);
53
+ return { content: [{ type: "text", text: `Transaction broadcasted! TXID: ${bData.txid}\nStatus: ${bData.txStatus}` }] };
54
+ case "status":
55
+ if (!txid)
56
+ throw new Error("txid is required for status check");
57
+ const sResp = await fetch(`${arcadeUrl}/v1/tx/${txid}`);
58
+ const sData = await sResp.json();
59
+ if (!sResp.ok)
60
+ throw new Error(`Status check failed: ${JSON.stringify(sData)}`);
61
+ return { content: [{ type: "text", text: `Transaction ${txid}:\nStatus: ${sData.txStatus}\nBlock: ${sData.blockHeight || 'Pending'}` }] };
62
+ case "proof":
63
+ if (!txid)
64
+ throw new Error("txid is required for proof retrieval");
65
+ const pResp = await fetch(`${arcadeUrl}/v1/tx/${txid}/proof`);
66
+ if (!pResp.ok)
67
+ throw new Error(`Proof retrieval failed: ${pResp.status}`);
68
+ const pData = await pResp.arrayBuffer();
69
+ const base64Proof = Buffer.from(pData).toString('base64');
70
+ return { content: [{ type: "text", text: `Merkle Proof (Base64): ${base64Proof}` }] };
71
+ case "config":
72
+ return { content: [{ type: "text", text: `Arcade Configuration:\nURL: ${arcadeUrl}\nNetwork: ${network}` }] };
73
+ default:
74
+ throw new Error(`Unknown action: ${action}`);
75
+ }
76
+ }
77
+ catch (error) {
78
+ return {
79
+ content: [{
80
+ type: "text",
81
+ text: `Error: ${error.message || String(error)}`
82
+ }]
83
+ };
84
+ }
85
+ }
86
+ });
87
+ }
88
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/index.ts ADDED
@@ -0,0 +1,91 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+
4
+ /**
5
+ * OpenClaw Arcade Plugin
6
+ * Transaction broadcasting and lifecycle tracking via BSV Arcade.
7
+ */
8
+ export default function register(api: any) {
9
+ const entries = api.getConfig?.()?.plugins?.entries || {};
10
+ const entry = entries['openclaw-arcade']
11
+ || entries['openclaw-arcade-plugin']
12
+ || entries['bsv-arcade']
13
+ || {};
14
+
15
+ const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
16
+ const arcadeUrl = (pluginConfig.arcadeUrl || 'https://arcade.bsv.direct').replace(/\/$/, '');
17
+ const network = pluginConfig.network || 'mainnet';
18
+
19
+ api.logger.info(`[arcade] Initializing Arcade Plugin (network: ${network}, host: ${arcadeUrl})`);
20
+
21
+ // Register the arcade tool
22
+ api.registerTool({
23
+ name: "arcade",
24
+ description: "Submit and track BSV transactions with full lifecycle visibility",
25
+ parameters: {
26
+ type: "object",
27
+ properties: {
28
+ action: {
29
+ type: "string",
30
+ enum: ["broadcast", "status", "proof", "config"],
31
+ description: "Action to perform"
32
+ },
33
+ txhex: {
34
+ type: "string",
35
+ description: "Hex-encoded raw transaction to broadcast"
36
+ },
37
+ txid: {
38
+ type: "string",
39
+ description: "Transaction ID to track or fetch proof for"
40
+ }
41
+ },
42
+ required: ["action"]
43
+ },
44
+ async execute(_id: string, params: any) {
45
+ try {
46
+ const { action, txhex, txid } = params;
47
+
48
+ switch (action) {
49
+ case "broadcast":
50
+ if (!txhex) throw new Error("txhex is required for broadcast");
51
+ const bResp = await fetch(`${arcadeUrl}/v1/tx`, {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/json' },
54
+ body: JSON.stringify({ rawTx: txhex })
55
+ });
56
+ const bData: any = await bResp.json();
57
+ if (!bResp.ok) throw new Error(`Broadcast failed: ${JSON.stringify(bData)}`);
58
+ return { content: [{ type: "text", text: `Transaction broadcasted! TXID: ${bData.txid}\nStatus: ${bData.txStatus}` }] };
59
+
60
+ case "status":
61
+ if (!txid) throw new Error("txid is required for status check");
62
+ const sResp = await fetch(`${arcadeUrl}/v1/tx/${txid}`);
63
+ const sData: any = await sResp.json();
64
+ if (!sResp.ok) throw new Error(`Status check failed: ${JSON.stringify(sData)}`);
65
+ return { content: [{ type: "text", text: `Transaction ${txid}:\nStatus: ${sData.txStatus}\nBlock: ${sData.blockHeight || 'Pending'}` }] };
66
+
67
+ case "proof":
68
+ if (!txid) throw new Error("txid is required for proof retrieval");
69
+ const pResp = await fetch(`${arcadeUrl}/v1/tx/${txid}/proof`);
70
+ if (!pResp.ok) throw new Error(`Proof retrieval failed: ${pResp.status}`);
71
+ const pData = await pResp.arrayBuffer();
72
+ const base64Proof = Buffer.from(pData).toString('base64');
73
+ return { content: [{ type: "text", text: `Merkle Proof (Base64): ${base64Proof}` }] };
74
+
75
+ case "config":
76
+ return { content: [{ type: "text", text: `Arcade Configuration:\nURL: ${arcadeUrl}\nNetwork: ${network}` }] };
77
+
78
+ default:
79
+ throw new Error(`Unknown action: ${action}`);
80
+ }
81
+ } catch (error: any) {
82
+ return {
83
+ content: [{
84
+ type: "text",
85
+ text: `Error: ${error.message || String(error)}`
86
+ }]
87
+ };
88
+ }
89
+ }
90
+ });
91
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "id": "openclaw-arcade",
3
+ "name": "BSV Arcade Broadcaster",
4
+ "description": "Submit and track BSV transactions with full lifecycle visibility",
5
+ "version": "0.1.0",
6
+ "skills": [
7
+ "./SKILL.md"
8
+ ],
9
+ "configSchema": {
10
+ "type": "object",
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "arcadeUrl": {
14
+ "type": "string",
15
+ "default": "https://arcade.bsv.direct",
16
+ "description": "Arcade server URL"
17
+ },
18
+ "network": {
19
+ "type": "string",
20
+ "enum": ["mainnet", "testnet"],
21
+ "default": "mainnet"
22
+ }
23
+ }
24
+ },
25
+ "uiHints": {
26
+ "arcadeUrl": {
27
+ "label": "Arcade Server URL",
28
+ "placeholder": "https://arcade.bsv.direct"
29
+ }
30
+ }
31
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "openclaw-arcade-plugin",
3
+ "version": "0.1.0",
4
+ "description": "OpenClaw plugin for transaction broadcasting and lifecycle tracking via BSV Arcade",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "files": [
8
+ "index.ts",
9
+ "openclaw.plugin.json",
10
+ "src/",
11
+ "dist/",
12
+ "SKILL.md",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "prepublishOnly": "npm run build",
18
+ "lint": "eslint src/**/*.ts",
19
+ "test": "npx tsx src/**/*.test.ts"
20
+ },
21
+ "dependencies": {
22
+ "@bsv/sdk": "^2.0.13"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^22.10.0",
26
+ "typescript": "^6.0.2",
27
+ "eslint": "^10.1.0"
28
+ },
29
+ "openclaw": {
30
+ "extensions": [
31
+ "./index.ts"
32
+ ]
33
+ },
34
+ "keywords": [
35
+ "openclaw",
36
+ "plugin",
37
+ "bsv",
38
+ "arcade",
39
+ "broadcast",
40
+ "transaction",
41
+ "tracking"
42
+ ],
43
+ "author": "Tomás Díaz",
44
+ "license": "MIT"
45
+ }