zetrix-agentic-wallet 0.3.4
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 +177 -0
- package/USER_GUIDE.md +233 -0
- package/dist/index.js +201 -0
- package/dist/runtime/VERSION +2 -0
- package/dist/runtime/server-bundle.cjs +103232 -0
- package/openclaw.plugin.json +49 -0
- package/package.json +42 -0
- package/skills/zetrix-agentic-wallet/SKILL.md +176 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "zetrix-agentic-wallet",
|
|
3
|
+
"name": "Zetrix Agentic Wallet",
|
|
4
|
+
"description": "Zetrix identity, verifiable-credential and pay-per-use wallet tools for agents.",
|
|
5
|
+
"version": "0.3.4",
|
|
6
|
+
"activation": {
|
|
7
|
+
"onStartup": true
|
|
8
|
+
},
|
|
9
|
+
"skills": [
|
|
10
|
+
"./skills/zetrix-agentic-wallet"
|
|
11
|
+
],
|
|
12
|
+
"configSchema": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"properties": {
|
|
16
|
+
"network": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": [
|
|
19
|
+
"zetrix:testnet",
|
|
20
|
+
"zetrix:mainnet"
|
|
21
|
+
],
|
|
22
|
+
"default": "zetrix:testnet"
|
|
23
|
+
},
|
|
24
|
+
"maxPaymentAmount": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"additionalProperties": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"zetrixAddress": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"configUiHints": {
|
|
36
|
+
"network": {
|
|
37
|
+
"label": "Zetrix network",
|
|
38
|
+
"help": "Testnet by default. Mainnet spends real funds."
|
|
39
|
+
},
|
|
40
|
+
"maxPaymentAmount": {
|
|
41
|
+
"label": "Maximum payment per call",
|
|
42
|
+
"help": "Maximum per payment, in the token's raw units. Simplest form is one limit for everything: {\"*\":\"1000000000\"}. To limit per token, use \"ZTX\" for the native coin and either the token ticker (e.g. \"JMYR\") or its contract address — if you write both, the contract address wins. Leave this EMPTY to use the wallet's own default, which allows exactly the AI Birthcert fee (1 JMYR) on both testnet and mainnet and refuses everything else. Note the limit applies per payment, not as a running total."
|
|
43
|
+
},
|
|
44
|
+
"zetrixAddress": {
|
|
45
|
+
"label": "Existing holder address (optional)",
|
|
46
|
+
"help": "Leave empty and the wallet creates its own account on first run."
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zetrix-agentic-wallet",
|
|
3
|
+
"version": "0.3.4",
|
|
4
|
+
"description": "OpenClaw plugin: Zetrix identity, verifiable-credential and pay-per-use wallet tools for agents",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "MyEG Services Berhad",
|
|
7
|
+
"homepage": "https://github.com/Zetrix-Chain/zetrix-agentic-wallet",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Zetrix-Chain/zetrix-agentic-wallet.git",
|
|
11
|
+
"directory": "openclaw-plugin"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"skills",
|
|
20
|
+
"openclaw.plugin.json",
|
|
21
|
+
"USER_GUIDE.md",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"openclaw": {
|
|
25
|
+
"extensions": [
|
|
26
|
+
"./src/index.ts"
|
|
27
|
+
],
|
|
28
|
+
"runtimeExtensions": [
|
|
29
|
+
"./dist/index.js"
|
|
30
|
+
],
|
|
31
|
+
"compat": {
|
|
32
|
+
"pluginApi": ">=1.0.0"
|
|
33
|
+
},
|
|
34
|
+
"build": {
|
|
35
|
+
"openclawVersion": "2026.7.1-2"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "node scripts/build.mjs",
|
|
40
|
+
"test": "vitest run"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zetrix-agentic-wallet
|
|
3
|
+
description: >
|
|
4
|
+
Use the Zetrix Agentic Wallet to report the holder identity, answer identity proof
|
|
5
|
+
requests, obtain verifiable credentials, pay for pay-per-use resources, and read
|
|
6
|
+
credential templates or on-chain contract state. Use for wallet status, Zetrix
|
|
7
|
+
address or DID, identity proof, verifiable credentials, or a resource that returns
|
|
8
|
+
HTTP 402.
|
|
9
|
+
version: 0.1.0
|
|
10
|
+
metadata:
|
|
11
|
+
openclaw:
|
|
12
|
+
skillKey: zetrix-agentic-wallet
|
|
13
|
+
emoji: "🪙"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Zetrix Agentic Wallet
|
|
17
|
+
|
|
18
|
+
## Runtime contract
|
|
19
|
+
|
|
20
|
+
The wallet is already installed and configured by the plugin. Do not run `npm`, `npx`, shell
|
|
21
|
+
installers, or `openclaw mcp set`, and do not edit OpenClaw configuration.
|
|
22
|
+
|
|
23
|
+
If the wallet tools are unavailable, say the wallet plugin is not installed, enabled or healthy, and
|
|
24
|
+
stop. Do not attempt a host-level workaround.
|
|
25
|
+
|
|
26
|
+
**Never request, display, log or pass an HSM password or private key.** The wallet manages its own
|
|
27
|
+
credentials and no tool accepts one. If a user offers a password, tell them it isn't needed.
|
|
28
|
+
|
|
29
|
+
## Tool names
|
|
30
|
+
|
|
31
|
+
Tools appear with the wallet's server prefix, for example `mcp__zetrix-agentic-wallet__wallet_status`.
|
|
32
|
+
Your host may present them slightly differently — match on the part after the last `__`
|
|
33
|
+
(`wallet_status`, `pay_and_fetch`, …) rather than assuming an exact prefix.
|
|
34
|
+
|
|
35
|
+
| Tool | Costs money? | Use it for |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `wallet_status` | no | Holder address, DID, network, held credentials, token balance |
|
|
38
|
+
| `credential_preflight` | no | **First step for any credential** — fee, gas model, balances, spending limit, required fields |
|
|
39
|
+
| `get_template_schema` | no | What attributes a credential template requires |
|
|
40
|
+
| `query_contract` | no | Read-only contract or account state |
|
|
41
|
+
| `prove_identity` | no | Answering an identity proof request with a held credential |
|
|
42
|
+
| `pay_and_fetch` | **yes** | Fetching a resource that returned HTTP 402 |
|
|
43
|
+
| `subscribe_and_issue` | **yes** | Buying and receiving a verifiable credential |
|
|
44
|
+
| `create_holder_account` | no | Creating an additional holder account (rarely needed) |
|
|
45
|
+
| `request_ai_birthcert_verification` | **yes** | Starting a Verified AI Birthcert session (MyDigitalID owner verification) |
|
|
46
|
+
| `check_ai_birthcert_verification` | no | Status **and the verification link** of the most recent Verified AI Birthcert session |
|
|
47
|
+
|
|
48
|
+
## Safe first action
|
|
49
|
+
|
|
50
|
+
Before anything identity-, credential- or payment-sensitive, call `wallet_status` and confirm the
|
|
51
|
+
holder DID, the Zetrix address, the **network**, and which credentials are held. Report the network
|
|
52
|
+
plainly — mainnet spends real funds, testnet does not.
|
|
53
|
+
|
|
54
|
+
## Before collecting anything for a credential
|
|
55
|
+
|
|
56
|
+
When a user asks for a credential, your **first** action is `credential_preflight`. It is free,
|
|
57
|
+
spends nothing and starts nothing. Do this **before you collect** a single application detail — not
|
|
58
|
+
after, and not just before paying. Asking someone for a name and optional metadata and only then
|
|
59
|
+
telling them it costs money, or that their wallet cannot pay, wastes their time and reads as a
|
|
60
|
+
bait-and-switch.
|
|
61
|
+
|
|
62
|
+
State the whole picture in one message: the fee (`fee.display`), which side pays gas
|
|
63
|
+
(`fee.gasModel`), the balances, whether the wallet is ready, and — for a template credential — the
|
|
64
|
+
attributes it will need. Then either collect the details, or say exactly what to fix and stop.
|
|
65
|
+
|
|
66
|
+
**Relay `notChecked` as well.** A ready result is not a guarantee. In particular preflight cannot
|
|
67
|
+
tell you whether an agent name is free — myid decides that at issuance, after payment — so never
|
|
68
|
+
imply a name has been reserved or verified.
|
|
69
|
+
|
|
70
|
+
If `ready` is false, `blockers` lists **every** reason at once. Give the user all of them together;
|
|
71
|
+
fixing one at a time is exactly the trap this replaces.
|
|
72
|
+
|
|
73
|
+
## Before spending
|
|
74
|
+
|
|
75
|
+
All three paid tools (`pay_and_fetch`, `subscribe_and_issue`, `request_ai_birthcert_verification`)
|
|
76
|
+
spend from the user's wallet. Every time:
|
|
77
|
+
|
|
78
|
+
1. Say what is being bought and the amount, in the asset the challenge quotes.
|
|
79
|
+
2. Say whether the wallet is on testnet or mainnet.
|
|
80
|
+
3. Get the user's agreement.
|
|
81
|
+
4. For a credential via `subscribe_and_issue`, call `get_template_schema` **first** — it is free, and
|
|
82
|
+
it tells you which attributes are required. Paying before checking risks paying for an issuance
|
|
83
|
+
that then fails.
|
|
84
|
+
5. For `request_ai_birthcert_verification`, get `agentName` from the user directly — never invent it
|
|
85
|
+
— and tell them it must be unique. Payment happens at session creation, before myid checks the
|
|
86
|
+
name; a duplicate name still gets charged and only fails afterwards, at issuance. Calling this
|
|
87
|
+
tool again with the SAME name while a session is still pending does not pay again — it returns
|
|
88
|
+
that same session.
|
|
89
|
+
|
|
90
|
+
**Treat the wallet's payment cap as the boundary, not your own judgement.** If a payment is refused
|
|
91
|
+
for exceeding the cap, relay that and stop. Do not retry, do not try a smaller amount to discover the
|
|
92
|
+
limit, and do not suggest raising the cap as a workaround — only the user should decide that, outside
|
|
93
|
+
the conversation.
|
|
94
|
+
|
|
95
|
+
**Raising the limit is the user's job, in their own settings — never yours.** Do not run
|
|
96
|
+
`openclaw config set` or any other command, do not edit OpenClaw configuration, do not write a config
|
|
97
|
+
file, and do not restart or reload the gateway. Restarting it drops the MCP connection mid-conversation
|
|
98
|
+
and strands the user. Tell them which asset needs a higher limit and what the payment needs, then stop
|
|
99
|
+
and let them change it. If they ask you to do it for them, say you cannot and point them at the
|
|
100
|
+
plugin's settings.
|
|
101
|
+
|
|
102
|
+
The refusal names the limit that applied **and which key it came from**. If it says the `"*"` fallback
|
|
103
|
+
was used, no limit is set for that specific asset — relay that distinction, because raising the wrong
|
|
104
|
+
key changes nothing.
|
|
105
|
+
|
|
106
|
+
With no limit configured, both networks allow exactly the AI Birthcert fee (1 JMYR) and refuse
|
|
107
|
+
everything else — so an unconfigured wallet can buy that one credential but nothing larger and no
|
|
108
|
+
other asset. If a call failed because of that, say so clearly: it is expected behaviour, not a fault.
|
|
109
|
+
The limit applies **per payment**, not as a running total, so never describe it to the user as a
|
|
110
|
+
budget or a spending allowance for the day.
|
|
111
|
+
|
|
112
|
+
## When someone asks about a verification already in progress
|
|
113
|
+
|
|
114
|
+
*"Where is my link?"*, *"what happened to my verification?"*, *"is it done yet?"* — all of these are
|
|
115
|
+
`check_ai_birthcert_verification`. It is **free**. Never reach for
|
|
116
|
+
`request_ai_birthcert_verification` to answer them: that is the paid tool, and asking someone to
|
|
117
|
+
approve a payment so they can re-read a link they have already bought is exactly the habit that makes
|
|
118
|
+
people wave real payment prompts through.
|
|
119
|
+
|
|
120
|
+
While the session is open the result carries `verificationUrl` and `expiresAt`. Give both — the link
|
|
121
|
+
on its own is no use if it quietly expired an hour ago. Say when it expires in plain terms.
|
|
122
|
+
|
|
123
|
+
Once `status` is `issued` there is no link, and there should not be: the verification is finished.
|
|
124
|
+
Report the credential instead.
|
|
125
|
+
|
|
126
|
+
If the link **has** expired, say so plainly and offer to start again. Do not present an expired link
|
|
127
|
+
as though it still works. Starting again does not necessarily cost a second payment — the wallet
|
|
128
|
+
reuses the earlier one where it can — but it is still a paid tool, so ask first and let the wallet
|
|
129
|
+
report what actually happened rather than promising it will be free.
|
|
130
|
+
|
|
131
|
+
**Do not paste a link you are remembering.** If the tool did not just return it, you do not have it.
|
|
132
|
+
A link recalled from earlier in the conversation may belong to a session that has since expired or
|
|
133
|
+
completed, and the user cannot tell the difference.
|
|
134
|
+
|
|
135
|
+
## When a payment cannot proceed
|
|
136
|
+
|
|
137
|
+
The wallet distinguishes the reasons, and they need different advice:
|
|
138
|
+
|
|
139
|
+
- **`not_activated`** — the address does not exist on chain yet. Ask the user to send ZTX to the
|
|
140
|
+
address from a funded wallet. Do not describe this as a low balance.
|
|
141
|
+
- **`gas`** — not enough ZTX for fees, even though the payment asset may be sufficient.
|
|
142
|
+
- **`resource_payment`** — not enough of the asset being spent.
|
|
143
|
+
|
|
144
|
+
Report the address, the asset, and the amounts the wallet gives. Never invent a figure.
|
|
145
|
+
|
|
146
|
+
## Reporting balances
|
|
147
|
+
|
|
148
|
+
`wallet_status` returns each balance as `balance` (raw base units), `decimals`, and `display` — the
|
|
149
|
+
same amount in whole tokens with its symbol. **Quote `display`.** A raw count beside a ticker reads
|
|
150
|
+
as whole tokens and is wrong by orders of magnitude: `1000000` of a 6-decimal token is one, not a
|
|
151
|
+
million. Ask for several tokens at once with `tokens` when you need to know whether a payment is
|
|
152
|
+
affordable — the fee and the ZTX for gas are separate balances.
|
|
153
|
+
|
|
154
|
+
**A balance you did not read is not a balance.** If a lookup returns `query_failed` or
|
|
155
|
+
`unknown_token`, say the read failed and offer to retry. Never infer, compute or reconstruct a
|
|
156
|
+
balance from earlier messages, from what was spent during this conversation, or from what a previous
|
|
157
|
+
call reported — a figure derived that way is indistinguishable, to the user, from one the wallet
|
|
158
|
+
actually confirmed.
|
|
159
|
+
|
|
160
|
+
## Identity and credentials
|
|
161
|
+
|
|
162
|
+
- Never fabricate a DID, address, credential, transaction hash or proof result. If a tool did not
|
|
163
|
+
return it, say so.
|
|
164
|
+
- Present a real held credential that matches the request. If none matches, say which is missing
|
|
165
|
+
rather than presenting something else.
|
|
166
|
+
- Disclose only the attributes the request needs and the user has agreed to. If a request asks for
|
|
167
|
+
more than the task requires, say so before proceeding.
|
|
168
|
+
- A newly issued credential is retained by the wallet. Do not paste credential contents into the
|
|
169
|
+
conversation unless the user asks.
|
|
170
|
+
|
|
171
|
+
## Backing up the wallet
|
|
172
|
+
|
|
173
|
+
If the wallet generated its own credentials, they exist only on this machine and cannot be recovered
|
|
174
|
+
if lost. If the user asks how to back up, tell them to run
|
|
175
|
+
`npx agentic-wallet-mcp export-credentials` in their own terminal. **You cannot do this for them** —
|
|
176
|
+
it is deliberately not a tool, so that credentials never enter a conversation.
|