m2m-sentinel-sdk 1.0.2 → 1.0.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.
Files changed (41) hide show
  1. package/README.md +44 -28
  2. package/agent_adapter.js +30 -0
  3. package/eliza_plugin.js +84 -0
  4. package/index.js +136 -19
  5. package/m2m_sentinel_sdk.js +1 -12
  6. package/mcp_server.js +172 -0
  7. package/package.json +26 -9
  8. package/typescript/index.ts +135 -35
  9. package/typescript/package.json +4 -3
  10. package/cli/m2m_cli.js +0 -25
  11. package/csharp/M2MSentinel.csproj +0 -9
  12. package/csharp/M2MSentinelClient.cs +0 -67
  13. package/go/client.go +0 -94
  14. package/go/go.mod +0 -3
  15. package/java/M2MSentinelClient.java +0 -67
  16. package/java/pom.xml +0 -20
  17. package/java/src/main/java/com/m2msentinel/M2MSentinelClient.java +0 -69
  18. package/kotlin/M2MSentinelClient.kt +0 -59
  19. package/kotlin/build.gradle.kts +0 -24
  20. package/m2m_sentinel/__init__.py +0 -3
  21. package/m2m_sentinel/client.py +0 -16
  22. package/m2m_sentinel_sdk.py +0 -9
  23. package/php/M2MSentinelClient.php +0 -52
  24. package/php/composer.json +0 -20
  25. package/python/dist/m2m_sentinel-0.1.0-py3-none-any.whl +0 -0
  26. package/python/dist/m2m_sentinel-0.1.0.tar.gz +0 -0
  27. package/python/dist/m2m_sentinel-0.1.1-py3-none-any.whl +0 -0
  28. package/python/dist/m2m_sentinel-0.1.1.tar.gz +0 -0
  29. package/python/m2m_sentinel/__pycache__/client.cpython-314.pyc +0 -0
  30. package/python/m2m_sentinel/client.py +0 -40
  31. package/python/m2m_sentinel.egg-info/PKG-INFO +0 -35
  32. package/python/m2m_sentinel.egg-info/SOURCES.txt +0 -5
  33. package/python/m2m_sentinel.egg-info/dependency_links.txt +0 -1
  34. package/python/m2m_sentinel.egg-info/top_level.txt +0 -1
  35. package/python/setup.py +0 -35
  36. package/ruby/m2m_sentinel.gemspec +0 -17
  37. package/ruby/m2m_sentinel.rb +0 -55
  38. package/rust/Cargo.toml +0 -11
  39. package/rust/src/lib.rs +0 -61
  40. package/swift/M2MSentinelClient.swift +0 -65
  41. package/swift/Package.swift +0 -23
@@ -1,49 +1,149 @@
1
- export class M2MSentinelClient {
2
- private baseUrl: string;
3
- public readonly payoutWallet: string = "0x1C79BfBFA67Ab140f72f0F6888123a70D9DaC23e";
1
+ export interface M2MSentinelClientOptions {
2
+ apiKey?: string;
3
+ baseUrl?: string;
4
+ timeoutMs?: number;
5
+ paymentSignature?: string;
6
+ }
4
7
 
5
- constructor(baseUrl: string = "https://m2msentinel.vercel.app") {
6
- this.baseUrl = baseUrl.replace(/\/$/, "");
7
- }
8
+ export interface M2MSentinelErrorOptions {
9
+ status?: number;
10
+ body?: any;
11
+ retryAfter?: string | null;
12
+ paymentRequired?: any;
13
+ paymentResponse?: any;
14
+ }
8
15
 
9
- private async get<T>(path: string): Promise<T> {
10
- const response = await fetch(`${this.baseUrl}${path}`);
11
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
12
- return response.json() as Promise<T>;
13
- }
16
+ export class M2MSentinelError extends Error {
17
+ public readonly status?: number;
18
+ public readonly body?: any;
19
+ public readonly retryAfter?: string | null;
20
+ public readonly paymentRequired?: any;
21
+ public readonly paymentResponse?: any;
14
22
 
15
- public async auditContract(address: string) {
16
- return this.get<any>(`/v1/audit/${address}`);
17
- }
23
+ constructor(message: string, options: M2MSentinelErrorOptions = {}) {
24
+ super(message);
25
+ this.name = new.target.name;
26
+ this.status = options.status;
27
+ this.body = options.body;
28
+ this.retryAfter = options.retryAfter || null;
29
+ this.paymentRequired = options.paymentRequired || null;
30
+ this.paymentResponse = options.paymentResponse || null;
31
+ }
32
+ }
18
33
 
19
- public async getDexMetrics() {
20
- return this.get<any>("/v1/dex/metrics");
21
- }
34
+ export class PaymentRequiredError extends M2MSentinelError {}
35
+ export class RateLimitedError extends M2MSentinelError {}
36
+ export class DataSourceUnavailableError extends M2MSentinelError {}
22
37
 
23
- public async getWhaleSignals() {
24
- return this.get<any>("/v1/whales/signals");
25
- }
38
+ const DEFAULT_BASE_URL = 'https://m2msentinel.vercel.app';
39
+ const DEFAULT_TIMEOUT_MS = 30000;
26
40
 
27
- public async getTokenPrice(symbol: string) {
28
- return this.get<any>(`/v1/token/price/${symbol}`);
29
- }
41
+ function parseHeaderJson(value: string | null): any {
42
+ if (!value) return null;
43
+ try { return JSON.parse(value); } catch { return null; }
44
+ }
30
45
 
31
- public async search(query: string) {
32
- const q = encodeURIComponent(query);
33
- return this.get<any>(`/v1/search?q=${q}`);
34
- }
46
+ export class M2MSentinelClient {
47
+ private baseUrl: string;
48
+ private apiKey?: string;
49
+ private timeoutMs: number;
50
+ private paymentSignature?: string;
51
+
52
+ constructor(optionsOrBaseUrl: M2MSentinelClientOptions | string = {}, apiKey?: string) {
53
+ const options = typeof optionsOrBaseUrl === 'string'
54
+ ? { baseUrl: optionsOrBaseUrl, apiKey }
55
+ : optionsOrBaseUrl;
56
+ this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, '');
57
+ this.apiKey = options.apiKey;
58
+ this.timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS;
59
+ this.paymentSignature = options.paymentSignature;
60
+ }
61
+
62
+ private async request<T>(method: 'GET' | 'POST', path: string, body?: any, options: M2MSentinelClientOptions = {}): Promise<T> {
63
+ const headers: Record<string, string> = {
64
+ Accept: 'application/json'
65
+ };
66
+ if (body !== undefined) headers['Content-Type'] = 'application/json';
67
+ const key = options.apiKey || this.apiKey;
68
+ if (key) headers['x-api-key'] = key;
69
+ const paymentSignature = options.paymentSignature || this.paymentSignature;
70
+ if (paymentSignature) headers['PAYMENT-SIGNATURE'] = paymentSignature;
35
71
 
36
- public async tokenAuditMulti() {
37
- return this.get<any>("/v1/token/audit/multi");
72
+ const controller = new AbortController();
73
+ const timeout = setTimeout(() => controller.abort(), options.timeoutMs || this.timeoutMs);
74
+ let response: Response;
75
+ try {
76
+ response = await fetch(this.baseUrl + path, {
77
+ method,
78
+ headers,
79
+ body: body === undefined ? undefined : JSON.stringify(body),
80
+ signal: controller.signal
81
+ });
82
+ } finally {
83
+ clearTimeout(timeout);
38
84
  }
39
85
 
40
- public async getNftFloor(collection: string) {
41
- const q = encodeURIComponent(collection);
42
- return this.get<any>(`/v1/nft/floor?collection=${q}`);
86
+ const text = await response.text();
87
+ let data: any = null;
88
+ if (text) {
89
+ try { data = JSON.parse(text); } catch { data = { raw: text }; }
43
90
  }
91
+ if (response.ok) return data as T;
44
92
 
45
- public async getAiSentiment(symbol: string) {
46
- const q = encodeURIComponent(symbol);
47
- return this.get<any>(`/v1/ai/sentiment?symbol=${q}`);
93
+ const errorOptions = {
94
+ status: response.status,
95
+ body: data,
96
+ retryAfter: response.headers.get('Retry-After'),
97
+ paymentRequired: parseHeaderJson(response.headers.get('PAYMENT-REQUIRED')),
98
+ paymentResponse: parseHeaderJson(response.headers.get('PAYMENT-RESPONSE')) || response.headers.get('PAYMENT-RESPONSE')
99
+ };
100
+ const message = data?.message || `M2M Sentinel HTTP ${response.status}`;
101
+ if (response.status === 402) throw new PaymentRequiredError(message, errorOptions);
102
+ if (response.status === 429) throw new RateLimitedError(message, errorOptions);
103
+ if (response.status === 503 && data?.error === 'DATA_SOURCE_UNAVAILABLE') throw new DataSourceUnavailableError(message, errorOptions);
104
+ throw new M2MSentinelError(message, errorOptions);
105
+ }
106
+
107
+ public getStatus() { return this.request<any>('GET', '/v1/status'); }
108
+ public getPlans() { return this.request<any>('GET', '/v1/plans'); }
109
+ public createFreeChallenge(userWallet: string) { return this.request<any>('POST', '/v1/subscribe/free/challenge', { userWallet }); }
110
+ public claimFreeTier(intentId: string, signature: string) { return this.request<any>('POST', '/v1/subscribe/free/claim', { intentId, signature }); }
111
+ public createSubscriptionIntent(tier: string, userWallet: string) { return this.request<any>('POST', '/v1/subscribe/intents', { tier, userWallet }); }
112
+ public claimSubscription(intentId: string, signature: string, txHash: string) { return this.request<any>('POST', '/v1/subscribe/crypto', { intentId, signature, txHash }); }
113
+ public auditContract(address: string, options?: M2MSentinelClientOptions) { return this.request<any>('GET', `/v1/audit/${encodeURIComponent(address)}`, undefined, options); }
114
+ public getSecurityScore(address: string, options?: M2MSentinelClientOptions) { return this.request<any>('GET', `/v1/security/score/${encodeURIComponent(address)}`, undefined, options); }
115
+ public getGasFees(options?: M2MSentinelClientOptions) { return this.request<any>('GET', '/v1/gas/fees', undefined, options); }
116
+ public getDexMetrics(options?: M2MSentinelClientOptions) { return this.request<any>('GET', '/v1/dex/metrics', undefined, options); }
117
+ public getTokenPrice(symbol: string, options?: M2MSentinelClientOptions) { return this.request<any>('GET', `/v1/token/price/${encodeURIComponent(symbol)}`, undefined, options); }
118
+ public getWhaleSignals(options?: M2MSentinelClientOptions) { return this.request<any>('GET', '/v1/whales/signals', undefined, options); }
119
+ public getKeySelf() { return this.request<any>('GET', '/v1/keys/self'); }
120
+ public revokeKey(confirm = true) { return this.request<any>('POST', '/v1/keys/revoke', { confirm }); }
121
+ }
122
+
123
+ export function createEthersSentinelMiddleware(apiKey?: string, baseUrl?: string) {
124
+ const client = new M2MSentinelClient({ apiKey, baseUrl });
125
+ return {
126
+ client,
127
+ verifyContractBeforeTx: async (targetAddress: string) => {
128
+ const audit = await client.auditContract(targetAddress);
129
+ if (audit?.audit?.verdict?.securityRating === 'HIGH_RISK') {
130
+ throw new Error(`[M2M Sentinel] Transaction blocked: ${targetAddress} flagged HIGH_RISK.`);
131
+ }
132
+ return audit;
48
133
  }
134
+ };
49
135
  }
136
+
137
+ export function createViemSentinelInterceptor(apiKey?: string, baseUrl?: string) {
138
+ const client = new M2MSentinelClient({ apiKey, baseUrl });
139
+ return {
140
+ client,
141
+ inspectSwapTarget: async (address: string) => {
142
+ const score = await client.getSecurityScore(address);
143
+ if (score?.decisionGrade && typeof score.securityScore === 'number' && score.securityScore < 50) {
144
+ throw new Error(`[M2M Sentinel] Security score too low (${score.securityScore}/100) for ${address}`);
145
+ }
146
+ return score;
147
+ }
148
+ };
149
+ }
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "m2m-sentinel-sdk",
3
- "version": "0.1.0",
4
- "description": "M2M Sentinel TypeScript SDK",
3
+ "version": "1.0.4",
4
+ "description": "Source-distributed TypeScript client for M2M Sentinel Web3 API",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
+ "private": true,
7
8
  "scripts": {
8
9
  "build": "tsc"
9
10
  },
10
11
  "devDependencies": {
11
12
  "typescript": "^5.0.0"
12
13
  }
13
- }
14
+ }
package/cli/m2m_cli.js DELETED
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const command = process.argv[2];
4
- const address = process.argv[3];
5
-
6
- if (command === "audit" && address) {
7
- const url = `https://m2msentinel.vercel.app/v1/audit/${address}`;
8
- fetch(url)
9
- .then(res => {
10
- if (!res.ok) {
11
- throw new Error(`HTTP error! status: ${res.status}`);
12
- }
13
- return res.json();
14
- })
15
- .then(data => {
16
- console.log(JSON.stringify(data, null, 2));
17
- })
18
- .catch(err => {
19
- console.error("Error running audit:", err.message);
20
- process.exit(1);
21
- });
22
- } else {
23
- console.log("Usage: npx m2m-cli audit <address>");
24
- process.exit(1);
25
- }
@@ -1,9 +0,0 @@
1
- <Project Sdk="Microsoft.NET.Sdk">
2
- <PropertyGroup>
3
- <TargetFramework>netstandard2.0</TargetFramework>
4
- <PackageId>M2MSentinel</PackageId>
5
- <Version>1.0.0</Version>
6
- <Authors>M2M Sentinel</Authors>
7
- <Description>Enterprise C# SDK for M2M Sentinel.</Description>
8
- </PropertyGroup>
9
- </Project>
@@ -1,67 +0,0 @@
1
- using System;
2
- using System.Net.Http;
3
- using System.Threading.Tasks;
4
- using System.Web;
5
-
6
- namespace M2MSentinel
7
- {
8
- public class M2MSentinelClient
9
- {
10
- private readonly HttpClient _httpClient;
11
- private readonly string _baseUrl;
12
- public readonly string PayoutWallet = "0x1C79BfBFA67Ab140f72f0F6888123a70D9DaC23e";
13
-
14
- public M2MSentinelClient(string baseUrl = "https://m2msentinel.vercel.app")
15
- {
16
- _baseUrl = baseUrl.TrimEnd('/');
17
- _httpClient = new HttpClient();
18
- }
19
-
20
- private async Task<string> GetAsync(string path)
21
- {
22
- var response = await _httpClient.GetAsync($"{_baseUrl}{path}");
23
- response.EnsureSuccessStatusCode();
24
- return await response.Content.ReadAsStringAsync();
25
- }
26
-
27
- public Task<string> AuditContractAsync(string address)
28
- {
29
- return GetAsync($"/v1/audit/{HttpUtility.UrlEncode(address)}");
30
- }
31
-
32
- public Task<string> GetDexMetricsAsync()
33
- {
34
- return GetAsync("/v1/dex/metrics");
35
- }
36
-
37
- public Task<string> GetWhaleSignalsAsync()
38
- {
39
- return GetAsync("/v1/whales/signals");
40
- }
41
-
42
- public Task<string> GetTokenPriceAsync(string symbol)
43
- {
44
- return GetAsync($"/v1/token/price/{HttpUtility.UrlEncode(symbol)}");
45
- }
46
-
47
- public Task<string> SearchAsync(string query)
48
- {
49
- return GetAsync($"/v1/search?q={HttpUtility.UrlEncode(query)}");
50
- }
51
-
52
- public Task<string> TokenAuditMultiAsync()
53
- {
54
- return GetAsync("/v1/token/audit/multi");
55
- }
56
-
57
- public Task<string> GetNftFloorAsync(string collection)
58
- {
59
- return GetAsync($"/v1/nft/floor?collection={HttpUtility.UrlEncode(collection)}");
60
- }
61
-
62
- public Task<string> GetAiSentimentAsync(string symbol)
63
- {
64
- return GetAsync($"/v1/ai/sentiment?symbol={HttpUtility.UrlEncode(symbol)}");
65
- }
66
- }
67
- }
package/go/client.go DELETED
@@ -1,94 +0,0 @@
1
- package m2m_sentinel
2
-
3
- import (
4
- "encoding/json"
5
- "fmt"
6
- "net/http"
7
- "net/url"
8
- "strings"
9
- )
10
-
11
- type Client struct {
12
- BaseURL string
13
- PayoutWallet string
14
- HTTPClient *http.Client
15
- }
16
-
17
- func NewClient(baseURL string) *Client {
18
- if baseURL == "" {
19
- baseURL = "https://m2msentinel.vercel.app"
20
- }
21
- baseURL = strings.TrimRight(baseURL, "/")
22
- return &Client{
23
- BaseURL: baseURL,
24
- PayoutWallet: "0x1C79BfBFA67Ab140f72f0F6888123a70D9DaC23e",
25
- HTTPClient: &http.Client{},
26
- }
27
- }
28
-
29
- func (c *Client) get(path string, out interface{}) error {
30
- req, err := http.NewRequest("GET", c.BaseURL+path, nil)
31
- if err != nil {
32
- return err
33
- }
34
- resp, err := c.HTTPClient.Do(req)
35
- if err != nil {
36
- return err
37
- }
38
- defer resp.Body.Close()
39
- if resp.StatusCode < 200 || resp.StatusCode >= 300 {
40
- return fmt.Errorf("HTTP error: %s", resp.Status)
41
- }
42
- return json.NewDecoder(resp.Body).Decode(out)
43
- }
44
-
45
- func (c *Client) AuditContract(address string) (map[string]interface{}, error) {
46
- var result map[string]interface{}
47
- err := c.get(fmt.Sprintf("/v1/audit/%s", address), &result)
48
- return result, err
49
- }
50
-
51
- func (c *Client) GetDexMetrics() (map[string]interface{}, error) {
52
- var result map[string]interface{}
53
- err := c.get("/v1/dex/metrics", &result)
54
- return result, err
55
- }
56
-
57
- func (c *Client) GetWhaleSignals() (map[string]interface{}, error) {
58
- var result map[string]interface{}
59
- err := c.get("/v1/whales/signals", &result)
60
- return result, err
61
- }
62
-
63
- func (c *Client) GetTokenPrice(symbol string) (map[string]interface{}, error) {
64
- var result map[string]interface{}
65
- err := c.get(fmt.Sprintf("/v1/token/price/%s", symbol), &result)
66
- return result, err
67
- }
68
-
69
- func (c *Client) Search(query string) (map[string]interface{}, error) {
70
- var result map[string]interface{}
71
- q := url.QueryEscape(query)
72
- err := c.get(fmt.Sprintf("/v1/search?q=%s", q), &result)
73
- return result, err
74
- }
75
-
76
- func (c *Client) TokenAuditMulti() (map[string]interface{}, error) {
77
- var result map[string]interface{}
78
- err := c.get("/v1/token/audit/multi", &result)
79
- return result, err
80
- }
81
-
82
- func (c *Client) GetNftFloor(collection string) (map[string]interface{}, error) {
83
- var result map[string]interface{}
84
- q := url.QueryEscape(collection)
85
- err := c.get(fmt.Sprintf("/v1/nft/floor?collection=%s", q), &result)
86
- return result, err
87
- }
88
-
89
- func (c *Client) GetAiSentiment(symbol string) (map[string]interface{}, error) {
90
- var result map[string]interface{}
91
- q := url.QueryEscape(symbol)
92
- err := c.get(fmt.Sprintf("/v1/ai/sentiment?symbol=%s", q), &result)
93
- return result, err
94
- }
package/go/go.mod DELETED
@@ -1,3 +0,0 @@
1
- module github.com/m2msentinel/m2m-sentinel-go
2
-
3
- go 1.20
@@ -1,67 +0,0 @@
1
- import java.io.IOException;
2
- import java.net.URI;
3
- import java.net.URLEncoder;
4
- import java.net.http.HttpClient;
5
- import java.net.http.HttpRequest;
6
- import java.net.http.HttpResponse;
7
- import java.nio.charset.StandardCharsets;
8
-
9
- public class M2MSentinelClient {
10
- private final String baseUrl;
11
- private final HttpClient httpClient;
12
- public final String PAYOUT_WALLET = "0x1C79BfBFA67Ab140f72f0F6888123a70D9DaC23e";
13
-
14
- public M2MSentinelClient() {
15
- this("https://m2msentinel.vercel.app");
16
- }
17
-
18
- public M2MSentinelClient(String baseUrl) {
19
- if (baseUrl.endsWith("/")) {
20
- this.baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
21
- } else {
22
- this.baseUrl = baseUrl;
23
- }
24
- this.httpClient = HttpClient.newHttpClient();
25
- }
26
-
27
- private String get(String path) throws IOException, InterruptedException {
28
- HttpRequest request = HttpRequest.newBuilder()
29
- .uri(URI.create(this.baseUrl + path))
30
- .GET()
31
- .build();
32
- HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
33
- return response.body();
34
- }
35
-
36
- public String auditContract(String address) throws IOException, InterruptedException {
37
- return get("/v1/audit/" + URLEncoder.encode(address, StandardCharsets.UTF_8));
38
- }
39
-
40
- public String getDexMetrics() throws IOException, InterruptedException {
41
- return get("/v1/dex/metrics");
42
- }
43
-
44
- public String getWhaleSignals() throws IOException, InterruptedException {
45
- return get("/v1/whales/signals");
46
- }
47
-
48
- public String getTokenPrice(String symbol) throws IOException, InterruptedException {
49
- return get("/v1/token/price/" + URLEncoder.encode(symbol, StandardCharsets.UTF_8));
50
- }
51
-
52
- public String search(String query) throws IOException, InterruptedException {
53
- return get("/v1/search?q=" + URLEncoder.encode(query, StandardCharsets.UTF_8));
54
- }
55
-
56
- public String tokenAuditMulti() throws IOException, InterruptedException {
57
- return get("/v1/token/audit/multi");
58
- }
59
-
60
- public String getNftFloor(String collection) throws IOException, InterruptedException {
61
- return get("/v1/nft/floor?collection=" + URLEncoder.encode(collection, StandardCharsets.UTF_8));
62
- }
63
-
64
- public String getAiSentiment(String symbol) throws IOException, InterruptedException {
65
- return get("/v1/ai/sentiment?symbol=" + URLEncoder.encode(symbol, StandardCharsets.UTF_8));
66
- }
67
- }
package/java/pom.xml DELETED
@@ -1,20 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project xmlns="http://maven.apache.org/POM/4.0.0"
3
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
- <modelVersion>4.0.0</modelVersion>
6
-
7
- <groupId>com.m2msentinel</groupId>
8
- <artifactId>m2m-sentinel-client</artifactId>
9
- <version>1.0.0</version>
10
- <packaging>jar</packaging>
11
-
12
- <name>M2M Sentinel Client</name>
13
- <description>Enterprise Java SDK for M2M Sentinel.</description>
14
-
15
- <properties>
16
- <maven.compiler.source>11</maven.compiler.source>
17
- <maven.compiler.target>11</maven.compiler.target>
18
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19
- </properties>
20
- </project>
@@ -1,69 +0,0 @@
1
- package com.m2msentinel;
2
-
3
- import java.io.IOException;
4
- import java.net.URI;
5
- import java.net.URLEncoder;
6
- import java.net.http.HttpClient;
7
- import java.net.http.HttpRequest;
8
- import java.net.http.HttpResponse;
9
- import java.nio.charset.StandardCharsets;
10
-
11
- public class M2MSentinelClient {
12
- private final String baseUrl;
13
- private final HttpClient httpClient;
14
- public final String PAYOUT_WALLET = "0x1C79BfBFA67Ab140f72f0F6888123a70D9DaC23e";
15
-
16
- public M2MSentinelClient() {
17
- this("https://m2msentinel.vercel.app");
18
- }
19
-
20
- public M2MSentinelClient(String baseUrl) {
21
- if (baseUrl.endsWith("/")) {
22
- this.baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
23
- } else {
24
- this.baseUrl = baseUrl;
25
- }
26
- this.httpClient = HttpClient.newHttpClient();
27
- }
28
-
29
- private String get(String path) throws IOException, InterruptedException {
30
- HttpRequest request = HttpRequest.newBuilder()
31
- .uri(URI.create(this.baseUrl + path))
32
- .GET()
33
- .build();
34
- HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
35
- return response.body();
36
- }
37
-
38
- public String auditContract(String address) throws IOException, InterruptedException {
39
- return get("/v1/audit/" + URLEncoder.encode(address, StandardCharsets.UTF_8));
40
- }
41
-
42
- public String getDexMetrics() throws IOException, InterruptedException {
43
- return get("/v1/dex/metrics");
44
- }
45
-
46
- public String getWhaleSignals() throws IOException, InterruptedException {
47
- return get("/v1/whales/signals");
48
- }
49
-
50
- public String getTokenPrice(String symbol) throws IOException, InterruptedException {
51
- return get("/v1/token/price/" + URLEncoder.encode(symbol, StandardCharsets.UTF_8));
52
- }
53
-
54
- public String search(String query) throws IOException, InterruptedException {
55
- return get("/v1/search?q=" + URLEncoder.encode(query, StandardCharsets.UTF_8));
56
- }
57
-
58
- public String tokenAuditMulti() throws IOException, InterruptedException {
59
- return get("/v1/token/audit/multi");
60
- }
61
-
62
- public String getNftFloor(String collection) throws IOException, InterruptedException {
63
- return get("/v1/nft/floor?collection=" + URLEncoder.encode(collection, StandardCharsets.UTF_8));
64
- }
65
-
66
- public String getAiSentiment(String symbol) throws IOException, InterruptedException {
67
- return get("/v1/ai/sentiment?symbol=" + URLEncoder.encode(symbol, StandardCharsets.UTF_8));
68
- }
69
- }
@@ -1,59 +0,0 @@
1
- package com.m2msentinel
2
-
3
- import java.net.URL
4
- import java.net.HttpURLConnection
5
- import java.net.URLEncoder
6
- import java.io.BufferedReader
7
- import java.io.InputStreamReader
8
-
9
- class M2MSentinelClient(private val baseUrl: String = "https://m2msentinel.vercel.app") {
10
- val payoutWallet: String = "0x1C79BfBFA67Ab140f72f0F6888123a70D9DaC23e"
11
- private val normalizedBaseUrl: String = baseUrl.removeSuffix("/")
12
-
13
- private fun getRequest(path: String): String {
14
- val url = URL(normalizedBaseUrl + path)
15
- val connection = url.openConnection() as HttpURLConnection
16
- connection.requestMethod = "GET"
17
-
18
- return if (connection.responseCode in 200..299) {
19
- BufferedReader(InputStreamReader(connection.inputStream)).use { it.readText() }
20
- } else {
21
- BufferedReader(InputStreamReader(connection.errorStream ?: connection.inputStream)).use { it.readText() }
22
- }
23
- }
24
-
25
- fun auditContract(address: String): String {
26
- return getRequest("/v1/audit/$address")
27
- }
28
-
29
- fun getDexMetrics(): String {
30
- return getRequest("/v1/dex/metrics")
31
- }
32
-
33
- fun getWhaleSignals(): String {
34
- return getRequest("/v1/whales/signals")
35
- }
36
-
37
- fun getTokenPrice(symbol: String): String {
38
- return getRequest("/v1/token/price/$symbol")
39
- }
40
-
41
- fun search(query: String): String {
42
- val q = URLEncoder.encode(query, "UTF-8")
43
- return getRequest("/v1/search?q=$q")
44
- }
45
-
46
- fun tokenAuditMulti(): String {
47
- return getRequest("/v1/token/audit/multi")
48
- }
49
-
50
- fun getNftFloor(collection: String): String {
51
- val q = URLEncoder.encode(collection, "UTF-8")
52
- return getRequest("/v1/nft/floor?collection=$q")
53
- }
54
-
55
- fun getAiSentiment(symbol: String): String {
56
- val q = URLEncoder.encode(symbol, "UTF-8")
57
- return getRequest("/v1/ai/sentiment?symbol=$q")
58
- }
59
- }
@@ -1,24 +0,0 @@
1
- plugins {
2
- kotlin("jvm") version "1.9.22"
3
- }
4
-
5
- group = "com.m2msentinel"
6
- version = "1.0-SNAPSHOT"
7
-
8
- repositories {
9
- mavenCentral()
10
- }
11
-
12
- java {
13
- sourceCompatibility = JavaVersion.VERSION_1_8
14
- targetCompatibility = JavaVersion.VERSION_1_8
15
- }
16
-
17
- sourceSets {
18
- main {
19
- kotlin {
20
- srcDir(".")
21
- exclude("build.gradle.kts")
22
- }
23
- }
24
- }
@@ -1,3 +0,0 @@
1
- from .client import M2MSentinelClient
2
-
3
- __all__ = ['M2MSentinelClient']
@@ -1,16 +0,0 @@
1
- import requests
2
-
3
- class M2MSentinelClient:
4
- def __init__(self, api_key: str, base_url: str = "https://m2msentinel.vercel.app"):
5
- self.api_key = api_key
6
- self.base_url = base_url.rstrip("/")
7
- self.session = requests.Session()
8
- self.session.headers.update({
9
- "Authorization": f"Bearer {self.api_key}",
10
- "Content-Type": "application/json"
11
- })
12
-
13
- def get_status(self):
14
- response = self.session.get(f"{self.base_url}/v1/status")
15
- response.raise_for_status()
16
- return response.json()