xdcai 0.1.13 → 0.1.14
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 +1 -1
- package/SKILL.md +2 -2
- package/bin/xdcai.js +143 -46
- package/package.json +2 -2
- package/providers.json +4 -4
- package/skill.json +1 -1
package/README.md
CHANGED
|
@@ -10,4 +10,4 @@ npx xdcai marketplace list --search lending,rates # find the most relevant x402
|
|
|
10
10
|
npx xdcai call <x402-url> # auto-pays the 402 and returns the result
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
See https://
|
|
13
|
+
See https://xdcai.tech/integrate. MIT licensed.
|
package/SKILL.md
CHANGED
|
@@ -16,7 +16,7 @@ This skill is a **CLI** - it needs a shell and outbound network. That means:
|
|
|
16
16
|
- ✅ **Claude Code, Cursor, Codex, a terminal** - `npx xdcai ...` works directly.
|
|
17
17
|
- ❌ **claude.ai web** - its sandbox blocks outbound network, so `login` can't reach the
|
|
18
18
|
auth/wallet service. In claude.ai, **add the MCP connector instead**:
|
|
19
|
-
`https://
|
|
19
|
+
`https://api.xdcai.tech/mcp` (Settings → Connectors → Add custom
|
|
20
20
|
connector). It exposes the same flow as tools (`login_start`, `login_verify`,
|
|
21
21
|
`wallet_address`, `wallet_balance`, `marketplace_list`, `call`, `wallet_transfer`) and runs
|
|
22
22
|
the network work server-side.
|
|
@@ -42,7 +42,7 @@ resends with the `X-PAYMENT` header, and returns the result. **You never pay gas
|
|
|
42
42
|
- a relayer settles the signed authorization on-chain.
|
|
43
43
|
|
|
44
44
|
## Commands
|
|
45
|
-
- `login [--email <e>] [--code <c>] [--accept-terms]` - authenticate; creates/loads your XDC wallet. Login requires accepting the Terms & Conditions (https://
|
|
45
|
+
- `login [--email <e>] [--code <c>] [--accept-terms]` - authenticate; creates/loads your XDC wallet. Login requires accepting the Terms & Conditions (https://xdcai.tech/terms): show them to the user and pass `--accept-terms` (non-interactive) only with the user's consent, or answer the interactive prompt.
|
|
46
46
|
- `whoami` / `logout`
|
|
47
47
|
- `wallet address|balance|fund`
|
|
48
48
|
- `marketplace list [--search <a,b,c>] [--capability <c>] [--max-price <usdc>]` - `--search` ranks live services by tags + capability (OR over the terms, best first).
|
package/bin/xdcai.js
CHANGED
|
@@ -5653,15 +5653,15 @@ function wNAF(c, bits) {
|
|
|
5653
5653
|
const { windows, windowSize } = calcWOpts(W, bits);
|
|
5654
5654
|
const points = [];
|
|
5655
5655
|
let p = elm;
|
|
5656
|
-
let
|
|
5656
|
+
let base2 = p;
|
|
5657
5657
|
for (let window = 0; window < windows; window++) {
|
|
5658
|
-
|
|
5659
|
-
points.push(
|
|
5658
|
+
base2 = p;
|
|
5659
|
+
points.push(base2);
|
|
5660
5660
|
for (let i = 1; i < windowSize; i++) {
|
|
5661
|
-
|
|
5662
|
-
points.push(
|
|
5661
|
+
base2 = base2.add(p);
|
|
5662
|
+
points.push(base2);
|
|
5663
5663
|
}
|
|
5664
|
-
p =
|
|
5664
|
+
p = base2.double();
|
|
5665
5665
|
}
|
|
5666
5666
|
return points;
|
|
5667
5667
|
},
|
|
@@ -9538,17 +9538,17 @@ async function call(client, args) {
|
|
|
9538
9538
|
}
|
|
9539
9539
|
}
|
|
9540
9540
|
const params = (() => {
|
|
9541
|
-
const
|
|
9541
|
+
const base2 = [
|
|
9542
9542
|
request2,
|
|
9543
9543
|
block
|
|
9544
9544
|
];
|
|
9545
9545
|
if (rpcStateOverride && rpcBlockOverrides)
|
|
9546
|
-
return [...
|
|
9546
|
+
return [...base2, rpcStateOverride, rpcBlockOverrides];
|
|
9547
9547
|
if (rpcStateOverride)
|
|
9548
|
-
return [...
|
|
9548
|
+
return [...base2, rpcStateOverride];
|
|
9549
9549
|
if (rpcBlockOverrides)
|
|
9550
|
-
return [...
|
|
9551
|
-
return
|
|
9550
|
+
return [...base2, {}, rpcBlockOverrides];
|
|
9551
|
+
return base2;
|
|
9552
9552
|
})();
|
|
9553
9553
|
const response = await client.request({
|
|
9554
9554
|
method: "eth_call",
|
|
@@ -10358,7 +10358,7 @@ async function internal_estimateFeesPerGas(client, args) {
|
|
|
10358
10358
|
throw new BaseFeeScalarError();
|
|
10359
10359
|
const decimals = baseFeeMultiplier.toString().split(".")[1]?.length ?? 0;
|
|
10360
10360
|
const denominator = 10 ** decimals;
|
|
10361
|
-
const multiply = (
|
|
10361
|
+
const multiply = (base2) => base2 * BigInt(Math.ceil(baseFeeMultiplier * denominator)) / BigInt(denominator);
|
|
10362
10362
|
const block = block_ ? block_ : await getAction(client, getBlock, "getBlock")({});
|
|
10363
10363
|
if (typeof chain2?.fees?.estimateFeesPerGas === "function") {
|
|
10364
10364
|
const fees = await chain2.fees.estimateFeesPerGas({
|
|
@@ -10726,7 +10726,7 @@ async function fillTransaction(client, parameters) {
|
|
|
10726
10726
|
throw new BaseFeeScalarError();
|
|
10727
10727
|
const decimals = feeMultiplier.toString().split(".")[1]?.length ?? 0;
|
|
10728
10728
|
const denominator = 10 ** decimals;
|
|
10729
|
-
const multiplyFee = (
|
|
10729
|
+
const multiplyFee = (base2) => base2 * BigInt(Math.ceil(feeMultiplier * denominator)) / BigInt(denominator);
|
|
10730
10730
|
if (!transaction.feePayerSignature) {
|
|
10731
10731
|
if (transaction.maxFeePerGas && !parameters.maxFeePerGas)
|
|
10732
10732
|
transaction.maxFeePerGas = multiplyFee(transaction.maxFeePerGas);
|
|
@@ -12436,12 +12436,12 @@ function createClient(parameters) {
|
|
|
12436
12436
|
uid: uid(),
|
|
12437
12437
|
...experimental_blockTag ? { experimental_blockTag } : {}
|
|
12438
12438
|
};
|
|
12439
|
-
function extend(
|
|
12439
|
+
function extend(base2) {
|
|
12440
12440
|
return (extendFn) => {
|
|
12441
|
-
const extended = extendFn(
|
|
12441
|
+
const extended = extendFn(base2);
|
|
12442
12442
|
for (const key2 in client)
|
|
12443
12443
|
delete extended[key2];
|
|
12444
|
-
const combined = { ...
|
|
12444
|
+
const combined = { ...base2, ...extended };
|
|
12445
12445
|
return Object.assign(combined, { extend: extend(combined) });
|
|
12446
12446
|
};
|
|
12447
12447
|
}
|
|
@@ -13935,10 +13935,10 @@ function defineChain(chain2) {
|
|
|
13935
13935
|
serializers: void 0,
|
|
13936
13936
|
...chain2
|
|
13937
13937
|
};
|
|
13938
|
-
function extend(
|
|
13938
|
+
function extend(base2) {
|
|
13939
13939
|
return (fnOrExtended) => {
|
|
13940
|
-
const properties = typeof fnOrExtended === "function" ? fnOrExtended(
|
|
13941
|
-
const combined = { ...
|
|
13940
|
+
const properties = typeof fnOrExtended === "function" ? fnOrExtended(base2) : fnOrExtended;
|
|
13941
|
+
const combined = { ...base2, ...properties };
|
|
13942
13942
|
return Object.assign(combined, { extend: extend(combined) });
|
|
13943
13943
|
};
|
|
13944
13944
|
}
|
|
@@ -14333,9 +14333,9 @@ function validateTypedData(parameters) {
|
|
|
14333
14333
|
const value = data[name];
|
|
14334
14334
|
const integerMatch = type.match(integerRegex2);
|
|
14335
14335
|
if (integerMatch && (typeof value === "number" || typeof value === "bigint")) {
|
|
14336
|
-
const [_type,
|
|
14336
|
+
const [_type, base2, size_] = integerMatch;
|
|
14337
14337
|
numberToHex(value, {
|
|
14338
|
-
signed:
|
|
14338
|
+
signed: base2 === "int",
|
|
14339
14339
|
size: Number.parseInt(size_, 10) / 8
|
|
14340
14340
|
});
|
|
14341
14341
|
}
|
|
@@ -22499,23 +22499,23 @@ var ZodEffects = class extends ZodType {
|
|
|
22499
22499
|
}
|
|
22500
22500
|
if (effect.type === "transform") {
|
|
22501
22501
|
if (ctx.common.async === false) {
|
|
22502
|
-
const
|
|
22502
|
+
const base2 = this._def.schema._parseSync({
|
|
22503
22503
|
data: ctx.data,
|
|
22504
22504
|
path: ctx.path,
|
|
22505
22505
|
parent: ctx
|
|
22506
22506
|
});
|
|
22507
|
-
if (!isValid(
|
|
22507
|
+
if (!isValid(base2))
|
|
22508
22508
|
return INVALID;
|
|
22509
|
-
const result = effect.transform(
|
|
22509
|
+
const result = effect.transform(base2.value, checkCtx);
|
|
22510
22510
|
if (result instanceof Promise) {
|
|
22511
22511
|
throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
|
|
22512
22512
|
}
|
|
22513
22513
|
return { status: status.value, value: result };
|
|
22514
22514
|
} else {
|
|
22515
|
-
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((
|
|
22516
|
-
if (!isValid(
|
|
22515
|
+
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base2) => {
|
|
22516
|
+
if (!isValid(base2))
|
|
22517
22517
|
return INVALID;
|
|
22518
|
-
return Promise.resolve(effect.transform(
|
|
22518
|
+
return Promise.resolve(effect.transform(base2.value, checkCtx)).then((result) => ({
|
|
22519
22519
|
status: status.value,
|
|
22520
22520
|
value: result
|
|
22521
22521
|
}));
|
|
@@ -23372,9 +23372,9 @@ var SponsoredFacilitator = class {
|
|
|
23372
23372
|
this.#usdc = deps.usdc;
|
|
23373
23373
|
}
|
|
23374
23374
|
async verify(payment, requirements) {
|
|
23375
|
-
const
|
|
23376
|
-
if (!
|
|
23377
|
-
log.warn("verify failed", { reason:
|
|
23375
|
+
const base2 = await verifyPayment(payment, requirements, this.#usdc);
|
|
23376
|
+
if (!base2.valid) {
|
|
23377
|
+
log.warn("verify failed", { reason: base2.reason });
|
|
23378
23378
|
return false;
|
|
23379
23379
|
}
|
|
23380
23380
|
const auth = payment.payload.authorization;
|
|
@@ -45078,7 +45078,7 @@ function loadSdkConfig(env = process.env) {
|
|
|
45078
45078
|
providersFile: env.PROVIDERS_FILE || "./providers.json",
|
|
45079
45079
|
privyAppId,
|
|
45080
45080
|
privyClientId: env.PRIVY_CLIENT_ID || void 0,
|
|
45081
|
-
walletServiceUrl: env.WALLET_SERVICE_URL || "https://
|
|
45081
|
+
walletServiceUrl: env.WALLET_SERVICE_URL || "https://xdcai.tech",
|
|
45082
45082
|
privyOrigin: env.PRIVY_ORIGIN || "https://xdctaskman-web.vercel.app"
|
|
45083
45083
|
};
|
|
45084
45084
|
}
|
|
@@ -45256,8 +45256,8 @@ import { randomBytes as randomBytes4 } from "node:crypto";
|
|
|
45256
45256
|
|
|
45257
45257
|
// src/explorer.ts
|
|
45258
45258
|
function explorerTxUrl(network, hash3) {
|
|
45259
|
-
const
|
|
45260
|
-
return `${
|
|
45259
|
+
const base2 = network === "mainnet" ? "https://xdcscan.com/tx/" : "https://apothem.xdcscan.io/tx/";
|
|
45260
|
+
return `${base2}${hash3}`;
|
|
45261
45261
|
}
|
|
45262
45262
|
function xdcNetworkFromX402(network) {
|
|
45263
45263
|
return network === "xdc-apothem" ? "apothem" : "mainnet";
|
|
@@ -45275,7 +45275,7 @@ function parseSettlementTxHash(headerValue) {
|
|
|
45275
45275
|
var log3 = createLogger("x402");
|
|
45276
45276
|
async function x402Call(opts) {
|
|
45277
45277
|
const doFetch = opts.fetchImpl ?? fetch;
|
|
45278
|
-
const method = opts.method ?? "GET";
|
|
45278
|
+
const method = opts.method ?? (opts.data !== void 0 ? "POST" : "GET");
|
|
45279
45279
|
const first = await request(doFetch, opts.url, method, opts.data);
|
|
45280
45280
|
if (first.status !== 402) {
|
|
45281
45281
|
return { status: first.status, body: first.body, paid: false };
|
|
@@ -45305,7 +45305,7 @@ async function request(doFetch, url, method, data, extraHeaders = {}) {
|
|
|
45305
45305
|
const init = { method, headers };
|
|
45306
45306
|
if (method === "POST" && data !== void 0) {
|
|
45307
45307
|
headers["content-type"] = "application/json";
|
|
45308
|
-
init.body = JSON.stringify(data);
|
|
45308
|
+
init.body = typeof data === "string" ? data : JSON.stringify(data);
|
|
45309
45309
|
}
|
|
45310
45310
|
const res = await doFetch(url, init);
|
|
45311
45311
|
const text = await res.text();
|
|
@@ -45362,7 +45362,7 @@ function resolveToken(token, network) {
|
|
|
45362
45362
|
async function transferToken(opts) {
|
|
45363
45363
|
const asset = resolveToken(opts.token, opts.network);
|
|
45364
45364
|
const value = usdcToBaseUnits(opts.amount).toString();
|
|
45365
|
-
const
|
|
45365
|
+
const base2 = { from: opts.fromAddress, to: getAddress(opts.to), amount: opts.amount, token: "USDC" };
|
|
45366
45366
|
const requirements = {
|
|
45367
45367
|
scheme: "exact",
|
|
45368
45368
|
network: x402NetworkFor(opts.network),
|
|
@@ -45381,15 +45381,73 @@ async function transferToken(opts) {
|
|
|
45381
45381
|
});
|
|
45382
45382
|
try {
|
|
45383
45383
|
if (!await opts.facilitator.verify(payment, requirements)) {
|
|
45384
|
-
return { ...
|
|
45384
|
+
return { ...base2, success: false, error: "Payment not valid (insufficient USDC balance or bad signature)" };
|
|
45385
45385
|
}
|
|
45386
45386
|
const { txHash } = await opts.facilitator.settle(payment);
|
|
45387
|
-
return { ...
|
|
45387
|
+
return { ...base2, success: true, txHash, explorerUrl: explorerTxUrl(opts.network, txHash) };
|
|
45388
45388
|
} catch (err) {
|
|
45389
|
-
return { ...
|
|
45389
|
+
return { ...base2, success: false, error: err instanceof Error ? err.message : "transfer failed" };
|
|
45390
45390
|
}
|
|
45391
45391
|
}
|
|
45392
45392
|
|
|
45393
|
+
// src/history.ts
|
|
45394
|
+
function base(serviceUrl) {
|
|
45395
|
+
return serviceUrl.replace(/\/$/, "");
|
|
45396
|
+
}
|
|
45397
|
+
async function postTransaction(serviceUrl, token, tx) {
|
|
45398
|
+
try {
|
|
45399
|
+
await fetch(`${base(serviceUrl)}/api/transactions`, {
|
|
45400
|
+
method: "POST",
|
|
45401
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
45402
|
+
body: JSON.stringify(tx)
|
|
45403
|
+
});
|
|
45404
|
+
} catch {
|
|
45405
|
+
}
|
|
45406
|
+
}
|
|
45407
|
+
async function getHistory(serviceUrl, token, limit = 20, page = 1) {
|
|
45408
|
+
const res = await fetch(`${base(serviceUrl)}/api/transactions?limit=${limit}&page=${page}`, {
|
|
45409
|
+
headers: { authorization: `Bearer ${token}` }
|
|
45410
|
+
});
|
|
45411
|
+
return res.json();
|
|
45412
|
+
}
|
|
45413
|
+
async function getVerify(serviceUrl, token, txHash) {
|
|
45414
|
+
const res = await fetch(`${base(serviceUrl)}/api/transactions/verify?txHash=${encodeURIComponent(txHash)}`, {
|
|
45415
|
+
headers: { authorization: `Bearer ${token}` }
|
|
45416
|
+
});
|
|
45417
|
+
return res.json();
|
|
45418
|
+
}
|
|
45419
|
+
function callToTx(opts) {
|
|
45420
|
+
const req = opts.result.requirements;
|
|
45421
|
+
const amount = req ? formatUnits(BigInt(req.maxAmountRequired), 6) : "0";
|
|
45422
|
+
return {
|
|
45423
|
+
kind: "call",
|
|
45424
|
+
status: opts.result.status < 400 ? "success" : "failed",
|
|
45425
|
+
...opts.result.txHash ? { txHash: opts.result.txHash } : {},
|
|
45426
|
+
amountUSDC: req ? amount : "0",
|
|
45427
|
+
network: opts.network,
|
|
45428
|
+
fromAddress: opts.fromAddress,
|
|
45429
|
+
...req?.payTo ? { toAddress: req.payTo } : {},
|
|
45430
|
+
resourceUrl: opts.url,
|
|
45431
|
+
method: opts.method,
|
|
45432
|
+
httpStatus: opts.result.status,
|
|
45433
|
+
...opts.result.explorerUrl ? { explorerUrl: opts.result.explorerUrl } : {}
|
|
45434
|
+
};
|
|
45435
|
+
}
|
|
45436
|
+
function transferToTx(opts) {
|
|
45437
|
+
return {
|
|
45438
|
+
kind: "transfer",
|
|
45439
|
+
status: opts.result.success ? "success" : "failed",
|
|
45440
|
+
...opts.result.txHash ? { txHash: opts.result.txHash } : {},
|
|
45441
|
+
amountUSDC: opts.amount,
|
|
45442
|
+
token: opts.token,
|
|
45443
|
+
network: opts.network,
|
|
45444
|
+
fromAddress: opts.fromAddress,
|
|
45445
|
+
toAddress: opts.to,
|
|
45446
|
+
...opts.result.explorerUrl ? { explorerUrl: opts.result.explorerUrl } : {},
|
|
45447
|
+
...opts.result.error ? { error: opts.result.error } : {}
|
|
45448
|
+
};
|
|
45449
|
+
}
|
|
45450
|
+
|
|
45393
45451
|
// src/remote-wallet.ts
|
|
45394
45452
|
var RemoteWalletProvider = class {
|
|
45395
45453
|
#baseUrl;
|
|
@@ -45603,6 +45661,13 @@ async function cmdTransfer(sdk, args, session) {
|
|
|
45603
45661
|
facilitator,
|
|
45604
45662
|
network: sdk.config.network
|
|
45605
45663
|
});
|
|
45664
|
+
if (sdk.config.authProvider === "privy") {
|
|
45665
|
+
await postTransaction(
|
|
45666
|
+
sdk.config.walletServiceUrl,
|
|
45667
|
+
session.token,
|
|
45668
|
+
transferToTx({ network: sdk.config.network, fromAddress: session.address, to, amount, token: result.token, result })
|
|
45669
|
+
);
|
|
45670
|
+
}
|
|
45606
45671
|
out({
|
|
45607
45672
|
success: result.success,
|
|
45608
45673
|
amount,
|
|
@@ -45616,11 +45681,11 @@ async function cmdTransfer(sdk, args, session) {
|
|
|
45616
45681
|
}
|
|
45617
45682
|
async function cmdMarketplace(sdk, args) {
|
|
45618
45683
|
if (args._[1] !== "list") {
|
|
45619
|
-
out("Usage: xdcai marketplace list [--search <a,b,c>] [--capability <c>] [--max-price <usdc>]");
|
|
45684
|
+
out("Usage: xdcai marketplace list [--search <a,b,c>] [--capability <c>] [--max-price <usdc>] [--sort most-used] [--min-calls <n>]");
|
|
45620
45685
|
return;
|
|
45621
45686
|
}
|
|
45622
|
-
const
|
|
45623
|
-
const res = await fetch(`${
|
|
45687
|
+
const base2 = sdk.config.walletServiceUrl.replace(/\/$/, "");
|
|
45688
|
+
const res = await fetch(`${base2}/api/catalog`);
|
|
45624
45689
|
if (!res.ok) throw new Error(`Failed to fetch the marketplace catalog (${res.status})`);
|
|
45625
45690
|
const body = await res.json();
|
|
45626
45691
|
let list = (body.services ?? []).map((s) => ({ ...s, tags: Array.isArray(s.tags) ? s.tags : [] }));
|
|
@@ -45632,9 +45697,16 @@ async function cmdMarketplace(sdk, args) {
|
|
|
45632
45697
|
const max = Number(args.flags["max-price"]);
|
|
45633
45698
|
if (Number.isFinite(max)) list = list.filter((s) => Number(s.priceUSDC) <= max);
|
|
45634
45699
|
}
|
|
45700
|
+
if (typeof args.flags["min-calls"] === "string") {
|
|
45701
|
+
const min = Number(args.flags["min-calls"]);
|
|
45702
|
+
if (Number.isFinite(min)) list = list.filter((s) => (s.calls ?? 0) >= min);
|
|
45703
|
+
}
|
|
45635
45704
|
if (typeof args.flags.search === "string") {
|
|
45636
45705
|
list = searchServices(list, parseSearchTerms(args.flags.search));
|
|
45637
45706
|
}
|
|
45707
|
+
if (args.flags.sort === "most-used" || args.flags.sort === "usage") {
|
|
45708
|
+
list = [...list].sort((a, b) => (b.calls ?? 0) - (a.calls ?? 0) || (b.volumeUSDC ?? 0) - (a.volumeUSDC ?? 0));
|
|
45709
|
+
}
|
|
45638
45710
|
out(
|
|
45639
45711
|
list.map((s) => ({
|
|
45640
45712
|
id: s.id,
|
|
@@ -45643,7 +45715,9 @@ async function cmdMarketplace(sdk, args) {
|
|
|
45643
45715
|
method: s.method,
|
|
45644
45716
|
url: s.url,
|
|
45645
45717
|
payTo: s.payTo,
|
|
45646
|
-
tags: s.tags
|
|
45718
|
+
tags: s.tags,
|
|
45719
|
+
calls: s.calls ?? 0,
|
|
45720
|
+
volumeUSDC: s.volumeUSDC ?? 0
|
|
45647
45721
|
}))
|
|
45648
45722
|
);
|
|
45649
45723
|
}
|
|
@@ -45651,16 +45725,23 @@ async function cmdCall(sdk, args) {
|
|
|
45651
45725
|
const url = args._[1];
|
|
45652
45726
|
if (!url) throw new Error("Usage: xdcai call <serviceUrl> [--method GET|POST] [--data <json>]");
|
|
45653
45727
|
const session = await freshSession(sdk, await requireSession(sdk));
|
|
45654
|
-
const method = args.flags.method === "POST" ? "POST" : "GET";
|
|
45728
|
+
const method = args.flags.method === "POST" ? "POST" : args.flags.method === "GET" ? "GET" : void 0;
|
|
45655
45729
|
const data = typeof args.flags.data === "string" ? JSON.parse(args.flags.data) : void 0;
|
|
45656
45730
|
const result = await x402Call({
|
|
45657
45731
|
url,
|
|
45658
|
-
method,
|
|
45732
|
+
...method ? { method } : {},
|
|
45659
45733
|
data,
|
|
45660
45734
|
ownerId: session.ownerId,
|
|
45661
45735
|
fromAddress: session.address,
|
|
45662
45736
|
wallet: signingWallet(sdk, session)
|
|
45663
45737
|
});
|
|
45738
|
+
if (sdk.config.authProvider === "privy") {
|
|
45739
|
+
await postTransaction(
|
|
45740
|
+
sdk.config.walletServiceUrl,
|
|
45741
|
+
session.token,
|
|
45742
|
+
callToTx({ url, method: method ?? (data !== void 0 ? "POST" : "GET"), network: sdk.config.network, fromAddress: session.address, result })
|
|
45743
|
+
);
|
|
45744
|
+
}
|
|
45664
45745
|
if (result.status >= 400) {
|
|
45665
45746
|
throw new Error(`Request failed (${result.status}): ${JSON.stringify(result.body)}`);
|
|
45666
45747
|
}
|
|
@@ -45673,6 +45754,18 @@ async function cmdCall(sdk, args) {
|
|
|
45673
45754
|
result: result.body
|
|
45674
45755
|
});
|
|
45675
45756
|
}
|
|
45757
|
+
async function cmdHistory(sdk, args) {
|
|
45758
|
+
const session = await freshSession(sdk, await requireSession(sdk));
|
|
45759
|
+
if (args._[1] === "verify") {
|
|
45760
|
+
const hash3 = args._[2];
|
|
45761
|
+
if (!hash3) throw new Error("Usage: xdcai history verify <txHash>");
|
|
45762
|
+
out(await getVerify(sdk.config.walletServiceUrl, session.token, hash3));
|
|
45763
|
+
return;
|
|
45764
|
+
}
|
|
45765
|
+
const limit = typeof args.flags.limit === "string" ? Math.max(1, Math.min(100, Number(args.flags.limit) || 20)) : 20;
|
|
45766
|
+
const page = typeof args.flags.page === "string" ? Number(args.flags.page) || 1 : 1;
|
|
45767
|
+
out(await getHistory(sdk.config.walletServiceUrl, session.token, limit, page));
|
|
45768
|
+
}
|
|
45676
45769
|
async function cmdWhoami(sdk) {
|
|
45677
45770
|
const session = await sdk.sessions.load();
|
|
45678
45771
|
out(
|
|
@@ -45687,8 +45780,10 @@ Usage:
|
|
|
45687
45780
|
xdcai logout
|
|
45688
45781
|
xdcai wallet <address|balance|fund>
|
|
45689
45782
|
xdcai wallet transfer <amount> <token> <to-address> # gasless USDC transfer
|
|
45690
|
-
xdcai marketplace list [--search <a,b,c>] [--capability <c>] [--max-price <usdc>]
|
|
45783
|
+
xdcai marketplace list [--search <a,b,c>] [--capability <c>] [--max-price <usdc>] [--sort most-used] [--min-calls <n>]
|
|
45691
45784
|
xdcai call <serviceUrl> [--method GET|POST] [--data <json>]
|
|
45785
|
+
xdcai history [--limit <n>] [--page <n>] # your transaction history
|
|
45786
|
+
xdcai history verify <txHash> # did a tx go through?
|
|
45692
45787
|
|
|
45693
45788
|
--search ranks live services by tags + capability (comma-separated terms,
|
|
45694
45789
|
best match first) so an agent can find the most relevant API for a prompt.
|
|
@@ -45715,6 +45810,8 @@ async function main() {
|
|
|
45715
45810
|
return cmdMarketplace(sdk, args);
|
|
45716
45811
|
case "call":
|
|
45717
45812
|
return cmdCall(sdk, args);
|
|
45813
|
+
case "history":
|
|
45814
|
+
return cmdHistory(sdk, args);
|
|
45718
45815
|
default:
|
|
45719
45816
|
info(HELP);
|
|
45720
45817
|
out({ error: `Unknown command: ${command}` });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xdcai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Pay for x402 services on XDC with USDC via a custodial wallet. The agent never pays gas (EIP-3009).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"type": "git",
|
|
30
30
|
"url": "git+https://github.com/0xbeny/xdctaskman.git"
|
|
31
31
|
},
|
|
32
|
-
"homepage": "https://
|
|
32
|
+
"homepage": "https://xdcai.tech",
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|
|
35
35
|
}
|
package/providers.json
CHANGED
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
"id": "x402-server",
|
|
4
4
|
"name": "XDC AI x402 Server",
|
|
5
5
|
"description": "First-party pay-per-call resources on XDC via x402. Gasless (EIP-3009) - agents pay only USDC, gas is sponsored. Discovery over MCP at /mcp.",
|
|
6
|
-
"mcpUrl": "https://
|
|
6
|
+
"mcpUrl": "https://api.xdcai.tech/mcp",
|
|
7
7
|
"services": [
|
|
8
8
|
{
|
|
9
|
-
"url": "https://
|
|
9
|
+
"url": "https://api.xdcai.tech/x402/echo",
|
|
10
10
|
"method": "GET",
|
|
11
11
|
"priceUSDC": "0.0001",
|
|
12
12
|
"capability": "demo.echo"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"url": "https://
|
|
15
|
+
"url": "https://api.xdcai.tech/x402/time",
|
|
16
16
|
"method": "GET",
|
|
17
17
|
"priceUSDC": "0.0003",
|
|
18
18
|
"capability": "demo.time"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
|
-
"url": "https://
|
|
21
|
+
"url": "https://api.xdcai.tech/x402/xdc-gas",
|
|
22
22
|
"method": "GET",
|
|
23
23
|
"priceUSDC": "0.0002",
|
|
24
24
|
"capability": "xdc.gas-price"
|
package/skill.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"tools": [
|
|
7
7
|
{
|
|
8
8
|
"name": "login",
|
|
9
|
-
"description": "Authenticate with email + OTP; creates or loads the user's XDC wallet. Login requires Terms & Conditions acceptance: before running, show the user https://
|
|
9
|
+
"description": "Authenticate with email + OTP; creates or loads the user's XDC wallet. Login requires Terms & Conditions acceptance: before running, show the user https://xdcai.tech/terms and only pass --accept-terms with their consent.",
|
|
10
10
|
"command": "xdcai login --email {email} --code {code} --accept-terms",
|
|
11
11
|
"parameters": {
|
|
12
12
|
"type": "object",
|