ape-claw 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/.cursor/skills/ape-claw/SKILL.md +322 -0
- package/LICENSE +21 -0
- package/README.md +826 -0
- package/allowlists/opensea-slug-overrides.json +13 -0
- package/allowlists/recommended.apechain.json +322 -0
- package/config/clawbots.example.json +3 -0
- package/config/policy.example.json +27 -0
- package/data/starter-pack-bundle.json +1 -0
- package/data/starter-pack.json +495 -0
- package/docs/ACP_BOUNTIES.md +108 -0
- package/docs/APECLAW_V2_ALPHA.md +206 -0
- package/docs/AUTONOMY_AND_SUBSTRATE.md +69 -0
- package/docs/CLAWBOTS_AND_INVITES.md +102 -0
- package/docs/CLI_GUIDE.md +124 -0
- package/docs/CONTRIBUTING.md +130 -0
- package/docs/DASHBOARD_GUIDE.md +108 -0
- package/docs/GLOBAL_BACKEND.md +145 -0
- package/docs/ONCHAIN_V2_GUIDE.md +140 -0
- package/docs/PRODUCT_OVERVIEW.md +127 -0
- package/docs/README.md +40 -0
- package/docs/SKILLCARDS_AND_IMPORTER.md +147 -0
- package/docs/STARTER_PACK.md +297 -0
- package/docs/SUPPORTED_NETWORKS.md +58 -0
- package/docs/TELEMETRY_AND_EVENTS.md +103 -0
- package/docs/THE_POD_RUNNER.md +198 -0
- package/docs/V1_WORKFLOWS.md +108 -0
- package/docs/V2_ONCHAIN_SKILLS.md +157 -0
- package/docs/WEB4_PLAN_STATUS.md +95 -0
- package/docs/WEB4_SWARM_MODEL.md +104 -0
- package/docs/archive/AUTONOMY_AND_SUBSTRATE.md +66 -0
- package/docs/archive/WEB4_PLAN_STATUS.md +93 -0
- package/docs/archive/WEB4_SWARM_MODEL.md +98 -0
- package/docs/developer/01-architecture.md +345 -0
- package/docs/developer/02-contracts.md +1034 -0
- package/docs/developer/03-writing-modules.md +513 -0
- package/docs/developer/04-skillcard-spec.md +336 -0
- package/docs/developer/05-backend-api.md +1079 -0
- package/docs/developer/06-telemetry.md +798 -0
- package/docs/developer/07-testing.md +546 -0
- package/docs/developer/08-contributing.md +211 -0
- package/docs/operator/01-quickstart.md +49 -0
- package/docs/operator/02-dashboard.md +174 -0
- package/docs/operator/03-cli-reference.md +818 -0
- package/docs/operator/04-skills-library.md +169 -0
- package/docs/operator/05-pod-operations.md +314 -0
- package/docs/operator/06-deployment.md +299 -0
- package/docs/operator/07-safety-and-policy.md +311 -0
- package/docs/operator/08-troubleshooting.md +457 -0
- package/docs/operator/09-env-reference.md +238 -0
- package/docs/social/STARTER_PACK_THREAD.md +209 -0
- package/package.json +77 -0
- package/skillcards/import-sources.json +93 -0
- package/skillcards/seed/acp-bounty-poll.v1.json +38 -0
- package/skillcards/seed/acp-bounty-post.v1.json +55 -0
- package/skillcards/seed/acp-browse.v1.json +41 -0
- package/skillcards/seed/acp-fulfill-and-route.v1.json +56 -0
- package/skillcards/seed/apeclaw-bridge-relay.v1.json +46 -0
- package/skillcards/seed/apeclaw-nft-autobuy.v1.json +60 -0
- package/skillcards/seed/apeclaw-receipt-recorder.v1.json +64 -0
- package/skillcards/seed/humanizer.v1.json +74 -0
- package/skillcards/seed/otherside-navigator.v1.json +116 -0
- package/skillcards/seed/stonkbrokers-launcher.v1.json +280 -0
- package/skillcards/seed/walkie-p2p.v1.json +66 -0
- package/src/cli/index.mjs +8 -0
- package/src/cli.mjs +1929 -0
- package/src/lib/bridge-relay.mjs +294 -0
- package/src/lib/clawbots.mjs +94 -0
- package/src/lib/io.mjs +36 -0
- package/src/lib/market.mjs +233 -0
- package/src/lib/nft-opensea.mjs +159 -0
- package/src/lib/paths.mjs +17 -0
- package/src/lib/pod-init.mjs +40 -0
- package/src/lib/policy.mjs +112 -0
- package/src/lib/rpc.mjs +49 -0
- package/src/lib/telemetry.mjs +92 -0
- package/src/lib/v2-onchain-abi.mjs +294 -0
- package/src/lib/v2-skillcard.mjs +27 -0
- package/src/server/index.mjs +169 -0
- package/src/server/logger.mjs +21 -0
- package/src/server/middleware/auth.mjs +90 -0
- package/src/server/middleware/body-limit.mjs +35 -0
- package/src/server/middleware/cors.mjs +33 -0
- package/src/server/middleware/rate-limit.mjs +44 -0
- package/src/server/routes/chat.mjs +178 -0
- package/src/server/routes/clawbots.mjs +182 -0
- package/src/server/routes/events.mjs +95 -0
- package/src/server/routes/health.mjs +72 -0
- package/src/server/routes/pod.mjs +64 -0
- package/src/server/routes/quotes.mjs +161 -0
- package/src/server/routes/skills.mjs +239 -0
- package/src/server/routes/static.mjs +161 -0
- package/src/server/routes/v2.mjs +48 -0
- package/src/server/sse.mjs +73 -0
- package/src/server/storage/file-backend.mjs +295 -0
- package/src/server/storage/index.mjs +37 -0
- package/src/server/storage/sqlite-backend.mjs +380 -0
- package/src/telemetry-server.mjs +1604 -0
- package/ui/css/dashboard.css +792 -0
- package/ui/css/skills.css +689 -0
- package/ui/docs.html +840 -0
- package/ui/favicon-180.png +0 -0
- package/ui/favicon-192.png +0 -0
- package/ui/favicon-32.png +0 -0
- package/ui/favicon-lobster.png +0 -0
- package/ui/favicon.svg +10 -0
- package/ui/index.html +2957 -0
- package/ui/js/dashboard.js +1766 -0
- package/ui/js/skills.js +1621 -0
- package/ui/pod.html +909 -0
- package/ui/shared/motion.css +286 -0
- package/ui/shared/motion.js +170 -0
- package/ui/shared/sidebar-nav.css +379 -0
- package/ui/shared/sidebar-nav.js +137 -0
- package/ui/skills.html +2879 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# SkillCard Specification
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A SkillCard is a JSON document that describes a skill available to agents in the ApeClaw ecosystem. SkillCards define inputs, outputs, bindings, constraints, and metadata for skills that can be executed on-chain or off-chain.
|
|
6
|
+
|
|
7
|
+
## Schema
|
|
8
|
+
|
|
9
|
+
The canonical JSON structure for a SkillCard:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"slug": "my-skill",
|
|
14
|
+
"name": "My Skill",
|
|
15
|
+
"version": "1.0.0",
|
|
16
|
+
"description": "What this skill does",
|
|
17
|
+
"inputs_schema": { /* JSON Schema */ },
|
|
18
|
+
"outputs_schema": { /* JSON Schema */ },
|
|
19
|
+
"bindings": [ /* ... */ ],
|
|
20
|
+
"constraints": {
|
|
21
|
+
"riskTier": 2,
|
|
22
|
+
"notes": [ /* ... */ ]
|
|
23
|
+
},
|
|
24
|
+
"required_permissions": [ /* ... */ ],
|
|
25
|
+
"examples": [ /* ... */ ],
|
|
26
|
+
"eval_packs": [ /* ... */ ],
|
|
27
|
+
"provenance": { /* ... */ }
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Field Reference
|
|
32
|
+
|
|
33
|
+
### Core Fields
|
|
34
|
+
|
|
35
|
+
#### `name` (required)
|
|
36
|
+
- **Type**: `string`
|
|
37
|
+
- **Description**: Human-readable name of the skill
|
|
38
|
+
- **Example**: `"ApeClaw NFT Autobuy"`
|
|
39
|
+
- **Validation**: Non-empty string
|
|
40
|
+
|
|
41
|
+
#### `slug` (required)
|
|
42
|
+
- **Type**: `string`
|
|
43
|
+
- **Description**: URL-safe identifier for the skill. Must be unique within a version.
|
|
44
|
+
- **Example**: `"apeclaw-nft-autobuy"`
|
|
45
|
+
- **Validation**:
|
|
46
|
+
- Non-empty string
|
|
47
|
+
- Lowercase alphanumeric with hyphens
|
|
48
|
+
- Generated from `name` if not provided: lowercase, trim, replace non-alphanumeric with hyphens
|
|
49
|
+
|
|
50
|
+
#### `version` (required)
|
|
51
|
+
- **Type**: `string`
|
|
52
|
+
- **Description**: Semantic version of the skill
|
|
53
|
+
- **Example**: `"1.0.0"`
|
|
54
|
+
- **Validation**:
|
|
55
|
+
- Must match pattern: `^[0-9]+(\.[0-9]+){0,3}([\-+][0-9A-Za-z._-]+)?$`
|
|
56
|
+
- Examples: `"1.0.0"`, `"2.1.3"`, `"1.0.0-beta.1"`
|
|
57
|
+
|
|
58
|
+
#### `description` (required)
|
|
59
|
+
- **Type**: `string`
|
|
60
|
+
- **Description**: Human-readable description of what the skill does
|
|
61
|
+
- **Example**: `"Plan and (optionally) execute multi-collection NFT buys on ApeChain within strict policy gates."`
|
|
62
|
+
- **Validation**: Non-empty string
|
|
63
|
+
|
|
64
|
+
### Schema Definitions
|
|
65
|
+
|
|
66
|
+
#### `inputs_schema` (required)
|
|
67
|
+
- **Type**: `object` (JSON Schema)
|
|
68
|
+
- **Description**: JSON Schema defining the inputs required to execute this skill
|
|
69
|
+
- **Example**:
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"type": "object",
|
|
73
|
+
"required": ["count", "minPrice", "maxPrice"],
|
|
74
|
+
"properties": {
|
|
75
|
+
"count": { "type": "integer", "minimum": 1, "maximum": 25 },
|
|
76
|
+
"minPrice": { "type": "number", "minimum": 0 },
|
|
77
|
+
"maxPrice": { "type": "number", "exclusiveMinimum": 0 }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
- **Validation**: Must be a valid JSON Schema object
|
|
82
|
+
|
|
83
|
+
#### `outputs_schema` (required)
|
|
84
|
+
- **Type**: `object` (JSON Schema)
|
|
85
|
+
- **Description**: JSON Schema defining the outputs returned by this skill
|
|
86
|
+
- **Example**:
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"type": "object",
|
|
90
|
+
"required": ["ok", "planned"],
|
|
91
|
+
"properties": {
|
|
92
|
+
"ok": { "type": "boolean" },
|
|
93
|
+
"planned": {
|
|
94
|
+
"type": "array",
|
|
95
|
+
"items": {
|
|
96
|
+
"type": "object",
|
|
97
|
+
"required": ["quoteId", "collection", "tokenId"],
|
|
98
|
+
"properties": {
|
|
99
|
+
"quoteId": { "type": "string" },
|
|
100
|
+
"collection": { "type": "string" },
|
|
101
|
+
"tokenId": { "type": "string" }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
- **Validation**: Must be a valid JSON Schema object
|
|
109
|
+
|
|
110
|
+
### Bindings
|
|
111
|
+
|
|
112
|
+
#### `bindings` (required)
|
|
113
|
+
- **Type**: `array`
|
|
114
|
+
- **Description**: Array of execution bindings that describe how to invoke this skill
|
|
115
|
+
- **Example**:
|
|
116
|
+
```json
|
|
117
|
+
[
|
|
118
|
+
{
|
|
119
|
+
"type": "cli",
|
|
120
|
+
"command": "ape-claw nft autobuy --count <count> --minPrice <minPrice> --maxPrice <maxPrice> --json"
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
```
|
|
124
|
+
- **Validation**: Non-empty array
|
|
125
|
+
|
|
126
|
+
**Binding Object:**
|
|
127
|
+
- `type` (required): `string` - Type of binding (`"cli"`, `"http"`, etc.)
|
|
128
|
+
- `command` (required for CLI): `string` - Command template with placeholders
|
|
129
|
+
|
|
130
|
+
### Constraints
|
|
131
|
+
|
|
132
|
+
#### `constraints` (optional)
|
|
133
|
+
- **Type**: `object`
|
|
134
|
+
- **Description**: Constraints and risk information for this skill
|
|
135
|
+
|
|
136
|
+
**Fields:**
|
|
137
|
+
- `riskTier` (optional): `integer` - Risk tier (1-3, default: 2)
|
|
138
|
+
- `1`: Low risk (read-only, no on-chain execution)
|
|
139
|
+
- `2`: Medium risk (on-chain execution with policy gates)
|
|
140
|
+
- `3`: High risk (requires explicit confirmation)
|
|
141
|
+
- `notes` (optional): `array<string>` - Array of constraint notes
|
|
142
|
+
- Example: `["ApeClaw enforces allowlists, currency allowlist, spend caps, confirm phrases, simulation requirements, and replay protection at the CLI layer."]`
|
|
143
|
+
|
|
144
|
+
### Permissions
|
|
145
|
+
|
|
146
|
+
#### `required_permissions` (optional)
|
|
147
|
+
- **Type**: `array<string>`
|
|
148
|
+
- **Description**: List of permissions required to execute this skill
|
|
149
|
+
- **Example**: `["onchain_execute", "market_data"]`
|
|
150
|
+
- **Common Values**:
|
|
151
|
+
- `"onchain_execute"`: Requires ability to execute on-chain transactions
|
|
152
|
+
- `"market_data"`: Requires access to market data APIs
|
|
153
|
+
- `"network"`: Requires network access
|
|
154
|
+
|
|
155
|
+
### Examples
|
|
156
|
+
|
|
157
|
+
#### `examples` (optional)
|
|
158
|
+
- **Type**: `array<object>`
|
|
159
|
+
- **Description**: Example invocations of this skill
|
|
160
|
+
- **Example**:
|
|
161
|
+
```json
|
|
162
|
+
[
|
|
163
|
+
{
|
|
164
|
+
"title": "Find a video editor",
|
|
165
|
+
"value": {
|
|
166
|
+
"query": "short-form video editing for twitter thread"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Example Object:**
|
|
173
|
+
- `title` (required): `string` - Human-readable title
|
|
174
|
+
- `value` (required): `object` - Example input values matching `inputs_schema`
|
|
175
|
+
|
|
176
|
+
### Evaluation
|
|
177
|
+
|
|
178
|
+
#### `eval_packs` (optional)
|
|
179
|
+
- **Type**: `array`
|
|
180
|
+
- **Description**: Evaluation packs for testing this skill
|
|
181
|
+
- **Default**: `[]`
|
|
182
|
+
- **Validation**: Array (currently unused, reserved for future use)
|
|
183
|
+
|
|
184
|
+
### Provenance
|
|
185
|
+
|
|
186
|
+
#### `provenance` (optional)
|
|
187
|
+
- **Type**: `object`
|
|
188
|
+
- **Description**: Metadata about the origin and publisher of this skill
|
|
189
|
+
- **Example**:
|
|
190
|
+
```json
|
|
191
|
+
{
|
|
192
|
+
"publisher": "apeclaw",
|
|
193
|
+
"signed": false,
|
|
194
|
+
"sourceUrl": "https://github.com/apeclaw/skills"
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Fields:**
|
|
199
|
+
- `publisher` (optional): `string` - Publisher identifier (`"apeclaw"`, `"user"`, `"imported"`)
|
|
200
|
+
- `signed` (optional): `boolean` - Whether the skill is cryptographically signed
|
|
201
|
+
- `sourceUrl` (optional): `string` - URL to the source of this skill
|
|
202
|
+
|
|
203
|
+
## Content Hashing
|
|
204
|
+
|
|
205
|
+
The `contentHash` of a SkillCard is computed using the following algorithm (from `v2-skillcard.mjs`):
|
|
206
|
+
|
|
207
|
+
1. **Stable JSON Serialization**: Convert the SkillCard object to a canonical JSON string with sorted keys:
|
|
208
|
+
```javascript
|
|
209
|
+
function stableJsonStringify(obj) {
|
|
210
|
+
if (obj === null || typeof obj !== "object") return JSON.stringify(obj);
|
|
211
|
+
if (Array.isArray(obj)) return `[${obj.map(stableJsonStringify).join(",")}]`;
|
|
212
|
+
const keys = Object.keys(obj).sort();
|
|
213
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableJsonStringify(obj[k])}`).join(",")}}`;
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
2. **Keccak256 Hash**: Hash the canonical JSON string using Keccak256:
|
|
218
|
+
```javascript
|
|
219
|
+
const canon = stableJsonStringify(skillcardObj);
|
|
220
|
+
const contentHash = keccak256(toHex(canon));
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The content hash uniquely identifies the exact content of a SkillCard, allowing detection of changes even if the version number remains the same.
|
|
224
|
+
|
|
225
|
+
## Version Hashing
|
|
226
|
+
|
|
227
|
+
The `versionHash` is computed from the version string:
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
const version = String(versionString || "").trim() || "0.0.0";
|
|
231
|
+
const versionHash = keccak256(toHex(version));
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
This creates a deterministic hash of the version string, useful for on-chain version tracking.
|
|
235
|
+
|
|
236
|
+
## Risk Tiers
|
|
237
|
+
|
|
238
|
+
| Value | Label | Meaning | Example Skills |
|
|
239
|
+
|-------|-------|----------|----------------|
|
|
240
|
+
| `1` | Low Risk | Read-only operations, no on-chain execution, no financial risk | Browse/search skills, data queries |
|
|
241
|
+
| `2` | Medium Risk | On-chain execution with policy gates, requires allowlists and confirmations | NFT buying, bridging (with policy) |
|
|
242
|
+
| `3` | High Risk | High-value operations requiring explicit confirmation phrases | Large transfers, admin operations |
|
|
243
|
+
|
|
244
|
+
## Validation Rules
|
|
245
|
+
|
|
246
|
+
1. **Required Fields**: `name`, `slug`, `version`, `description`, `inputs_schema`, `outputs_schema`, `bindings` must be present
|
|
247
|
+
2. **Slug Uniqueness**: Within a version, slugs must be unique
|
|
248
|
+
3. **Version Format**: Must match semantic version pattern
|
|
249
|
+
4. **Schema Validity**: `inputs_schema` and `outputs_schema` must be valid JSON Schema
|
|
250
|
+
5. **Risk Tier Range**: `riskTier` must be 1, 2, or 3 (if provided)
|
|
251
|
+
6. **Binding Types**: Bindings must specify a valid `type` and appropriate fields for that type
|
|
252
|
+
|
|
253
|
+
## File Naming Convention
|
|
254
|
+
|
|
255
|
+
User-submitted SkillCards are stored with the filename pattern:
|
|
256
|
+
```
|
|
257
|
+
{slug}.v{version}.json
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Example: `apeclaw-nft-autobuy.v1.0.0.json`
|
|
261
|
+
|
|
262
|
+
## Example SkillCard
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"name": "ApeClaw NFT Autobuy",
|
|
267
|
+
"slug": "apeclaw-nft-autobuy",
|
|
268
|
+
"description": "Plan and (optionally) execute multi-collection NFT buys on ApeChain within strict policy gates. Designed for agents that collect NFTs while you sleep.",
|
|
269
|
+
"version": "1.0.0",
|
|
270
|
+
"inputs_schema": {
|
|
271
|
+
"type": "object",
|
|
272
|
+
"required": ["count", "minPrice", "maxPrice", "currency", "execute", "autonomous"],
|
|
273
|
+
"properties": {
|
|
274
|
+
"count": { "type": "integer", "minimum": 1, "maximum": 25 },
|
|
275
|
+
"scan": { "type": "integer", "minimum": 1, "maximum": 500 },
|
|
276
|
+
"minPrice": { "type": "number", "minimum": 0 },
|
|
277
|
+
"maxPrice": { "type": "number", "exclusiveMinimum": 0 },
|
|
278
|
+
"budget": { "type": ["number", "null"], "minimum": 0 },
|
|
279
|
+
"currency": { "type": "string", "enum": ["APE"] },
|
|
280
|
+
"execute": { "type": "boolean" },
|
|
281
|
+
"autonomous": { "type": "boolean" }
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
"outputs_schema": {
|
|
285
|
+
"type": "object",
|
|
286
|
+
"required": ["ok", "planned", "selectedCount"],
|
|
287
|
+
"properties": {
|
|
288
|
+
"ok": { "type": "boolean" },
|
|
289
|
+
"selectedCount": { "type": "integer" },
|
|
290
|
+
"planned": {
|
|
291
|
+
"type": "array",
|
|
292
|
+
"items": {
|
|
293
|
+
"type": "object",
|
|
294
|
+
"required": ["quoteId", "collection", "tokenId", "priceApe"],
|
|
295
|
+
"properties": {
|
|
296
|
+
"quoteId": { "type": "string" },
|
|
297
|
+
"collection": { "type": "string" },
|
|
298
|
+
"tokenId": { "type": "string" },
|
|
299
|
+
"priceApe": { "type": "number" }
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"bindings": [
|
|
306
|
+
{
|
|
307
|
+
"type": "cli",
|
|
308
|
+
"command": "ape-claw nft autobuy --count <count> --minPrice <minPrice> --maxPrice <maxPrice> [--scan <scan>] [--budget <budget>] [--execute] [--autonomous] --json"
|
|
309
|
+
}
|
|
310
|
+
],
|
|
311
|
+
"constraints": {
|
|
312
|
+
"riskTier": 2,
|
|
313
|
+
"notes": [
|
|
314
|
+
"ApeClaw enforces allowlists, currency allowlist, spend caps, confirm phrases, simulation requirements, and replay protection at the CLI layer."
|
|
315
|
+
]
|
|
316
|
+
},
|
|
317
|
+
"required_permissions": ["onchain_execute", "market_data"],
|
|
318
|
+
"examples": [],
|
|
319
|
+
"eval_packs": [],
|
|
320
|
+
"provenance": {
|
|
321
|
+
"publisher": "apeclaw",
|
|
322
|
+
"signed": false
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## On-Chain Integration
|
|
328
|
+
|
|
329
|
+
When a SkillCard is deployed on-chain (via V2 contracts), additional metadata is tracked:
|
|
330
|
+
|
|
331
|
+
- `skillId`: On-chain skill ID (uint256)
|
|
332
|
+
- `txHash`: Transaction hash of the mint/publish transaction
|
|
333
|
+
- `contentHash`: Keccak256 hash of the canonical JSON (computed as described above)
|
|
334
|
+
- `versionHash`: Keccak256 hash of the version string
|
|
335
|
+
|
|
336
|
+
These hashes enable verification that on-chain skills match their SkillCard definitions.
|