m2m-sentinel-sdk 1.1.0 → 1.1.2
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 +146 -71
- package/agent_adapter.js +266 -20
- package/eliza_plugin.js +7 -2
- package/index.d.ts +113 -94
- package/index.js +192 -183
- package/m2m_sentinel_sdk.js +1 -1
- package/mcp_server.js +492 -223
- package/package.json +27 -5
- package/smithery.yaml +27 -0
- package/typescript/index.ts +218 -204
- package/typescript/package.json +2 -2
- package/typescript/x402.ts +265 -0
- package/x402_signer.js +243 -0
package/README.md
CHANGED
|
@@ -1,71 +1,146 @@
|
|
|
1
|
-
# M2M Sentinel SDKs
|
|
2
|
-
|
|
3
|
-
Base URL: `https://m2msentinel.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
1
|
+
# M2M Sentinel SDKs
|
|
2
|
+
|
|
3
|
+
Production API Base URL: `https://api.m2msentinel.com` (with fallback `https://m2msentinel.com`).
|
|
4
|
+
|
|
5
|
+
Deterministic EVM bytecode and proxy capability intelligence on Base. Factual static capability observation — not a formal reachability audit, safety guarantee, or transaction advice. Live latency depends on RPC availability and deployment geography; transaction middleware requires a caller-defined policy and has no built-in decision threshold.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🏗️ Recommended Defense-in-Depth Pipeline for Agents
|
|
10
|
+
|
|
11
|
+
Autonomous agents handling value must never rely on a single oracle or heuristic. M2M Sentinel can supply static observations as Layer 1 of a caller-owned pipeline:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
[Agent Intent]
|
|
15
|
+
│
|
|
16
|
+
▼
|
|
17
|
+
[Transaction Builder]
|
|
18
|
+
│
|
|
19
|
+
▼
|
|
20
|
+
[Stage 1: M2M Sentinel Observation] ── (Bytecode hash, proxy target, selected opcode/selector evidence)
|
|
21
|
+
│
|
|
22
|
+
▼
|
|
23
|
+
[Stage 2: Local Policy Engine] ── (Caller-defined rules: Check spending bounds, reject DELEGATECALL, verify allowlist)
|
|
24
|
+
│
|
|
25
|
+
▼
|
|
26
|
+
[Stage 3: Execution Simulation] ── (eth_call / Tenderly / Trace state simulation)
|
|
27
|
+
│
|
|
28
|
+
▼
|
|
29
|
+
[Stage 4: Sub-Wallet Signing] ── (Scoped ephemeral wallet signs & broadcasts on Base)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
### JavaScript / TypeScript (npm)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Scoped package (recommended)
|
|
40
|
+
npm install @m2msentinel/sdk
|
|
41
|
+
|
|
42
|
+
# Or unscoped package
|
|
43
|
+
npm install m2m-sentinel-sdk@1.1.2
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Python (PyPI)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install m2m-sentinel==1.1.2
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### MCP Server (Model Context Protocol)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx -y @m2msentinel/sdk
|
|
56
|
+
# or
|
|
57
|
+
npx -y m2m-sentinel-sdk
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Quickstart: JavaScript / TypeScript
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const { M2MSentinelClient, X402SignerClient } = require('@m2msentinel/sdk');
|
|
66
|
+
|
|
67
|
+
// 1. Standard API Client (Header Authentication)
|
|
68
|
+
const client = new M2MSentinelClient({
|
|
69
|
+
apiKey: process.env.M2M_SENTINEL_API_KEY,
|
|
70
|
+
baseUrl: 'https://api.m2msentinel.com'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Inspect contract capabilities before transaction
|
|
74
|
+
const audit = await client.auditContract('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
75
|
+
console.log('Contract capabilities:', audit.audit.verdict.executableCapabilities);
|
|
76
|
+
console.log('Capability evidence:', audit.audit.dissection.capabilities);
|
|
77
|
+
console.log('Proxy Target:', audit.audit.proxyResolution.targetAddress);
|
|
78
|
+
console.log('Reachability:', audit.audit.reachability || 'NOT_ESTABLISHED');
|
|
79
|
+
|
|
80
|
+
// 2. Autonomous Headless x402 Micropayments (EIP-3009 Local Signing)
|
|
81
|
+
const x402Client = new X402SignerClient({
|
|
82
|
+
walletSigner: myAgentWallet, // ethers / viem signer
|
|
83
|
+
baseUrl: 'https://api.m2msentinel.com',
|
|
84
|
+
maxPriceUsd: 0.01 // Optional: strict spending limit (default $0.05)
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const res = await x402Client.fetchWithAutoPayment('/v1/audit/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
88
|
+
console.log('Paid analysis result:', res.json);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 🛡️ Autonomous Wallet Policy & Security Boundaries
|
|
94
|
+
|
|
95
|
+
To prevent autonomous AI agents from blindly signing arbitrary or spoofed HTTP 402 challenges from untrusted sources, `X402SignerClient` enforces **4 strict client-side invariants** locally before generating any cryptographic signature:
|
|
96
|
+
|
|
97
|
+
| Client Invariant | Enforced Value | Security Protection |
|
|
98
|
+
| :--- | :--- | :--- |
|
|
99
|
+
| **Chain ID** | `8453` (Base Mainnet) | Rejects signing on any unapproved EVM chain. |
|
|
100
|
+
| **Asset Contract** | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | Rejects signing for unapproved tokens (Base USDC only). |
|
|
101
|
+
| **Payout Recipient** | `0x6d6c398390cfb88f1cd42715b84906a0bd6652aa` | Rejects signing payments to unexpected recipient addresses. |
|
|
102
|
+
| **Price Ceiling** | `maxPriceUsd` (Default: `$0.05`) | Throws if remote challenge requests funds exceeding caller's authorized ceiling. |
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
import { X402SignerClient } from '@m2msentinel/sdk';
|
|
106
|
+
|
|
107
|
+
// Fully policy-constrained autonomous signer with immutable recipient & domain constants
|
|
108
|
+
const signer = new X402SignerClient({
|
|
109
|
+
wallet: agentWallet,
|
|
110
|
+
maxPriceUsd: 0.005 // Strict spending limit: 0.5 cents max per decision (default $0.05)
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Authentication and x402
|
|
117
|
+
|
|
118
|
+
Send API keys only in `x-api-key` (or `Authorization: Bearer`). Query-string credentials are rejected with HTTP 401. Payable routes also support x402 v2 on Base USDC. An unpaid call returns a base64 `PAYMENT-REQUIRED` challenge; a successful settlement returns `PAYMENT-RESPONSE`.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Public Routes
|
|
123
|
+
|
|
124
|
+
- `GET /v1/status`
|
|
125
|
+
- `GET /v1/stats` (public privacy envelope; exact aggregate commercial counters are operator-only)
|
|
126
|
+
- `GET /v1/plans`
|
|
127
|
+
- `GET /v1/demo/audit/:address` for the published sample allowlist
|
|
128
|
+
- `GET /v1/audit/:address` (requires API key or x402 payment)
|
|
129
|
+
|
|
130
|
+
The JavaScript, TypeScript, and Python clients expose multi-period purchase/renewal and wallet recovery without requiring callers to hand-build requests:
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
await client.createSubscriptionIntent('GROWTH', wallet, {
|
|
134
|
+
durationDays: 90,
|
|
135
|
+
renewExistingKey: true,
|
|
136
|
+
apiKey: existingPaidKey
|
|
137
|
+
});
|
|
138
|
+
const challenge = await client.createRecoveryChallenge(wallet, { txHash });
|
|
139
|
+
await client.claimRecoveredKey(challenge.intent.id, walletSignature);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Disclaimer & Limitations
|
|
145
|
+
|
|
146
|
+
Deterministic EVM bytecode and proxy capability intelligence on Base. Factual static capability observation — not a formal reachability audit, safety guarantee, or transaction advice. Live latency depends on RPC availability and deployment geography.
|
package/agent_adapter.js
CHANGED
|
@@ -1,30 +1,276 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Coinbase AgentKit Action Provider for M2M Sentinel.
|
|
5
|
+
*
|
|
6
|
+
* Exposes pre-transaction contract bytecode capability inspection, proxy resolution,
|
|
7
|
+
* and market observations to autonomous Base agents using @coinbase/agentkit.
|
|
8
|
+
*/
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
const https = require('https');
|
|
11
|
+
const http = require('http');
|
|
12
|
+
|
|
13
|
+
const DEFAULT_BASE_URL = process.env.M2M_SENTINEL_BASE_URL || 'https://api.m2msentinel.com';
|
|
14
|
+
const DEFAULT_TIMEOUT_MS = Number(process.env.M2M_SENTINEL_TIMEOUT_MS || 30000);
|
|
15
|
+
|
|
16
|
+
function summarizeAuditResponse(body, requestedAddress) {
|
|
17
|
+
const audit = body && body.audit ? body.audit : {};
|
|
18
|
+
const proxy = audit.proxyResolution || {};
|
|
19
|
+
const capabilities = Array.isArray(audit.verdict && audit.verdict.executableCapabilities)
|
|
20
|
+
? audit.verdict.executableCapabilities
|
|
21
|
+
: (audit.dissection && Array.isArray(audit.dissection.capabilities)
|
|
22
|
+
? audit.dissection.capabilities
|
|
23
|
+
.map((item) => typeof item === 'string' ? item : item && item.type)
|
|
24
|
+
.filter(Boolean)
|
|
25
|
+
: []);
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
address: audit.address || requestedAddress,
|
|
29
|
+
isContract: Boolean(audit.dissection && audit.dissection.isValidContract),
|
|
30
|
+
isProxy: Boolean(proxy.isProxy),
|
|
31
|
+
proxyType: proxy.proxyType || 'NONE',
|
|
32
|
+
targetAddress: proxy.targetAddress || null,
|
|
33
|
+
executableCapabilities: capabilities,
|
|
34
|
+
reachability: audit.reachability || 'NOT_ESTABLISHED',
|
|
35
|
+
trustLevel: audit.provenance && audit.provenance.trustLevel
|
|
36
|
+
? audit.provenance.trustLevel
|
|
37
|
+
: 'NOT_REPORTED'
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class M2MSentinelActionProvider {
|
|
6
42
|
constructor(options = {}) {
|
|
7
|
-
this.name = '
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
10
|
-
|
|
11
|
-
|
|
43
|
+
this.name = 'm2m_sentinel';
|
|
44
|
+
this.actionProviderName = 'm2m_sentinel';
|
|
45
|
+
this.baseUrl = options.baseUrl || DEFAULT_BASE_URL;
|
|
46
|
+
this.apiKey = options.apiKey || process.env.M2M_SENTINEL_API_KEY || '';
|
|
47
|
+
this.timeoutMs = Number(options.timeoutMs || DEFAULT_TIMEOUT_MS);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
supportsNetwork(network) {
|
|
51
|
+
if (!network) return true;
|
|
52
|
+
const chainId = String(network.chainId || network.networkId || '');
|
|
53
|
+
const protocolFamily = String(network.protocolFamily || 'evm').toLowerCase();
|
|
54
|
+
return protocolFamily === 'evm' && (
|
|
55
|
+
chainId === '8453' ||
|
|
56
|
+
chainId === 'base' ||
|
|
57
|
+
chainId === 'base-mainnet' ||
|
|
58
|
+
chainId === 'base-sepolia' ||
|
|
59
|
+
chainId === '84532'
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async _queryApi(endpointPath, options = {}) {
|
|
64
|
+
const url = new URL(endpointPath, this.baseUrl);
|
|
65
|
+
const isHttps = url.protocol === 'https:';
|
|
66
|
+
const transport = isHttps ? https : http;
|
|
67
|
+
|
|
68
|
+
const headers = {
|
|
69
|
+
Accept: 'application/json',
|
|
70
|
+
'User-Agent': 'M2MSentinel-AgentKit/1.1.2',
|
|
71
|
+
...options.headers
|
|
72
|
+
};
|
|
73
|
+
if (this.apiKey && !headers['x-api-key']) {
|
|
74
|
+
headers['x-api-key'] = this.apiKey;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const req = transport.request(url, {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
headers,
|
|
81
|
+
timeout: this.timeoutMs
|
|
82
|
+
}, (res) => {
|
|
83
|
+
let data = '';
|
|
84
|
+
res.setEncoding('utf8');
|
|
85
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
86
|
+
res.on('end', () => {
|
|
87
|
+
let body = null;
|
|
88
|
+
if (data) {
|
|
89
|
+
try { body = JSON.parse(data); } catch (_) { body = { raw: data }; }
|
|
90
|
+
}
|
|
91
|
+
resolve({
|
|
92
|
+
statusCode: res.statusCode,
|
|
93
|
+
ok: res.statusCode >= 200 && res.statusCode < 300,
|
|
94
|
+
body
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
req.on('timeout', () => req.destroy(new Error('M2M Sentinel request timed out')));
|
|
100
|
+
req.on('error', reject);
|
|
101
|
+
req.end();
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async auditContract(args) {
|
|
106
|
+
const address = String(args.address || args.contractAddress || '').trim();
|
|
107
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
|
|
108
|
+
return JSON.stringify({
|
|
109
|
+
status: 'ERROR',
|
|
110
|
+
error: 'INVALID_ADDRESS',
|
|
111
|
+
message: 'A valid 40-hex 0x-prefixed Base contract address is required.'
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const res = await this._queryApi(`/v1/audit/${encodeURIComponent(address)}`);
|
|
116
|
+
if (!res.ok) {
|
|
117
|
+
return JSON.stringify({
|
|
118
|
+
status: 'ERROR',
|
|
119
|
+
statusCode: res.statusCode,
|
|
120
|
+
error: res.body && res.body.error ? res.body.error : 'API_ERROR',
|
|
121
|
+
message: res.body && res.body.message ? res.body.message : 'Contract audit query failed',
|
|
122
|
+
notASafetyGuarantee: true
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const observation = summarizeAuditResponse(res.body, address);
|
|
127
|
+
return JSON.stringify({
|
|
128
|
+
status: 'SUCCESS',
|
|
129
|
+
data: res.body,
|
|
130
|
+
notASafetyGuarantee: true,
|
|
131
|
+
observation,
|
|
132
|
+
observationSummary: `Contract ${observation.address}: isContract=${observation.isContract}, isProxy=${observation.isProxy}, proxyTarget=${observation.targetAddress || 'UNRESOLVED'}, capabilities=${observation.executableCapabilities.join(',') || 'NONE_OBSERVED'}, reachability=${observation.reachability}`
|
|
12
133
|
});
|
|
13
134
|
}
|
|
14
135
|
|
|
15
|
-
async
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
136
|
+
async getGasMetrics() {
|
|
137
|
+
const res = await this._queryApi('/v1/gas/fees');
|
|
138
|
+
if (!res.ok) {
|
|
139
|
+
return JSON.stringify({ status: 'ERROR', statusCode: res.statusCode, message: 'Failed to retrieve gas fees' });
|
|
140
|
+
}
|
|
141
|
+
return JSON.stringify(res.body);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async getTokenPrice(args) {
|
|
145
|
+
const symbol = String(args.symbol || args.tokenSymbol || '').trim().toUpperCase();
|
|
146
|
+
if (!symbol) {
|
|
147
|
+
return JSON.stringify({ status: 'ERROR', message: 'Token symbol is required (e.g. USDC, WETH)' });
|
|
148
|
+
}
|
|
149
|
+
const res = await this._queryApi(`/v1/token/price/${encodeURIComponent(symbol)}`);
|
|
150
|
+
if (!res.ok) {
|
|
151
|
+
return JSON.stringify({ status: 'ERROR', statusCode: res.statusCode, message: `Failed to retrieve price for ${symbol}` });
|
|
152
|
+
}
|
|
153
|
+
return JSON.stringify(res.body);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async getServiceStatus() {
|
|
157
|
+
const res = await this._queryApi('/v1/status');
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
return JSON.stringify({ status: 'UNAVAILABLE', statusCode: res.statusCode });
|
|
26
160
|
}
|
|
161
|
+
return JSON.stringify(res.body);
|
|
27
162
|
}
|
|
163
|
+
|
|
164
|
+
async getDexLiquidity(args = {}) {
|
|
165
|
+
const pair = String(args.pair || 'WETH-USDC').trim();
|
|
166
|
+
const res = await this._queryApi(`/v1/dex/metrics?pair=${encodeURIComponent(pair)}`);
|
|
167
|
+
if (!res.ok) {
|
|
168
|
+
return JSON.stringify({ status: 'ERROR', statusCode: res.statusCode, message: 'Failed to retrieve DEX liquidity' });
|
|
169
|
+
}
|
|
170
|
+
return JSON.stringify(res.body);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async getWhaleSignals(args = {}) {
|
|
174
|
+
const limit = Number(args.limit || 10);
|
|
175
|
+
const res = await this._queryApi(`/v1/whales/signals?limit=${encodeURIComponent(limit)}`);
|
|
176
|
+
if (!res.ok) {
|
|
177
|
+
return JSON.stringify({ status: 'ERROR', statusCode: res.statusCode, message: 'Failed to retrieve whale signals' });
|
|
178
|
+
}
|
|
179
|
+
return JSON.stringify(res.body);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
getActions(_walletProvider) {
|
|
183
|
+
return [
|
|
184
|
+
{
|
|
185
|
+
name: 'm2m_audit_contract',
|
|
186
|
+
description: 'Inspect Base target contract bytecode capability observations, proxy implementation slots, and limitations before executing transactions. Returns factual evidence, not a safety guarantee.',
|
|
187
|
+
schema: {
|
|
188
|
+
type: 'object',
|
|
189
|
+
properties: {
|
|
190
|
+
address: {
|
|
191
|
+
type: 'string',
|
|
192
|
+
description: 'Target Base contract address (0x-prefixed 40-hex)'
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
required: ['address']
|
|
196
|
+
},
|
|
197
|
+
invoke: (args) => this.auditContract(args)
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: 'm2m_get_gas_metrics',
|
|
201
|
+
description: 'Get real-time Base network gas execution metrics and recommendations before submitting on-chain transactions.',
|
|
202
|
+
schema: {
|
|
203
|
+
type: 'object',
|
|
204
|
+
properties: {}
|
|
205
|
+
},
|
|
206
|
+
invoke: () => this.getGasMetrics()
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: 'm2m_get_token_price',
|
|
210
|
+
description: 'Observe real-time Base DEX token price for slippage check and valuation.',
|
|
211
|
+
schema: {
|
|
212
|
+
type: 'object',
|
|
213
|
+
properties: {
|
|
214
|
+
symbol: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
description: 'Token symbol on Base (e.g. USDC, WETH)'
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
required: ['symbol']
|
|
220
|
+
},
|
|
221
|
+
invoke: (args) => this.getTokenPrice(args)
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: 'm2m_get_dex_liquidity',
|
|
225
|
+
description: 'Get tracked Base DEX pool reserve and liquidity metrics.',
|
|
226
|
+
schema: {
|
|
227
|
+
type: 'object',
|
|
228
|
+
properties: {
|
|
229
|
+
pair: {
|
|
230
|
+
type: 'string',
|
|
231
|
+
description: 'DEX pair identifier (e.g. WETH-USDC)'
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
invoke: (args) => this.getDexLiquidity(args)
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: 'm2m_get_whale_signals',
|
|
239
|
+
description: 'Get tracked Base whale transfer and concentration signals.',
|
|
240
|
+
schema: {
|
|
241
|
+
type: 'object',
|
|
242
|
+
properties: {
|
|
243
|
+
limit: {
|
|
244
|
+
type: 'number',
|
|
245
|
+
description: 'Maximum signals to retrieve (1-50)'
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
invoke: (args) => this.getWhaleSignals(args)
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: 'm2m_get_service_status',
|
|
253
|
+
description: 'Check operational status of M2M Sentinel upstream verification rails.',
|
|
254
|
+
schema: {
|
|
255
|
+
type: 'object',
|
|
256
|
+
properties: {}
|
|
257
|
+
},
|
|
258
|
+
invoke: () => this.getServiceStatus()
|
|
259
|
+
}
|
|
260
|
+
];
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function m2mSentinelActionProvider(options = {}) {
|
|
265
|
+
return new M2MSentinelActionProvider(options);
|
|
28
266
|
}
|
|
29
267
|
|
|
30
|
-
|
|
268
|
+
// Backward compatibility alias
|
|
269
|
+
class M2MSentinelAgentTool extends M2MSentinelActionProvider {}
|
|
270
|
+
|
|
271
|
+
module.exports = {
|
|
272
|
+
M2MSentinelActionProvider,
|
|
273
|
+
m2mSentinelActionProvider,
|
|
274
|
+
M2MSentinelAgentTool,
|
|
275
|
+
summarizeAuditResponse
|
|
276
|
+
};
|
package/eliza_plugin.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* M2M Sentinel ElizaOS Production Adapter Plugin
|
|
3
|
+
*
|
|
4
|
+
* Provides automated pre-transaction contract capability preflight and proxy inspection
|
|
5
|
+
* actions for autonomous agents running on the ElizaOS runtime framework.
|
|
6
|
+
*/
|
|
2
7
|
|
|
3
8
|
const { M2MSentinelClient } = require('./index.js');
|
|
4
9
|
|
|
@@ -81,4 +86,4 @@ const m2mSentinelPlugin = {
|
|
|
81
86
|
]
|
|
82
87
|
};
|
|
83
88
|
|
|
84
|
-
module.exports = { m2mSentinelPlugin };
|
|
89
|
+
module.exports = { m2mSentinelPlugin };
|