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.
- package/README.md +44 -28
- package/agent_adapter.js +30 -0
- package/eliza_plugin.js +84 -0
- package/index.js +136 -19
- package/m2m_sentinel_sdk.js +1 -12
- package/mcp_server.js +172 -0
- package/package.json +26 -9
- package/typescript/index.ts +135 -35
- package/typescript/package.json +4 -3
- package/cli/m2m_cli.js +0 -25
- package/csharp/M2MSentinel.csproj +0 -9
- package/csharp/M2MSentinelClient.cs +0 -67
- package/go/client.go +0 -94
- package/go/go.mod +0 -3
- package/java/M2MSentinelClient.java +0 -67
- package/java/pom.xml +0 -20
- package/java/src/main/java/com/m2msentinel/M2MSentinelClient.java +0 -69
- package/kotlin/M2MSentinelClient.kt +0 -59
- package/kotlin/build.gradle.kts +0 -24
- package/m2m_sentinel/__init__.py +0 -3
- package/m2m_sentinel/client.py +0 -16
- package/m2m_sentinel_sdk.py +0 -9
- package/php/M2MSentinelClient.php +0 -52
- package/php/composer.json +0 -20
- package/python/dist/m2m_sentinel-0.1.0-py3-none-any.whl +0 -0
- package/python/dist/m2m_sentinel-0.1.0.tar.gz +0 -0
- package/python/dist/m2m_sentinel-0.1.1-py3-none-any.whl +0 -0
- package/python/dist/m2m_sentinel-0.1.1.tar.gz +0 -0
- package/python/m2m_sentinel/__pycache__/client.cpython-314.pyc +0 -0
- package/python/m2m_sentinel/client.py +0 -40
- package/python/m2m_sentinel.egg-info/PKG-INFO +0 -35
- package/python/m2m_sentinel.egg-info/SOURCES.txt +0 -5
- package/python/m2m_sentinel.egg-info/dependency_links.txt +0 -1
- package/python/m2m_sentinel.egg-info/top_level.txt +0 -1
- package/python/setup.py +0 -35
- package/ruby/m2m_sentinel.gemspec +0 -17
- package/ruby/m2m_sentinel.rb +0 -55
- package/rust/Cargo.toml +0 -11
- package/rust/src/lib.rs +0 -61
- package/swift/M2MSentinelClient.swift +0 -65
- package/swift/Package.swift +0 -23
package/typescript/index.ts
CHANGED
|
@@ -1,49 +1,149 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export interface M2MSentinelClientOptions {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
timeoutMs?: number;
|
|
5
|
+
paymentSignature?: string;
|
|
6
|
+
}
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
16
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
34
|
+
export class PaymentRequiredError extends M2MSentinelError {}
|
|
35
|
+
export class RateLimitedError extends M2MSentinelError {}
|
|
36
|
+
export class DataSourceUnavailableError extends M2MSentinelError {}
|
|
22
37
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
38
|
+
const DEFAULT_BASE_URL = 'https://m2msentinel.vercel.app';
|
|
39
|
+
const DEFAULT_TIMEOUT_MS = 30000;
|
|
26
40
|
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
+
}
|
package/typescript/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "m2m-sentinel-sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "M2M Sentinel
|
|
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,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
|
-
}
|
package/kotlin/build.gradle.kts
DELETED
|
@@ -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
|
-
}
|
package/m2m_sentinel/__init__.py
DELETED
package/m2m_sentinel/client.py
DELETED
|
@@ -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()
|