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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/sdk.js +97 -27
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentshield-protocol",
3
- "version": "1.0.0",
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
- this.apiKey = options.apiKey || null;
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
- * Verify a smart contract for safety risks
25
- * @param {string} contract - Contract address (0x...)
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
- const url = `${this.baseUrl}/verify?contract=${contract}&chain=${chain}`;
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
- const res = await fetch(`${this.baseUrl}/monitor`, {
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 an agent's wallet to stop dangerous interactions
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
- const res = await fetch(`${this.baseUrl}/freeze`, {
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
- const res = await fetch(`${this.baseUrl}/agent-context`, { headers: this._headers() });
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;