@aifinpay/mcp 2.4.1 → 2.7.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/README.md +161 -31
- package/dist/config.d.ts +15 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +65 -7
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/native-price.d.ts +18 -9
- package/dist/native-price.d.ts.map +1 -1
- package/dist/native-price.js +37 -32
- package/dist/native-price.js.map +1 -1
- package/dist/pay-chains.d.ts +32 -0
- package/dist/pay-chains.d.ts.map +1 -0
- package/dist/pay-chains.js +38 -0
- package/dist/pay-chains.js.map +1 -0
- package/dist/payment-identity.d.ts +17 -0
- package/dist/payment-identity.d.ts.map +1 -0
- package/dist/payment-identity.js +75 -0
- package/dist/payment-identity.js.map +1 -0
- package/dist/payment-state.d.ts +2 -1
- package/dist/payment-state.d.ts.map +1 -1
- package/dist/payment-state.js +52 -17
- package/dist/payment-state.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +11 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/agent-address.d.ts.map +1 -1
- package/dist/tools/agent-address.js +1 -1
- package/dist/tools/agent-address.js.map +1 -1
- package/dist/tools/agent-claim-self.d.ts +3 -3
- package/dist/tools/agent-claim-self.d.ts.map +1 -1
- package/dist/tools/agent-claim-self.js +65 -88
- package/dist/tools/agent-claim-self.js.map +1 -1
- package/dist/tools/agent-history.d.ts +0 -1
- package/dist/tools/agent-history.d.ts.map +1 -1
- package/dist/tools/agent-history.js +51 -52
- package/dist/tools/agent-history.js.map +1 -1
- package/dist/tools/agent-quota.d.ts.map +1 -1
- package/dist/tools/agent-quota.js +42 -11
- package/dist/tools/agent-quota.js.map +1 -1
- package/dist/tools/payable-fetch.d.ts.map +1 -1
- package/dist/tools/payable-fetch.js +178 -66
- package/dist/tools/payable-fetch.js.map +1 -1
- package/package.json +6 -6
- package/skills/SKILL.md +168 -34
- package/smithery.yaml +72 -40
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-address.js","sourceRoot":"","sources":["../../src/tools/agent-address.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,2DAA2D;YAC3D,kEAAkE;YAClE,yIAAyI;QAC3I,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;SACf;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE;QACjF,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;gBAChE,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,WAAW,
|
|
1
|
+
{"version":3,"file":"agent-address.js","sourceRoot":"","sources":["../../src/tools/agent-address.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,2DAA2D;YAC3D,kEAAkE;YAClE,yIAAyI;QAC3I,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;SACf;QACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE;QACjF,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;gBAChE,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,WAAW,EACT,qHAAqH;iBACxH;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EACT,0IAA0I;iBAC7I;gBACD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACxB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aAC9B;YACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;SAC5B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAgB,EAAE,KAA8B;IACpF,MAAM,OAAO,GAAG;QACd,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa;QAC/B,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU;QACzB,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa;QAC/B,IAAI,EACF,uFAAuF;YACvF,sFAAsF;YACtF,2CAA2C;QAC7C,SAAS,EACP,4FAA4F;YAC5F,4FAA4F;YAC5F,wBAAwB;KAC3B,CAAC;IACF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACnE,iBAAiB,EAAE,OAAO;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -10,8 +10,8 @@ import type { ToolContext } from "../server.js";
|
|
|
10
10
|
* using this magic link"
|
|
11
11
|
* 3. Agent calls this tool with the magic_link_url
|
|
12
12
|
* 4. Tool hits the magic link → server issues session cookie
|
|
13
|
-
* 5. Tool
|
|
14
|
-
* 6. Tool signs
|
|
13
|
+
* 5. Tool requests a challenge for the owner-selected payment family
|
|
14
|
+
* 6. Tool signs only that address's claim (EIP-191 or Ed25519)
|
|
15
15
|
* 7. Tool POSTs to /api/me/agents/claim → server verifies signature →
|
|
16
16
|
* agent attached to user's watchlist
|
|
17
17
|
*
|
|
@@ -19,7 +19,7 @@ import type { ToolContext } from "../server.js";
|
|
|
19
19
|
*
|
|
20
20
|
* Security model:
|
|
21
21
|
* - Magic-link URL is one-shot, 15-min TTL, identifies the user
|
|
22
|
-
* - Signature proves the agent
|
|
22
|
+
* - Signature proves the agent controls the selected wallet
|
|
23
23
|
* - Combination: "this user OWNS this agent". Either alone is
|
|
24
24
|
* insufficient (signature alone can't pick an account; magic link
|
|
25
25
|
* alone can't prove key control).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-claim-self.d.ts","sourceRoot":"","sources":["../../src/tools/agent-claim-self.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-claim-self.d.ts","sourceRoot":"","sources":["../../src/tools/agent-claim-self.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;EA8BjC;AAqED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GAyKtF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { payChain } from "../pay-chains.js";
|
|
1
2
|
/**
|
|
2
3
|
* `agent_claim_self` — agent attaches itself to a user's AiFinPay account
|
|
3
4
|
* autonomously by signing a claim challenge with its own key.
|
|
@@ -9,8 +10,8 @@
|
|
|
9
10
|
* using this magic link"
|
|
10
11
|
* 3. Agent calls this tool with the magic_link_url
|
|
11
12
|
* 4. Tool hits the magic link → server issues session cookie
|
|
12
|
-
* 5. Tool
|
|
13
|
-
* 6. Tool signs
|
|
13
|
+
* 5. Tool requests a challenge for the owner-selected payment family
|
|
14
|
+
* 6. Tool signs only that address's claim (EIP-191 or Ed25519)
|
|
14
15
|
* 7. Tool POSTs to /api/me/agents/claim → server verifies signature →
|
|
15
16
|
* agent attached to user's watchlist
|
|
16
17
|
*
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
*
|
|
19
20
|
* Security model:
|
|
20
21
|
* - Magic-link URL is one-shot, 15-min TTL, identifies the user
|
|
21
|
-
* - Signature proves the agent
|
|
22
|
+
* - Signature proves the agent controls the selected wallet
|
|
22
23
|
* - Combination: "this user OWNS this agent". Either alone is
|
|
23
24
|
* insufficient (signature alone can't pick an account; magic link
|
|
24
25
|
* alone can't prove key control).
|
|
@@ -162,10 +163,10 @@ export async function runAgentClaimSelf(ctx, args) {
|
|
|
162
163
|
};
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
|
-
catch
|
|
166
|
+
catch {
|
|
166
167
|
return {
|
|
167
168
|
isError: true,
|
|
168
|
-
content: [{ type: "text", text:
|
|
169
|
+
content: [{ type: "text", text: "Failed to fetch magic link; no claim was completed." }],
|
|
169
170
|
};
|
|
170
171
|
}
|
|
171
172
|
// Some setups split multiple cookies; grab the session one we care about.
|
|
@@ -173,14 +174,12 @@ export async function runAgentClaimSelf(ctx, args) {
|
|
|
173
174
|
.split(",")
|
|
174
175
|
.map((c) => c.trim().split(";")[0])
|
|
175
176
|
.join("; ");
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
// The owner-selected payment family is required. The other wallet is
|
|
178
|
+
// best-effort and can never turn a failed primary claim into success.
|
|
179
|
+
const selected = payChain(ctx.config?.payChain);
|
|
180
|
+
const primarySolana = selected.name === "solana";
|
|
180
181
|
const evmAddr = ctx.agent.evmAddress;
|
|
181
182
|
const solAddr = ctx.agent.solanaAddress;
|
|
182
|
-
const innerAny = ctx.agent.inner;
|
|
183
|
-
const solSecret = innerAny.secretKey; // tweetnacl 64-byte secretKey
|
|
184
183
|
async function claimOne(address, sigFn) {
|
|
185
184
|
// 1) challenge
|
|
186
185
|
const cr = await fetch(`${apiBase}/api/me/agents/challenge`, {
|
|
@@ -190,8 +189,8 @@ export async function runAgentClaimSelf(ctx, args) {
|
|
|
190
189
|
body: JSON.stringify({ address }),
|
|
191
190
|
});
|
|
192
191
|
const cj = (await cr.json());
|
|
193
|
-
if (!cr.ok || !cj.challenge_id || !cj.message) {
|
|
194
|
-
return { ok: false, reason:
|
|
192
|
+
if (!cr.ok || !cj || typeof cj.challenge_id !== "string" || !cj.challenge_id || typeof cj.message !== "string") {
|
|
193
|
+
return { ok: false, reason: `challenge refused (HTTP ${cr.status})` };
|
|
195
194
|
}
|
|
196
195
|
// 2) sign — but only the one shape this exchange is defined to produce.
|
|
197
196
|
if (!challengeIsWellFormed(cj.message, address)) {
|
|
@@ -204,8 +203,8 @@ export async function runAgentClaimSelf(ctx, args) {
|
|
|
204
203
|
try {
|
|
205
204
|
sigPayload = await sigFn(cj.message);
|
|
206
205
|
}
|
|
207
|
-
catch
|
|
208
|
-
return { ok: false, reason:
|
|
206
|
+
catch {
|
|
207
|
+
return { ok: false, reason: "local claim signer unavailable" };
|
|
209
208
|
}
|
|
210
209
|
// 3) submit
|
|
211
210
|
const sr = await fetch(`${apiBase}/api/me/agents/claim`, {
|
|
@@ -215,86 +214,64 @@ export async function runAgentClaimSelf(ctx, args) {
|
|
|
215
214
|
body: JSON.stringify({ challenge_id: cj.challenge_id, label, ...sigPayload }),
|
|
216
215
|
});
|
|
217
216
|
const sj = (await sr.json());
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
const expectedChain = address.startsWith("0x") ? "polygon" : "solana";
|
|
218
|
+
const sameAddress = typeof sj?.agent_address === "string" &&
|
|
219
|
+
(expectedChain === "polygon"
|
|
220
|
+
? sj.agent_address.toLowerCase() === address.toLowerCase()
|
|
221
|
+
: sj.agent_address === address);
|
|
222
|
+
if (!sr.ok || sj?.ok !== true || sj.chain !== expectedChain || !sameAddress) {
|
|
223
|
+
return { ok: false, reason: "claim response does not confirm this wallet and family" };
|
|
220
224
|
}
|
|
221
225
|
return { ok: true };
|
|
222
226
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
catch (e) {
|
|
244
|
-
solRes = { ok: false, reason: `solana_signer_unavailable: ${e.message}` };
|
|
245
|
-
}
|
|
246
|
-
// ── 4. Balance check (best-effort) — drives funded-vs-unfunded copy ─
|
|
247
|
-
// Never block the claim flow on a balance check; if the RPC is down or
|
|
248
|
-
// balance() throws, fall back to the standard funding recommendation.
|
|
249
|
-
// payable_fetch settles AIFP-1 v1.4 in native POL, so POL is what counts.
|
|
250
|
-
let polygonPol = 0;
|
|
251
|
-
let polUsd = null;
|
|
252
|
-
try {
|
|
253
|
-
const bal = await ctx.agent.balance();
|
|
254
|
-
polygonPol = bal.chains.polygon.matic ?? 0;
|
|
255
|
-
polUsd = Number.isFinite(bal.prices?.pol?.usd) ? bal.prices.pol.usd : null;
|
|
256
|
-
}
|
|
257
|
-
catch {
|
|
258
|
-
/* swallow — keep funding_recommendation as-is */
|
|
259
|
-
}
|
|
260
|
-
// ── 5. Report ──────────────────────────────────────────────────────
|
|
261
|
-
try {
|
|
262
|
-
// The dashboard is dash.aifinpay.io; /me redirects to My Agents.
|
|
263
|
-
// (dashboard.aifinpay.io only 301s here.)
|
|
264
|
-
const DASHBOARD_BASE = "https://dash.aifinpay.io";
|
|
265
|
-
// Funded threshold: $0.20 of POL — the smallest batch ($0.10) plus gas.
|
|
266
|
-
// At or above it we say so, so the agent does not ask for money it has.
|
|
267
|
-
const FUNDED_USD_THRESHOLD = 0.2;
|
|
268
|
-
const polValueUsd = polUsd === null ? null : polygonPol * polUsd;
|
|
269
|
-
const fundingFields = polValueUsd !== null && polValueUsd >= FUNDED_USD_THRESHOLD
|
|
270
|
-
? { funding_status: `Funded — ${polygonPol.toFixed(4)} POL (≈ $${polValueUsd.toFixed(2)}) on Polygon` }
|
|
271
|
-
: {
|
|
272
|
-
// AIFP-1 v1.4 settles in native POL on Polygon, and gas is POL too.
|
|
273
|
-
funding_recommendation: `Send POL on Polygon to ${evmAddr}. The smallest batch is $0.10 plus gas; 2–3 POL covers many batches.`,
|
|
274
|
-
};
|
|
275
|
-
return {
|
|
276
|
-
content: [
|
|
277
|
-
{
|
|
278
|
-
type: "text",
|
|
279
|
-
text: JSON.stringify({
|
|
280
|
-
ok: true,
|
|
281
|
-
polygon_address: evmAddr,
|
|
282
|
-
polygon_claim: "ok",
|
|
283
|
-
solana_address: solAddr,
|
|
284
|
-
solana_claim: solRes.ok ? "ok" : `skipped (${solRes.reason})`,
|
|
285
|
-
label: label || null,
|
|
286
|
-
...fundingFields,
|
|
287
|
-
next: `Open ${DASHBOARD_BASE}/me (My Agents) to see this agent's balance, payments and receipts. Public page: ${DASHBOARD_BASE}/agents/${evmAddr}.`,
|
|
288
|
-
}, null, 2),
|
|
289
|
-
},
|
|
290
|
-
],
|
|
291
|
-
};
|
|
227
|
+
async function claimFamily(solana) {
|
|
228
|
+
try {
|
|
229
|
+
if (!solana) {
|
|
230
|
+
return await claimOne(evmAddr, async (msg) => ({
|
|
231
|
+
signature: await ctx.agent.evmAccount.signMessage({ message: msg }),
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
const nacl = (await import("tweetnacl")).default;
|
|
235
|
+
const bs58 = (await import("bs58")).default;
|
|
236
|
+
const inner = ctx.agent.inner;
|
|
237
|
+
return await claimOne(solAddr, async (msg) => ({
|
|
238
|
+
signature_base58: bs58.encode(nacl.sign.detached(Buffer.from(msg, "utf8"), inner.secretKey)),
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// Do not echo URL tokens, cookies, signing material or remote error text.
|
|
243
|
+
return { ok: false, reason: "claim exchange failed" };
|
|
244
|
+
}
|
|
292
245
|
}
|
|
293
|
-
|
|
246
|
+
const primary = await claimFamily(primarySolana);
|
|
247
|
+
if (!primary.ok) {
|
|
294
248
|
return {
|
|
295
249
|
isError: true,
|
|
296
|
-
content: [{ type: "text", text:
|
|
250
|
+
content: [{ type: "text", text: `${primarySolana ? "Solana" : "EVM"} claim failed: ${primary.reason}` }],
|
|
297
251
|
};
|
|
298
252
|
}
|
|
253
|
+
const secondary = await claimFamily(!primarySolana);
|
|
254
|
+
const evmResult = primarySolana ? secondary : primary;
|
|
255
|
+
const solanaResult = primarySolana ? primary : secondary;
|
|
256
|
+
const primaryAddress = primarySolana ? solAddr : evmAddr;
|
|
257
|
+
return {
|
|
258
|
+
content: [
|
|
259
|
+
{
|
|
260
|
+
type: "text",
|
|
261
|
+
text: JSON.stringify({
|
|
262
|
+
ok: true,
|
|
263
|
+
primary_family: primarySolana ? "solana" : "evm",
|
|
264
|
+
primary_address: primaryAddress,
|
|
265
|
+
payment_chain: selected.name,
|
|
266
|
+
polygon_address: evmAddr,
|
|
267
|
+
polygon_claim: evmResult.ok ? "ok" : `skipped (${evmResult.reason})`,
|
|
268
|
+
solana_address: solAddr,
|
|
269
|
+
solana_claim: solanaResult.ok ? "ok" : `skipped (${solanaResult.reason})`,
|
|
270
|
+
label: label || null,
|
|
271
|
+
next: `Open https://dash.aifinpay.io/my-agents/${encodeURIComponent(primaryAddress)}. Use Fund to view available payment networks and assets. Wallet binding does not enable payments on a disabled network.`,
|
|
272
|
+
}, null, 2),
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
};
|
|
299
276
|
}
|
|
300
277
|
//# sourceMappingURL=agent-claim-self.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-claim-self.js","sourceRoot":"","sources":["../../src/tools/agent-claim-self.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-claim-self.js","sourceRoot":"","sources":["../../src/tools/agent-claim-self.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-history.d.ts","sourceRoot":"","sources":["../../src/tools/agent-history.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-history.d.ts","sourceRoot":"","sources":["../../src/tools/agent-history.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAShD,wBAAgB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0B/B;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;GA+HpF"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { AGENT_RECEIPT_FIELDS, AGENT_TRANSACTION_FIELDS } from "@aifinpay/agent";
|
|
1
2
|
import { apiUrl } from "../api.js";
|
|
3
|
+
import { isSolanaPublicKey, solanaHistorySelection, assertSolanaReadContext, solanaIndexingMetadata, } from "../payment-identity.js";
|
|
2
4
|
export function agentHistoryTool() {
|
|
3
5
|
return {
|
|
4
6
|
name: "agent_history",
|
|
5
|
-
description: "Read an agent's payment history by
|
|
7
|
+
description: "Read an agent's indexed AiFinPay payment history by wallet address, public passport identifier, or both. Defaults to the configured payment chain and its local wallet. Solana history requires the owner-selected cluster; arbitrary wallet transfers are excluded. Receipts include retained prepaid batches and test payments. Never pass a seed, private key or API secret as a passport.",
|
|
6
8
|
inputSchema: {
|
|
7
9
|
type: "object",
|
|
8
10
|
additionalProperties: false,
|
|
@@ -14,8 +16,7 @@ export function agentHistoryTool() {
|
|
|
14
16
|
},
|
|
15
17
|
network: {
|
|
16
18
|
type: "string",
|
|
17
|
-
|
|
18
|
-
description: "Exact passport wallet network; indexed transactions currently support polygon only",
|
|
19
|
+
description: "Exact wallet chain; defaults to the configured payment chain (Polygon when unset). Solana cluster comes from owner configuration.",
|
|
19
20
|
},
|
|
20
21
|
source: { type: "string", enum: ["transactions", "receipts"], default: "transactions" },
|
|
21
22
|
limit: { type: "integer", minimum: 1, maximum: 100, default: 25 },
|
|
@@ -27,7 +28,8 @@ export function agentHistoryTool() {
|
|
|
27
28
|
}
|
|
28
29
|
export async function runAgentHistory(ctx, args) {
|
|
29
30
|
const base = ctx.config.baseUrl || "https://aifinpay.io";
|
|
30
|
-
const source = args.source ?? "transactions", network = args.network ?? "polygon";
|
|
31
|
+
const source = args.source ?? "transactions", network = args.network ?? ctx.config.payChain ?? "polygon";
|
|
32
|
+
const solana = network === "solana";
|
|
31
33
|
const limit = args.limit ?? 25, offset = args.offset ?? 0;
|
|
32
34
|
const failure = (message) => ({
|
|
33
35
|
isError: true,
|
|
@@ -51,6 +53,9 @@ export async function runAgentHistory(ctx, args) {
|
|
|
51
53
|
return (await response.json());
|
|
52
54
|
}
|
|
53
55
|
try {
|
|
56
|
+
if (typeof network !== "string")
|
|
57
|
+
throw new Error("History network must be an exact chain name");
|
|
58
|
+
const solanaSelection = solana ? solanaHistorySelection(ctx.config) : undefined;
|
|
54
59
|
let address = args.address == null ? undefined : String(args.address);
|
|
55
60
|
if (args.passport) {
|
|
56
61
|
const identifier = String(args.passport).trim();
|
|
@@ -60,67 +65,59 @@ export async function runAgentHistory(ctx, args) {
|
|
|
60
65
|
const resolved = await get(`/api/agent/resolve/${encodeURIComponent(identifier)}`);
|
|
61
66
|
if (resolved?.agent?.status !== "active" || !Array.isArray(resolved.agent.wallets))
|
|
62
67
|
throw new Error("Passport is not active or has no verified wallets");
|
|
63
|
-
const wallets = resolved.agent.wallets.filter((w) => w.network === network && w.chain_family === "evm" && Number(w.verified_at) > 0);
|
|
68
|
+
const wallets = resolved.agent.wallets.filter((w) => w.network === network && w.chain_family === (solana ? "solana" : "evm") && Number(w.verified_at) > 0);
|
|
64
69
|
const wallet = wallets.find((w) => w.is_primary) || wallets[0];
|
|
65
70
|
if (!wallet || typeof wallet.address !== "string")
|
|
66
|
-
throw new Error("Passport has no verified
|
|
67
|
-
if (address && address.toLowerCase() !== wallet.address.toLowerCase())
|
|
71
|
+
throw new Error("Passport has no verified wallet on the requested network");
|
|
72
|
+
if (address && (solana ? address !== wallet.address : address.toLowerCase() !== wallet.address.toLowerCase()))
|
|
68
73
|
throw new Error("Address does not match passport wallet");
|
|
69
74
|
address = wallet.address;
|
|
70
75
|
}
|
|
71
|
-
address ??= ctx.agent.evmAddress;
|
|
72
|
-
if (!/^0x[0-9a-fA-F]{40}$/.test(address))
|
|
73
|
-
return failure("Expected an EVM address");
|
|
76
|
+
address ??= solana ? ctx.agent.solanaAddress : ctx.agent.evmAddress;
|
|
77
|
+
if (solana ? !isSolanaPublicKey(address) : !/^0x[0-9a-fA-F]{40}$/.test(address))
|
|
78
|
+
return failure(solana ? "Expected a canonical 32-byte Solana address" : "Expected an EVM address");
|
|
79
|
+
const canonicalAddress = solana ? address : address.toLowerCase();
|
|
74
80
|
const query = new URLSearchParams({ limit: String(limit), offset: String(offset) });
|
|
75
|
-
if (source === "transactions")
|
|
81
|
+
if (source === "transactions" || solana)
|
|
76
82
|
query.set("chain", String(network));
|
|
77
|
-
|
|
83
|
+
if (solanaSelection) {
|
|
84
|
+
query.set("network", solanaSelection.network);
|
|
85
|
+
query.set("program", solanaSelection.program);
|
|
86
|
+
}
|
|
87
|
+
const body = await get(`/v1/agents/${canonicalAddress}/${source}?${query}`);
|
|
78
88
|
if (!Array.isArray(body?.[source]))
|
|
79
89
|
throw new Error("Invalid history response");
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
"tx_hash",
|
|
104
|
-
"log_index",
|
|
105
|
-
"chain",
|
|
106
|
-
"payment_id",
|
|
107
|
-
"block_number",
|
|
108
|
-
"block_ts",
|
|
109
|
-
"agent_address",
|
|
110
|
-
"merchant_address",
|
|
111
|
-
"token_address",
|
|
112
|
-
"total_amount",
|
|
113
|
-
"merchant_amount",
|
|
114
|
-
"treasury_fee",
|
|
115
|
-
"ip_creator_fee",
|
|
116
|
-
];
|
|
117
|
-
const items = body[source].map((row) => Object.fromEntries(fields.filter((f) => row?.[f] !== undefined).map((f) => [f, row[f]])));
|
|
90
|
+
if (solanaSelection)
|
|
91
|
+
assertSolanaReadContext(body, canonicalAddress, solanaSelection, "address");
|
|
92
|
+
const fields = [
|
|
93
|
+
...(source === "receipts" ? AGENT_RECEIPT_FIELDS : AGENT_TRANSACTION_FIELDS),
|
|
94
|
+
"program_id",
|
|
95
|
+
"idl_sha256",
|
|
96
|
+
"token_decimals",
|
|
97
|
+
"asset",
|
|
98
|
+
"cost_allocation",
|
|
99
|
+
];
|
|
100
|
+
const items = body[source].map((row) => {
|
|
101
|
+
if (solanaSelection)
|
|
102
|
+
assertSolanaReadContext(row, canonicalAddress, solanaSelection, source === "receipts" ? "payer" : "agent_address");
|
|
103
|
+
if (solanaSelection &&
|
|
104
|
+
fields.some((f) => row[f] !== undefined &&
|
|
105
|
+
row[f] !== null &&
|
|
106
|
+
(typeof row[f] === "object" ||
|
|
107
|
+
!["string", "number", "boolean"].includes(typeof row[f]) ||
|
|
108
|
+
(typeof row[f] === "number" && !Number.isFinite(row[f])))))
|
|
109
|
+
throw new Error("Invalid structured Solana public metadata");
|
|
110
|
+
return Object.fromEntries(fields.filter((f) => row?.[f] !== undefined).map((f) => [f, row[f]]));
|
|
111
|
+
});
|
|
112
|
+
const indexing = solanaSelection && source === "transactions" ? solanaIndexingMetadata(body.indexing) : undefined;
|
|
118
113
|
return {
|
|
119
114
|
content: [
|
|
120
115
|
{
|
|
121
116
|
type: "text",
|
|
122
117
|
text: JSON.stringify({
|
|
123
|
-
address:
|
|
118
|
+
address: canonicalAddress,
|
|
119
|
+
...(solanaSelection ? { chain: "solana", ...solanaSelection } : {}),
|
|
120
|
+
...(indexing ? { indexing } : {}),
|
|
124
121
|
source,
|
|
125
122
|
items,
|
|
126
123
|
limit,
|
|
@@ -128,7 +125,9 @@ export async function runAgentHistory(ctx, args) {
|
|
|
128
125
|
next_offset: typeof body.next_offset === "number" ? body.next_offset : null,
|
|
129
126
|
coverage: source === "receipts"
|
|
130
127
|
? "Retained receipts only; externally metered quotas may lag"
|
|
131
|
-
:
|
|
128
|
+
: solanaSelection
|
|
129
|
+
? "Verified Solana settlements from retained RPC inventory only; partial history, no full archive or wallet coverage attestation; shared or unquoted transaction costs may be unavailable"
|
|
130
|
+
: "Indexed AiFinPay settlements for the requested chain and cluster; excludes arbitrary wallet transfers and may lag the chain",
|
|
132
131
|
}, null, 2),
|
|
133
132
|
},
|
|
134
133
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-history.js","sourceRoot":"","sources":["../../src/tools/agent-history.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-history.js","sourceRoot":"","sources":["../../src/tools/agent-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-quota.d.ts","sourceRoot":"","sources":["../../src/tools/agent-quota.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-quota.d.ts","sourceRoot":"","sources":["../../src/tools/agent-quota.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAUhD,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;EA0B7B;AAkBD,wBAAsB,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;GAgGlF"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { isSolanaPublicKey, solanaHistorySelection, assertSolanaReadContext, assertSolanaQuota, } from "../payment-identity.js";
|
|
1
2
|
const DEFAULT_BASE = "https://api.aifinpay.io";
|
|
2
3
|
export function agentQuotaTool() {
|
|
3
4
|
return {
|
|
4
5
|
name: "agent_quota",
|
|
5
|
-
description: "
|
|
6
|
+
description: "Read this agent's prepaid quota, per service. Lists the " +
|
|
6
7
|
"agent's active quota batches (merchant, resource, used, remaining, " +
|
|
7
8
|
"expiry). Read-only; never spends, pays, or signs anything. Ask it " +
|
|
8
|
-
"things like: how
|
|
9
|
+
"things like: how much prepaid quota do I have left at mrch_x?",
|
|
9
10
|
inputSchema: {
|
|
10
11
|
type: "object",
|
|
11
12
|
properties: {
|
|
@@ -27,12 +28,21 @@ export function agentQuotaTool() {
|
|
|
27
28
|
}
|
|
28
29
|
export async function runAgentQuota(ctx, args) {
|
|
29
30
|
const base = (ctx.config.baseUrl ?? DEFAULT_BASE).replace(/\/+$/, "");
|
|
30
|
-
const
|
|
31
|
+
const solana = ctx.config.payChain === "solana";
|
|
32
|
+
const address = solana ? ctx.agent.solanaAddress : ctx.agent.evmAddress;
|
|
31
33
|
const merchantFilter = typeof args.merchant_id === "string" && args.merchant_id ? args.merchant_id : null;
|
|
32
34
|
const includeExhausted = args.include_exhausted === true;
|
|
33
35
|
let resp;
|
|
36
|
+
let solanaSelection;
|
|
34
37
|
try {
|
|
35
|
-
|
|
38
|
+
let query = "";
|
|
39
|
+
if (solana) {
|
|
40
|
+
if (!isSolanaPublicKey(address))
|
|
41
|
+
throw new Error("Expected a canonical 32-byte Solana address");
|
|
42
|
+
solanaSelection = solanaHistorySelection(ctx.config);
|
|
43
|
+
query = `?${new URLSearchParams({ chain: "solana", network: solanaSelection.network, program: solanaSelection.program })}`;
|
|
44
|
+
}
|
|
45
|
+
resp = await ctx.agent.inner.fetchImpl(`${base}/v1/agents/${address}/receipts${query}`, {
|
|
36
46
|
method: "GET",
|
|
37
47
|
});
|
|
38
48
|
}
|
|
@@ -43,7 +53,22 @@ export async function runAgentQuota(ctx, args) {
|
|
|
43
53
|
if (!resp.ok) {
|
|
44
54
|
return errorResult(`quota lookup failed: HTTP ${resp.status}`);
|
|
45
55
|
}
|
|
46
|
-
|
|
56
|
+
let body;
|
|
57
|
+
try {
|
|
58
|
+
body = (await resp.json());
|
|
59
|
+
if (solanaSelection) {
|
|
60
|
+
assertSolanaReadContext(body, address, solanaSelection, "address");
|
|
61
|
+
if (!Array.isArray(body.receipts))
|
|
62
|
+
throw new Error("Invalid Solana quota response");
|
|
63
|
+
for (const row of body.receipts) {
|
|
64
|
+
assertSolanaReadContext(row, address, solanaSelection, "payer");
|
|
65
|
+
assertSolanaQuota(row);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return errorResult("Quota metadata is unavailable or does not match the selected wallet/network/program");
|
|
71
|
+
}
|
|
47
72
|
const now = Math.floor(Date.now() / 1000);
|
|
48
73
|
let batches = (body.receipts ?? [])
|
|
49
74
|
.filter((r) => r.exp == null || r.exp > now)
|
|
@@ -56,7 +81,7 @@ export async function runAgentQuota(ctx, args) {
|
|
|
56
81
|
tier: r.tier,
|
|
57
82
|
used: r.used ?? 0,
|
|
58
83
|
remaining: r.remaining ?? 0,
|
|
59
|
-
quota: r.quota ?? 1,
|
|
84
|
+
quota: solanaSelection ? r.unit_quota : (r.quota ?? 1),
|
|
60
85
|
paid: r.amount != null ? `${r.amount} ${r.currency ?? "USD"}` : undefined,
|
|
61
86
|
expires: r.exp != null ? new Date(r.exp * 1000).toISOString() : undefined,
|
|
62
87
|
receipt_id: r.receipt_id,
|
|
@@ -70,19 +95,25 @@ export async function runAgentQuota(ctx, args) {
|
|
|
70
95
|
const key = b.merchant_id ?? "unknown";
|
|
71
96
|
const cur = perMerchant.get(key) ?? { remaining: 0, batches: 0 };
|
|
72
97
|
cur.remaining += b.remaining;
|
|
98
|
+
if (solanaSelection && !Number.isSafeInteger(cur.remaining))
|
|
99
|
+
return errorResult("Quota total exceeds safe integer range");
|
|
73
100
|
cur.batches += 1;
|
|
74
101
|
perMerchant.set(key, cur);
|
|
75
102
|
}
|
|
76
103
|
const payload = {
|
|
77
104
|
agent: address,
|
|
105
|
+
...(solanaSelection ? { chain: "solana", ...solanaSelection } : {}),
|
|
106
|
+
...(solanaSelection ? { unit: "billing_units" } : {}),
|
|
78
107
|
...(merchantFilter ? { merchant_filter: merchantFilter } : {}),
|
|
79
108
|
totals: Object.fromEntries(perMerchant),
|
|
80
109
|
batches,
|
|
81
|
-
note:
|
|
82
|
-
?
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
110
|
+
note: solanaSelection
|
|
111
|
+
? "Solana remaining/used/quota are billing units. The number of callable requests depends on each route's server-defined cost_units. Hosted gateway usage is durable; external merchant metering may lag. An empty result means no retained active quota in this selected wallet/network/program."
|
|
112
|
+
: batches.length === 0
|
|
113
|
+
? merchantFilter
|
|
114
|
+
? `no active quota at ${merchantFilter} — a new batch starts with that service's 402 (or agent_quote its URL first)`
|
|
115
|
+
: "no active quota anywhere — pay a service's 402 to start a batch"
|
|
116
|
+
: "`remaining` is authoritative where AiFinPay meters (hosted gateway); a merchant running its own @aifinpay/gate meters locally and our copy can lag behind by their traffic.",
|
|
86
117
|
};
|
|
87
118
|
return {
|
|
88
119
|
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|