@agentwonderland/mcp 0.1.23 → 0.1.24
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/dist/core/__tests__/card-setup.test.d.ts +1 -0
- package/dist/core/__tests__/card-setup.test.js +99 -0
- package/dist/core/__tests__/formatters.test.d.ts +1 -0
- package/dist/core/__tests__/formatters.test.js +15 -0
- package/dist/core/__tests__/passes.test.d.ts +1 -0
- package/dist/core/__tests__/passes.test.js +82 -0
- package/dist/core/__tests__/payments.test.d.ts +1 -0
- package/dist/core/__tests__/payments.test.js +52 -0
- package/dist/core/__tests__/principal.test.d.ts +1 -0
- package/dist/core/__tests__/principal.test.js +67 -0
- package/dist/core/api-client.d.ts +9 -4
- package/dist/core/api-client.js +52 -22
- package/dist/core/card-setup.d.ts +20 -13
- package/dist/core/card-setup.js +85 -29
- package/dist/core/config.d.ts +3 -0
- package/dist/core/config.js +24 -2
- package/dist/core/formatters.d.ts +2 -0
- package/dist/core/formatters.js +5 -1
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/ows-adapter.d.ts +10 -2
- package/dist/core/ows-adapter.js +54 -10
- package/dist/core/passes.d.ts +40 -0
- package/dist/core/passes.js +32 -0
- package/dist/core/payments.d.ts +8 -0
- package/dist/core/payments.js +97 -13
- package/dist/core/principal.d.ts +2 -0
- package/dist/core/principal.js +109 -0
- package/dist/core/solana-charge.d.ts +9 -0
- package/dist/core/solana-charge.js +95 -0
- package/dist/core/types.d.ts +10 -0
- package/dist/index.js +8 -3
- package/dist/prompts/index.js +1 -1
- package/dist/resources/wallet.js +8 -1
- package/dist/tools/__tests__/_payment-confirmation.test.d.ts +1 -0
- package/dist/tools/__tests__/_payment-confirmation.test.js +30 -0
- package/dist/tools/_payment-confirmation.d.ts +6 -0
- package/dist/tools/_payment-confirmation.js +28 -0
- package/dist/tools/agent-info.js +14 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +1 -0
- package/dist/tools/passes.d.ts +2 -0
- package/dist/tools/passes.js +157 -0
- package/dist/tools/run.js +113 -51
- package/dist/tools/solve.js +102 -44
- package/dist/tools/wallet.js +85 -50
- package/package.json +3 -1
- package/src/core/__tests__/card-setup.test.ts +118 -0
- package/src/core/__tests__/formatters.test.ts +17 -0
- package/src/core/__tests__/passes.test.ts +94 -0
- package/src/core/__tests__/payments.test.ts +60 -0
- package/src/core/__tests__/principal.test.ts +87 -0
- package/src/core/api-client.ts +70 -23
- package/src/core/card-setup.ts +109 -34
- package/src/core/config.ts +29 -3
- package/src/core/formatters.ts +7 -1
- package/src/core/index.ts +2 -0
- package/src/core/ows-adapter.ts +74 -8
- package/src/core/passes.ts +74 -0
- package/src/core/payments.ts +113 -13
- package/src/core/principal.ts +128 -0
- package/src/core/solana-charge.ts +149 -0
- package/src/core/types.ts +10 -0
- package/src/index.ts +8 -3
- package/src/prompts/index.ts +1 -1
- package/src/resources/wallet.ts +8 -1
- package/src/tools/__tests__/_payment-confirmation.test.ts +45 -0
- package/src/tools/_payment-confirmation.ts +52 -0
- package/src/tools/agent-info.ts +23 -0
- package/src/tools/index.ts +1 -0
- package/src/tools/passes.ts +234 -0
- package/src/tools/run.ts +171 -55
- package/src/tools/solve.ts +149 -56
- package/src/tools/wallet.ts +102 -52
package/dist/core/card-setup.js
CHANGED
|
@@ -1,41 +1,50 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { apiPost, apiGet, ApiError } from "./api-client.js";
|
|
2
|
+
import { getApiUrl, setCardConfig, getPendingCardSetupToken, setPendingCardSetupToken, } from "./config.js";
|
|
3
|
+
let cachedCapabilities = null;
|
|
4
|
+
function buildCardSetupUrl(token) {
|
|
5
|
+
return `${getApiUrl()}/card/handoff/${token}`;
|
|
6
|
+
}
|
|
4
7
|
/**
|
|
5
|
-
*
|
|
6
|
-
* QR code + short URL for the user to scan.
|
|
8
|
+
* Create a new card setup session or resume the pending one from config.
|
|
7
9
|
*/
|
|
8
|
-
export async function
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
return {
|
|
10
|
+
export async function getOrCreatePendingCardSetup() {
|
|
11
|
+
const pendingToken = getPendingCardSetupToken();
|
|
12
|
+
if (pendingToken) {
|
|
13
|
+
const url = buildCardSetupUrl(pendingToken);
|
|
14
|
+
return {
|
|
15
|
+
url,
|
|
16
|
+
token: pendingToken,
|
|
17
|
+
isNew: false,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const { token } = await apiPost("/card/setup", {});
|
|
21
|
+
setPendingCardSetupToken(token);
|
|
22
|
+
const url = buildCardSetupUrl(token);
|
|
23
|
+
return {
|
|
24
|
+
url,
|
|
25
|
+
token,
|
|
26
|
+
isNew: true,
|
|
27
|
+
};
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
|
-
* Format the card setup prompt as
|
|
25
|
-
*
|
|
26
|
-
*
|
|
30
|
+
* Format the card setup prompt as a single text block.
|
|
31
|
+
*
|
|
32
|
+
* Some MCP clients only surface one text chunk or collapse multi-part tool
|
|
33
|
+
* output, which can hide the QR code entirely. Keeping everything in one
|
|
34
|
+
* message makes the browser handoff much more reliable.
|
|
27
35
|
*/
|
|
28
|
-
export function formatCardSetupBlocks(
|
|
36
|
+
export function formatCardSetupBlocks(url) {
|
|
29
37
|
return [
|
|
30
|
-
"\n" + qr.trim(),
|
|
31
38
|
[
|
|
32
|
-
|
|
39
|
+
"Open this setup page to connect your card:",
|
|
33
40
|
"",
|
|
34
41
|
url,
|
|
35
42
|
"",
|
|
36
|
-
|
|
43
|
+
"The setup page will take you to Stripe to securely save the card.",
|
|
44
|
+
"",
|
|
45
|
+
`Tell the user: "Open this setup page to connect your card. Let me know when you're done."`,
|
|
37
46
|
`After they confirm, call wallet_setup({ action: "add-card" }) to complete setup.`,
|
|
38
|
-
`Crypto wallets (
|
|
47
|
+
`Crypto wallets (Tempo, Base, or Solana USDC) are also available via wallet_setup({ action: "create" }).`,
|
|
39
48
|
].join("\n"),
|
|
40
49
|
];
|
|
41
50
|
}
|
|
@@ -45,7 +54,6 @@ export function formatCardSetupBlocks(qr, url) {
|
|
|
45
54
|
export async function pollCardSetup(token, timeoutMs = 120_000) {
|
|
46
55
|
const deadline = Date.now() + timeoutMs;
|
|
47
56
|
while (Date.now() < deadline) {
|
|
48
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
49
57
|
try {
|
|
50
58
|
const status = await apiGet(`/card/status?token=${token}`);
|
|
51
59
|
if (status.status === "complete" && status.consumer_token) {
|
|
@@ -61,12 +69,60 @@ export async function pollCardSetup(token, timeoutMs = 120_000) {
|
|
|
61
69
|
last4: card.last4,
|
|
62
70
|
brand: card.brand,
|
|
63
71
|
});
|
|
72
|
+
setPendingCardSetupToken(null);
|
|
64
73
|
return card;
|
|
65
74
|
}
|
|
66
75
|
}
|
|
67
|
-
catch {
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
78
|
+
setPendingCardSetupToken(null);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
68
81
|
// Keep polling
|
|
69
82
|
}
|
|
83
|
+
const remainingMs = deadline - Date.now();
|
|
84
|
+
if (remainingMs <= 0)
|
|
85
|
+
break;
|
|
86
|
+
await new Promise((r) => setTimeout(r, Math.min(3000, remainingMs)));
|
|
70
87
|
}
|
|
71
88
|
return null;
|
|
72
89
|
}
|
|
90
|
+
export async function getCardCapabilities() {
|
|
91
|
+
const apiUrl = getApiUrl();
|
|
92
|
+
if (cachedCapabilities && cachedCapabilities.apiUrl === apiUrl && cachedCapabilities.expiresAt > Date.now()) {
|
|
93
|
+
return cachedCapabilities.value;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const capabilities = await apiGet("/card/capabilities");
|
|
97
|
+
cachedCapabilities = {
|
|
98
|
+
value: capabilities,
|
|
99
|
+
apiUrl,
|
|
100
|
+
expiresAt: Date.now() + 30_000,
|
|
101
|
+
};
|
|
102
|
+
return capabilities;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (err instanceof ApiError) {
|
|
106
|
+
const fallback = {
|
|
107
|
+
spt_status: "unknown",
|
|
108
|
+
message: err.message,
|
|
109
|
+
};
|
|
110
|
+
cachedCapabilities = {
|
|
111
|
+
value: fallback,
|
|
112
|
+
apiUrl,
|
|
113
|
+
expiresAt: Date.now() + 10_000,
|
|
114
|
+
};
|
|
115
|
+
return fallback;
|
|
116
|
+
}
|
|
117
|
+
const fallback = {
|
|
118
|
+
spt_status: "unknown",
|
|
119
|
+
message: "Could not determine card payment availability.",
|
|
120
|
+
};
|
|
121
|
+
cachedCapabilities = {
|
|
122
|
+
value: fallback,
|
|
123
|
+
apiUrl,
|
|
124
|
+
expiresAt: Date.now() + 10_000,
|
|
125
|
+
};
|
|
126
|
+
return fallback;
|
|
127
|
+
}
|
|
128
|
+
}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface Config {
|
|
|
21
21
|
defaultWallet: string | null;
|
|
22
22
|
defaultPaymentMethod?: string;
|
|
23
23
|
card: CardConfig | null;
|
|
24
|
+
pendingCardSetupToken?: string | null;
|
|
24
25
|
favorites: string[];
|
|
25
26
|
/** Require user confirmation before spending. Default: true. Set false for headless/automated use. */
|
|
26
27
|
confirmBeforeSpend: boolean;
|
|
@@ -73,6 +74,8 @@ export declare function getCardConfig(): CardConfig | null;
|
|
|
73
74
|
* Save card configuration after setup.
|
|
74
75
|
*/
|
|
75
76
|
export declare function setCardConfig(card: CardConfig | null): void;
|
|
77
|
+
export declare function getPendingCardSetupToken(): string | null;
|
|
78
|
+
export declare function setPendingCardSetupToken(token: string | null): void;
|
|
76
79
|
/**
|
|
77
80
|
* Resolve a payment method string to a wallet + chain.
|
|
78
81
|
* Accepts: wallet ID, chain name, or "card".
|
package/dist/core/config.js
CHANGED
|
@@ -34,7 +34,9 @@ function migrateIfNeeded(raw) {
|
|
|
34
34
|
userId: raw.userId ?? null,
|
|
35
35
|
wallets: raw.wallets,
|
|
36
36
|
defaultWallet: raw.defaultWallet ?? null,
|
|
37
|
+
defaultPaymentMethod: raw.defaultPaymentMethod ?? undefined,
|
|
37
38
|
card: raw.card ?? null,
|
|
39
|
+
pendingCardSetupToken: r.pendingCardSetupToken ?? null,
|
|
38
40
|
favorites: r.favorites ?? [],
|
|
39
41
|
confirmBeforeSpend: r.confirmBeforeSpend !== false,
|
|
40
42
|
defaultTipAmount: typeof r.defaultTipAmount === "number" ? r.defaultTipAmount : 0,
|
|
@@ -103,7 +105,9 @@ function migrateIfNeeded(raw) {
|
|
|
103
105
|
userId: raw.userId ?? null,
|
|
104
106
|
wallets,
|
|
105
107
|
defaultWallet,
|
|
108
|
+
defaultPaymentMethod: raw.defaultPaymentMethod ?? undefined,
|
|
106
109
|
card,
|
|
110
|
+
pendingCardSetupToken: null,
|
|
107
111
|
favorites: [],
|
|
108
112
|
confirmBeforeSpend: true,
|
|
109
113
|
defaultTipAmount: 0,
|
|
@@ -124,6 +128,7 @@ export function getConfig() {
|
|
|
124
128
|
wallets: [],
|
|
125
129
|
defaultWallet: null,
|
|
126
130
|
card: null,
|
|
131
|
+
pendingCardSetupToken: null,
|
|
127
132
|
favorites: [],
|
|
128
133
|
confirmBeforeSpend: true,
|
|
129
134
|
defaultTipAmount: 0,
|
|
@@ -263,13 +268,30 @@ export function getCardConfig() {
|
|
|
263
268
|
* Save card configuration after setup.
|
|
264
269
|
*/
|
|
265
270
|
export function setCardConfig(card) {
|
|
271
|
+
const current = getConfig();
|
|
266
272
|
if (card) {
|
|
267
|
-
saveConfig({
|
|
273
|
+
saveConfig({
|
|
274
|
+
card,
|
|
275
|
+
defaultPaymentMethod: "card",
|
|
276
|
+
pendingCardSetupToken: null,
|
|
277
|
+
});
|
|
268
278
|
}
|
|
269
279
|
else {
|
|
270
|
-
saveConfig({
|
|
280
|
+
saveConfig({
|
|
281
|
+
card,
|
|
282
|
+
pendingCardSetupToken: null,
|
|
283
|
+
defaultPaymentMethod: current.defaultPaymentMethod === "card"
|
|
284
|
+
? undefined
|
|
285
|
+
: current.defaultPaymentMethod,
|
|
286
|
+
});
|
|
271
287
|
}
|
|
272
288
|
}
|
|
289
|
+
export function getPendingCardSetupToken() {
|
|
290
|
+
return getConfig().pendingCardSetupToken ?? null;
|
|
291
|
+
}
|
|
292
|
+
export function setPendingCardSetupToken(token) {
|
|
293
|
+
saveConfig({ pendingCardSetupToken: token });
|
|
294
|
+
}
|
|
273
295
|
/**
|
|
274
296
|
* Resolve a payment method string to a wallet + chain.
|
|
275
297
|
* Accepts: wallet ID, chain name, or "card".
|
|
@@ -43,6 +43,8 @@ interface RunResultLike {
|
|
|
43
43
|
estimated_cost?: number;
|
|
44
44
|
input_tokens?: number;
|
|
45
45
|
tags?: string[];
|
|
46
|
+
consumption_mode?: string;
|
|
47
|
+
credit_pack_id?: string;
|
|
46
48
|
}
|
|
47
49
|
export declare function formatRunResult(result: RunResultLike, opts?: {
|
|
48
50
|
paymentMethod?: string;
|
package/dist/core/formatters.js
CHANGED
|
@@ -110,6 +110,7 @@ export function formatRunResult(result, opts) {
|
|
|
110
110
|
}
|
|
111
111
|
// Summary line
|
|
112
112
|
const cost = result.cost ?? result.estimated_cost;
|
|
113
|
+
const usedCreditPack = result.consumption_mode === "credit_pack";
|
|
113
114
|
const status = result.status === "success" || result.status === "completed" ? "✓" : "✗";
|
|
114
115
|
const agent = result.agent_name ?? result.agent_id ?? "";
|
|
115
116
|
const costStr = cost != null ? `$${cost.toFixed(cost < 0.01 ? 6 : 2)}` : "";
|
|
@@ -119,7 +120,10 @@ export function formatRunResult(result, opts) {
|
|
|
119
120
|
if (result.error_code) {
|
|
120
121
|
lines.push(`Error: ${result.error_code}`);
|
|
121
122
|
}
|
|
122
|
-
if (
|
|
123
|
+
if (usedCreditPack) {
|
|
124
|
+
lines.push(`Covered by credit pack${result.credit_pack_id ? ` (${result.credit_pack_id})` : ""}`);
|
|
125
|
+
}
|
|
126
|
+
if (costStr && !usedCreditPack) {
|
|
123
127
|
lines.push(`Paid: ${costStr}${method ? ` via ${method}` : ""}`);
|
|
124
128
|
}
|
|
125
129
|
if (result.job_id) {
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* ALL imports are dynamic so the MCP server works without OWS installed.
|
|
9
9
|
*/
|
|
10
10
|
import type { LocalAccount } from "viem/accounts";
|
|
11
|
+
import type { Keypair } from "@solana/web3.js";
|
|
11
12
|
/**
|
|
12
13
|
* Check whether the OWS native module can be loaded.
|
|
13
14
|
*/
|
|
@@ -19,17 +20,19 @@ export declare function isOwsAvailable(): Promise<boolean>;
|
|
|
19
20
|
* @param chain - OWS chain identifier (default "evm")
|
|
20
21
|
*/
|
|
21
22
|
export declare function owsAccountFromWalletId(walletId: string, _chain?: string): Promise<LocalAccount>;
|
|
23
|
+
export declare function owsSolanaKeypairFromWalletId(walletId: string): Promise<Keypair>;
|
|
24
|
+
export declare function getOwsWalletAddress(walletId: string, chain?: "evm" | "solana"): Promise<string>;
|
|
22
25
|
/**
|
|
23
26
|
* Create a new OWS wallet and return its ID + EVM address.
|
|
24
27
|
*/
|
|
25
|
-
export declare function createOwsWallet(name: string): Promise<{
|
|
28
|
+
export declare function createOwsWallet(name: string, chain?: "evm" | "solana"): Promise<{
|
|
26
29
|
walletId: string;
|
|
27
30
|
address: string;
|
|
28
31
|
}>;
|
|
29
32
|
/**
|
|
30
33
|
* Import an existing EVM private key into OWS.
|
|
31
34
|
*/
|
|
32
|
-
export declare function importKeyToOws(privateKey: string, name: string): Promise<{
|
|
35
|
+
export declare function importKeyToOws(privateKey: string, name: string, chain?: "evm" | "solana"): Promise<{
|
|
33
36
|
walletId: string;
|
|
34
37
|
address: string;
|
|
35
38
|
}>;
|
|
@@ -41,3 +44,8 @@ export declare function listOwsWallets(): Promise<Array<{
|
|
|
41
44
|
name: string;
|
|
42
45
|
address: string;
|
|
43
46
|
}>>;
|
|
47
|
+
export declare function listOwsWalletsByChain(chain?: "evm" | "solana"): Promise<Array<{
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
address: string;
|
|
51
|
+
}>>;
|
package/dist/core/ows-adapter.js
CHANGED
|
@@ -38,6 +38,26 @@ function findEvmAccount(wallet) {
|
|
|
38
38
|
}
|
|
39
39
|
return evm;
|
|
40
40
|
}
|
|
41
|
+
function findSolanaAccount(wallet) {
|
|
42
|
+
const solana = wallet.accounts.find((a) => a.chainId.startsWith("solana"));
|
|
43
|
+
if (!solana) {
|
|
44
|
+
throw new Error(`Wallet "${wallet.name}" (${wallet.id}) has no Solana account.`);
|
|
45
|
+
}
|
|
46
|
+
return solana;
|
|
47
|
+
}
|
|
48
|
+
function ed25519HexToBytes(privateKeyHex) {
|
|
49
|
+
return Uint8Array.from(Buffer.from(privateKeyHex, "hex"));
|
|
50
|
+
}
|
|
51
|
+
function keypairFromEd25519Hex(privateKeyHex, KeypairCtor) {
|
|
52
|
+
const bytes = ed25519HexToBytes(privateKeyHex);
|
|
53
|
+
if (bytes.length === 32) {
|
|
54
|
+
return KeypairCtor.fromSeed(bytes);
|
|
55
|
+
}
|
|
56
|
+
if (bytes.length === 64) {
|
|
57
|
+
return KeypairCtor.fromSecretKey(bytes);
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Unsupported ed25519 key length: ${bytes.length} bytes.`);
|
|
60
|
+
}
|
|
41
61
|
// ── Public API ───────────────────────────────────────────────────
|
|
42
62
|
/**
|
|
43
63
|
* Check whether the OWS native module can be loaded.
|
|
@@ -73,38 +93,62 @@ export async function owsAccountFromWalletId(walletId, _chain) {
|
|
|
73
93
|
const { privateKeyToAccount } = await import("viem/accounts");
|
|
74
94
|
return privateKeyToAccount(`0x${keys.secp256k1}`);
|
|
75
95
|
}
|
|
96
|
+
export async function owsSolanaKeypairFromWalletId(walletId) {
|
|
97
|
+
const ows = await loadOws();
|
|
98
|
+
const wallet = ows.getWallet(walletId);
|
|
99
|
+
findSolanaAccount(wallet);
|
|
100
|
+
const exported = ows.exportWallet(walletId);
|
|
101
|
+
const keys = JSON.parse(exported);
|
|
102
|
+
if (!keys.ed25519) {
|
|
103
|
+
throw new Error(`Wallet "${wallet.name}" has no ed25519 key for Solana signing.`);
|
|
104
|
+
}
|
|
105
|
+
const { Keypair } = await import("@solana/web3.js");
|
|
106
|
+
return keypairFromEd25519Hex(keys.ed25519, Keypair);
|
|
107
|
+
}
|
|
108
|
+
export async function getOwsWalletAddress(walletId, chain = "evm") {
|
|
109
|
+
const ows = await loadOws();
|
|
110
|
+
const wallet = ows.getWallet(walletId);
|
|
111
|
+
return chain === "solana"
|
|
112
|
+
? findSolanaAccount(wallet).address
|
|
113
|
+
: findEvmAccount(wallet).address;
|
|
114
|
+
}
|
|
76
115
|
/**
|
|
77
116
|
* Create a new OWS wallet and return its ID + EVM address.
|
|
78
117
|
*/
|
|
79
|
-
export async function createOwsWallet(name) {
|
|
118
|
+
export async function createOwsWallet(name, chain = "evm") {
|
|
80
119
|
const ows = await loadOws();
|
|
81
120
|
const wallet = ows.createWallet(name);
|
|
82
|
-
const
|
|
83
|
-
return { walletId: wallet.id, address:
|
|
121
|
+
const account = chain === "solana" ? findSolanaAccount(wallet) : findEvmAccount(wallet);
|
|
122
|
+
return { walletId: wallet.id, address: account.address };
|
|
84
123
|
}
|
|
85
124
|
/**
|
|
86
125
|
* Import an existing EVM private key into OWS.
|
|
87
126
|
*/
|
|
88
|
-
export async function importKeyToOws(privateKey, name) {
|
|
127
|
+
export async function importKeyToOws(privateKey, name, chain = "evm") {
|
|
89
128
|
const ows = await loadOws();
|
|
90
129
|
const normalizedKey = privateKey.startsWith("0x")
|
|
91
130
|
? privateKey.slice(2)
|
|
92
131
|
: privateKey;
|
|
93
|
-
const wallet = ows.importWalletPrivateKey(name, normalizedKey, null, null,
|
|
94
|
-
const
|
|
95
|
-
return { walletId: wallet.id, address:
|
|
132
|
+
const wallet = ows.importWalletPrivateKey(name, normalizedKey, null, null, chain);
|
|
133
|
+
const account = chain === "solana" ? findSolanaAccount(wallet) : findEvmAccount(wallet);
|
|
134
|
+
return { walletId: wallet.id, address: account.address };
|
|
96
135
|
}
|
|
97
136
|
/**
|
|
98
137
|
* List all OWS wallets that have an EVM account.
|
|
99
138
|
*/
|
|
100
139
|
export async function listOwsWallets() {
|
|
140
|
+
return listOwsWalletsByChain("evm");
|
|
141
|
+
}
|
|
142
|
+
export async function listOwsWalletsByChain(chain = "evm") {
|
|
101
143
|
const ows = await loadOws();
|
|
102
144
|
const wallets = ows.listWallets();
|
|
103
145
|
const result = [];
|
|
104
146
|
for (const w of wallets) {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
147
|
+
const account = chain === "solana"
|
|
148
|
+
? w.accounts.find((a) => a.chainId.startsWith("solana"))
|
|
149
|
+
: w.accounts.find((a) => a.chainId.startsWith("eip155") || a.chainId.startsWith("evm"));
|
|
150
|
+
if (account) {
|
|
151
|
+
result.push({ id: w.id, name: w.name, address: account.address });
|
|
108
152
|
}
|
|
109
153
|
}
|
|
110
154
|
return result;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AgentRecord } from "./types.js";
|
|
2
|
+
export interface CreditPackOffer {
|
|
3
|
+
pack_id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
included_units: number;
|
|
6
|
+
price_usd: string;
|
|
7
|
+
effective_price_per_unit_usd?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CreditPackRecord {
|
|
10
|
+
id: string;
|
|
11
|
+
status: string;
|
|
12
|
+
unit_type: string;
|
|
13
|
+
included_units: number;
|
|
14
|
+
remaining_units: number;
|
|
15
|
+
price_usd: string;
|
|
16
|
+
purchased_at: string;
|
|
17
|
+
pack?: {
|
|
18
|
+
name?: string | null;
|
|
19
|
+
key?: string | null;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface CreditPackProgramInfo {
|
|
23
|
+
unit_type?: string;
|
|
24
|
+
packs?: Array<{
|
|
25
|
+
key?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
included_units?: number;
|
|
28
|
+
price_usd?: string;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
31
|
+
export interface CreditPackInventory {
|
|
32
|
+
consumer_principal: string | null;
|
|
33
|
+
offers: CreditPackOffer[];
|
|
34
|
+
balances: CreditPackRecord[];
|
|
35
|
+
}
|
|
36
|
+
export declare function getCreditPackProgram(agent: AgentRecord): CreditPackProgramInfo | null;
|
|
37
|
+
export declare function getCreditPackInventory(agentId: string): Promise<CreditPackInventory | null>;
|
|
38
|
+
export declare function getActiveCreditPack(inventory: CreditPackInventory | null): CreditPackRecord | null;
|
|
39
|
+
export declare function formatCreditPackOffer(offer: CreditPackOffer): string;
|
|
40
|
+
export declare function formatCreditPack(pack: CreditPackRecord): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { apiGet } from "./api-client.js";
|
|
2
|
+
export function getCreditPackProgram(agent) {
|
|
3
|
+
const payment = (agent.payment ?? {});
|
|
4
|
+
const creditPacks = payment.credit_packs;
|
|
5
|
+
return creditPacks ?? null;
|
|
6
|
+
}
|
|
7
|
+
export async function getCreditPackInventory(agentId) {
|
|
8
|
+
try {
|
|
9
|
+
return await apiGet(`/agents/${agentId}/credit-packs`, { ensureConsumerPrincipal: true });
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function getActiveCreditPack(inventory) {
|
|
16
|
+
if (!inventory)
|
|
17
|
+
return null;
|
|
18
|
+
return inventory.balances
|
|
19
|
+
.filter((pack) => pack.status === "active" && pack.remaining_units > 0)
|
|
20
|
+
.sort((a, b) => new Date(a.purchased_at).getTime() - new Date(b.purchased_at).getTime())[0] ?? null;
|
|
21
|
+
}
|
|
22
|
+
export function formatCreditPackOffer(offer) {
|
|
23
|
+
const unitPrice = offer.effective_price_per_unit_usd
|
|
24
|
+
? ` ($${Number(offer.effective_price_per_unit_usd).toFixed(2)}/unit)`
|
|
25
|
+
: "";
|
|
26
|
+
return `${offer.label} — ${offer.included_units} units for $${offer.price_usd}${unitPrice}`;
|
|
27
|
+
}
|
|
28
|
+
export function formatCreditPack(pack) {
|
|
29
|
+
const label = pack.pack?.name ?? pack.pack?.key ?? "Credit Pack";
|
|
30
|
+
const statusPrefix = pack.status === "active" ? "" : `${pack.status} • `;
|
|
31
|
+
return `${label}: ${statusPrefix}${pack.remaining_units}/${pack.included_units} ${pack.unit_type}s remaining`;
|
|
32
|
+
}
|
package/dist/core/payments.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Users can configure multiple wallets with different chains and select
|
|
10
10
|
* which to use per-request via `--pay-with <wallet-id|chain|card>`.
|
|
11
11
|
*/
|
|
12
|
+
import type { AgentRecord } from "./types.js";
|
|
12
13
|
/**
|
|
13
14
|
* Returns a payment-aware fetch for a specific method, or the best
|
|
14
15
|
* available method if none is specified.
|
|
@@ -21,6 +22,11 @@ export declare function getPaymentFetch(method?: string): Promise<typeof fetch>;
|
|
|
21
22
|
* (with default wallet's default chain first) + "card" if configured.
|
|
22
23
|
*/
|
|
23
24
|
export declare function getConfiguredMethods(): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Normalize a requested payment method into the MCP-visible method identifier.
|
|
27
|
+
* Accepts chain names, wallet IDs, or "card".
|
|
28
|
+
*/
|
|
29
|
+
export declare function normalizePaymentMethod(method: string): string | null;
|
|
24
30
|
/**
|
|
25
31
|
* Human-friendly display name for a payment method identifier.
|
|
26
32
|
*/
|
|
@@ -31,6 +37,8 @@ export declare function paymentMethodDisplayName(method: string): string;
|
|
|
31
37
|
* (tempo_usdc, base_usdc, stripe_card).
|
|
32
38
|
*/
|
|
33
39
|
export declare function getAcceptedPaymentMethods(): string[];
|
|
40
|
+
export declare function toRegistryPaymentMethod(method: string): string | null;
|
|
41
|
+
export declare function getCompatiblePaymentMethods(agent: Pick<AgentRecord, "payment"> | null | undefined, configuredMethods?: string[]): string[];
|
|
34
42
|
/**
|
|
35
43
|
* Check whether any payment method is configured.
|
|
36
44
|
*/
|