@m2msentinel/sdk 1.2.1 → 1.2.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/README.md +15 -3
- package/agent_adapter.js +1 -1
- package/index.d.ts +10 -0
- package/index.js +3 -0
- package/mcp_server.js +2 -2
- package/package.json +1 -1
- package/typescript/index.ts +10 -0
- package/typescript/package.json +1 -1
- package/typescript/x402.ts +10 -1
- package/x402_signer.js +7 -1
package/README.md
CHANGED
|
@@ -40,13 +40,13 @@ Autonomous agents handling value must never rely on a single oracle or heuristic
|
|
|
40
40
|
npm install @m2msentinel/sdk
|
|
41
41
|
|
|
42
42
|
# Or unscoped package
|
|
43
|
-
npm install m2m-sentinel-sdk@1.2.
|
|
43
|
+
npm install m2m-sentinel-sdk@1.2.3
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
### Python (PyPI)
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
pip install m2m-sentinel==1.2.
|
|
49
|
+
pip install m2m-sentinel==1.2.3
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
### MCP Server (Model Context Protocol)
|
|
@@ -77,6 +77,17 @@ console.log('Capability evidence:', audit.audit.dissection.capabilities);
|
|
|
77
77
|
console.log('Proxy Target:', audit.audit.proxyResolution.targetAddress);
|
|
78
78
|
console.log('Reachability:', audit.audit.reachability || 'NOT_ESTABLISHED');
|
|
79
79
|
|
|
80
|
+
// Transaction-specific observation before a caller-owned signing decision.
|
|
81
|
+
const preflight = await client.preflightTransaction({
|
|
82
|
+
chainId: 8453,
|
|
83
|
+
to: '0x1111111111111111111111111111111111111111',
|
|
84
|
+
data: '0x40c10f19'
|
|
85
|
+
});
|
|
86
|
+
console.log('Selector:', preflight.selectorHex);
|
|
87
|
+
console.log('Executing target:', preflight.resolvedExecutionTarget);
|
|
88
|
+
console.log('Observation block:', preflight.observationBlock.blockNumber);
|
|
89
|
+
// The caller must apply its own policy; M2M Sentinel does not return a safety verdict.
|
|
90
|
+
|
|
80
91
|
// 2. Autonomous Headless x402 Micropayments (EIP-3009 Local Signing)
|
|
81
92
|
const x402Client = new X402SignerClient({
|
|
82
93
|
walletSigner: myAgentWallet, // ethers / viem signer
|
|
@@ -115,7 +126,7 @@ const signer = new X402SignerClient({
|
|
|
115
126
|
|
|
116
127
|
## Authentication and x402
|
|
117
128
|
|
|
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`.
|
|
129
|
+
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`. `POST /v1/transaction/preflight` is API-key/RapidAPI metered and is deliberately not in the x402 catalog; it has no x402 price.
|
|
119
130
|
|
|
120
131
|
---
|
|
121
132
|
|
|
@@ -126,6 +137,7 @@ Send API keys only in `x-api-key` (or `Authorization: Bearer`). Query-string cre
|
|
|
126
137
|
- `GET /v1/plans`
|
|
127
138
|
- `GET /v1/demo/audit/:address` for the published sample allowlist
|
|
128
139
|
- `GET /v1/audit/:address` (requires API key or x402 payment)
|
|
140
|
+
- `POST /v1/transaction/preflight` (requires an API key or verified RapidAPI proxy authentication; not x402-payable)
|
|
129
141
|
|
|
130
142
|
The JavaScript, TypeScript, and Python clients expose multi-period purchase/renewal and wallet recovery without requiring callers to hand-build requests:
|
|
131
143
|
|
package/agent_adapter.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -14,6 +14,15 @@ export interface RecoveryChallengeOptions {
|
|
|
14
14
|
txHash?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export interface TransactionPreflightRequest {
|
|
18
|
+
chainId: number | string;
|
|
19
|
+
to: string;
|
|
20
|
+
data: string;
|
|
21
|
+
from?: string;
|
|
22
|
+
value?: number | string;
|
|
23
|
+
blockNumber?: number | string;
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
export interface M2MSentinelErrorOptions {
|
|
18
27
|
status?: number;
|
|
19
28
|
body?: unknown;
|
|
@@ -56,6 +65,7 @@ export class M2MSentinelClient {
|
|
|
56
65
|
getCapabilityScore(address: string, options?: M2MSentinelClientOptions): Promise<any>;
|
|
57
66
|
/** Legacy alias. The response is a capability coverage index, not a safety score. */
|
|
58
67
|
getSecurityScore(address: string, options?: M2MSentinelClientOptions): Promise<any>;
|
|
68
|
+
preflightTransaction(transaction: TransactionPreflightRequest, options?: M2MSentinelClientOptions): Promise<any>;
|
|
59
69
|
getGasFees(options?: M2MSentinelClientOptions): Promise<any>;
|
|
60
70
|
getDexMetrics(options?: M2MSentinelClientOptions): Promise<any>;
|
|
61
71
|
getTokenPrice(symbol: string, options?: M2MSentinelClientOptions): Promise<any>;
|
package/index.js
CHANGED
|
@@ -128,6 +128,9 @@ class M2MSentinelClient {
|
|
|
128
128
|
getCapabilityScore(address, options) { return this.request('GET', '/v1/security/score/' + encodeURIComponent(address), undefined, options); }
|
|
129
129
|
// Legacy method name; the response is a capability coverage index, not a safety score.
|
|
130
130
|
getSecurityScore(address, options) { return this.request('GET', '/v1/security/score/' + encodeURIComponent(address), undefined, options); }
|
|
131
|
+
preflightTransaction(transaction, options) {
|
|
132
|
+
return this.request('POST', '/v1/transaction/preflight', transaction, options);
|
|
133
|
+
}
|
|
131
134
|
getGasFees(options) { return this.request('GET', '/v1/gas/fees', undefined, options); }
|
|
132
135
|
getDexMetrics(options) { return this.request('GET', '/v1/dex/metrics', undefined, options); }
|
|
133
136
|
getTokenPrice(symbol, options) { return this.request('GET', '/v1/token/price/' + encodeURIComponent(symbol), undefined, options); }
|
package/mcp_server.js
CHANGED
|
@@ -8,7 +8,7 @@ const readline = require('readline');
|
|
|
8
8
|
let BASE_URL = process.env.M2M_SENTINEL_BASE_URL || 'https://api.m2msentinel.com';
|
|
9
9
|
let API_KEY = process.env.M2M_SENTINEL_API_KEY || '';
|
|
10
10
|
const TIMEOUT_MS = Number(process.env.M2M_SENTINEL_TIMEOUT_MS || 30000);
|
|
11
|
-
const VERSION = '1.2.
|
|
11
|
+
const VERSION = '1.2.3';
|
|
12
12
|
|
|
13
13
|
const TOOLS = [
|
|
14
14
|
{
|
|
@@ -387,7 +387,7 @@ async function runCli(args) {
|
|
|
387
387
|
console.log(`Network: Base Mainnet (8453)`);
|
|
388
388
|
console.log(`Latency: ${res.latencyMs}ms`);
|
|
389
389
|
console.log('================================================================');
|
|
390
|
-
|
|
390
|
+
|
|
391
391
|
const proxy = auditObj.proxyResolution || auditObj.proxy || {};
|
|
392
392
|
const isProxy = !!proxy.isProxy;
|
|
393
393
|
if (isProxy) {
|
package/package.json
CHANGED
package/typescript/index.ts
CHANGED
|
@@ -18,6 +18,15 @@ export interface RecoveryChallengeOptions {
|
|
|
18
18
|
txHash?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export interface TransactionPreflightRequest {
|
|
22
|
+
chainId: number | string;
|
|
23
|
+
to: string;
|
|
24
|
+
data: string;
|
|
25
|
+
from?: string;
|
|
26
|
+
value?: number | string;
|
|
27
|
+
blockNumber?: number | string;
|
|
28
|
+
}
|
|
29
|
+
|
|
21
30
|
export interface M2MSentinelErrorOptions {
|
|
22
31
|
status?: number;
|
|
23
32
|
body?: any;
|
|
@@ -155,6 +164,7 @@ export class M2MSentinelClient {
|
|
|
155
164
|
public getCapabilityScore(address: string, options?: M2MSentinelClientOptions) { return this.request<any>('GET', `/v1/security/score/${encodeURIComponent(address)}`, undefined, options); }
|
|
156
165
|
/** Legacy name. The response is a capability coverage index, not a safety score. */
|
|
157
166
|
public getSecurityScore(address: string, options?: M2MSentinelClientOptions) { return this.request<any>('GET', `/v1/security/score/${encodeURIComponent(address)}`, undefined, options); }
|
|
167
|
+
public preflightTransaction(transaction: TransactionPreflightRequest, options?: M2MSentinelClientOptions) { return this.request<any>('POST', '/v1/transaction/preflight', transaction, options); }
|
|
158
168
|
public getGasFees(options?: M2MSentinelClientOptions) { return this.request<any>('GET', '/v1/gas/fees', undefined, options); }
|
|
159
169
|
public getDexMetrics(options?: M2MSentinelClientOptions) { return this.request<any>('GET', '/v1/dex/metrics', undefined, options); }
|
|
160
170
|
public getTokenPrice(symbol: string, options?: M2MSentinelClientOptions) { return this.request<any>('GET', `/v1/token/price/${encodeURIComponent(symbol)}`, undefined, options); }
|
package/typescript/package.json
CHANGED
package/typescript/x402.ts
CHANGED
|
@@ -39,6 +39,9 @@ export interface X402PaymentChallenge {
|
|
|
39
39
|
export interface X402SignedAuthorizationV2 {
|
|
40
40
|
x402Version: 2;
|
|
41
41
|
resource?: any;
|
|
42
|
+
/** The server's advertised extensions, echoed back. The CDP Bazaar indexes a
|
|
43
|
+
* resource from the bazaar extension carried by the settlement. */
|
|
44
|
+
extensions?: any;
|
|
42
45
|
/** The chosen offer echoed back verbatim. The server deep-equality matches
|
|
43
46
|
* this against its own requirements to learn which offer is being paid. */
|
|
44
47
|
accepted: any;
|
|
@@ -271,6 +274,12 @@ export class X402SignerClient {
|
|
|
271
274
|
x402Version: 2,
|
|
272
275
|
resource: challenge.resource,
|
|
273
276
|
accepted: offer,
|
|
277
|
+
// Echo the server's advertised extensions back. The canonical client
|
|
278
|
+
// merges paymentRequired.extensions into the payload; omitting the
|
|
279
|
+
// field still settles the payment, so this failed silently -- but the
|
|
280
|
+
// CDP Bazaar indexes a resource from the bazaar extension carried by
|
|
281
|
+
// the settlement, so a payment without it is invisible to discovery.
|
|
282
|
+
extensions: challenge.extensions,
|
|
274
283
|
payload: {
|
|
275
284
|
authorization: {
|
|
276
285
|
from: fromAddress,
|
|
@@ -309,7 +318,7 @@ export class X402SignerClient {
|
|
|
309
318
|
|
|
310
319
|
async fetchWithAutoPayment(path: string, options: any = {}): Promise<any> {
|
|
311
320
|
const url = path.startsWith('http') ? path : `${this.baseUrl}/${path.replace(/^\/+/, '')}`;
|
|
312
|
-
const headers = { 'Accept': 'application/json', 'User-Agent': '@m2msentinel/sdk-ts/1.2.
|
|
321
|
+
const headers = { 'Accept': 'application/json', 'User-Agent': '@m2msentinel/sdk-ts/1.2.3', ...(options.headers || {}) };
|
|
313
322
|
|
|
314
323
|
let res = await fetch(url, { method: options.method || 'GET', headers, body: options.body });
|
|
315
324
|
if (res.status !== 402) {
|
package/x402_signer.js
CHANGED
|
@@ -189,6 +189,12 @@ class X402SignerClient {
|
|
|
189
189
|
x402Version: 2,
|
|
190
190
|
resource: challenge.resource,
|
|
191
191
|
accepted: offer,
|
|
192
|
+
// Echo the server's advertised extensions back. The canonical client
|
|
193
|
+
// merges paymentRequired.extensions into the payload; omitting the
|
|
194
|
+
// field still settles the payment, so this failed silently -- but the
|
|
195
|
+
// CDP Bazaar indexes a resource from the bazaar extension carried by
|
|
196
|
+
// the settlement, so a payment without it is invisible to discovery.
|
|
197
|
+
extensions: challenge.extensions,
|
|
192
198
|
payload: {
|
|
193
199
|
authorization: {
|
|
194
200
|
from: message.from,
|
|
@@ -265,7 +271,7 @@ class X402SignerClient {
|
|
|
265
271
|
path: url.pathname + url.search,
|
|
266
272
|
method: options.method || 'GET',
|
|
267
273
|
headers: {
|
|
268
|
-
'User-Agent': 'M2M-Sentinel-X402Signer/1.2.
|
|
274
|
+
'User-Agent': 'M2M-Sentinel-X402Signer/1.2.3',
|
|
269
275
|
'Accept': 'application/json',
|
|
270
276
|
...(options.headers || {})
|
|
271
277
|
},
|