@paybox-sh/sdk 0.8.5 → 1.0.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/README.md +18 -9
- package/SKILL.md +99 -25
- package/dist/{chunk-WRPYONXW.js → chunk-SMPW2GUM.js} +176 -60
- package/dist/chunk-SMPW2GUM.js.map +1 -0
- package/dist/cli.js +33 -32
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +74 -26
- package/dist/index.js +1 -1
- package/package.json +2 -3
- package/dist/chunk-WRPYONXW.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,10 +4,9 @@ Typed Node SDK and `paybox` CLI for the PayBox agent API. It mirrors the MCP too
|
|
|
4
4
|
surface — `list_credentials`, `request_payment`, `claim_payment_credentials`,
|
|
5
5
|
`request_wallet_sign`, `request_secret`, `request_swap`, `discover_services`,
|
|
6
6
|
`pay_x402`, `use_service`, `get_portfolio`, `get_buy_link`,
|
|
7
|
-
`request_account_change`, `get_request`, and
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Geofenced World money tools are MCP-only.
|
|
7
|
+
`request_account_change`, `get_request`, and the generic plugin discovery,
|
|
8
|
+
contract, and invocation flow. Core operations use the REST API; plugins use
|
|
9
|
+
the same MCP tools as connector hosts, with no hardcoded per-plugin paths.
|
|
11
10
|
|
|
12
11
|
Wallet signing is **non-custodial and runs in-process**: the SDK reuses the exact
|
|
13
12
|
signing core from the wallet-sign iframe (`@paybox/mcp-app`), builds the chain
|
|
@@ -24,7 +23,7 @@ npx @paybox-sh/sdk login # or use the CLI directly
|
|
|
24
23
|
Driving this CLI from an agent? [`SKILL.md`](SKILL.md) ships in the package and
|
|
25
24
|
describes the install and login flow as an agent skill: what the human has to do
|
|
26
25
|
(approve wallets, paste one signing key), and what the agent should not do
|
|
27
|
-
around it. Use the CLI on **Grok Bot**, **Grok Computer**, and any agent on a
|
|
26
|
+
around it. Use the CLI on **Muse**, **Grok Bot**, **Grok Computer**, and any agent on a
|
|
28
27
|
computer with no connector screen — not the grok.com MCP connector path.
|
|
29
28
|
|
|
30
29
|
## CLI
|
|
@@ -60,8 +59,9 @@ paybox account-change --note "need a wallet grant" # manage_url for the user to
|
|
|
60
59
|
paybox request <request_id> --wait # poll a pending request
|
|
61
60
|
|
|
62
61
|
# Plugins (enable them in the paybox app first)
|
|
63
|
-
paybox
|
|
64
|
-
paybox
|
|
62
|
+
paybox plugins list --status enabled
|
|
63
|
+
paybox plugins contract paybox://plugins/world
|
|
64
|
+
paybox plugins use world world_get_events --input '{"status":"active"}'
|
|
65
65
|
|
|
66
66
|
paybox version # installed version (+ update check)
|
|
67
67
|
paybox update # update the global install to latest
|
|
@@ -77,7 +77,7 @@ its own binary). For project installs use `pnpm up`/`pnpm rm`, or `npx
|
|
|
77
77
|
@paybox-sh/sdk@latest` to always run the latest without installing.
|
|
78
78
|
|
|
79
79
|
`sign`, `swap`, `pay-x402`, and `use-service` can complete in-process with a
|
|
80
|
-
configured `pbxk1.` key.
|
|
80
|
+
configured `pbxk1.` key. Plugin calls return the raw MCP tool result.
|
|
81
81
|
|
|
82
82
|
For a Solana `swap` the SDK re-pins a fresh recent blockhash immediately before
|
|
83
83
|
signing (parity with the signing window — the quote-time blockhash expires
|
|
@@ -85,7 +85,7 @@ within ~60–90s, often before signing), so a swap that dwells for approval no
|
|
|
85
85
|
longer broadcasts as `BlockhashNotFound`. EVM swaps are unaffected.
|
|
86
86
|
|
|
87
87
|
`pay-x402` is header mode — on success `output.value.x_payment` is the `X-PAYMENT`
|
|
88
|
-
header to replay on the original request. `use-service` is gateway mode —
|
|
88
|
+
header to replay on the original request. `use-service` is gateway mode — PayBox
|
|
89
89
|
makes the paid call for you and returns the resource's reply on
|
|
90
90
|
`output.value.response`. Pass `--accepts` from the resource's own 402 (start from
|
|
91
91
|
the curated Bazaar set with `paybox discover`).
|
|
@@ -122,6 +122,15 @@ const services = await paybox.discoverServices("weather api");
|
|
|
122
122
|
const rawServices = await paybox.discoverServices("weather api", { raw: true }); // debug only
|
|
123
123
|
const paid = await paybox.useService({ credentialId: walletId, url: services[0].resource });
|
|
124
124
|
// paid.response.output.value.response holds the resource's reply
|
|
125
|
+
|
|
126
|
+
const plugins = await paybox.discoverPlugins({ status: "enabled" });
|
|
127
|
+
const selected = plugins.plugins.find((plugin) => plugin.id === "aave");
|
|
128
|
+
const contract = await paybox.getPluginContract(selected!.contract_uri!);
|
|
129
|
+
const result = await paybox.usePlugin({
|
|
130
|
+
pluginId: contract.contract.id,
|
|
131
|
+
toolId: contract.contract.tools[0].id,
|
|
132
|
+
input: {},
|
|
133
|
+
});
|
|
125
134
|
```
|
|
126
135
|
|
|
127
136
|
## Configuration
|
package/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: PayBox CLI setup
|
|
3
|
-
version: 0.8.
|
|
3
|
+
version: 0.8.13
|
|
4
4
|
description: >-
|
|
5
5
|
Install and log in to the PayBox CLI (@paybox-sh/sdk) so an agent can pay,
|
|
6
6
|
sign, and hold wallet, card, and secret credentials on the user's behalf. Use
|
|
@@ -12,11 +12,11 @@ description: >-
|
|
|
12
12
|
|
|
13
13
|
The human and agent guide is `https://docs.paybox.sh` (start at
|
|
14
14
|
getting-started and connect/mcp). This file is only the CLI film. Grok
|
|
15
|
-
(grok.com)
|
|
15
|
+
(grok.com), Grok Bots, and Muse are different hosts; do not treat one as another.
|
|
16
16
|
|
|
17
17
|
## Which host
|
|
18
18
|
|
|
19
|
-
- **Grok Bot, Grok Computer, or any agent on a computer or VM with no connector
|
|
19
|
+
- **Muse, Grok Bot, Grok Computer, or any agent on a computer or VM with no connector
|
|
20
20
|
screen:** this skill is the path. Install and run `paybox login` on that
|
|
21
21
|
machine. Do not send the user to grok.com/connectors and do not paste the MCP
|
|
22
22
|
URL as setup.
|
|
@@ -24,13 +24,65 @@ getting-started and connect/mcp). This file is only the CLI film. Grok
|
|
|
24
24
|
grok.com/connectors. Do not run this CLI install flow unless they explicitly
|
|
25
25
|
want the CLI on a separate machine.
|
|
26
26
|
|
|
27
|
-
When the user says "install PayBox" and you are Grok Bot or running on a
|
|
27
|
+
When the user says "install PayBox" and you are Muse, Grok Bot, or running on a
|
|
28
28
|
computer, start here immediately.
|
|
29
29
|
|
|
30
30
|
The user asks to install PayBox. Two things need them: they approve wallet
|
|
31
31
|
access with a passkey, and they paste one signing key. Everything else is yours,
|
|
32
32
|
and they should not see it happen.
|
|
33
33
|
|
|
34
|
+
## Muse
|
|
35
|
+
|
|
36
|
+
On Muse this section wins over Grok Bot phone-app and masked-field rules below.
|
|
37
|
+
Prod is `https://api.paybox.sh` / `https://app.paybox.sh`. Stay quiet until they
|
|
38
|
+
say install PayBox / install paybox / Install Paybox. English. Few words. No
|
|
39
|
+
secret dumps. No invented click paths.
|
|
40
|
+
|
|
41
|
+
Do not send them to Settings → Connectors → Add custom, or to paste an MCP URL.
|
|
42
|
+
Muse **Manage Connectors** (OpenAI, Anthropic, and the rest) is not where
|
|
43
|
+
PayBox is added. Do not run passkey inside Muse. Muse is a chat host, not a
|
|
44
|
+
Grok Bot computer VM. Do not ask for done, listo, or a screenshot. Do not
|
|
45
|
+
fake ready.
|
|
46
|
+
Never wipe `~/.config/paybox`.
|
|
47
|
+
|
|
48
|
+
Two chat controls, then Welcome. Muse does **not** open those links the way
|
|
49
|
+
Grok Bot does. Every link you send must tell them to tap it. A bare
|
|
50
|
+
markdown pill with no "tap this" line is a failed take.
|
|
51
|
+
|
|
52
|
+
1. Run device-code login (`paybox login`, or the PayBox capability Authorize
|
|
53
|
+
flow if this host already has it). The moment you have
|
|
54
|
+
`verification_uri_complete` and `user_code`, send **one** message:
|
|
55
|
+
**Tap [Authorize wallets](verification_uri_complete) on your phone
|
|
56
|
+
browser.** plus `Code: XXXX-XXXX`. One short extra line only if the
|
|
57
|
+
PayBox **Capability** screen shows **Authorize**: "Or tap Authorize on
|
|
58
|
+
Paybox under Capabilities." Never mention Add custom. Phone browser
|
|
59
|
+
(Safari or Chrome), not the native PayBox app and not inside Muse.
|
|
60
|
+
You do not open the URL. Poll until OAuth is live. Do not end the
|
|
61
|
+
turn while polling.
|
|
62
|
+
2. When OAuth is live and the signing key is missing, send **Tap
|
|
63
|
+
[Provision agent key](https://app.paybox.sh/agent-key?client_id=<cid>)
|
|
64
|
+
on your phone browser.** Then this exact line: **Muse does not have a
|
|
65
|
+
secure field for the signing key yet; the team is working on it. For
|
|
66
|
+
now paste the pbxk1 here and rotate it after.** `cid` is the
|
|
67
|
+
access-token UUID, never `oauth.clientId`. Muse has no masked field.
|
|
68
|
+
Write `signingKey` into an isolated config. Never `login --signing-key`
|
|
69
|
+
on argv. Never echo the key.
|
|
70
|
+
|
|
71
|
+
Ready only when OAuth or an API key is live **and** `canSign` is true. Then
|
|
72
|
+
Welcome to PayBox with two buttons: **Swap 20 USDC to SOL**, **Pay a Solana
|
|
73
|
+
briefing**. Do the one they tap. Stop when that job is done.
|
|
74
|
+
|
|
75
|
+
If token exchange fails (`refresh_rejected` / egress): one stop line, "Host
|
|
76
|
+
blocks PayBox token exchange. Install NOT complete." Do not offer Settings →
|
|
77
|
+
Add custom as a workaround. If a PayBox capability with **Authorize** is
|
|
78
|
+
visible, point only there. If MCP is already Connected under Manage your MCP
|
|
79
|
+
servers, use that grant — still no Add custom story.
|
|
80
|
+
|
|
81
|
+
Install the CLI only when this host still needs device-code:
|
|
82
|
+
`npm install -g @paybox-sh/sdk@latest`, then `paybox --json version` (0.8.5+).
|
|
83
|
+
Fresh `PAYBOX_CONFIG_DIR`. Unset `PAYBOX_API_URL` `PAYBOX_API_KEY`
|
|
84
|
+
`PAYBOX_SIGNING_KEY` `PAYBOX_ACCESS_TOKEN`.
|
|
85
|
+
|
|
34
86
|
## Install
|
|
35
87
|
|
|
36
88
|
```bash
|
|
@@ -90,9 +142,10 @@ Send that link even though the CLI also tries to open a browser. When the CLI
|
|
|
90
142
|
is not on the user's machine, that local open is useless or invisible, and your
|
|
91
143
|
message is the only way they reach the page.
|
|
92
144
|
|
|
93
|
-
On
|
|
94
|
-
correct path. After they tap Connect CLI, the app opens Generate a
|
|
95
|
-
key by itself. Do not tell them to come back to chat first.
|
|
145
|
+
On Grok Bot, Authorize wallets should open the PayBox app. That is the
|
|
146
|
+
correct path there. After they tap Connect CLI, the app opens Generate a
|
|
147
|
+
signing key by itself. Do not tell them to come back to chat first. On Muse
|
|
148
|
+
use the Muse section: phone browser, not the native app, not inside Muse.
|
|
96
149
|
|
|
97
150
|
Then wait. The poll is the continue signal. Do not ask the user to type `done`,
|
|
98
151
|
confirm, or send a screenshot, and do not end your turn while login is running.
|
|
@@ -120,9 +173,12 @@ showing the box does not need that machine.
|
|
|
120
173
|
The moment **this** login has an agent-key URL (stderr, or `cid` from the oauth
|
|
121
174
|
it just saved), put **Generate Signing Key** in chat as that link plus a
|
|
122
175
|
**masked input** for the `pbxk1.` value, in the same turn. Seconds after they
|
|
123
|
-
finish Authorize wallets, not minutes. That chat link must use the JWT `cid
|
|
124
|
-
|
|
125
|
-
does.
|
|
176
|
+
finish Authorize wallets, not minutes. That chat link must use the JWT `cid`.
|
|
177
|
+
On Grok Bot it must open the PayBox app on the first tap, the same way
|
|
178
|
+
Authorize wallets does. On Muse tell them to tap the link, then say Muse does
|
|
179
|
+
not have a secure field for the signing key yet; the team is working
|
|
180
|
+
on it. For now paste the pbxk1 here and rotate it after. There is no
|
|
181
|
+
masked field. The link opens in the phone browser. Do not `Start-Process`, `open`, `rundll32`, or `xdg-open` the authorize,
|
|
126
182
|
connect, or agent-key URL yourself. Write what they give you to login's
|
|
127
183
|
prompt stdin when that prompt is alive. If login is wedged after this oauth
|
|
128
184
|
write, keep the box on screen and merge `signingKey` when the host can write
|
|
@@ -153,9 +209,15 @@ rather than continuing, because signing and swaps will fail without it.
|
|
|
153
209
|
From the install request until `canSign` is `true`, exactly two messages, in
|
|
154
210
|
this order:
|
|
155
211
|
|
|
156
|
-
1. The **Authorize wallets** link plus the code.
|
|
157
|
-
|
|
212
|
+
1. The **Authorize wallets** link plus the code. On Muse, the line says
|
|
213
|
+
to tap that link on the phone browser. Grok Bot can omit that; it
|
|
214
|
+
opens the link itself.
|
|
215
|
+
2. **Generate Signing Key** plus the signing-key control, as soon as
|
|
158
216
|
**this** login prints `/agent-key?client_id=` or writes a new `oauth`.
|
|
217
|
+
Grok Bot: masked `pbxk1.` field. Muse: tell them to tap Provision
|
|
218
|
+
agent key on the phone browser, then: Muse does not have a secure
|
|
219
|
+
field for the signing key yet; the team is working on it. For now
|
|
220
|
+
paste the pbxk1 here and rotate it after.
|
|
159
221
|
|
|
160
222
|
Nothing else. No "Installing…", "Opening…", "Got it", no CLI version, package
|
|
161
223
|
manager, config path, or request id, and no narration of a retry or fallback. If
|
|
@@ -232,24 +294,30 @@ catalog index. There may be tens or thousands.
|
|
|
232
294
|
app, not a host Settings → Plugins screen. Ask them to turn on what
|
|
233
295
|
they want to use, then say when they are back.
|
|
234
296
|
|
|
235
|
-
2. Then
|
|
236
|
-
|
|
297
|
+
2. Then run `paybox --json plugins list --status enabled --limit 10`. That page
|
|
298
|
+
is what they have on, not the store. From
|
|
237
299
|
those plugins plus the portfolio, suggest a few concrete next moves
|
|
238
300
|
(about six, not one row per plugin). Use each result's `name` and
|
|
239
301
|
contract. Be specific: amounts, which wallet UUID, which market or
|
|
240
302
|
vault from the contract. Mix two enabled plugins in one suggestion
|
|
241
303
|
when that serves the same goal (for example fund or swap, then put
|
|
242
|
-
the result to work).
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
304
|
+
the result to work). On Muse, Welcome is those two buttons first:
|
|
305
|
+
**Swap 20 USDC to SOL** on the granted Solana wallet, then **Pay a
|
|
306
|
+
Solana briefing**. Do not offer 0.001 SOL to USDC. If nothing is
|
|
307
|
+
enabled, skip the extra plugin list and stay on the Plugins link.
|
|
308
|
+
|
|
309
|
+
When they name a plugin or a job, search with `paybox --json plugins list
|
|
310
|
+
<query> --status enabled`, then page with `--cursor <next_cursor>` only while
|
|
311
|
+
the current page has no match. For an official plugin, run `paybox --json
|
|
312
|
+
plugins contract <contract_uri>` with the URI unchanged, then `paybox --json
|
|
313
|
+
plugins use <plugin_id> <tool_id> --input <json>` with input matching that
|
|
314
|
+
contract. Unofficial discovery results already contain their tool schemas;
|
|
315
|
+
reuse `--invocation-id` only to retrieve the exact same ambiguous call. Plugin
|
|
316
|
+
money always pauses for passkey.
|
|
317
|
+
|
|
318
|
+
There are no per-plugin commands. `paybox world …` and `paybox hyperliquid …`
|
|
319
|
+
were removed in 1.0.0; reach World and Hyperliquid through `paybox plugins`
|
|
320
|
+
like every other plugin.
|
|
253
321
|
|
|
254
322
|
If prod MCP (`https://api.paybox.sh/mcp`) is `unreachable` or `needsAuth` while
|
|
255
323
|
`paybox --json whoami` still works, say that. Do not send the human to Settings.
|
|
@@ -272,3 +340,9 @@ Do not switch to staging. Do not report the dollar as sent.
|
|
|
272
340
|
got its own window).
|
|
273
341
|
- Setup chat contained anything besides those two messages.
|
|
274
342
|
- A token, API key, or `pbxk1.` value reached the transcript.
|
|
343
|
+
- On Muse you sent Settings → Connectors → Add custom, or Manage Connectors.
|
|
344
|
+
- On Muse you opened passkey inside Muse.
|
|
345
|
+
- On Muse Authorize wallets opened in the PayBox app or inside Muse.
|
|
346
|
+
- On Muse you sent a link without telling them to tap it.
|
|
347
|
+
- On Muse you faked ready before `canSign` was true.
|
|
348
|
+
- On Muse token exchange failed and you invented an MCP Add custom path.
|
|
@@ -133,7 +133,7 @@ async function loginDevice(baseUrl, opts = {}) {
|
|
|
133
133
|
const meta = await metadata(baseUrl);
|
|
134
134
|
if (!meta.device_authorization_endpoint) {
|
|
135
135
|
throw new Error(
|
|
136
|
-
"this
|
|
136
|
+
"this PayBox API does not advertise device_authorization_endpoint \u2014 upgrade the API and retry `paybox login`"
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
139
|
const resource = mcpResource(baseUrl);
|
|
@@ -301,18 +301,52 @@ import { Buffer as Buffer2 } from "buffer";
|
|
|
301
301
|
import nacl from "tweetnacl";
|
|
302
302
|
import { MoonXEvmSigner, EvmSchemeMismatchError } from "@moon-x/evm-adapter";
|
|
303
303
|
import { MoonXSolanaSigner, SolanaSchemeMismatchError } from "@moon-x/solana-adapter";
|
|
304
|
-
import { Transaction } from "@solana/web3.js";
|
|
304
|
+
import { Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
305
305
|
import { hashTypedData, keccak256, serializeTransaction } from "viem";
|
|
306
|
+
function parseWireU128(value, field) {
|
|
307
|
+
if (value === void 0 || value === null) {
|
|
308
|
+
throw new Error(`transaction is missing ${field}`);
|
|
309
|
+
}
|
|
310
|
+
if (typeof value === "bigint") {
|
|
311
|
+
if (value < 0n) {
|
|
312
|
+
throw new Error(`transaction field ${field} must be a non-negative integer`);
|
|
313
|
+
}
|
|
314
|
+
return value;
|
|
315
|
+
}
|
|
316
|
+
if (typeof value === "number") {
|
|
317
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
318
|
+
throw new Error(`transaction field ${field} must be a non-negative integer`);
|
|
319
|
+
}
|
|
320
|
+
return BigInt(value);
|
|
321
|
+
}
|
|
322
|
+
if (typeof value === "string") {
|
|
323
|
+
const trimmed = value.trim();
|
|
324
|
+
if (!trimmed) {
|
|
325
|
+
throw new Error(`transaction field ${field} is empty`);
|
|
326
|
+
}
|
|
327
|
+
if (/^0[xX][0-9a-fA-F]+$/.test(trimmed)) {
|
|
328
|
+
return BigInt(trimmed);
|
|
329
|
+
}
|
|
330
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
331
|
+
throw new Error(`transaction field ${field} is not a valid integer`);
|
|
332
|
+
}
|
|
333
|
+
return BigInt(trimmed);
|
|
334
|
+
}
|
|
335
|
+
throw new Error(`transaction field ${field} has an invalid type`);
|
|
336
|
+
}
|
|
306
337
|
function reviveTx(w) {
|
|
338
|
+
if (typeof w !== "object" || w === null || Array.isArray(w)) {
|
|
339
|
+
throw new Error("transaction must be an object, not a JSON-encoded string");
|
|
340
|
+
}
|
|
307
341
|
return {
|
|
308
342
|
type: "eip1559",
|
|
309
343
|
to: w.to,
|
|
310
|
-
value:
|
|
344
|
+
value: parseWireU128(w.value ?? "0", "value"),
|
|
311
345
|
data: w.data,
|
|
312
346
|
chainId: w.chainId,
|
|
313
|
-
gas:
|
|
314
|
-
maxPriorityFeePerGas:
|
|
315
|
-
maxFeePerGas:
|
|
347
|
+
gas: parseWireU128(w.gas, "gas"),
|
|
348
|
+
maxPriorityFeePerGas: parseWireU128(w.maxPriorityFeePerGas, "maxPriorityFeePerGas"),
|
|
349
|
+
maxFeePerGas: parseWireU128(w.maxFeePerGas, "maxFeePerGas"),
|
|
316
350
|
nonce: w.nonce
|
|
317
351
|
};
|
|
318
352
|
}
|
|
@@ -356,6 +390,14 @@ function solanaSigningPayload(base64Tx) {
|
|
|
356
390
|
}
|
|
357
391
|
return bytesToHex(new Uint8Array(raw.subarray(i + sigCount * 64)));
|
|
358
392
|
}
|
|
393
|
+
function deserializeSolanaTx(base64Tx) {
|
|
394
|
+
const raw = Buffer2.from(base64Tx, "base64");
|
|
395
|
+
try {
|
|
396
|
+
return Transaction.from(raw);
|
|
397
|
+
} catch {
|
|
398
|
+
return VersionedTransaction.deserialize(new Uint8Array(raw));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
359
401
|
function buildSwapEnvelopes(txs, binding, creds) {
|
|
360
402
|
if (!binding.walletId) {
|
|
361
403
|
throw new Error("PayBox did not supply a wallet id for this operation.");
|
|
@@ -484,7 +526,7 @@ async function signIntent(intent, creds, binding, transport) {
|
|
|
484
526
|
return { ok: true, artifact: { signature: bytesToHex(sig) } };
|
|
485
527
|
}
|
|
486
528
|
case "solanaTransaction": {
|
|
487
|
-
const tx =
|
|
529
|
+
const tx = deserializeSolanaTx(intent.transactionBase64);
|
|
488
530
|
const signed = await new MoonXSolanaSigner(ed25519Sign, intent.address).signTransaction(
|
|
489
531
|
tx
|
|
490
532
|
);
|
|
@@ -607,6 +649,100 @@ async function signX402Request(post, requestId, plan, creds) {
|
|
|
607
649
|
await post(`/agent/requests/${requestId}/envelopes`, { envelopes: [envelope] });
|
|
608
650
|
}
|
|
609
651
|
|
|
652
|
+
// src/mcp.ts
|
|
653
|
+
var PROTOCOL_VERSION = "2025-06-18";
|
|
654
|
+
function responseBody(text) {
|
|
655
|
+
const events = text.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim());
|
|
656
|
+
return events.length === 0 ? text : events.join("");
|
|
657
|
+
}
|
|
658
|
+
function errorText(result) {
|
|
659
|
+
return result.content.filter((item) => item.type === "text" && typeof item.text === "string").map((item) => item.text).join("\n");
|
|
660
|
+
}
|
|
661
|
+
function toolJson(tool, result) {
|
|
662
|
+
if (result.isError) {
|
|
663
|
+
throw new Error(errorText(result) || `paybox ${tool} failed`);
|
|
664
|
+
}
|
|
665
|
+
const text = result.content.find(
|
|
666
|
+
(item) => item.type === "text" && typeof item.text === "string"
|
|
667
|
+
)?.text;
|
|
668
|
+
if (typeof text !== "string") {
|
|
669
|
+
throw new Error(`paybox ${tool} returned no JSON content`);
|
|
670
|
+
}
|
|
671
|
+
return JSON.parse(text);
|
|
672
|
+
}
|
|
673
|
+
var McpTransport = class {
|
|
674
|
+
endpoint;
|
|
675
|
+
bearer;
|
|
676
|
+
fetchImpl;
|
|
677
|
+
nextId = 0;
|
|
678
|
+
initialization;
|
|
679
|
+
constructor(options) {
|
|
680
|
+
this.endpoint = `${options.baseUrl}/mcp`;
|
|
681
|
+
this.bearer = options.bearer;
|
|
682
|
+
this.fetchImpl = options.fetchImpl;
|
|
683
|
+
}
|
|
684
|
+
async callTool(name, args) {
|
|
685
|
+
await this.initialize();
|
|
686
|
+
return this.rpc("tools/call", { name, arguments: args });
|
|
687
|
+
}
|
|
688
|
+
async initialize() {
|
|
689
|
+
this.initialization ??= this.rpc("initialize", {
|
|
690
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
691
|
+
capabilities: {},
|
|
692
|
+
clientInfo: { name: "paybox-sdk", version: "1" }
|
|
693
|
+
}).then(() => this.notify("notifications/initialized", {}));
|
|
694
|
+
try {
|
|
695
|
+
await this.initialization;
|
|
696
|
+
} catch (error) {
|
|
697
|
+
this.initialization = void 0;
|
|
698
|
+
throw error;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
async post(payload, method) {
|
|
702
|
+
const response = await this.fetchImpl(this.endpoint, {
|
|
703
|
+
method: "POST",
|
|
704
|
+
headers: {
|
|
705
|
+
accept: "application/json, text/event-stream",
|
|
706
|
+
authorization: `Bearer ${await this.bearer()}`,
|
|
707
|
+
"content-type": "application/json",
|
|
708
|
+
"mcp-protocol-version": PROTOCOL_VERSION
|
|
709
|
+
},
|
|
710
|
+
body: JSON.stringify(payload)
|
|
711
|
+
});
|
|
712
|
+
const text = await response.text();
|
|
713
|
+
if (!response.ok) {
|
|
714
|
+
throw new Error(
|
|
715
|
+
`paybox MCP ${method} failed (${response.status}): ${text}`
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
return text;
|
|
719
|
+
}
|
|
720
|
+
async notify(method, params) {
|
|
721
|
+
await this.post({ jsonrpc: "2.0", method, params }, method);
|
|
722
|
+
}
|
|
723
|
+
async rpc(method, params) {
|
|
724
|
+
const text = await this.post(
|
|
725
|
+
{
|
|
726
|
+
jsonrpc: "2.0",
|
|
727
|
+
id: ++this.nextId,
|
|
728
|
+
method,
|
|
729
|
+
params
|
|
730
|
+
},
|
|
731
|
+
method
|
|
732
|
+
);
|
|
733
|
+
const parsed = JSON.parse(responseBody(text));
|
|
734
|
+
if (parsed.error) {
|
|
735
|
+
throw new Error(
|
|
736
|
+
`paybox MCP ${method} failed (${parsed.error.code}): ${parsed.error.message}`
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
if (parsed.result === void 0) {
|
|
740
|
+
throw new Error(`paybox MCP ${method} returned no result`);
|
|
741
|
+
}
|
|
742
|
+
return parsed.result;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
|
|
610
746
|
// src/client.ts
|
|
611
747
|
var DEFAULT_BASE_URL = "https://api.paybox.sh";
|
|
612
748
|
var EXPIRY_SKEW_MS = 6e4;
|
|
@@ -631,10 +767,16 @@ var PayboxClient = class _PayboxClient {
|
|
|
631
767
|
fetchImpl;
|
|
632
768
|
oauth;
|
|
633
769
|
configBacked = false;
|
|
770
|
+
mcp;
|
|
634
771
|
constructor(options = {}) {
|
|
635
772
|
this.opts = options;
|
|
636
773
|
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
637
774
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
775
|
+
this.mcp = new McpTransport({
|
|
776
|
+
baseUrl: this.baseUrl,
|
|
777
|
+
bearer: () => this.bearer(),
|
|
778
|
+
fetchImpl: this.fetchImpl
|
|
779
|
+
});
|
|
638
780
|
}
|
|
639
781
|
static fromConfig(overrides = {}) {
|
|
640
782
|
const cfg = loadConfig();
|
|
@@ -852,6 +994,32 @@ var PayboxClient = class _PayboxClient {
|
|
|
852
994
|
}
|
|
853
995
|
});
|
|
854
996
|
}
|
|
997
|
+
async discoverPlugins(args = {}) {
|
|
998
|
+
return toolJson(
|
|
999
|
+
"discover_plugins",
|
|
1000
|
+
await this.mcp.callTool("discover_plugins", {
|
|
1001
|
+
query: args.query,
|
|
1002
|
+
source: args.source,
|
|
1003
|
+
status: args.status,
|
|
1004
|
+
limit: args.limit,
|
|
1005
|
+
cursor: args.cursor
|
|
1006
|
+
})
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
async getPluginContract(contractUri) {
|
|
1010
|
+
return toolJson(
|
|
1011
|
+
"get_contract",
|
|
1012
|
+
await this.mcp.callTool("get_contract", { contract_uri: contractUri })
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
usePlugin(args) {
|
|
1016
|
+
return this.mcp.callTool("use_plugin", {
|
|
1017
|
+
plugin_id: args.pluginId,
|
|
1018
|
+
tool_id: args.toolId,
|
|
1019
|
+
input: args.input,
|
|
1020
|
+
invocation_id: args.invocationId
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
855
1023
|
async payX402(args, opts = {}) {
|
|
856
1024
|
return this.withExpiryRetry(
|
|
857
1025
|
async () => {
|
|
@@ -922,58 +1090,6 @@ var PayboxClient = class _PayboxClient {
|
|
|
922
1090
|
}
|
|
923
1091
|
});
|
|
924
1092
|
}
|
|
925
|
-
worldMarkets(args = {}) {
|
|
926
|
-
return this.request("GET", "/agent/world/markets", {
|
|
927
|
-
query: {
|
|
928
|
-
events: args.events ? "true" : void 0,
|
|
929
|
-
limit: args.limit?.toString(),
|
|
930
|
-
cursor: args.cursor?.toString(),
|
|
931
|
-
event_ticker: args.eventTicker,
|
|
932
|
-
series_ticker: args.seriesTicker,
|
|
933
|
-
status: args.status
|
|
934
|
-
}
|
|
935
|
-
});
|
|
936
|
-
}
|
|
937
|
-
worldMarket(eventTicker, withNestedMarkets = true) {
|
|
938
|
-
return this.request("GET", "/agent/world/market", {
|
|
939
|
-
query: {
|
|
940
|
-
event_ticker: eventTicker,
|
|
941
|
-
with_nested_markets: withNestedMarkets ? void 0 : "false"
|
|
942
|
-
}
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
worldOrderbook(id, byMint = false) {
|
|
946
|
-
return this.request("GET", "/agent/world/orderbook", {
|
|
947
|
-
query: { id, by_mint: byMint ? "true" : void 0 }
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
worldPrices(args) {
|
|
951
|
-
return this.request("GET", "/agent/world/prices", {
|
|
952
|
-
query: {
|
|
953
|
-
ticker: args.ticker,
|
|
954
|
-
start_ts: args.startTs.toString(),
|
|
955
|
-
end_ts: args.endTs.toString(),
|
|
956
|
-
resolution: args.resolution?.toString()
|
|
957
|
-
}
|
|
958
|
-
});
|
|
959
|
-
}
|
|
960
|
-
worldFilterOutcomeMints(addresses) {
|
|
961
|
-
return this.request("POST", "/agent/world/filter-outcome-mints", {
|
|
962
|
-
body: { addresses }
|
|
963
|
-
});
|
|
964
|
-
}
|
|
965
|
-
worldPositions(address) {
|
|
966
|
-
return this.request("GET", "/agent/world/positions", { query: { address } });
|
|
967
|
-
}
|
|
968
|
-
hyperliquidMarkets() {
|
|
969
|
-
return this.request("GET", "/agent/hyperliquid/markets");
|
|
970
|
-
}
|
|
971
|
-
hyperliquidPrices() {
|
|
972
|
-
return this.request("GET", "/agent/hyperliquid/prices");
|
|
973
|
-
}
|
|
974
|
-
hyperliquidToken(name) {
|
|
975
|
-
return this.request("GET", "/agent/hyperliquid/token", { query: { name } });
|
|
976
|
-
}
|
|
977
1093
|
getRequest(requestId) {
|
|
978
1094
|
return this.request("GET", `/agent/requests/${requestId}`);
|
|
979
1095
|
}
|
|
@@ -1010,4 +1126,4 @@ export {
|
|
|
1010
1126
|
PayboxError,
|
|
1011
1127
|
PayboxClient
|
|
1012
1128
|
};
|
|
1013
|
-
//# sourceMappingURL=chunk-
|
|
1129
|
+
//# sourceMappingURL=chunk-SMPW2GUM.js.map
|