@zeroxyz/cli 0.0.9 → 0.0.11
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/index.js +73 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command as Command8 } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@zeroxyz/cli",
|
|
9
|
-
version: "0.0.
|
|
9
|
+
version: "0.0.11",
|
|
10
10
|
type: "module",
|
|
11
11
|
bin: {
|
|
12
12
|
zero: "dist/index.js",
|
|
@@ -151,11 +151,13 @@ var fetchCommand = (appContext2) => new Command2("fetch").description("Fetch a c
|
|
|
151
151
|
if (options.data && !headers["content-type"]) {
|
|
152
152
|
headers["content-type"] = "application/json";
|
|
153
153
|
}
|
|
154
|
+
const log = (msg) => console.error(` ${msg}`);
|
|
154
155
|
const requestInit = {
|
|
155
156
|
method: options.data ? "POST" : "GET",
|
|
156
157
|
headers,
|
|
157
158
|
body: options.data
|
|
158
159
|
};
|
|
160
|
+
log(`Calling ${url}...`);
|
|
159
161
|
const response = await fetch(url, requestInit);
|
|
160
162
|
const paymentReq = detectPaymentRequirement(
|
|
161
163
|
response.headers,
|
|
@@ -164,11 +166,15 @@ var fetchCommand = (appContext2) => new Command2("fetch").description("Fetch a c
|
|
|
164
166
|
let finalResponse;
|
|
165
167
|
let paymentMeta;
|
|
166
168
|
if (paymentReq) {
|
|
169
|
+
log(
|
|
170
|
+
`Payment required (${paymentReq.protocol}) \u2014 preparing payment...`
|
|
171
|
+
);
|
|
167
172
|
const result = await paymentService.handlePayment(
|
|
168
173
|
url,
|
|
169
174
|
requestInit,
|
|
170
175
|
paymentReq,
|
|
171
|
-
options.maxPay
|
|
176
|
+
options.maxPay,
|
|
177
|
+
log
|
|
172
178
|
);
|
|
173
179
|
finalResponse = result.response;
|
|
174
180
|
paymentMeta = {
|
|
@@ -178,6 +184,9 @@ var fetchCommand = (appContext2) => new Command2("fetch").description("Fetch a c
|
|
|
178
184
|
amount: result.amount,
|
|
179
185
|
asset: result.asset
|
|
180
186
|
};
|
|
187
|
+
log(
|
|
188
|
+
`Paid ${result.amount} ${result.asset} via ${result.protocol} on ${result.chain}`
|
|
189
|
+
);
|
|
181
190
|
} else {
|
|
182
191
|
finalResponse = response;
|
|
183
192
|
}
|
|
@@ -207,11 +216,13 @@ var fetchCommand = (appContext2) => new Command2("fetch").description("Fetch a c
|
|
|
207
216
|
} catch {
|
|
208
217
|
}
|
|
209
218
|
const lastSearch = stateService.loadLastSearch();
|
|
210
|
-
|
|
219
|
+
const matchedCapability = lastSearch?.capabilities.find(
|
|
220
|
+
(c) => url.startsWith(c.url)
|
|
221
|
+
);
|
|
222
|
+
if (matchedCapability && lastSearch && apiService.walletAddress) {
|
|
211
223
|
try {
|
|
212
224
|
const runResult = await apiService.createRun({
|
|
213
|
-
capabilityId:
|
|
214
|
-
paymentMethodId: "",
|
|
225
|
+
capabilityId: matchedCapability.id,
|
|
215
226
|
searchId: lastSearch.searchId,
|
|
216
227
|
status: finalResponse.status,
|
|
217
228
|
latencyMs,
|
|
@@ -581,7 +592,8 @@ var formatSearchResults = (results) => {
|
|
|
581
592
|
return results.map((r) => {
|
|
582
593
|
const successPct = `${Math.round(Number.parseFloat(r.rating.successRate) * 100)}%`;
|
|
583
594
|
const reviews = formatReviewCount(r.rating.reviews);
|
|
584
|
-
|
|
595
|
+
const displayName = r.canonicalName ?? r.name;
|
|
596
|
+
return ` ${r.position}. ${displayName} \u2014 $${r.cost.amount}/call \u2014 \u2605 ${Number.parseFloat(r.rating.score).toFixed(1)} (${successPct} success, ${reviews} reviews)
|
|
585
597
|
"${r.description}"`;
|
|
586
598
|
}).join("\n");
|
|
587
599
|
};
|
|
@@ -593,7 +605,8 @@ var searchCommand = (appContext2) => new Command6("search").description("Search
|
|
|
593
605
|
searchId: result.searchId,
|
|
594
606
|
capabilities: result.capabilities.map((c) => ({
|
|
595
607
|
position: c.position,
|
|
596
|
-
id: c.id
|
|
608
|
+
id: c.id,
|
|
609
|
+
url: c.url
|
|
597
610
|
}))
|
|
598
611
|
});
|
|
599
612
|
analyticsService.capture("search_executed", {
|
|
@@ -820,6 +833,7 @@ var searchResultSchema = z2.object({
|
|
|
820
833
|
slug: z2.string(),
|
|
821
834
|
name: z2.string(),
|
|
822
835
|
description: z2.string(),
|
|
836
|
+
url: z2.string(),
|
|
823
837
|
cost: z2.object({ amount: z2.string(), asset: z2.string() }),
|
|
824
838
|
rating: z2.object({
|
|
825
839
|
score: z2.string(),
|
|
@@ -953,6 +967,7 @@ var ApiService = class {
|
|
|
953
967
|
// src/services/payment-service.ts
|
|
954
968
|
import {
|
|
955
969
|
adaptViemWallet,
|
|
970
|
+
convertViemChainToRelayChain,
|
|
956
971
|
createClient as createRelayClient,
|
|
957
972
|
getClient as getRelayClient,
|
|
958
973
|
MAINNET_RELAY_API
|
|
@@ -978,6 +993,12 @@ var PATHUSD_TEMPO = "0x20c0000000000000000000000000000000000000";
|
|
|
978
993
|
var BASE_CHAIN_ID = 8453;
|
|
979
994
|
var TEMPO_CHAIN_ID = 4217;
|
|
980
995
|
var TEMPO_TESTNET_CHAIN_ID = 42431;
|
|
996
|
+
var DEFAULT_MAX_DEPOSIT = "100";
|
|
997
|
+
var buildRelayClientOptions = () => ({
|
|
998
|
+
baseApiUrl: MAINNET_RELAY_API,
|
|
999
|
+
source: "zero-cli",
|
|
1000
|
+
chains: [convertViemChainToRelayChain(base)]
|
|
1001
|
+
});
|
|
981
1002
|
var calculateBuffer = (baseBalance) => {
|
|
982
1003
|
const twentyFivePercent = baseBalance / 4n;
|
|
983
1004
|
const twoDollars = 2000000n;
|
|
@@ -1016,14 +1037,11 @@ var PaymentService = class {
|
|
|
1016
1037
|
relayInitialized = false;
|
|
1017
1038
|
ensureRelayClient = () => {
|
|
1018
1039
|
if (!this.relayInitialized) {
|
|
1019
|
-
createRelayClient(
|
|
1020
|
-
baseApiUrl: MAINNET_RELAY_API,
|
|
1021
|
-
source: "zero-cli"
|
|
1022
|
-
});
|
|
1040
|
+
createRelayClient(buildRelayClientOptions());
|
|
1023
1041
|
this.relayInitialized = true;
|
|
1024
1042
|
}
|
|
1025
1043
|
};
|
|
1026
|
-
bridgeToTempo = async (requiredAmount) => {
|
|
1044
|
+
bridgeToTempo = async (requiredAmount, onProgress) => {
|
|
1027
1045
|
if (!this.account) throw new Error("No wallet configured");
|
|
1028
1046
|
this.ensureRelayClient();
|
|
1029
1047
|
const baseBalance = await this.getBalanceRaw("base");
|
|
@@ -1034,6 +1052,9 @@ var PaymentService = class {
|
|
|
1034
1052
|
`Insufficient Base USDC to bridge: have ${formatUnits(baseBalance, 6)}, need ${formatUnits(bridgeAmount, 6)} (${formatUnits(requiredAmount, 6)} + ${formatUnits(buffer, 6)} buffer)`
|
|
1035
1053
|
);
|
|
1036
1054
|
}
|
|
1055
|
+
onProgress?.(
|
|
1056
|
+
`Bridging ${formatUnits(bridgeAmount, 6)} USDC from Base to Tempo...`
|
|
1057
|
+
);
|
|
1037
1058
|
const walletClient = createWalletClient({
|
|
1038
1059
|
account: this.account,
|
|
1039
1060
|
chain: base,
|
|
@@ -1047,7 +1068,10 @@ var PaymentService = class {
|
|
|
1047
1068
|
amount: bridgeAmount.toString(),
|
|
1048
1069
|
tradeType: "EXACT_INPUT",
|
|
1049
1070
|
user: this.account.address,
|
|
1050
|
-
recipient: this.account.address
|
|
1071
|
+
recipient: this.account.address,
|
|
1072
|
+
options: {
|
|
1073
|
+
usePermit: true
|
|
1074
|
+
}
|
|
1051
1075
|
});
|
|
1052
1076
|
let bridgeTxHash = null;
|
|
1053
1077
|
await getRelayClient().actions.execute({
|
|
@@ -1061,17 +1085,25 @@ var PaymentService = class {
|
|
|
1061
1085
|
});
|
|
1062
1086
|
return bridgeTxHash;
|
|
1063
1087
|
};
|
|
1064
|
-
handlePayment = async (url, request, paymentRequirement, maxPay) => {
|
|
1088
|
+
handlePayment = async (url, request, paymentRequirement, maxPay, onProgress) => {
|
|
1065
1089
|
if (!this.account) {
|
|
1066
1090
|
throw new Error(
|
|
1067
1091
|
"No wallet configured \u2014 run `zero init` or set ZERO_PRIVATE_KEY"
|
|
1068
1092
|
);
|
|
1069
1093
|
}
|
|
1070
1094
|
if (paymentRequirement.protocol === "x402") {
|
|
1095
|
+
onProgress?.("Paying via x402 on Base...");
|
|
1071
1096
|
return this.payX402(url, request, paymentRequirement.raw, maxPay);
|
|
1072
1097
|
}
|
|
1073
1098
|
if (paymentRequirement.protocol === "mpp") {
|
|
1074
|
-
|
|
1099
|
+
onProgress?.("Paying via MPP on Tempo...");
|
|
1100
|
+
return this.payMpp(
|
|
1101
|
+
url,
|
|
1102
|
+
request,
|
|
1103
|
+
paymentRequirement.raw,
|
|
1104
|
+
maxPay,
|
|
1105
|
+
onProgress
|
|
1106
|
+
);
|
|
1075
1107
|
}
|
|
1076
1108
|
throw new Error("Unrecognized 402 payment protocol");
|
|
1077
1109
|
};
|
|
@@ -1120,16 +1152,35 @@ var PaymentService = class {
|
|
|
1120
1152
|
asset: "USDC"
|
|
1121
1153
|
};
|
|
1122
1154
|
};
|
|
1123
|
-
payMpp = async (url, request, _raw, maxPay) => {
|
|
1155
|
+
payMpp = async (url, request, _raw, maxPay, onProgress) => {
|
|
1124
1156
|
if (!this.account) throw new Error("No wallet configured");
|
|
1125
1157
|
let capturedAmount = "0";
|
|
1126
1158
|
const mppx = Mppx.create({
|
|
1127
1159
|
polyfill: false,
|
|
1128
|
-
methods: [
|
|
1160
|
+
methods: [
|
|
1161
|
+
tempo({
|
|
1162
|
+
account: this.account,
|
|
1163
|
+
maxDeposit: maxPay ?? DEFAULT_MAX_DEPOSIT
|
|
1164
|
+
})
|
|
1165
|
+
],
|
|
1129
1166
|
onChallenge: async (challenge) => {
|
|
1130
1167
|
const challengeRequest = challenge.request;
|
|
1131
|
-
const
|
|
1132
|
-
|
|
1168
|
+
const intent = challenge.intent;
|
|
1169
|
+
let requiredRaw;
|
|
1170
|
+
if (intent === "session") {
|
|
1171
|
+
const suggestedDeposit = challengeRequest.suggestedDeposit;
|
|
1172
|
+
if (suggestedDeposit) {
|
|
1173
|
+
requiredRaw = BigInt(suggestedDeposit);
|
|
1174
|
+
} else {
|
|
1175
|
+
const depositStr = maxPay ?? DEFAULT_MAX_DEPOSIT;
|
|
1176
|
+
requiredRaw = BigInt(
|
|
1177
|
+
Math.floor(Number.parseFloat(depositStr) * 1e6)
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
} else {
|
|
1181
|
+
requiredRaw = BigInt(challengeRequest.amount);
|
|
1182
|
+
}
|
|
1183
|
+
capturedAmount = formatUnits(requiredRaw, 6);
|
|
1133
1184
|
if (maxPay && Number.parseFloat(capturedAmount) > Number.parseFloat(maxPay)) {
|
|
1134
1185
|
throw new Error(
|
|
1135
1186
|
`Payment of ${capturedAmount} USDC exceeds --max-pay ${maxPay}`
|
|
@@ -1139,14 +1190,15 @@ var PaymentService = class {
|
|
|
1139
1190
|
const challengeChainId = challengeRequest.chainId ?? methodDetails?.chainId;
|
|
1140
1191
|
const isTestnet = challengeChainId === TEMPO_TESTNET_CHAIN_ID;
|
|
1141
1192
|
const balanceChain = isTestnet ? "tempo-testnet" : "tempo";
|
|
1193
|
+
onProgress?.(`Checking Tempo balance...`);
|
|
1142
1194
|
const tempoBalance = await this.getBalanceRaw(balanceChain);
|
|
1143
|
-
if (tempoBalance <
|
|
1195
|
+
if (tempoBalance < requiredRaw) {
|
|
1144
1196
|
if (isTestnet) {
|
|
1145
1197
|
throw new Error(
|
|
1146
1198
|
`Insufficient pathUSD on Tempo testnet: have ${formatUnits(tempoBalance, 6)}, need ${capturedAmount}. Fund your wallet with the Tempo testnet faucet: https://docs.tempo.xyz/quickstart/faucet`
|
|
1147
1199
|
);
|
|
1148
1200
|
}
|
|
1149
|
-
await this.bridgeToTempo(
|
|
1201
|
+
await this.bridgeToTempo(requiredRaw, onProgress);
|
|
1150
1202
|
}
|
|
1151
1203
|
return void 0;
|
|
1152
1204
|
}
|