openclaw-arcade-plugin 0.1.1 → 0.1.3
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/src/arcade.test.d.ts +8 -0
- package/dist/src/arcade.test.d.ts.map +1 -0
- package/dist/src/arcade.test.js +82 -0
- package/dist/src/arcade.test.js.map +1 -0
- package/index.ts +51 -1
- package/openclaw.plugin.json +18 -3
- package/package.json +8 -4
- package/src/arcade.test.ts +92 -0
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,GAAG,iBAEtC;AAID,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,GAAG,QA+HxC"}
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,25 @@
|
|
|
2
2
|
* OpenClaw Arcade Plugin
|
|
3
3
|
* Transaction broadcasting and lifecycle tracking via BSV Arcade.
|
|
4
4
|
*/
|
|
5
|
+
export async function activate(api) {
|
|
6
|
+
return register(api);
|
|
7
|
+
}
|
|
8
|
+
let isInitialized = false;
|
|
5
9
|
export default function register(api) {
|
|
10
|
+
if (isInitialized)
|
|
11
|
+
return;
|
|
12
|
+
isInitialized = true;
|
|
6
13
|
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
7
14
|
const entry = entries['openclaw-arcade']
|
|
8
15
|
|| entries['openclaw-arcade-plugin']
|
|
9
16
|
|| entries['bsv-arcade']
|
|
10
17
|
|| {};
|
|
11
18
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
12
|
-
const arcadeUrl = (pluginConfig.arcadeUrl || 'https://arcade.bsv.direct').replace(/\/$/, '');
|
|
13
19
|
const network = pluginConfig.network || 'mainnet';
|
|
20
|
+
const defaultArcadeUrl = network === 'testnet'
|
|
21
|
+
? 'https://testnet.arc.gorillapool.io'
|
|
22
|
+
: 'https://arc.gorillapool.io';
|
|
23
|
+
const arcadeUrl = (pluginConfig.arcadeUrl || defaultArcadeUrl).replace(/\/$/, '');
|
|
14
24
|
api.logger.info(`[arcade] Initializing Arcade Plugin (network: ${network}, host: ${arcadeUrl})`);
|
|
15
25
|
// Register the arcade tool
|
|
16
26
|
api.registerTool({
|
|
@@ -84,5 +94,41 @@ export default function register(api) {
|
|
|
84
94
|
}
|
|
85
95
|
}
|
|
86
96
|
});
|
|
97
|
+
// Register the /arcade slash command for direct chat interaction (Autoreply)
|
|
98
|
+
api.registerCommand({
|
|
99
|
+
name: "arcade",
|
|
100
|
+
description: "BSV transaction tracking commands",
|
|
101
|
+
acceptsArgs: true,
|
|
102
|
+
requireAuth: true,
|
|
103
|
+
handler: async (ctx) => {
|
|
104
|
+
try {
|
|
105
|
+
const args = ctx.args || [];
|
|
106
|
+
const action = args[0] || 'config';
|
|
107
|
+
const params = { action };
|
|
108
|
+
if (action === 'status' && args[1])
|
|
109
|
+
params.txid = args[1];
|
|
110
|
+
if (action === 'broadcast' && args[1])
|
|
111
|
+
params.txhex = args[1];
|
|
112
|
+
// Custom logic for simplified chat output
|
|
113
|
+
if (action === 'status' && params.txid) {
|
|
114
|
+
const res = await fetch(`${arcadeUrl}/v1/tx/${params.txid}`);
|
|
115
|
+
const data = await res.json();
|
|
116
|
+
return { text: `🛡️ **Transaction Status**\n**TXID**: ${params.txid}\n**Status**: ${data.txStatus || 'Unknown'}` };
|
|
117
|
+
}
|
|
118
|
+
return { text: `Command '${action}' executed.` };
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
return { text: `❌ Arcade Error: ${error.message}` };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
// Register CLI extensions
|
|
126
|
+
api.registerCli(({ program }) => {
|
|
127
|
+
program.command("arcade")
|
|
128
|
+
.description("BSV transaction tracking commands")
|
|
129
|
+
.action(() => {
|
|
130
|
+
console.log("Usage: arcade <action> [args]");
|
|
131
|
+
});
|
|
132
|
+
}, { commands: ["arcade"] });
|
|
87
133
|
}
|
|
88
134
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAQ;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC;WACnC,OAAO,CAAC,wBAAwB,CAAC;WACjC,OAAO,CAAC,YAAY,CAAC;WACrB,EAAE,CAAC;IAER,MAAM,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;IAClF,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAQ;IACrC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAQ;IACvC,IAAI,aAAa;QAAE,OAAO;IAC1B,aAAa,GAAG,IAAI,CAAC;IAErB,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC;WACnC,OAAO,CAAC,wBAAwB,CAAC;WACjC,OAAO,CAAC,YAAY,CAAC;WACrB,EAAE,CAAC;IAER,MAAM,YAAY,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;IAClF,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,IAAI,SAAS,CAAC;IAClD,MAAM,gBAAgB,GAAG,OAAO,KAAK,SAAS;QAC5C,CAAC,CAAC,oCAAoC;QACtC,CAAC,CAAC,4BAA4B,CAAC;IACjC,MAAM,SAAS,GAAG,CAAC,YAAY,CAAC,SAAS,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAElF,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,iDAAiD,OAAO,WAAW,SAAS,GAAG,CAAC,CAAC;IAEjG,2BAA2B;IAC3B,GAAG,CAAC,YAAY,CAAC;QACf,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,kEAAkE;QAC/E,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;oBAChD,WAAW,EAAE,mBAAmB;iBACjC;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,0CAA0C;iBACxD;gBACD,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,4CAA4C;iBAC1D;aACF;YACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;SACrB;QACD,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,MAAW;YACpC,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;gBAEvC,QAAQ,MAAM,EAAE,CAAC;oBACf,KAAK,WAAW;wBACd,IAAI,CAAC,KAAK;4BAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;wBAC/D,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,QAAQ,EAAE;4BAC9C,MAAM,EAAE,MAAM;4BACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;4BAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;yBACvC,CAAC,CAAC;wBACH,MAAM,KAAK,GAAQ,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;wBACtC,IAAI,CAAC,KAAK,CAAC,EAAE;4BAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;wBAC7E,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC;oBAE1H,KAAK,QAAQ;wBACX,IAAI,CAAC,IAAI;4BAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;wBAChE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,UAAU,IAAI,EAAE,CAAC,CAAC;wBACxD,MAAM,KAAK,GAAQ,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;wBACtC,IAAI,CAAC,KAAK,CAAC,EAAE;4BAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;wBAChF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,IAAI,cAAc,KAAK,CAAC,QAAQ,YAAY,KAAK,CAAC,WAAW,IAAI,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC;oBAE5I,KAAK,OAAO;wBACV,IAAI,CAAC,IAAI;4BAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;wBACnE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,UAAU,IAAI,QAAQ,CAAC,CAAC;wBAC9D,IAAI,CAAC,KAAK,CAAC,EAAE;4BAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;wBAC1E,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC;wBACxC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBAC1D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,0BAA0B,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC;oBAExF,KAAK,QAAQ;wBACX,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,SAAS,cAAc,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;oBAEhH;wBACE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,UAAU,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE;yBACjD,CAAC;iBACH,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,6EAA6E;IAC7E,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mCAAmC;QAChD,WAAW,EAAE,IAAI;QACjB,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,KAAK,EAAE,GAAQ,EAAE,EAAE;YAC1B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;gBACnC,MAAM,MAAM,GAAQ,EAAE,MAAM,EAAE,CAAC;gBAE/B,IAAI,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC;oBAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC1D,IAAI,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC;oBAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBAE9D,0CAA0C;gBAC1C,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;oBACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,SAAS,UAAU,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC7D,MAAM,IAAI,GAAQ,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;oBACnC,OAAO,EAAE,IAAI,EAAE,yCAAyC,MAAM,CAAC,IAAI,iBAAiB,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,EAAE,CAAC;gBACrH,CAAC;gBAED,OAAO,EAAE,IAAI,EAAE,YAAY,MAAM,aAAa,EAAE,CAAC;YACnD,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,EAAE,IAAI,EAAE,mBAAmB,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YACtD,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,0BAA0B;IAC1B,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE,OAAO,EAAO,EAAE,EAAE;QACnC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;aACtB,WAAW,CAAC,mCAAmC,CAAC;aAChD,MAAM,CAAC,GAAG,EAAE;YACX,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arcade.test.d.ts","sourceRoot":"","sources":["../../src/arcade.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arcade Plugin tests
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the arcade tool is registered correctly and handles
|
|
5
|
+
* actions as expected.
|
|
6
|
+
*/
|
|
7
|
+
import register from '../index.js';
|
|
8
|
+
// Simple test runner
|
|
9
|
+
let passed = 0;
|
|
10
|
+
let failed = 0;
|
|
11
|
+
async function test(name, fn) {
|
|
12
|
+
try {
|
|
13
|
+
await fn();
|
|
14
|
+
console.log(` ✓ ${name}`);
|
|
15
|
+
passed++;
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
console.log(` ✗ ${name}`);
|
|
19
|
+
console.log(err);
|
|
20
|
+
failed++;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function assert(condition, message) {
|
|
24
|
+
if (!condition)
|
|
25
|
+
throw new Error(`Assertion failed: ${message}`);
|
|
26
|
+
}
|
|
27
|
+
async function run() {
|
|
28
|
+
console.log('Arcade Plugin tests\n');
|
|
29
|
+
let registeredTool = null;
|
|
30
|
+
const mockApi = {
|
|
31
|
+
logger: {
|
|
32
|
+
info: () => { },
|
|
33
|
+
error: () => { },
|
|
34
|
+
warn: () => { }
|
|
35
|
+
},
|
|
36
|
+
registerTool: (tool) => {
|
|
37
|
+
registeredTool = tool;
|
|
38
|
+
},
|
|
39
|
+
getConfig: () => ({
|
|
40
|
+
plugins: {
|
|
41
|
+
entries: {
|
|
42
|
+
'openclaw-arcade': {
|
|
43
|
+
config: {
|
|
44
|
+
arcadeUrl: 'https://arc.gorillapool.io',
|
|
45
|
+
network: 'mainnet'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
};
|
|
52
|
+
await test('Plugin registers arcade tool', async () => {
|
|
53
|
+
register(mockApi);
|
|
54
|
+
assert(registeredTool !== null, 'tool should be registered');
|
|
55
|
+
assert(registeredTool.name === 'arcade', 'tool name should be arcade');
|
|
56
|
+
});
|
|
57
|
+
await test('Arcade tool config action returns mock config', async () => {
|
|
58
|
+
const result = await registeredTool.execute('1', { action: 'config' });
|
|
59
|
+
assert(result.content[0].text.includes('https://arc.gorillapool.io'), 'output should include mock URL');
|
|
60
|
+
assert(result.content[0].text.includes('mainnet'), 'output should include mock network');
|
|
61
|
+
});
|
|
62
|
+
await test('Arcade tool broadcast action fails without txhex', async () => {
|
|
63
|
+
const result = await registeredTool.execute('1', { action: 'broadcast' });
|
|
64
|
+
assert(result.content[0].text.includes('Error: txhex is required'), 'should return error message');
|
|
65
|
+
});
|
|
66
|
+
await test('Arcade tool status action fails without txid', async () => {
|
|
67
|
+
const result = await registeredTool.execute('1', { action: 'status' });
|
|
68
|
+
assert(result.content[0].text.includes('Error: txid is required'), 'should return error message');
|
|
69
|
+
});
|
|
70
|
+
await test('Arcade tool proof action fails without txid', async () => {
|
|
71
|
+
const result = await registeredTool.execute('1', { action: 'proof' });
|
|
72
|
+
assert(result.content[0].text.includes('Error: txid is required'), 'should return error message');
|
|
73
|
+
});
|
|
74
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
75
|
+
if (failed > 0)
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
run().catch(err => {
|
|
79
|
+
console.error(err);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=arcade.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arcade.test.js","sourceRoot":"","sources":["../../src/arcade.test.ts"],"names":[],"mappings":"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"}
|
package/index.ts
CHANGED
|
@@ -5,7 +5,16 @@ import os from "node:os";
|
|
|
5
5
|
* OpenClaw Arcade Plugin
|
|
6
6
|
* Transaction broadcasting and lifecycle tracking via BSV Arcade.
|
|
7
7
|
*/
|
|
8
|
+
export async function activate(api: any) {
|
|
9
|
+
return register(api);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let isInitialized = false;
|
|
13
|
+
|
|
8
14
|
export default function register(api: any) {
|
|
15
|
+
if (isInitialized) return;
|
|
16
|
+
isInitialized = true;
|
|
17
|
+
|
|
9
18
|
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
10
19
|
const entry = entries['openclaw-arcade']
|
|
11
20
|
|| entries['openclaw-arcade-plugin']
|
|
@@ -13,8 +22,11 @@ export default function register(api: any) {
|
|
|
13
22
|
|| {};
|
|
14
23
|
|
|
15
24
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
16
|
-
const arcadeUrl = (pluginConfig.arcadeUrl || 'https://arcade.bsv.direct').replace(/\/$/, '');
|
|
17
25
|
const network = pluginConfig.network || 'mainnet';
|
|
26
|
+
const defaultArcadeUrl = network === 'testnet'
|
|
27
|
+
? 'https://testnet.arc.gorillapool.io'
|
|
28
|
+
: 'https://arc.gorillapool.io';
|
|
29
|
+
const arcadeUrl = (pluginConfig.arcadeUrl || defaultArcadeUrl).replace(/\/$/, '');
|
|
18
30
|
|
|
19
31
|
api.logger.info(`[arcade] Initializing Arcade Plugin (network: ${network}, host: ${arcadeUrl})`);
|
|
20
32
|
|
|
@@ -88,4 +100,42 @@ export default function register(api: any) {
|
|
|
88
100
|
}
|
|
89
101
|
}
|
|
90
102
|
});
|
|
103
|
+
|
|
104
|
+
// Register the /arcade slash command for direct chat interaction (Autoreply)
|
|
105
|
+
api.registerCommand({
|
|
106
|
+
name: "arcade",
|
|
107
|
+
description: "BSV transaction tracking commands",
|
|
108
|
+
acceptsArgs: true,
|
|
109
|
+
requireAuth: true,
|
|
110
|
+
handler: async (ctx: any) => {
|
|
111
|
+
try {
|
|
112
|
+
const args = ctx.args || [];
|
|
113
|
+
const action = args[0] || 'config';
|
|
114
|
+
const params: any = { action };
|
|
115
|
+
|
|
116
|
+
if (action === 'status' && args[1]) params.txid = args[1];
|
|
117
|
+
if (action === 'broadcast' && args[1]) params.txhex = args[1];
|
|
118
|
+
|
|
119
|
+
// Custom logic for simplified chat output
|
|
120
|
+
if (action === 'status' && params.txid) {
|
|
121
|
+
const res = await fetch(`${arcadeUrl}/v1/tx/${params.txid}`);
|
|
122
|
+
const data: any = await res.json();
|
|
123
|
+
return { text: `🛡️ **Transaction Status**\n**TXID**: ${params.txid}\n**Status**: ${data.txStatus || 'Unknown'}` };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { text: `Command '${action}' executed.` };
|
|
127
|
+
} catch (error: any) {
|
|
128
|
+
return { text: `❌ Arcade Error: ${error.message}` };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Register CLI extensions
|
|
134
|
+
api.registerCli(({ program }: any) => {
|
|
135
|
+
program.command("arcade")
|
|
136
|
+
.description("BSV transaction tracking commands")
|
|
137
|
+
.action(() => {
|
|
138
|
+
console.log("Usage: arcade <action> [args]");
|
|
139
|
+
});
|
|
140
|
+
}, { commands: ["arcade"] });
|
|
91
141
|
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -6,13 +6,28 @@
|
|
|
6
6
|
"skills": [
|
|
7
7
|
"./SKILL.md"
|
|
8
8
|
],
|
|
9
|
+
"commands": [
|
|
10
|
+
{
|
|
11
|
+
"name": "arcade",
|
|
12
|
+
"description": "BSV transaction tracking commands",
|
|
13
|
+
"isAutoreply": true
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"contracts": {
|
|
17
|
+
"tools": [
|
|
18
|
+
{
|
|
19
|
+
"name": "arcade",
|
|
20
|
+
"description": "Submit and track BSV transactions with full lifecycle visibility"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
9
24
|
"configSchema": {
|
|
10
25
|
"type": "object",
|
|
11
|
-
"additionalProperties":
|
|
26
|
+
"additionalProperties": true,
|
|
12
27
|
"properties": {
|
|
13
28
|
"arcadeUrl": {
|
|
14
29
|
"type": "string",
|
|
15
|
-
"default": "https://
|
|
30
|
+
"default": "https://arc.gorillapool.io",
|
|
16
31
|
"description": "Arcade server URL"
|
|
17
32
|
},
|
|
18
33
|
"network": {
|
|
@@ -25,7 +40,7 @@
|
|
|
25
40
|
"uiHints": {
|
|
26
41
|
"arcadeUrl": {
|
|
27
42
|
"label": "Arcade Server URL",
|
|
28
|
-
"placeholder": "https://
|
|
43
|
+
"placeholder": "https://arc.gorillapool.io"
|
|
29
44
|
}
|
|
30
45
|
}
|
|
31
46
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-arcade-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "OpenClaw plugin for transaction broadcasting and lifecycle tracking via BSV Arcade",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"build": "tsc",
|
|
17
17
|
"prepublishOnly": "npm run build",
|
|
18
18
|
"lint": "eslint src/**/*.ts",
|
|
19
|
-
"test": "npx tsx src
|
|
19
|
+
"test": "npx tsx src/arcade.test.ts"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@bsv/sdk": "^2.0.13"
|
|
@@ -28,8 +28,12 @@
|
|
|
28
28
|
},
|
|
29
29
|
"openclaw": {
|
|
30
30
|
"extensions": [
|
|
31
|
-
"./index.
|
|
32
|
-
]
|
|
31
|
+
"./dist/index.js"
|
|
32
|
+
],
|
|
33
|
+
"compat": {
|
|
34
|
+
"pluginApi": "1",
|
|
35
|
+
"minGatewayVersion": "2026.3.1"
|
|
36
|
+
}
|
|
33
37
|
},
|
|
34
38
|
"keywords": [
|
|
35
39
|
"openclaw",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arcade Plugin tests
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the arcade tool is registered correctly and handles
|
|
5
|
+
* actions as expected.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import register from '../index.js';
|
|
9
|
+
|
|
10
|
+
// Simple test runner
|
|
11
|
+
let passed = 0;
|
|
12
|
+
let failed = 0;
|
|
13
|
+
|
|
14
|
+
async function test(name: string, fn: () => void | Promise<void>) {
|
|
15
|
+
try {
|
|
16
|
+
await fn();
|
|
17
|
+
console.log(` ✓ ${name}`);
|
|
18
|
+
passed++;
|
|
19
|
+
} catch (err: unknown) {
|
|
20
|
+
console.log(` ✗ ${name}`);
|
|
21
|
+
console.log(err);
|
|
22
|
+
failed++;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function assert(condition: boolean, message: string) {
|
|
27
|
+
if (!condition) throw new Error(`Assertion failed: ${message}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function run() {
|
|
31
|
+
console.log('Arcade Plugin tests\n');
|
|
32
|
+
|
|
33
|
+
let registeredTool: any = null;
|
|
34
|
+
|
|
35
|
+
const mockApi = {
|
|
36
|
+
logger: {
|
|
37
|
+
info: () => {},
|
|
38
|
+
error: () => {},
|
|
39
|
+
warn: () => {}
|
|
40
|
+
},
|
|
41
|
+
registerTool: (tool: any) => {
|
|
42
|
+
registeredTool = tool;
|
|
43
|
+
},
|
|
44
|
+
getConfig: () => ({
|
|
45
|
+
plugins: {
|
|
46
|
+
entries: {
|
|
47
|
+
'openclaw-arcade': {
|
|
48
|
+
config: {
|
|
49
|
+
arcadeUrl: 'https://arc.gorillapool.io',
|
|
50
|
+
network: 'mainnet'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
await test('Plugin registers arcade tool', async () => {
|
|
59
|
+
register(mockApi);
|
|
60
|
+
assert(registeredTool !== null, 'tool should be registered');
|
|
61
|
+
assert(registeredTool.name === 'arcade', 'tool name should be arcade');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await test('Arcade tool config action returns mock config', async () => {
|
|
65
|
+
const result = await registeredTool.execute('1', { action: 'config' });
|
|
66
|
+
assert(result.content[0].text.includes('https://arc.gorillapool.io'), 'output should include mock URL');
|
|
67
|
+
assert(result.content[0].text.includes('mainnet'), 'output should include mock network');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await test('Arcade tool broadcast action fails without txhex', async () => {
|
|
71
|
+
const result = await registeredTool.execute('1', { action: 'broadcast' });
|
|
72
|
+
assert(result.content[0].text.includes('Error: txhex is required'), 'should return error message');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await test('Arcade tool status action fails without txid', async () => {
|
|
76
|
+
const result = await registeredTool.execute('1', { action: 'status' });
|
|
77
|
+
assert(result.content[0].text.includes('Error: txid is required'), 'should return error message');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await test('Arcade tool proof action fails without txid', async () => {
|
|
81
|
+
const result = await registeredTool.execute('1', { action: 'proof' });
|
|
82
|
+
assert(result.content[0].text.includes('Error: txid is required'), 'should return error message');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
86
|
+
if (failed > 0) process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
run().catch(err => {
|
|
90
|
+
console.error(err);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
});
|