@xona-labs/xpay 0.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/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/cli/accounts.d.ts +13 -0
- package/dist/cli/accounts.d.ts.map +1 -0
- package/dist/cli/accounts.js +66 -0
- package/dist/cli/accounts.js.map +1 -0
- package/dist/cli/balance.d.ts +14 -0
- package/dist/cli/balance.d.ts.map +1 -0
- package/dist/cli/balance.js +60 -0
- package/dist/cli/balance.js.map +1 -0
- package/dist/cli/common.d.ts +20 -0
- package/dist/cli/common.d.ts.map +1 -0
- package/dist/cli/common.js +58 -0
- package/dist/cli/common.js.map +1 -0
- package/dist/cli/discover.d.ts +12 -0
- package/dist/cli/discover.d.ts.map +1 -0
- package/dist/cli/discover.js +69 -0
- package/dist/cli/discover.js.map +1 -0
- package/dist/cli/guardrail.d.ts +16 -0
- package/dist/cli/guardrail.d.ts.map +1 -0
- package/dist/cli/guardrail.js +71 -0
- package/dist/cli/guardrail.js.map +1 -0
- package/dist/cli/history.d.ts +16 -0
- package/dist/cli/history.d.ts.map +1 -0
- package/dist/cli/history.js +59 -0
- package/dist/cli/history.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +165 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +23 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +114 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp-server.d.ts +26 -0
- package/dist/cli/mcp-server.d.ts.map +1 -0
- package/dist/cli/mcp-server.js +112 -0
- package/dist/cli/mcp-server.js.map +1 -0
- package/dist/cli/pay.d.ts +15 -0
- package/dist/cli/pay.d.ts.map +1 -0
- package/dist/cli/pay.js +76 -0
- package/dist/cli/pay.js.map +1 -0
- package/dist/cli/transfer.d.ts +19 -0
- package/dist/cli/transfer.d.ts.map +1 -0
- package/dist/cli/transfer.js +66 -0
- package/dist/cli/transfer.js.map +1 -0
- package/dist/discover/cache.d.ts +24 -0
- package/dist/discover/cache.d.ts.map +1 -0
- package/dist/discover/cache.js +94 -0
- package/dist/discover/cache.js.map +1 -0
- package/dist/discover/index.d.ts +21 -0
- package/dist/discover/index.d.ts.map +1 -0
- package/dist/discover/index.js +88 -0
- package/dist/discover/index.js.map +1 -0
- package/dist/discover/payai.d.ts +18 -0
- package/dist/discover/payai.d.ts.map +1 -0
- package/dist/discover/payai.js +56 -0
- package/dist/discover/payai.js.map +1 -0
- package/dist/do/index.d.ts +17 -0
- package/dist/do/index.d.ts.map +1 -0
- package/dist/do/index.js +32 -0
- package/dist/do/index.js.map +1 -0
- package/dist/guardrail/index.d.ts +47 -0
- package/dist/guardrail/index.d.ts.map +1 -0
- package/dist/guardrail/index.js +99 -0
- package/dist/guardrail/index.js.map +1 -0
- package/dist/history/evm.d.ts +21 -0
- package/dist/history/evm.d.ts.map +1 -0
- package/dist/history/evm.js +118 -0
- package/dist/history/evm.js.map +1 -0
- package/dist/history/index.d.ts +19 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/index.js +45 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/solana.d.ts +20 -0
- package/dist/history/solana.d.ts.map +1 -0
- package/dist/history/solana.js +97 -0
- package/dist/history/solana.js.map +1 -0
- package/dist/history/types.d.ts +26 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/history/types.js +10 -0
- package/dist/history/types.js.map +1 -0
- package/dist/index.d.ts +94 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/dist/profile/derive.d.ts +28 -0
- package/dist/profile/derive.d.ts.map +1 -0
- package/dist/profile/derive.js +75 -0
- package/dist/profile/derive.js.map +1 -0
- package/dist/profile/index.d.ts +74 -0
- package/dist/profile/index.d.ts.map +1 -0
- package/dist/profile/index.js +115 -0
- package/dist/profile/index.js.map +1 -0
- package/dist/profile/storage.d.ts +35 -0
- package/dist/profile/storage.d.ts.map +1 -0
- package/dist/profile/storage.js +162 -0
- package/dist/profile/storage.js.map +1 -0
- package/dist/profile/types.d.ts +69 -0
- package/dist/profile/types.d.ts.map +1 -0
- package/dist/profile/types.js +9 -0
- package/dist/profile/types.js.map +1 -0
- package/dist/signers/index.d.ts +5 -0
- package/dist/signers/index.d.ts.map +1 -0
- package/dist/signers/index.js +5 -0
- package/dist/signers/index.js.map +1 -0
- package/dist/signers/phantom.d.ts +14 -0
- package/dist/signers/phantom.d.ts.map +1 -0
- package/dist/signers/phantom.js +12 -0
- package/dist/signers/phantom.js.map +1 -0
- package/dist/signers/privy.d.ts +20 -0
- package/dist/signers/privy.d.ts.map +1 -0
- package/dist/signers/privy.js +15 -0
- package/dist/signers/privy.js.map +1 -0
- package/dist/signers/raw-evm.d.ts +15 -0
- package/dist/signers/raw-evm.d.ts.map +1 -0
- package/dist/signers/raw-evm.js +70 -0
- package/dist/signers/raw-evm.js.map +1 -0
- package/dist/signers/raw-solana.d.ts +15 -0
- package/dist/signers/raw-solana.d.ts.map +1 -0
- package/dist/signers/raw-solana.js +88 -0
- package/dist/signers/raw-solana.js.map +1 -0
- package/dist/tools/index.d.ts +48 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +164 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/transfer/index.d.ts +30 -0
- package/dist/transfer/index.d.ts.map +1 -0
- package/dist/transfer/index.js +86 -0
- package/dist/transfer/index.js.map +1 -0
- package/dist/types.d.ts +203 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +56 -0
- package/dist/types.js.map +1 -0
- package/dist/use/index.d.ts +38 -0
- package/dist/use/index.d.ts.map +1 -0
- package/dist/use/index.js +173 -0
- package/dist/use/index.js.map +1 -0
- package/dist/wallet/index.d.ts +31 -0
- package/dist/wallet/index.d.ts.map +1 -0
- package/dist/wallet/index.js +56 -0
- package/dist/wallet/index.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Use — call a paid resource, handling x402 payment end-to-end.
|
|
3
|
+
*
|
|
4
|
+
* Two modes:
|
|
5
|
+
* - **Catalog mode** (`resource` has `accepts[]`): we pick a requirement up
|
|
6
|
+
* front, run guardrail, pay, then call with the X-Payment header.
|
|
7
|
+
* - **Live challenge mode** (`resource.accepts` empty *or* `useByUrl()`): we
|
|
8
|
+
* call the URL first, expect a `402` with a body listing accepted payment
|
|
9
|
+
* options, then settle and retry. This is the canonical x402 v2 flow and
|
|
10
|
+
* lets agents pay resources they discovered *outside* of any catalog.
|
|
11
|
+
*
|
|
12
|
+
* Both paths converge on the same {@link UseResult}.
|
|
13
|
+
*/
|
|
14
|
+
import { ResourceSchema, } from "../types.js";
|
|
15
|
+
export async function use(args) {
|
|
16
|
+
// If we have accepts up front, take the fast path.
|
|
17
|
+
if (args.resource.accepts.length > 0) {
|
|
18
|
+
return useWithRequirements(args, args.resource.accepts);
|
|
19
|
+
}
|
|
20
|
+
// Otherwise probe the resource for a 402 challenge.
|
|
21
|
+
return useWithLiveChallenge(args);
|
|
22
|
+
}
|
|
23
|
+
export async function useByUrl(args) {
|
|
24
|
+
const resource = {
|
|
25
|
+
resource: args.url,
|
|
26
|
+
type: "http",
|
|
27
|
+
method: args.method ?? "GET",
|
|
28
|
+
accepts: [],
|
|
29
|
+
};
|
|
30
|
+
return useWithLiveChallenge({
|
|
31
|
+
resource,
|
|
32
|
+
wallet: args.wallet,
|
|
33
|
+
guardrail: args.guardrail,
|
|
34
|
+
body: args.body,
|
|
35
|
+
headers: args.headers,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function useWithRequirements(args, reqs) {
|
|
39
|
+
const req = args.wallet.pickRequirement(reqs);
|
|
40
|
+
if (!req) {
|
|
41
|
+
throw new Error(`xpay.use: no compatible payment option. Resource accepts: ${reqs.map((a) => a.network).join(", ")}`);
|
|
42
|
+
}
|
|
43
|
+
// Guardrail runs *before* signing — this is the security boundary.
|
|
44
|
+
await args.guardrail.check({ resource: args.resource, requirement: req });
|
|
45
|
+
const network = normalizeNetwork(req.network);
|
|
46
|
+
const signer = args.wallet.signer(network);
|
|
47
|
+
const txSig = await signer.pay(req);
|
|
48
|
+
const res = await callResource(args, paymentHeader(req, txSig, args.resource.x402Version ?? 1));
|
|
49
|
+
return finalize(res, network, req.amount ?? "0", txSig);
|
|
50
|
+
}
|
|
51
|
+
async function useWithLiveChallenge(args) {
|
|
52
|
+
// Step 1: probe without payment.
|
|
53
|
+
const probe = await callResource(args, undefined);
|
|
54
|
+
if (probe.res.status !== 402) {
|
|
55
|
+
// No payment required — return the probe response as-is. (Useful when a
|
|
56
|
+
// resource later becomes free or for sanity checks.)
|
|
57
|
+
return finalize(probe, "unknown", "0");
|
|
58
|
+
}
|
|
59
|
+
// Step 2: parse the 402 body. x402 v2 returns a body shaped like a Resource
|
|
60
|
+
// (`{ accepts: [...] }`); we accept either that or a bare PaymentRequirement[].
|
|
61
|
+
const reqs = parseChallenge(probe.data);
|
|
62
|
+
if (reqs.length === 0) {
|
|
63
|
+
throw new Error(`xpay.use: ${args.resource.resource} returned 402 but no parseable accepts[] payload`);
|
|
64
|
+
}
|
|
65
|
+
const req = args.wallet.pickRequirement(reqs);
|
|
66
|
+
if (!req) {
|
|
67
|
+
throw new Error(`xpay.use: ${args.resource.resource} accepts ${reqs.map((r) => r.network).join(", ")} but wallet has no matching signer`);
|
|
68
|
+
}
|
|
69
|
+
await args.guardrail.check({ resource: args.resource, requirement: req });
|
|
70
|
+
const network = normalizeNetwork(req.network);
|
|
71
|
+
const signer = args.wallet.signer(network);
|
|
72
|
+
const txSig = await signer.pay(req);
|
|
73
|
+
// Step 3: retry with X-Payment.
|
|
74
|
+
const res = await callResource(args, paymentHeader(req, txSig, 2));
|
|
75
|
+
return finalize(res, network, req.amount ?? "0", txSig);
|
|
76
|
+
}
|
|
77
|
+
async function callResource(args, paymentHeader) {
|
|
78
|
+
const headers = {
|
|
79
|
+
accept: "application/json",
|
|
80
|
+
...args.headers,
|
|
81
|
+
};
|
|
82
|
+
if (paymentHeader)
|
|
83
|
+
headers["x-payment"] = paymentHeader;
|
|
84
|
+
let body;
|
|
85
|
+
if (args.body !== undefined && args.resource.method !== "GET") {
|
|
86
|
+
headers["content-type"] = "application/json";
|
|
87
|
+
body = JSON.stringify(args.body);
|
|
88
|
+
}
|
|
89
|
+
const res = await fetch(args.resource.resource, {
|
|
90
|
+
method: args.resource.method,
|
|
91
|
+
headers,
|
|
92
|
+
body,
|
|
93
|
+
});
|
|
94
|
+
const text = await res.text();
|
|
95
|
+
let data = text;
|
|
96
|
+
try {
|
|
97
|
+
data = JSON.parse(text);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
/* keep as string */
|
|
101
|
+
}
|
|
102
|
+
return { res, data };
|
|
103
|
+
}
|
|
104
|
+
function finalize(raw, network, amountPaid, txSig) {
|
|
105
|
+
if (!raw.res.ok) {
|
|
106
|
+
throw new Error(`xpay.use: ${raw.res.status} ${raw.res.statusText} — ${typeof raw.data === "string" ? raw.data : JSON.stringify(raw.data)}`);
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
data: raw.data,
|
|
110
|
+
status: raw.res.status,
|
|
111
|
+
network,
|
|
112
|
+
amountPaid,
|
|
113
|
+
txSig,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* x402 `X-Payment` header.
|
|
118
|
+
*
|
|
119
|
+
* Format is a base64-encoded JSON blob with the settlement details. Each
|
|
120
|
+
* facilitator validates differently, but the common subset (txSig, payTo,
|
|
121
|
+
* asset, amount, network) is what's encoded here.
|
|
122
|
+
*/
|
|
123
|
+
function paymentHeader(req, txSig, x402Version) {
|
|
124
|
+
const payload = {
|
|
125
|
+
scheme: req.scheme,
|
|
126
|
+
network: req.network,
|
|
127
|
+
payTo: req.payTo,
|
|
128
|
+
asset: req.asset,
|
|
129
|
+
amount: req.amount ?? "0",
|
|
130
|
+
txSig,
|
|
131
|
+
x402Version,
|
|
132
|
+
};
|
|
133
|
+
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Parse a 402 response body into PaymentRequirement[].
|
|
137
|
+
* Accepts either the v2 envelope (`{ accepts: [...] }` matching Resource) or a
|
|
138
|
+
* bare array (some facilitators ship this).
|
|
139
|
+
*/
|
|
140
|
+
function parseChallenge(data) {
|
|
141
|
+
if (Array.isArray(data)) {
|
|
142
|
+
const parsed = ResourceSchema.safeParse({
|
|
143
|
+
resource: "",
|
|
144
|
+
type: "http",
|
|
145
|
+
method: "GET",
|
|
146
|
+
accepts: data,
|
|
147
|
+
});
|
|
148
|
+
return parsed.success ? parsed.data.accepts : [];
|
|
149
|
+
}
|
|
150
|
+
if (data && typeof data === "object") {
|
|
151
|
+
const parsed = ResourceSchema.safeParse({
|
|
152
|
+
resource: "",
|
|
153
|
+
type: "http",
|
|
154
|
+
method: "GET",
|
|
155
|
+
...data,
|
|
156
|
+
});
|
|
157
|
+
if (parsed.success)
|
|
158
|
+
return parsed.data.accepts;
|
|
159
|
+
}
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
function normalizeNetwork(raw) {
|
|
163
|
+
if (raw === "eip155:8453")
|
|
164
|
+
return "base";
|
|
165
|
+
if (raw === "eip155:1")
|
|
166
|
+
return "ethereum";
|
|
167
|
+
if (raw === "eip155:42161")
|
|
168
|
+
return "arbitrum";
|
|
169
|
+
if (raw === "eip155:10")
|
|
170
|
+
return "optimism";
|
|
171
|
+
return raw;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/use/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-network wallet. Thin facade over per-network {@link Signer}s.
|
|
3
|
+
*
|
|
4
|
+
* The wallet doesn't hold keys — signers do. This module just exposes a
|
|
5
|
+
* unified view (addresses, balances) and lets callers pick which network to
|
|
6
|
+
* use for a given payment.
|
|
7
|
+
*/
|
|
8
|
+
import type { Network, PaymentRequirement, Signer } from "../types.js";
|
|
9
|
+
export interface WalletOptions {
|
|
10
|
+
networks: Network[];
|
|
11
|
+
signers: Partial<Record<Network, Signer>>;
|
|
12
|
+
}
|
|
13
|
+
export interface Wallet {
|
|
14
|
+
/** Networks this wallet is configured for. */
|
|
15
|
+
readonly networks: Network[];
|
|
16
|
+
/** Get the address on a specific network. */
|
|
17
|
+
address(network?: Network): string;
|
|
18
|
+
/** Get the signer for a network, or throw if not configured. */
|
|
19
|
+
signer(network: Network): Signer;
|
|
20
|
+
/** True if a signer is configured for the network. */
|
|
21
|
+
has(network: Network): boolean;
|
|
22
|
+
/** USDC balance on a network in human units (e.g. 4.70). Returns 0 if unsupported. */
|
|
23
|
+
balance(network?: Network): Promise<number>;
|
|
24
|
+
/**
|
|
25
|
+
* Pick the best network to satisfy one of the given payment requirements.
|
|
26
|
+
* Strategy v0: first match where we have a signer + (eventually) enough balance.
|
|
27
|
+
*/
|
|
28
|
+
pickRequirement(reqs: PaymentRequirement[]): PaymentRequirement | undefined;
|
|
29
|
+
}
|
|
30
|
+
export declare function createWallet(opts: WalletOptions): Wallet;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wallet/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,MAAM;IACrB,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC7B,6CAA6C;IAC7C,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACnC,gEAAgE;IAChE,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,sDAAsD;IACtD,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;IAC/B,sFAAsF;IACtF,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,kBAAkB,GAAG,SAAS,CAAC;CAC7E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAwCxD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-network wallet. Thin facade over per-network {@link Signer}s.
|
|
3
|
+
*
|
|
4
|
+
* The wallet doesn't hold keys — signers do. This module just exposes a
|
|
5
|
+
* unified view (addresses, balances) and lets callers pick which network to
|
|
6
|
+
* use for a given payment.
|
|
7
|
+
*/
|
|
8
|
+
export function createWallet(opts) {
|
|
9
|
+
const networks = opts.networks;
|
|
10
|
+
const signers = opts.signers;
|
|
11
|
+
function signer(network) {
|
|
12
|
+
const s = signers[network];
|
|
13
|
+
if (!s)
|
|
14
|
+
throw new Error(`No signer configured for network "${network}"`);
|
|
15
|
+
return s;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
networks,
|
|
19
|
+
address(network = networks[0]) {
|
|
20
|
+
return signer(network).address;
|
|
21
|
+
},
|
|
22
|
+
signer,
|
|
23
|
+
has: (network) => Boolean(signers[network]),
|
|
24
|
+
async balance(network = networks[0]) {
|
|
25
|
+
// v0: signers may expose a `balance()` method; fall back to 0 if not.
|
|
26
|
+
const s = signers[network];
|
|
27
|
+
if (!s)
|
|
28
|
+
return 0;
|
|
29
|
+
if (typeof s.balance === "function")
|
|
30
|
+
return s.balance();
|
|
31
|
+
return 0;
|
|
32
|
+
},
|
|
33
|
+
pickRequirement(reqs) {
|
|
34
|
+
// Normalize EIP-155 strings ("eip155:8453") to our network slugs.
|
|
35
|
+
const matchNetwork = (raw) => {
|
|
36
|
+
if (signers[raw])
|
|
37
|
+
return raw;
|
|
38
|
+
if (raw === "eip155:8453" && signers["base"])
|
|
39
|
+
return "base";
|
|
40
|
+
if (raw === "eip155:1" && signers["ethereum"])
|
|
41
|
+
return "ethereum";
|
|
42
|
+
if (raw === "eip155:42161" && signers["arbitrum"])
|
|
43
|
+
return "arbitrum";
|
|
44
|
+
if (raw === "eip155:10" && signers["optimism"])
|
|
45
|
+
return "optimism";
|
|
46
|
+
return undefined;
|
|
47
|
+
};
|
|
48
|
+
for (const req of reqs) {
|
|
49
|
+
if (matchNetwork(req.network))
|
|
50
|
+
return req;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wallet/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA2BH,MAAM,UAAU,YAAY,CAAC,IAAmB;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAE7B,SAAS,MAAM,CAAC,OAAgB;QAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,OAAO,GAAG,CAAC,CAAC;QACzE,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO;QACL,QAAQ;QACR,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC;YAC3B,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QACjC,CAAC;QACD,MAAM;QACN,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3C,KAAK,CAAC,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC;YACjC,sEAAsE;YACtE,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAA6D,CAAC;YACvF,IAAI,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC;YACjB,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,UAAU;gBAAE,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;YACxD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,eAAe,CAAC,IAAI;YAClB,kEAAkE;YAClE,MAAM,YAAY,GAAG,CAAC,GAAW,EAAuB,EAAE;gBACxD,IAAI,OAAO,CAAC,GAAG,CAAC;oBAAE,OAAO,GAAG,CAAC;gBAC7B,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC;gBAC5D,IAAI,GAAG,KAAK,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;oBAAE,OAAO,UAAU,CAAC;gBACjE,IAAI,GAAG,KAAK,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC;oBAAE,OAAO,UAAU,CAAC;gBACrE,IAAI,GAAG,KAAK,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC;oBAAE,OAAO,UAAU,CAAC;gBAClE,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC;YACF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,OAAO,GAAG,CAAC;YAC5C,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xona-labs/xpay",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Discovery and usage layer for agentic commerce — multi-network wallet, x402 payments, 20k+ services via PayAI and other catalogs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"xpay": "dist/cli/index.js",
|
|
10
|
+
"xpay-mcp": "dist/cli/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"dev": "tsx src/cli/index.ts",
|
|
21
|
+
"demo": "tsx examples/discover-and-pay.ts"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/xona-labs/xpay"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://xpay.xona.xyz",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"x402",
|
|
30
|
+
"agentic-commerce",
|
|
31
|
+
"payai",
|
|
32
|
+
"solana",
|
|
33
|
+
"base",
|
|
34
|
+
"ai-agent",
|
|
35
|
+
"mcp",
|
|
36
|
+
"xona",
|
|
37
|
+
"discovery",
|
|
38
|
+
"wallet",
|
|
39
|
+
"usdc"
|
|
40
|
+
],
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
44
|
+
"@solana/spl-token": "^0.4.14",
|
|
45
|
+
"@solana/web3.js": "^1.95.0",
|
|
46
|
+
"bip39": "^3.1.0",
|
|
47
|
+
"chalk": "^5.4.1",
|
|
48
|
+
"commander": "^13.1.0",
|
|
49
|
+
"dotenv": "^16.4.7",
|
|
50
|
+
"ed25519-hd-key": "^2.0.0",
|
|
51
|
+
"ethers": "^6.16.0",
|
|
52
|
+
"inquirer": "^13.4.3",
|
|
53
|
+
"tweetnacl": "^1.0.3",
|
|
54
|
+
"zod": "^3.23.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@privy-io/react-auth": "^2.0.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"@privy-io/react-auth": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/inquirer": "^9.0.9",
|
|
66
|
+
"@types/node": "^22.15.0",
|
|
67
|
+
"tsx": "^4.19.4",
|
|
68
|
+
"typescript": "^5.8.3"
|
|
69
|
+
}
|
|
70
|
+
}
|