agentshield-protocol 1.0.0 → 1.1.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.
- package/package.json +1 -1
- package/sdk.js +97 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentshield-protocol",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Security protocol for autonomous AI agents — contract verification, wallet monitoring, freeze protection, and x402 machine payments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "sdk.js",
|
package/sdk.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* AgentShield SDK
|
|
3
3
|
* Security protocol for autonomous AI agents
|
|
4
4
|
* https://agentshield.workers.dev
|
|
5
|
+
*
|
|
6
|
+
* Auto-handles x402 payments — agents pay per call, no setup needed.
|
|
7
|
+
* Supports USDC on Base and SOL on Solana.
|
|
5
8
|
*/
|
|
6
9
|
|
|
7
10
|
const BASE_URL = 'https://agentshield.workers.dev';
|
|
@@ -10,70 +13,137 @@ export class AgentShield {
|
|
|
10
13
|
constructor(options = {}) {
|
|
11
14
|
this.baseUrl = options.baseUrl || BASE_URL;
|
|
12
15
|
this.wallet = options.wallet || null;
|
|
13
|
-
|
|
16
|
+
// Payment options — provide one to enable auto-pay after free tier
|
|
17
|
+
this.privateKey = options.privateKey || null; // EVM private key for USDC on Base
|
|
18
|
+
this.solanaKeypair = options.solanaKeypair || null; // Solana Keypair for SOL payments
|
|
19
|
+
this.maxPayPerCall = options.maxPayPerCall || 0.002; // max $ willing to pay per call
|
|
20
|
+
this._paid = 0; // total spent this session
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
_headers() {
|
|
17
24
|
const h = { 'Content-Type': 'application/json' };
|
|
18
25
|
if (this.wallet) h['X-Wallet'] = this.wallet;
|
|
19
|
-
if (this.apiKey) h['X-API-Key'] = this.apiKey;
|
|
20
26
|
return h;
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
30
|
+
* Pay x402 and retry the request automatically.
|
|
31
|
+
* Handles USDC on Base (EVM) or SOL on Solana.
|
|
32
|
+
*/
|
|
33
|
+
async _payAndRetry(url, fetchOptions, paymentSpec) {
|
|
34
|
+
const accepts = paymentSpec.accepts || [];
|
|
35
|
+
|
|
36
|
+
// ── Try SOL payment if Solana keypair provided ──────────────
|
|
37
|
+
const solSpec = accepts.find(a => a.network === 'solana');
|
|
38
|
+
if (solSpec && this.solanaKeypair) {
|
|
39
|
+
try {
|
|
40
|
+
const { Connection, SystemProgram, Transaction,
|
|
41
|
+
sendAndConfirmTransaction, PublicKey, LAMPORTS_PER_SOL } = await import('@solana/web3.js');
|
|
42
|
+
const conn = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
|
|
43
|
+
const lamports = parseInt(solSpec.lamports || 500);
|
|
44
|
+
const recipient = new PublicKey(solSpec.payTo);
|
|
45
|
+
const tx = new Transaction().add(
|
|
46
|
+
SystemProgram.transfer({ fromPubkey: this.solanaKeypair.publicKey, toPubkey: recipient, lamports })
|
|
47
|
+
);
|
|
48
|
+
const sig = await sendAndConfirmTransaction(conn, tx, [this.solanaKeypair]);
|
|
49
|
+
this._paid += lamports / LAMPORTS_PER_SOL * 150; // approx USD
|
|
50
|
+
const payment = JSON.stringify({ network: 'solana', txSignature: sig });
|
|
51
|
+
const retryRes = await fetch(url, {
|
|
52
|
+
...fetchOptions,
|
|
53
|
+
headers: { ...fetchOptions.headers, 'X-PAYMENT': payment }
|
|
54
|
+
});
|
|
55
|
+
return retryRes.json();
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// fall through to EVM
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── Try USDC on Base if EVM key provided ────────────────────
|
|
62
|
+
const evmSpec = accepts.find(a => a.network === 'base' || a.network === 'ethereum');
|
|
63
|
+
if (evmSpec && this.privateKey) {
|
|
64
|
+
try {
|
|
65
|
+
const { ethers } = await import('ethers');
|
|
66
|
+
const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');
|
|
67
|
+
const signer = new ethers.Wallet(this.privateKey, provider);
|
|
68
|
+
const USDC = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
69
|
+
const usdc = new ethers.Contract(USDC, [
|
|
70
|
+
'function transfer(address to, uint256 amount) returns (bool)'
|
|
71
|
+
], signer);
|
|
72
|
+
const amount = ethers.parseUnits(evmSpec.maxAmountRequired || '0.001', 6);
|
|
73
|
+
const tx = await usdc.transfer(evmSpec.payTo, amount);
|
|
74
|
+
await tx.wait();
|
|
75
|
+
this._paid += parseFloat(evmSpec.maxAmountRequired || '0.001');
|
|
76
|
+
const payment = JSON.stringify({ network: 'base', txHash: tx.hash });
|
|
77
|
+
const retryRes = await fetch(url, {
|
|
78
|
+
...fetchOptions,
|
|
79
|
+
headers: { ...fetchOptions.headers, 'X-PAYMENT': payment }
|
|
80
|
+
});
|
|
81
|
+
return retryRes.json();
|
|
82
|
+
} catch (e) {
|
|
83
|
+
throw new Error(`x402 payment failed: ${e.message}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// No payment method — return the 402 info so caller can handle it
|
|
88
|
+
return { error: 'payment_required', spec: paymentSpec, message: 'Provide privateKey or solanaKeypair to enable auto-payment' };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Make a request, auto-paying if a 402 is returned.
|
|
93
|
+
*/
|
|
94
|
+
async _fetch(url, options = {}) {
|
|
95
|
+
const fetchOptions = { headers: this._headers(), ...options };
|
|
96
|
+
const res = await fetch(url, fetchOptions);
|
|
97
|
+
if (res.status === 402) {
|
|
98
|
+
const spec = await res.json().catch(() => ({}));
|
|
99
|
+
return this._payAndRetry(url, fetchOptions, spec);
|
|
100
|
+
}
|
|
101
|
+
return res.json();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Verify a smart contract for safety risks.
|
|
106
|
+
* Auto-pays $0.001 after free tier (5 calls).
|
|
107
|
+
* @param {string} contract - Contract address (0x... or Solana address)
|
|
26
108
|
* @param {string} chain - Chain name (default: 'ethereum')
|
|
27
109
|
*/
|
|
28
110
|
async verify(contract, chain = 'ethereum') {
|
|
29
|
-
|
|
30
|
-
const res = await fetch(url, { headers: this._headers() });
|
|
31
|
-
return res.json();
|
|
111
|
+
return this._fetch(`${this.baseUrl}/verify?contract=${contract}&chain=${chain}`);
|
|
32
112
|
}
|
|
33
113
|
|
|
34
114
|
/**
|
|
35
|
-
* Monitor a wallet address for suspicious activity
|
|
36
|
-
* @param {string} wallet - Wallet address to monitor
|
|
115
|
+
* Monitor a wallet address for suspicious activity.
|
|
37
116
|
*/
|
|
38
117
|
async monitor(wallet) {
|
|
39
|
-
|
|
118
|
+
return this._fetch(`${this.baseUrl}/monitor`, {
|
|
40
119
|
method: 'POST',
|
|
41
|
-
headers: this._headers(),
|
|
42
120
|
body: JSON.stringify({ wallet }),
|
|
43
121
|
});
|
|
44
|
-
return res.json();
|
|
45
122
|
}
|
|
46
123
|
|
|
47
124
|
/**
|
|
48
|
-
* Freeze
|
|
49
|
-
* @param {string} wallet - Wallet address to freeze
|
|
50
|
-
* @param {string} reason - Reason for freeze
|
|
125
|
+
* Freeze a wallet to stop dangerous interactions.
|
|
51
126
|
*/
|
|
52
127
|
async freeze(wallet, reason) {
|
|
53
|
-
|
|
128
|
+
return this._fetch(`${this.baseUrl}/freeze`, {
|
|
54
129
|
method: 'POST',
|
|
55
|
-
headers: this._headers(),
|
|
56
130
|
body: JSON.stringify({ wallet, reason }),
|
|
57
131
|
});
|
|
58
|
-
return res.json();
|
|
59
132
|
}
|
|
60
133
|
|
|
61
|
-
/**
|
|
62
|
-
* Get agent context / manifest info
|
|
63
|
-
*/
|
|
134
|
+
/** Get agent context / manifest. */
|
|
64
135
|
async agentContext() {
|
|
65
|
-
|
|
66
|
-
return res.json();
|
|
136
|
+
return this._fetch(`${this.baseUrl}/agent-context`);
|
|
67
137
|
}
|
|
68
138
|
|
|
69
|
-
/**
|
|
70
|
-
* Get OpenAPI spec
|
|
71
|
-
*/
|
|
139
|
+
/** Get OpenAPI spec. */
|
|
72
140
|
async openapi() {
|
|
73
141
|
const res = await fetch(`${this.baseUrl}/openapi.json`);
|
|
74
142
|
return res.json();
|
|
75
143
|
}
|
|
144
|
+
|
|
145
|
+
/** Total USD paid this session. */
|
|
146
|
+
get totalPaid() { return this._paid; }
|
|
76
147
|
}
|
|
77
148
|
|
|
78
|
-
// CommonJS + ESM compat default export
|
|
79
149
|
export default AgentShield;
|