@keeperhub/wallet 0.1.1 → 0.1.3
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 +3 -1
- package/dist/cli.cjs +48 -141
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +48 -141
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +128 -141
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -52
- package/dist/index.d.ts +45 -52
- package/dist/index.js +128 -141
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/keeperhub-wallet.skill.md +23 -6
package/dist/index.cjs
CHANGED
|
@@ -127,124 +127,6 @@ var tempo = (0, import_viem.defineChain)({
|
|
|
127
127
|
var BASE_USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
128
128
|
var TEMPO_USDC_E = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
129
129
|
|
|
130
|
-
// src/hmac.ts
|
|
131
|
-
var import_node_crypto = require("crypto");
|
|
132
|
-
function computeSignature(secret, method, path, subOrgId, body, timestamp) {
|
|
133
|
-
const bodyDigest = (0, import_node_crypto.createHash)("sha256").update(body).digest("hex");
|
|
134
|
-
const signingString = `${method}
|
|
135
|
-
${path}
|
|
136
|
-
${subOrgId}
|
|
137
|
-
${bodyDigest}
|
|
138
|
-
${timestamp}`;
|
|
139
|
-
return (0, import_node_crypto.createHmac)("sha256", secret).update(signingString).digest("hex");
|
|
140
|
-
}
|
|
141
|
-
function buildHmacHeaders(secret, method, path, subOrgId, body) {
|
|
142
|
-
const timestamp = String(Math.floor(Date.now() / 1e3));
|
|
143
|
-
const signature = computeSignature(
|
|
144
|
-
secret,
|
|
145
|
-
method,
|
|
146
|
-
path,
|
|
147
|
-
subOrgId,
|
|
148
|
-
body,
|
|
149
|
-
timestamp
|
|
150
|
-
);
|
|
151
|
-
return {
|
|
152
|
-
"X-KH-Sub-Org": subOrgId,
|
|
153
|
-
"X-KH-Timestamp": timestamp,
|
|
154
|
-
"X-KH-Signature": signature
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// src/types.ts
|
|
159
|
-
var KeeperHubError = class extends Error {
|
|
160
|
-
code;
|
|
161
|
-
constructor(code, message) {
|
|
162
|
-
super(message);
|
|
163
|
-
this.name = "KeeperHubError";
|
|
164
|
-
this.code = code;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
var WalletConfigMissingError = class extends Error {
|
|
168
|
-
constructor() {
|
|
169
|
-
super(
|
|
170
|
-
"Wallet config not found at ~/.keeperhub/wallet.json. Run `npx @keeperhub/wallet add` to provision."
|
|
171
|
-
);
|
|
172
|
-
this.name = "WalletConfigMissingError";
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
// src/client.ts
|
|
177
|
-
var TRAILING_SLASH = /\/$/;
|
|
178
|
-
function defaultCodeForStatus(status) {
|
|
179
|
-
if (status === 401) {
|
|
180
|
-
return "HMAC_INVALID";
|
|
181
|
-
}
|
|
182
|
-
if (status === 403) {
|
|
183
|
-
return "POLICY_BLOCKED";
|
|
184
|
-
}
|
|
185
|
-
if (status === 404) {
|
|
186
|
-
return "NOT_FOUND";
|
|
187
|
-
}
|
|
188
|
-
if (status === 502) {
|
|
189
|
-
return "TURNKEY_UPSTREAM";
|
|
190
|
-
}
|
|
191
|
-
return `HTTP_${status}`;
|
|
192
|
-
}
|
|
193
|
-
var KeeperHubClient = class {
|
|
194
|
-
baseUrl;
|
|
195
|
-
fetchImpl;
|
|
196
|
-
wallet;
|
|
197
|
-
constructor(wallet, opts = {}) {
|
|
198
|
-
this.wallet = wallet;
|
|
199
|
-
const envBase = process.env.KEEPERHUB_API_URL;
|
|
200
|
-
this.baseUrl = (opts.baseUrl ?? envBase ?? "https://app.keeperhub.com").replace(TRAILING_SLASH, "");
|
|
201
|
-
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* HMAC-signed POST/GET to any /api/agentic-wallet/* route except
|
|
205
|
-
* /provision. Path MUST start with a leading slash. Body is
|
|
206
|
-
* JSON.stringify'd (or the empty string for GET).
|
|
207
|
-
*
|
|
208
|
-
* Error mapping: non-2xx/non-202 surface as `KeeperHubError(code,
|
|
209
|
-
* message)` where `code` is the server-supplied field or the default
|
|
210
|
-
* taxonomy (`HMAC_INVALID`, `POLICY_BLOCKED`, `NOT_FOUND`,
|
|
211
|
-
* `TURNKEY_UPSTREAM`, `HTTP_<status>`). 202 ask-tier surfaces as an
|
|
212
|
-
* AskTierResponse envelope.
|
|
213
|
-
*/
|
|
214
|
-
async request(method, path, body) {
|
|
215
|
-
const bodyStr = body === void 0 ? "" : JSON.stringify(body);
|
|
216
|
-
const hmacHeaders = buildHmacHeaders(
|
|
217
|
-
this.wallet.hmacSecret,
|
|
218
|
-
method,
|
|
219
|
-
path,
|
|
220
|
-
this.wallet.subOrgId,
|
|
221
|
-
bodyStr
|
|
222
|
-
);
|
|
223
|
-
const headers = method === "POST" ? { ...hmacHeaders, "content-type": "application/json" } : { ...hmacHeaders };
|
|
224
|
-
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
225
|
-
method,
|
|
226
|
-
headers,
|
|
227
|
-
body: method === "POST" ? bodyStr : void 0
|
|
228
|
-
});
|
|
229
|
-
if (response.status === 202) {
|
|
230
|
-
const data = await response.json();
|
|
231
|
-
return { _status: 202, approvalRequestId: data.approvalRequestId };
|
|
232
|
-
}
|
|
233
|
-
if (!response.ok) {
|
|
234
|
-
let code = "UNKNOWN";
|
|
235
|
-
let message = `HTTP ${response.status}`;
|
|
236
|
-
try {
|
|
237
|
-
const data = await response.json();
|
|
238
|
-
code = data.code ?? defaultCodeForStatus(response.status);
|
|
239
|
-
message = data.error ?? message;
|
|
240
|
-
} catch {
|
|
241
|
-
}
|
|
242
|
-
throw new KeeperHubError(code, message);
|
|
243
|
-
}
|
|
244
|
-
return await response.json();
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
|
|
248
130
|
// src/balance.ts
|
|
249
131
|
var USDC_DECIMALS = 6;
|
|
250
132
|
async function checkBalance(wallet, opts = {}) {
|
|
@@ -256,8 +138,7 @@ async function checkBalance(wallet, opts = {}) {
|
|
|
256
138
|
chain: tempo,
|
|
257
139
|
transport: (0, import_viem2.http)()
|
|
258
140
|
});
|
|
259
|
-
const
|
|
260
|
-
const [baseRaw, tempoRaw, credit] = await Promise.all([
|
|
141
|
+
const [baseRaw, tempoRaw] = await Promise.all([
|
|
261
142
|
baseClient.readContract({
|
|
262
143
|
address: BASE_USDC,
|
|
263
144
|
abi: import_viem2.erc20Abi,
|
|
@@ -269,12 +150,8 @@ async function checkBalance(wallet, opts = {}) {
|
|
|
269
150
|
abi: import_viem2.erc20Abi,
|
|
270
151
|
functionName: "balanceOf",
|
|
271
152
|
args: [wallet.walletAddress]
|
|
272
|
-
})
|
|
273
|
-
khClient.request("GET", "/api/agentic-wallet/credit")
|
|
153
|
+
})
|
|
274
154
|
]);
|
|
275
|
-
if ("_status" in credit) {
|
|
276
|
-
throw new Error("Unexpected 202 response from /api/agentic-wallet/credit");
|
|
277
|
-
}
|
|
278
155
|
return {
|
|
279
156
|
base: {
|
|
280
157
|
chain: "base",
|
|
@@ -287,10 +164,6 @@ async function checkBalance(wallet, opts = {}) {
|
|
|
287
164
|
token: "USDC.e",
|
|
288
165
|
amount: (0, import_viem2.formatUnits)(tempoRaw, USDC_DECIMALS),
|
|
289
166
|
address: wallet.walletAddress
|
|
290
|
-
},
|
|
291
|
-
offChainCredit: {
|
|
292
|
-
amount: credit.amount,
|
|
293
|
-
currency: "USD"
|
|
294
167
|
}
|
|
295
168
|
};
|
|
296
169
|
}
|
|
@@ -321,6 +194,34 @@ function fund(walletAddress) {
|
|
|
321
194
|
};
|
|
322
195
|
}
|
|
323
196
|
|
|
197
|
+
// src/hmac.ts
|
|
198
|
+
var import_node_crypto = require("crypto");
|
|
199
|
+
function computeSignature(secret, method, path, subOrgId, body, timestamp) {
|
|
200
|
+
const bodyDigest = (0, import_node_crypto.createHash)("sha256").update(body).digest("hex");
|
|
201
|
+
const signingString = `${method}
|
|
202
|
+
${path}
|
|
203
|
+
${subOrgId}
|
|
204
|
+
${bodyDigest}
|
|
205
|
+
${timestamp}`;
|
|
206
|
+
return (0, import_node_crypto.createHmac)("sha256", secret).update(signingString).digest("hex");
|
|
207
|
+
}
|
|
208
|
+
function buildHmacHeaders(secret, method, path, subOrgId, body) {
|
|
209
|
+
const timestamp = String(Math.floor(Date.now() / 1e3));
|
|
210
|
+
const signature = computeSignature(
|
|
211
|
+
secret,
|
|
212
|
+
method,
|
|
213
|
+
path,
|
|
214
|
+
subOrgId,
|
|
215
|
+
body,
|
|
216
|
+
timestamp
|
|
217
|
+
);
|
|
218
|
+
return {
|
|
219
|
+
"X-KH-Sub-Org": subOrgId,
|
|
220
|
+
"X-KH-Timestamp": timestamp,
|
|
221
|
+
"X-KH-Signature": signature
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
324
225
|
// src/skill-install.ts
|
|
325
226
|
var import_promises = require("fs/promises");
|
|
326
227
|
var import_node_path2 = require("path");
|
|
@@ -420,6 +321,26 @@ async function installSkill(options = {}) {
|
|
|
420
321
|
var import_promises2 = require("fs/promises");
|
|
421
322
|
var import_node_os2 = require("os");
|
|
422
323
|
var import_node_path3 = require("path");
|
|
324
|
+
|
|
325
|
+
// src/types.ts
|
|
326
|
+
var KeeperHubError = class extends Error {
|
|
327
|
+
code;
|
|
328
|
+
constructor(code, message) {
|
|
329
|
+
super(message);
|
|
330
|
+
this.name = "KeeperHubError";
|
|
331
|
+
this.code = code;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
var WalletConfigMissingError = class extends Error {
|
|
335
|
+
constructor() {
|
|
336
|
+
super(
|
|
337
|
+
"Wallet config not found at ~/.keeperhub/wallet.json. Run `npx @keeperhub/wallet add` to provision."
|
|
338
|
+
);
|
|
339
|
+
this.name = "WalletConfigMissingError";
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// src/storage.ts
|
|
423
344
|
async function readWalletConfig() {
|
|
424
345
|
const walletPath = (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".keeperhub", "wallet.json");
|
|
425
346
|
let raw;
|
|
@@ -448,11 +369,11 @@ function getWalletConfigPath() {
|
|
|
448
369
|
}
|
|
449
370
|
|
|
450
371
|
// src/cli.ts
|
|
451
|
-
var
|
|
372
|
+
var TRAILING_SLASH = /\/$/;
|
|
452
373
|
var WALLET_ADDRESS_PATTERN = /^0x[a-fA-F0-9]{40}$/;
|
|
453
374
|
function resolveBaseUrl(override) {
|
|
454
375
|
const candidate = override ?? process.env.KEEPERHUB_API_URL ?? "https://app.keeperhub.com";
|
|
455
|
-
return candidate.replace(
|
|
376
|
+
return candidate.replace(TRAILING_SLASH, "");
|
|
456
377
|
}
|
|
457
378
|
function isNonEmptyString(value) {
|
|
458
379
|
return typeof value === "string" && value.length > 0;
|
|
@@ -566,14 +487,10 @@ async function cmdFund() {
|
|
|
566
487
|
async function cmdBalance() {
|
|
567
488
|
const wallet = await readWalletConfig();
|
|
568
489
|
const snap = await checkBalance(wallet);
|
|
569
|
-
process.stdout.write(`Base USDC:
|
|
490
|
+
process.stdout.write(`Base USDC: ${snap.base.amount}
|
|
570
491
|
`);
|
|
571
|
-
process.stdout.write(`Tempo USDC.e:
|
|
492
|
+
process.stdout.write(`Tempo USDC.e: ${snap.tempo.amount}
|
|
572
493
|
`);
|
|
573
|
-
process.stdout.write(
|
|
574
|
-
`KeeperHub credit: ${snap.offChainCredit.amount} ${snap.offChainCredit.currency}
|
|
575
|
-
`
|
|
576
|
-
);
|
|
577
494
|
}
|
|
578
495
|
async function cmdInfo() {
|
|
579
496
|
const wallet = await readWalletConfig();
|
|
@@ -586,7 +503,7 @@ async function runCli(argv = process.argv) {
|
|
|
586
503
|
const program = new import_commander.Command();
|
|
587
504
|
program.name("keeperhub-wallet").description(
|
|
588
505
|
"KeeperHub agentic wallet CLI (auto-pay x402 + MPP 402 responses)"
|
|
589
|
-
).version("0.1.
|
|
506
|
+
).version("0.1.3");
|
|
590
507
|
program.command("add").description("Provision a new agentic wallet (no account required)").option("--base-url <url>", "KeeperHub API base URL").action(async (opts) => {
|
|
591
508
|
await cmdAdd(opts);
|
|
592
509
|
});
|
|
@@ -600,9 +517,7 @@ async function runCli(argv = process.argv) {
|
|
|
600
517
|
).action(async () => {
|
|
601
518
|
await cmdFund();
|
|
602
519
|
});
|
|
603
|
-
program.command("balance").description(
|
|
604
|
-
"Print unified balance: Base USDC + Tempo USDC.e + off-chain KeeperHub credit"
|
|
605
|
-
).action(async () => {
|
|
520
|
+
program.command("balance").description("Print on-chain balance: Base USDC + Tempo USDC.e").action(async () => {
|
|
606
521
|
await cmdBalance();
|
|
607
522
|
});
|
|
608
523
|
program.command("info").description("Print subOrgId and walletAddress from local config").action(async () => {
|
|
@@ -657,6 +572,78 @@ async function runCli(argv = process.argv) {
|
|
|
657
572
|
}
|
|
658
573
|
}
|
|
659
574
|
|
|
575
|
+
// src/client.ts
|
|
576
|
+
var TRAILING_SLASH2 = /\/$/;
|
|
577
|
+
function defaultCodeForStatus(status) {
|
|
578
|
+
if (status === 401) {
|
|
579
|
+
return "HMAC_INVALID";
|
|
580
|
+
}
|
|
581
|
+
if (status === 403) {
|
|
582
|
+
return "POLICY_BLOCKED";
|
|
583
|
+
}
|
|
584
|
+
if (status === 404) {
|
|
585
|
+
return "NOT_FOUND";
|
|
586
|
+
}
|
|
587
|
+
if (status === 502) {
|
|
588
|
+
return "TURNKEY_UPSTREAM";
|
|
589
|
+
}
|
|
590
|
+
return `HTTP_${status}`;
|
|
591
|
+
}
|
|
592
|
+
var KeeperHubClient = class {
|
|
593
|
+
baseUrl;
|
|
594
|
+
fetchImpl;
|
|
595
|
+
wallet;
|
|
596
|
+
constructor(wallet, opts = {}) {
|
|
597
|
+
this.wallet = wallet;
|
|
598
|
+
const envBase = process.env.KEEPERHUB_API_URL;
|
|
599
|
+
this.baseUrl = (opts.baseUrl ?? envBase ?? "https://app.keeperhub.com").replace(TRAILING_SLASH2, "");
|
|
600
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* HMAC-signed POST/GET to any /api/agentic-wallet/* route except
|
|
604
|
+
* /provision. Path MUST start with a leading slash. Body is
|
|
605
|
+
* JSON.stringify'd (or the empty string for GET).
|
|
606
|
+
*
|
|
607
|
+
* Error mapping: non-2xx/non-202 surface as `KeeperHubError(code,
|
|
608
|
+
* message)` where `code` is the server-supplied field or the default
|
|
609
|
+
* taxonomy (`HMAC_INVALID`, `POLICY_BLOCKED`, `NOT_FOUND`,
|
|
610
|
+
* `TURNKEY_UPSTREAM`, `HTTP_<status>`). 202 ask-tier surfaces as an
|
|
611
|
+
* AskTierResponse envelope.
|
|
612
|
+
*/
|
|
613
|
+
async request(method, path, body) {
|
|
614
|
+
const bodyStr = body === void 0 ? "" : JSON.stringify(body);
|
|
615
|
+
const hmacHeaders = buildHmacHeaders(
|
|
616
|
+
this.wallet.hmacSecret,
|
|
617
|
+
method,
|
|
618
|
+
path,
|
|
619
|
+
this.wallet.subOrgId,
|
|
620
|
+
bodyStr
|
|
621
|
+
);
|
|
622
|
+
const headers = method === "POST" ? { ...hmacHeaders, "content-type": "application/json" } : { ...hmacHeaders };
|
|
623
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
624
|
+
method,
|
|
625
|
+
headers,
|
|
626
|
+
body: method === "POST" ? bodyStr : void 0
|
|
627
|
+
});
|
|
628
|
+
if (response.status === 202) {
|
|
629
|
+
const data = await response.json();
|
|
630
|
+
return { _status: 202, approvalRequestId: data.approvalRequestId };
|
|
631
|
+
}
|
|
632
|
+
if (!response.ok) {
|
|
633
|
+
let code = "UNKNOWN";
|
|
634
|
+
let message = `HTTP ${response.status}`;
|
|
635
|
+
try {
|
|
636
|
+
const data = await response.json();
|
|
637
|
+
code = data.code ?? defaultCodeForStatus(response.status);
|
|
638
|
+
message = data.error ?? message;
|
|
639
|
+
} catch {
|
|
640
|
+
}
|
|
641
|
+
throw new KeeperHubError(code, message);
|
|
642
|
+
}
|
|
643
|
+
return await response.json();
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
|
|
660
647
|
// src/safety-config.ts
|
|
661
648
|
var import_promises3 = require("fs/promises");
|
|
662
649
|
var import_node_os3 = require("os");
|