@xpr-agents/openclaw 0.3.2 → 0.4.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.
Files changed (53) hide show
  1. package/README.md +31 -5
  2. package/openclaw.plugin.json +15 -1
  3. package/package.json +7 -4
  4. package/skills/code-sandbox/SKILL.md +30 -0
  5. package/skills/code-sandbox/skill.json +13 -0
  6. package/skills/code-sandbox/src/index.ts +212 -0
  7. package/skills/creative/SKILL.md +32 -0
  8. package/skills/creative/skill.json +13 -0
  9. package/skills/creative/src/index.ts +679 -0
  10. package/skills/defi/SKILL.md +123 -0
  11. package/skills/defi/dist/index.js +1 -0
  12. package/skills/defi/skill.json +44 -0
  13. package/skills/defi/src/index.ts +1788 -0
  14. package/skills/defi/test-read.mjs +281 -0
  15. package/skills/governance/SKILL.md +69 -0
  16. package/skills/governance/dist/index.js +632 -0
  17. package/skills/governance/skill.json +21 -0
  18. package/skills/governance/src/index.ts +656 -0
  19. package/skills/governance/test-read.mjs +176 -0
  20. package/skills/lending/SKILL.md +63 -0
  21. package/skills/lending/dist/index.js +1039 -0
  22. package/skills/lending/skill.json +29 -0
  23. package/skills/lending/src/index.ts +1105 -0
  24. package/skills/lending/test-read.mjs +156 -0
  25. package/skills/nft/SKILL.md +95 -0
  26. package/skills/nft/dist/index.js +4 -10
  27. package/skills/nft/skill.json +37 -0
  28. package/skills/nft/src/index.ts +1539 -0
  29. package/skills/shellbook/SKILL.md +59 -0
  30. package/skills/shellbook/skill.json +29 -0
  31. package/skills/shellbook/src/index.ts +391 -0
  32. package/skills/shellbook/tsconfig.json +14 -0
  33. package/skills/smart-contracts/SKILL.md +128 -0
  34. package/skills/smart-contracts/skill.json +25 -0
  35. package/skills/smart-contracts/src/index.ts +1327 -0
  36. package/skills/smart-contracts/tsconfig.json +14 -0
  37. package/skills/structured-data/SKILL.md +36 -0
  38. package/skills/structured-data/dist/index.js +501 -0
  39. package/skills/structured-data/skill.json +13 -0
  40. package/skills/structured-data/src/index.ts +597 -0
  41. package/skills/tax/SKILL.md +109 -0
  42. package/skills/tax/dist/index.js +216 -32
  43. package/skills/tax/skill.json +20 -0
  44. package/skills/tax/src/index.ts +1985 -0
  45. package/skills/web-scraping/SKILL.md +29 -0
  46. package/skills/web-scraping/dist/index.js +311 -0
  47. package/skills/web-scraping/skill.json +13 -0
  48. package/skills/web-scraping/src/index.ts +371 -0
  49. package/skills/xmd/SKILL.md +52 -0
  50. package/skills/xmd/dist/index.js +596 -0
  51. package/skills/xmd/skill.json +22 -0
  52. package/skills/xmd/src/index.ts +635 -0
  53. package/skills/xmd/test-read.mjs +178 -0
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Quick integration test for XMD skill read-only tools.
3
+ * Calls mainnet xmd.token / xmd.treasury directly — no signing needed.
4
+ *
5
+ * Usage: node test-read.mjs
6
+ */
7
+
8
+ const RPC = 'https://proton.eosusa.io';
9
+ const XMD_TOKEN = 'xmd.token';
10
+ const XMD_TREASURY = 'xmd.treasury';
11
+ const ORACLE = 'oracles';
12
+
13
+ async function getTableRows(opts) {
14
+ const resp = await fetch(`${RPC}/v1/chain/get_table_rows`, {
15
+ method: 'POST',
16
+ headers: { 'Content-Type': 'application/json' },
17
+ body: JSON.stringify({
18
+ json: true,
19
+ code: opts.code,
20
+ scope: opts.scope,
21
+ table: opts.table,
22
+ lower_bound: opts.lower_bound,
23
+ upper_bound: opts.upper_bound,
24
+ limit: opts.limit || 100,
25
+ }),
26
+ });
27
+ const data = await resp.json();
28
+ return data.rows || [];
29
+ }
30
+
31
+ function parseExtSym(sym) {
32
+ if (!sym) return null;
33
+ const parts = (sym.sym || '').split(',');
34
+ if (parts.length !== 2) return null;
35
+ return { precision: parseInt(parts[0]), symbol: parts[1].trim(), contract: sym.contract || '' };
36
+ }
37
+
38
+ function parseQuantity(qty) {
39
+ const parts = qty.trim().split(' ');
40
+ if (parts.length !== 2) return null;
41
+ return { amount: parseFloat(parts[0]), symbol: parts[1] };
42
+ }
43
+
44
+ let passed = 0;
45
+ let failed = 0;
46
+
47
+ function assert(condition, msg) {
48
+ if (condition) { passed++; console.log(` PASS: ${msg}`); }
49
+ else { failed++; console.log(` FAIL: ${msg}`); }
50
+ }
51
+
52
+ // ── Test 1: xmd_get_config ──
53
+ console.log('\n--- xmd_get_config ---');
54
+ const globals = await getTableRows({ code: XMD_TREASURY, scope: XMD_TREASURY, table: 'xmdglobals', limit: 1 });
55
+ assert(globals.length === 1, 'xmdglobals singleton exists');
56
+ assert(globals[0].isPaused === 0, 'Treasury is not paused');
57
+ assert(globals[0].feeAccount === 'fee.metal', `Fee account = fee.metal (got ${globals[0].feeAccount})`);
58
+ assert(parseFloat(globals[0].minOraclePrice) >= 0.99, `Min oracle price >= 0.99 (got ${globals[0].minOraclePrice})`);
59
+
60
+ // ── Test 2: xmd_list_collateral ──
61
+ console.log('\n--- xmd_list_collateral ---');
62
+ const tokens = await getTableRows({ code: XMD_TREASURY, scope: XMD_TREASURY, table: 'tokens', limit: 50 });
63
+ assert(tokens.length >= 4, `Found ${tokens.length} collateral types (expected >= 4)`);
64
+
65
+ const xusdc = tokens.find(t => parseExtSym(t.symbol)?.symbol === 'XUSDC');
66
+ assert(!!xusdc, 'XUSDC collateral exists');
67
+ assert(parseExtSym(xusdc.symbol)?.contract === 'xtokens', 'XUSDC contract = xtokens');
68
+ assert(!!xusdc.isMintEnabled, 'XUSDC mint enabled');
69
+ assert(!!xusdc.isRedeemEnabled, 'XUSDC redeem enabled');
70
+ assert(parseFloat(xusdc.maxTreasuryPercent) === 60, `XUSDC max treasury = 60% (got ${xusdc.maxTreasuryPercent})`);
71
+ assert(parseFloat(xusdc.mintFee) === 0, `XUSDC mint fee = 0 (got ${xusdc.mintFee})`);
72
+ assert(parseFloat(xusdc.redemptionFee) === 0, `XUSDC redemption fee = 0 (got ${xusdc.redemptionFee})`);
73
+ assert(xusdc.oracleIndex === 5, `XUSDC oracle index = 5 (got ${xusdc.oracleIndex})`);
74
+ assert(parseFloat(xusdc.amountMinted) > 100000000, `XUSDC total minted > $100M (got ${parseFloat(xusdc.amountMinted).toFixed(0)})`);
75
+
76
+ const xpax = tokens.find(t => parseExtSym(t.symbol)?.symbol === 'XPAX');
77
+ assert(!!xpax, 'XPAX collateral exists');
78
+ assert(parseExtSym(xpax.symbol)?.contract === 'xtokens', 'XPAX contract = xtokens');
79
+
80
+ const xpyusd = tokens.find(t => parseExtSym(t.symbol)?.symbol === 'XPYUSD');
81
+ assert(!!xpyusd, 'XPYUSD collateral exists');
82
+
83
+ const mpd = tokens.find(t => parseExtSym(t.symbol)?.symbol === 'MPD');
84
+ assert(!!mpd, 'MPD collateral exists');
85
+ assert(parseExtSym(mpd.symbol)?.contract === 'mpd.token', 'MPD contract = mpd.token');
86
+
87
+ // ── Test 3: xmd_get_supply ──
88
+ console.log('\n--- xmd_get_supply ---');
89
+ const stats = await getTableRows({ code: XMD_TOKEN, scope: 'XMD', table: 'stat', limit: 1 });
90
+ assert(stats.length === 1, 'XMD stat row exists');
91
+ const supply = parseQuantity(stats[0].supply);
92
+ assert(supply.symbol === 'XMD', `Symbol = XMD`);
93
+ assert(supply.amount > 1000000, `Supply > 1M XMD (got ${supply.amount.toLocaleString()})`);
94
+ assert(stats[0].issuer === 'xmd.treasury', `Issuer = xmd.treasury (got ${stats[0].issuer})`);
95
+ const maxSupply = parseQuantity(stats[0].max_supply);
96
+ assert(maxSupply.amount === 0, `Max supply = 0 (unlimited)`);
97
+
98
+ // ── Test 4: xmd_get_balance ──
99
+ console.log('\n--- xmd_get_balance ---');
100
+ const balRows = await getTableRows({ code: XMD_TOKEN, scope: 'jamestaggart', table: 'accounts', limit: 5 });
101
+ const xmdBal = balRows.find(r => parseQuantity(r.balance)?.symbol === 'XMD');
102
+ assert(!!xmdBal, `jamestaggart has XMD balance`);
103
+ assert(parseQuantity(xmdBal.balance).amount > 0, `Balance > 0 (got ${xmdBal.balance})`);
104
+
105
+ // Non-existent user
106
+ const noBal = await getTableRows({ code: XMD_TOKEN, scope: 'zzzzzzzzzzz1', table: 'accounts', limit: 5 });
107
+ assert(noBal.length === 0, 'Non-existent user returns empty');
108
+
109
+ // ── Test 5: xmd_get_treasury_reserves ──
110
+ console.log('\n--- xmd_get_treasury_reserves ---');
111
+ const xusdcBal = await getTableRows({ code: 'xtokens', scope: XMD_TREASURY, table: 'accounts', limit: 20 });
112
+ const xusdcReserve = xusdcBal.find(r => parseQuantity(r.balance)?.symbol === 'XUSDC');
113
+ assert(!!xusdcReserve, 'Treasury holds XUSDC');
114
+ const xusdcAmount = parseQuantity(xusdcReserve.balance).amount;
115
+ assert(xusdcAmount > 100000, `XUSDC reserve > $100k (got ${xusdcAmount.toLocaleString()})`);
116
+
117
+ // Check total reserves roughly match XMD supply
118
+ let totalReserves = 0;
119
+ for (const row of xusdcBal) {
120
+ const parsed = parseQuantity(row.balance);
121
+ if (parsed) totalReserves += parsed.amount;
122
+ }
123
+ const mpdBal = await getTableRows({ code: 'mpd.token', scope: XMD_TREASURY, table: 'accounts', limit: 5 });
124
+ for (const row of mpdBal) {
125
+ const parsed = parseQuantity(row.balance);
126
+ if (parsed) totalReserves += parsed.amount;
127
+ }
128
+ const ratio = (totalReserves / supply.amount) * 100;
129
+ assert(ratio > 90 && ratio < 110, `Collateralization ratio ${ratio.toFixed(1)}% (expected ~100%)`);
130
+
131
+ // ── Test 6: xmd_get_oracle_price ──
132
+ console.log('\n--- xmd_get_oracle_price (XUSDC = feed 5) ---');
133
+ const oracleData = await getTableRows({ code: ORACLE, scope: ORACLE, table: 'data', lower_bound: 5, upper_bound: 5, limit: 1 });
134
+ assert(oracleData.length === 1, 'USDC/USD oracle data exists');
135
+ const usdcPrice = parseFloat(oracleData[0].aggregate?.d_double || 0);
136
+ assert(usdcPrice >= 0.99 && usdcPrice <= 1.01, `USDC/USD price = ${usdcPrice} (expected ~1.0)`);
137
+ assert(Array.isArray(oracleData[0].points), 'Has provider data points');
138
+
139
+ // PAX oracle
140
+ console.log('\n--- xmd_get_oracle_price (XPAX = feed 14) ---');
141
+ const paxOracle = await getTableRows({ code: ORACLE, scope: ORACLE, table: 'data', lower_bound: 14, upper_bound: 14, limit: 1 });
142
+ assert(paxOracle.length === 1, 'PAX/USD oracle data exists');
143
+ const paxPrice = parseFloat(paxOracle[0].aggregate?.d_double || 0);
144
+ assert(paxPrice >= 0.99 && paxPrice <= 1.01, `PAX/USD price = ${paxPrice.toFixed(6)}`);
145
+ assert(paxOracle[0].points.length >= 2, `PAX has ${paxOracle[0].points.length} oracle providers`);
146
+
147
+ // PYUSD oracle
148
+ console.log('\n--- xmd_get_oracle_price (XPYUSD = feed 17) ---');
149
+ const pyusdOracle = await getTableRows({ code: ORACLE, scope: ORACLE, table: 'data', lower_bound: 17, upper_bound: 17, limit: 1 });
150
+ assert(pyusdOracle.length === 1, 'PYUSD/USD oracle data exists');
151
+ const pyusdPrice = parseFloat(pyusdOracle[0].aggregate?.d_double || 0);
152
+ assert(pyusdPrice >= 0.99 && pyusdPrice <= 1.01, `PYUSD/USD price = ${pyusdPrice.toFixed(6)}`);
153
+
154
+ // Oracle feed names
155
+ console.log('\n--- oracle feed names ---');
156
+ const feedNames = await Promise.all([5, 14, 17, 20].map(async idx => {
157
+ const rows = await getTableRows({ code: ORACLE, scope: ORACLE, table: 'feeds', lower_bound: idx, upper_bound: idx, limit: 1 });
158
+ return { index: idx, name: rows[0]?.name || 'unknown' };
159
+ }));
160
+ for (const f of feedNames) {
161
+ assert(f.name !== 'unknown', `Feed ${f.index} = ${f.name}`);
162
+ }
163
+
164
+ // ── Test 7: net outstanding per collateral ──
165
+ console.log('\n--- net outstanding per collateral ---');
166
+ for (const t of tokens) {
167
+ const sym = parseExtSym(t.symbol);
168
+ if (!sym) continue;
169
+ const minted = parseFloat(t.amountMinted) || 0;
170
+ const redeemed = parseFloat(t.amountRedeemed) || 0;
171
+ const net = minted - redeemed;
172
+ assert(net >= 0, `${sym.symbol}: net outstanding = ${net.toFixed(2)} (minted ${minted.toFixed(0)} - redeemed ${redeemed.toFixed(0)})`);
173
+ }
174
+
175
+ // ── Summary ──
176
+ console.log(`\n${'='.repeat(40)}`);
177
+ console.log(`Results: ${passed} passed, ${failed} failed`);
178
+ process.exit(failed > 0 ? 1 : 0);