@paybox-sh/sdk 2.1.0 → 2.3.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.
@@ -372,7 +372,7 @@ import { Buffer as Buffer2 } from "buffer";
372
372
  import nacl from "tweetnacl";
373
373
  import { MoonXEvmSigner, EvmSchemeMismatchError } from "@moon-x/evm-adapter";
374
374
  import { MoonXSolanaSigner, SolanaSchemeMismatchError } from "@moon-x/solana-adapter";
375
- import { Transaction, VersionedTransaction } from "@solana/web3.js";
375
+ import { PublicKey, Transaction, VersionedTransaction } from "@solana/web3.js";
376
376
  import { hashTypedData, keccak256, serializeTransaction } from "viem";
377
377
  function parseWireU128(value, field) {
378
378
  if (value === void 0 || value === null) {
@@ -445,8 +445,42 @@ function buildEnvelope(rawSigningPayloadHex, binding, creds) {
445
445
  function eip1559SigningHash(tx) {
446
446
  return keccak256(serializeTransaction(reviveTx(tx)));
447
447
  }
448
+ var SOLANA_V1_PREFIX = 129;
449
+ var SOLANA_SIGNATURE_BYTES = 64;
450
+ var SOLANA_V1_FEE_PAYER_OFFSET = 42;
451
+ var SOLANA_PUBKEY_BYTES = 32;
452
+ function solanaV1Message(raw) {
453
+ const signatureCount = raw[1];
454
+ if (!signatureCount || raw.length <= signatureCount * SOLANA_SIGNATURE_BYTES) {
455
+ throw new Error("solana v1 tx has no signature slots");
456
+ }
457
+ return raw.subarray(0, raw.length - signatureCount * SOLANA_SIGNATURE_BYTES);
458
+ }
459
+ async function signSolanaV1(raw, address, sign) {
460
+ if (raw[1] !== 1) {
461
+ throw new Error("solana v1 transactions with more than one signer are not supported");
462
+ }
463
+ const feePayer = new PublicKey(
464
+ raw.subarray(SOLANA_V1_FEE_PAYER_OFFSET, SOLANA_V1_FEE_PAYER_OFFSET + SOLANA_PUBKEY_BYTES)
465
+ );
466
+ if (!feePayer.equals(new PublicKey(address))) {
467
+ throw new Error("solana v1 transaction signer is not the wallet address");
468
+ }
469
+ const message = solanaV1Message(raw);
470
+ const signature = await sign(message);
471
+ if (signature.length !== SOLANA_SIGNATURE_BYTES) {
472
+ throw new Error("the signing service returned an Ed25519 signature that is not 64 bytes");
473
+ }
474
+ const signed = new Uint8Array(message.length + SOLANA_SIGNATURE_BYTES);
475
+ signed.set(message);
476
+ signed.set(signature, message.length);
477
+ return signed;
478
+ }
448
479
  function solanaSigningPayload(base64Tx) {
449
480
  const raw = Buffer2.from(base64Tx, "base64");
481
+ if (raw[0] === SOLANA_V1_PREFIX) {
482
+ return bytesToHex(new Uint8Array(solanaV1Message(raw)));
483
+ }
450
484
  let i = 0;
451
485
  let sigCount = 0;
452
486
  let shift = 0;
@@ -479,8 +513,8 @@ function buildSwapEnvelopes(txs, binding, creds) {
479
513
  );
480
514
  }
481
515
  return txs.map((t) => {
482
- const payload = t.vm === "solana" ? solanaSigningPayload(t.transaction) : eip1559SigningHash(t.transaction);
483
- const { signed_body, agent_signature } = buildEnvelope(payload, binding, creds);
516
+ const payload2 = t.vm === "eip712" ? eip712SigningHash(t.transaction) : t.vm === "solana" ? solanaSigningPayload(t.transaction) : eip1559SigningHash(t.transaction);
517
+ const { signed_body, agent_signature } = buildEnvelope(payload2, binding, creds);
484
518
  return { api_pub: creds.apiPubHex, signed_body, agent_signature };
485
519
  });
486
520
  }
@@ -597,6 +631,14 @@ async function signIntent(intent, creds, binding, transport) {
597
631
  return { ok: true, artifact: { signature: bytesToHex(sig) } };
598
632
  }
599
633
  case "solanaTransaction": {
634
+ const raw = Buffer2.from(intent.transactionBase64, "base64");
635
+ if (raw[0] === SOLANA_V1_PREFIX) {
636
+ const signed2 = await signSolanaV1(raw, intent.address, ed25519Sign);
637
+ return {
638
+ ok: true,
639
+ artifact: { signedTransactionBase64: Buffer2.from(signed2).toString("base64") }
640
+ };
641
+ }
600
642
  const tx = deserializeSolanaTx(intent.transactionBase64);
601
643
  const signed = await new MoonXSolanaSigner(ed25519Sign, intent.address).signTransaction(
602
644
  tx
@@ -638,42 +680,43 @@ function credsFromToken(token) {
638
680
  function toBinding(b) {
639
681
  return { walletId: b.wallet_id, keyId: b.key_id ?? "", derivationPath: b.derivation_path ?? "" };
640
682
  }
641
- async function resolveBinding(post, requestId, creds) {
683
+ async function resolveBinding(post, requestId2, creds) {
642
684
  const env = buildIssuedAtEnvelope(creds);
643
- const r = await post(`/agent/requests/${requestId}/binding`, {
685
+ const r = await post(`/agent/requests/${requestId2}/binding`, {
644
686
  api_pub: creds.apiPubHex,
645
687
  signed_body: env.signed_body,
646
688
  agent_signature: env.agent_signature
647
689
  });
648
690
  return toBinding(r);
649
691
  }
650
- async function signWalletRequest(post, requestId, intent, creds, binding) {
651
- const resolved = binding && binding.key_id && binding.derivation_path ? toBinding(binding) : await resolveBinding(post, requestId, creds);
652
- const transport = (envelope) => post(`/agent/requests/${requestId}/moonx-sign`, {
692
+ async function signWalletRequest(post, requestId2, intent, creds, binding) {
693
+ const resolved = binding && binding.key_id && binding.derivation_path ? toBinding(binding) : await resolveBinding(post, requestId2, creds);
694
+ const transport = (envelope) => post(`/agent/requests/${requestId2}/moonx-sign`, {
653
695
  api_pub: creds.apiPubHex,
654
696
  ...envelope
655
697
  });
656
698
  const result = await signIntent(intent, creds, resolved, transport);
657
699
  if (!result.ok) throw new Error(result.error);
658
- await post(`/agent/requests/${requestId}/signature`, { artifact: result.artifact });
700
+ await post(`/agent/requests/${requestId2}/signature`, { artifact: result.artifact });
659
701
  return result.artifact;
660
702
  }
661
- function isSolanaRefreshablePlan(plan) {
703
+ function isRefreshablePlan(plan) {
704
+ if (typeof plan.refresh_before_sign === "boolean") return plan.refresh_before_sign;
662
705
  const txs = plan.txs;
663
706
  const solana = txs.some((t) => t.vm === "solana");
664
707
  return solana && txs.some(
665
- (t) => t.kind === "swap" || t.kind === "prediction_trade" || t.kind === "jupiter_swap"
708
+ (t) => t.kind === "swap" || t.kind === "prediction_trade"
666
709
  );
667
710
  }
668
- async function refreshPlan(post, requestId) {
669
- const r = await post(`/agent/requests/${requestId}/refresh`, {});
711
+ async function refreshPlan(post, requestId2) {
712
+ const r = await post(`/agent/requests/${requestId2}/refresh`, {});
670
713
  if (!r || typeof r.plan !== "object" || r.plan === null) {
671
714
  throw new Error("refresh returned no plan");
672
715
  }
673
716
  return r.plan;
674
717
  }
675
- async function refreshSwapPlan(post, requestId) {
676
- const refreshed = await refreshPlan(post, requestId);
718
+ async function refreshSwapPlan(post, requestId2) {
719
+ const refreshed = await refreshPlan(post, requestId2);
677
720
  if (!Array.isArray(refreshed.txs) || refreshed.txs.length === 0) {
678
721
  throw new Error("swap refresh returned a plan with no txs");
679
722
  }
@@ -682,42 +725,43 @@ async function refreshSwapPlan(post, requestId) {
682
725
  function isSolanaRailX402(plan) {
683
726
  return plan.x402?.rail === "solana";
684
727
  }
685
- async function refreshX402SolanaTx(post, requestId) {
686
- const refreshed = await refreshPlan(post, requestId);
728
+ async function refreshX402SolanaTx(post, requestId2) {
729
+ const refreshed = await refreshPlan(post, requestId2);
687
730
  const tx = refreshed.solana?.transaction;
688
731
  if (typeof tx !== "string" || tx.length === 0) {
689
732
  throw new Error("x402 refresh returned a plan with no Solana transaction");
690
733
  }
691
734
  return tx;
692
735
  }
693
- async function signSwapRequest(post, requestId, plan, creds) {
694
- const signPlan = isSolanaRefreshablePlan(plan) ? await refreshSwapPlan(post, requestId) : plan;
736
+ async function signSwapRequest(post, requestId2, plan, creds, validate) {
737
+ const signPlan = isRefreshablePlan(plan) ? await refreshSwapPlan(post, requestId2) : plan;
738
+ validate?.(signPlan);
695
739
  let binding = {
696
740
  walletId: signPlan.binding.wallet_id,
697
741
  keyId: signPlan.binding.key_id ?? "",
698
742
  derivationPath: signPlan.binding.derivation_path ?? ""
699
743
  };
700
744
  if (binding.walletId && (!binding.keyId || !binding.derivationPath)) {
701
- binding = await resolveBinding(post, requestId, creds);
745
+ binding = await resolveBinding(post, requestId2, creds);
702
746
  }
703
747
  const envelopes = buildSwapEnvelopes(signPlan.txs, binding, creds);
704
- await post(`/agent/requests/${requestId}/envelopes`, { envelopes });
748
+ await post(`/agent/requests/${requestId2}/envelopes`, { envelopes });
705
749
  }
706
- async function signX402Request(post, requestId, plan, creds) {
750
+ async function signX402Request(post, requestId2, plan, creds) {
707
751
  let binding = {
708
752
  walletId: plan.binding.wallet_id,
709
753
  keyId: plan.binding.key_id ?? "",
710
754
  derivationPath: plan.binding.derivation_path ?? ""
711
755
  };
712
756
  if (binding.walletId && (!binding.keyId || !binding.derivationPath)) {
713
- binding = await resolveBinding(post, requestId, creds);
757
+ binding = await resolveBinding(post, requestId2, creds);
714
758
  }
715
- const envelope = isSolanaRailX402(plan) ? buildX402SolanaEnvelope(await refreshX402SolanaTx(post, requestId), binding, creds) : buildX402Envelope(
759
+ const envelope = isSolanaRailX402(plan) ? buildX402SolanaEnvelope(await refreshX402SolanaTx(post, requestId2), binding, creds) : buildX402Envelope(
716
760
  plan.typed_data,
717
761
  binding,
718
762
  creds
719
763
  );
720
- await post(`/agent/requests/${requestId}/envelopes`, { envelopes: [envelope] });
764
+ await post(`/agent/requests/${requestId2}/envelopes`, { envelopes: [envelope] });
721
765
  }
722
766
 
723
767
  // src/mcp.ts
@@ -769,7 +813,7 @@ var McpTransport = class {
769
813
  throw error;
770
814
  }
771
815
  }
772
- async post(payload, method, signingSurface) {
816
+ async post(payload2, method, signingSurface) {
773
817
  const response = await this.fetchImpl(this.endpoint, {
774
818
  method: "POST",
775
819
  headers: {
@@ -779,7 +823,7 @@ var McpTransport = class {
779
823
  "mcp-protocol-version": PROTOCOL_VERSION,
780
824
  ...signingSurface ? { "x-paybox-signing-surface": signingSurface } : {}
781
825
  },
782
- body: JSON.stringify(payload)
826
+ body: JSON.stringify(payload2)
783
827
  });
784
828
  const text = await response.text();
785
829
  if (!response.ok) {
@@ -816,6 +860,220 @@ var McpTransport = class {
816
860
  }
817
861
  };
818
862
 
863
+ // src/execution.ts
864
+ import { setTimeout as delay } from "node:timers/promises";
865
+
866
+ // src/plugins/signing.ts
867
+ function supportedSigningAction(value) {
868
+ if (value.operation != null) {
869
+ const operation = value.operation;
870
+ const intent = operation.intent;
871
+ if (operation.type !== "wallet_sign" || value.next_action?.kind !== "sign" || !intent || !["transaction", "solanaTransaction"].includes(intent.op)) return null;
872
+ try {
873
+ if (intent.op === "transaction") eip1559SigningHash(intent.transaction);
874
+ else if (intent.op === "solanaTransaction" && typeof intent.address === "string" && intent.address) deserializeSolanaTx(intent.transactionBase64);
875
+ else return null;
876
+ } catch {
877
+ return null;
878
+ }
879
+ const binding = operation.wallet_id == null ? null : {
880
+ wallet_id: operation.wallet_id,
881
+ key_id: operation.key_id ?? null,
882
+ derivation_path: operation.derivation_path ?? null
883
+ };
884
+ if (binding && (typeof binding.wallet_id !== "string" || binding.key_id !== null && typeof binding.key_id !== "string" || binding.derivation_path !== null && typeof binding.derivation_path !== "string")) return null;
885
+ return { type: "wallet_sign", intent, binding };
886
+ }
887
+ const plan = supportedSigningPlan(value.plan);
888
+ return plan ? { type: "transactions", plan } : null;
889
+ }
890
+ function supportedSigningPlan(value) {
891
+ if (!value || typeof value !== "object") return null;
892
+ const plan = value;
893
+ if (plan.version !== void 0 || plan.schema_version !== void 0 || plan.gasless != null || typeof plan.refresh_before_sign !== "boolean") return null;
894
+ const binding = plan.binding;
895
+ if (!binding || typeof binding.wallet_id !== "string" || !binding.wallet_id || binding.key_id != null && typeof binding.key_id !== "string" || binding.derivation_path != null && typeof binding.derivation_path !== "string" || typeof plan.sender !== "string" || !plan.sender || !Array.isArray(plan.txs) || plan.txs.length === 0) return null;
896
+ try {
897
+ for (const tx of plan.txs) {
898
+ if (!tx || tx.vm !== plan.txs[0].vm) return null;
899
+ if (tx.vm === "solana" && typeof tx.transaction === "string") deserializeSolanaTx(tx.transaction);
900
+ else if (tx.vm === "evm" && tx.transaction && typeof tx.transaction === "object" && !Array.isArray(tx.transaction)) eip1559SigningHash(tx.transaction);
901
+ else return null;
902
+ }
903
+ } catch {
904
+ return null;
905
+ }
906
+ return value;
907
+ }
908
+
909
+ // src/execution.ts
910
+ var UnsupportedPlanError = class extends Error {
911
+ };
912
+ var invocationIdMeta = "com.moonpay.paybox/invocationId";
913
+ var requestIdMeta = "com.moonpay.paybox/requestId";
914
+ function requestId(value) {
915
+ return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value) ? value.toLowerCase() : null;
916
+ }
917
+ function payload(result) {
918
+ const value = result.structuredContent ?? toolJson("plugin execution", { ...result, isError: false });
919
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("invalid response");
920
+ return value;
921
+ }
922
+ var statuses = /* @__PURE__ */ new Set([
923
+ "pending_approval",
924
+ "pending_funding",
925
+ "pending_signature",
926
+ "pending_settlement",
927
+ "pending_confirmation",
928
+ "success",
929
+ "denied",
930
+ "error"
931
+ ]);
932
+ async function executePlugin(start, options, connect) {
933
+ const timeoutMs = options.timeoutMs ?? 3e5;
934
+ const intervalMs = options.intervalMs ?? 2e3;
935
+ if (!Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647 || !Number.isInteger(intervalMs) || intervalMs <= 0 || intervalMs > 3e4) {
936
+ throw new RangeError("timeoutMs must be 1..2147483647 and intervalMs must be 1..30000");
937
+ }
938
+ let id = typeof start === "string" ? requestId(start) : null;
939
+ if (typeof start === "string" && !id) throw new TypeError("requestId must be a UUID");
940
+ let response = null;
941
+ const result = (outcome, reason) => ({
942
+ outcome,
943
+ requestId: id,
944
+ response,
945
+ ...reason ? { reason } : {}
946
+ });
947
+ const controller = new AbortController();
948
+ let stopped = "cancelled";
949
+ const cancel = () => controller.abort();
950
+ options.signal?.addEventListener("abort", cancel, { once: true });
951
+ if (options.signal?.aborted) cancel();
952
+ const timer = setTimeout(() => {
953
+ if (!controller.signal.aborted) {
954
+ stopped = "deadline_exceeded";
955
+ controller.abort();
956
+ }
957
+ }, timeoutMs);
958
+ let onAbort;
959
+ const aborted = new Promise((resolve) => {
960
+ onAbort = () => resolve(result(stopped));
961
+ if (controller.signal.aborted) onAbort();
962
+ else controller.signal.addEventListener("abort", onAbort, { once: true });
963
+ });
964
+ const ports = connect(controller.signal);
965
+ const read = async () => {
966
+ controller.signal.throwIfAborted();
967
+ const next = await ports.getRequest(id);
968
+ controller.signal.throwIfAborted();
969
+ if (!next || requestId(next.request_id) !== id || !statuses.has(next.status)) {
970
+ throw new Error("invalid request response");
971
+ }
972
+ response = pendingFundingResponse(next) ?? next;
973
+ return response;
974
+ };
975
+ const terminal = (current) => {
976
+ if (current.status === "error" || current.status === "denied") return result("terminal");
977
+ if (current.status !== "success") return null;
978
+ const value = current.output?.value;
979
+ const fields = current.output?.output_type === "tx_hash" ? ["tx_hash"] : current.output?.output_type === "signature" ? ["signature", "serializedTransaction", "signedTransactionBase64"] : [];
980
+ return fields.some((field) => typeof value?.[field] === "string" && value[field].trim()) ? result("terminal") : result("unsupported", "success_output_not_supported");
981
+ };
982
+ const drive = async () => {
983
+ try {
984
+ controller.signal.throwIfAborted();
985
+ let toolError = false;
986
+ if (typeof start !== "string") {
987
+ const raw = await ports.callTool("use_plugin", {
988
+ plugin_id: start.pluginId,
989
+ tool_id: start.toolId,
990
+ input: start.input,
991
+ invocation_id: start.invocationId
992
+ });
993
+ controller.signal.throwIfAborted();
994
+ const funding = pendingFundingToolResponse(raw);
995
+ if (funding) {
996
+ response = funding;
997
+ id = requestId(funding.request_id);
998
+ return result("unsupported", "funding_required");
999
+ }
1000
+ let data;
1001
+ try {
1002
+ data = payload(raw);
1003
+ } catch {
1004
+ return result("reconcile_required", raw.isError ? "tool_error" : "invalid_plugin_result");
1005
+ }
1006
+ toolError = raw.isError === true || data.status === "error";
1007
+ const nextId = requestId(data.request_id);
1008
+ if (!nextId) return result(toolError ? "reconcile_required" : "unsupported", toolError ? "tool_error" : "no_request_id");
1009
+ if (requestId(start.pluginId)) {
1010
+ const invocationId = requestId(raw._meta?.[invocationIdMeta]);
1011
+ const expectedInvocationId = requestId(start.invocationId);
1012
+ const boundRequestId = requestId(raw._meta?.[requestIdMeta]);
1013
+ if (!invocationId || start.invocationId !== void 0 && invocationId !== expectedInvocationId || boundRequestId !== nextId) {
1014
+ return result("reconcile_required", "request_id_mismatch");
1015
+ }
1016
+ }
1017
+ id = nextId;
1018
+ }
1019
+ let current = await read();
1020
+ let attempted = false;
1021
+ let pauseMs = intervalMs;
1022
+ for (; ; ) {
1023
+ controller.signal.throwIfAborted();
1024
+ const done = terminal(current);
1025
+ if (done) return done;
1026
+ if (current.status === "pending_funding") return result("unsupported", "funding_required");
1027
+ if (toolError) return result("reconcile_required", "tool_error");
1028
+ if (current.status === "pending_approval" && !options.waitForApproval) {
1029
+ return result("approval_required");
1030
+ }
1031
+ if (current.status === "pending_signature") {
1032
+ if (attempted) return result("reconcile_required", "submission_not_confirmed");
1033
+ if (options.autoSign === false || !ports.sign) return result("signing_required");
1034
+ try {
1035
+ const raw = await ports.callTool("reopen_signing_window", { request_id: id });
1036
+ if (raw.isError) throw new Error("reopen failed");
1037
+ const reopened = payload(raw);
1038
+ if (requestId(reopened.request_id) !== id) return result("unsupported", "request_id_mismatch");
1039
+ current = await read();
1040
+ if (current.status !== "pending_signature") continue;
1041
+ if (reopened.status !== "pending_signature") return result("reconcile_required", "request_changed");
1042
+ const action = supportedSigningAction(reopened);
1043
+ if (!action) return result("unsupported", "signing_plan_not_supported");
1044
+ attempted = true;
1045
+ await ports.sign(id, action, (refreshed) => {
1046
+ controller.signal.throwIfAborted();
1047
+ if (!supportedSigningPlan(refreshed)) throw new UnsupportedPlanError();
1048
+ });
1049
+ } catch (error) {
1050
+ current = await read();
1051
+ const done2 = terminal(current);
1052
+ if (done2) return done2;
1053
+ if (error instanceof UnsupportedPlanError) return result("unsupported", "refreshed_plan_not_supported");
1054
+ if (current.status === "pending_signature") return result("reconcile_required", "signing_interrupted");
1055
+ }
1056
+ current = await read();
1057
+ continue;
1058
+ }
1059
+ await delay(pauseMs, void 0, { signal: controller.signal });
1060
+ const previous = current.status;
1061
+ current = await read();
1062
+ pauseMs = current.status === previous ? Math.min(pauseMs * 2, 3e4) : intervalMs;
1063
+ }
1064
+ } catch {
1065
+ return result(controller.signal.aborted ? stopped : "reconcile_required", "execution_interrupted");
1066
+ }
1067
+ };
1068
+ try {
1069
+ return await Promise.race([drive(), aborted]);
1070
+ } finally {
1071
+ clearTimeout(timer);
1072
+ options.signal?.removeEventListener("abort", cancel);
1073
+ controller.signal.removeEventListener("abort", onAbort);
1074
+ }
1075
+ }
1076
+
819
1077
  // src/client.ts
820
1078
  var DEFAULT_BASE_URL = "https://api.paybox.sh";
821
1079
  var EXPIRY_SKEW_MS = 6e4;
@@ -907,6 +1165,7 @@ var PayboxClient = class _PayboxClient {
907
1165
  );
908
1166
  }
909
1167
  async request(method, path, init = {}) {
1168
+ init.signal?.throwIfAborted();
910
1169
  const url = new URL(this.baseUrl + path);
911
1170
  for (const [k, v] of Object.entries(init.query ?? {})) {
912
1171
  if (v != null) url.searchParams.set(k, v);
@@ -917,8 +1176,10 @@ var PayboxClient = class _PayboxClient {
917
1176
  headers["content-type"] = "application/json";
918
1177
  body = JSON.stringify(init.body);
919
1178
  }
920
- const res = await this.fetchImpl(url, { method, headers, body });
1179
+ init.signal?.throwIfAborted();
1180
+ const res = await this.fetchImpl(url, { method, headers, body, signal: init.signal });
921
1181
  const text = await res.text();
1182
+ init.signal?.throwIfAborted();
922
1183
  if (!res.ok) throw new PayboxError(res.status, text, `${method} ${path}`);
923
1184
  return nonSigningFundingResult(text ? JSON.parse(text) : void 0);
924
1185
  }
@@ -991,21 +1252,21 @@ var PayboxClient = class _PayboxClient {
991
1252
  (r) => r
992
1253
  );
993
1254
  }
994
- async completeWalletSignRequest(requestId) {
1255
+ async completeWalletSignRequest(requestId2) {
995
1256
  const creds = this.signingCreds();
996
1257
  if (!creds) {
997
1258
  throw new Error("cannot complete wallet-sign request without a valid local signing key");
998
1259
  }
999
1260
  const result = await this.mcp.callTool(
1000
1261
  "reopen_signing_window",
1001
- { request_id: requestId },
1262
+ { request_id: requestId2 },
1002
1263
  "in-process"
1003
1264
  );
1004
1265
  const parked = toolJson("reopen_signing_window", result);
1005
- if (parked.request_id !== requestId) {
1266
+ if (parked.request_id !== requestId2) {
1006
1267
  throw new Error("paybox returned a different request_id for the parked signature");
1007
1268
  }
1008
- if (parked.status === "success") return this.getRequest(requestId);
1269
+ if (parked.status === "success") return this.getRequest(requestId2);
1009
1270
  if (parked.status !== "pending_signature") {
1010
1271
  throw new Error(`cannot complete wallet-sign request while it is ${parked.status ?? "unknown"}`);
1011
1272
  }
@@ -1019,10 +1280,10 @@ var PayboxClient = class _PayboxClient {
1019
1280
  derivation_path: parked.operation.derivation_path ?? null
1020
1281
  };
1021
1282
  await this.signWithReconcile(
1022
- requestId,
1023
- () => signWalletRequest(this.poster, requestId, intent, creds, binding)
1283
+ requestId2,
1284
+ () => signWalletRequest(this.poster, requestId2, intent, creds, binding)
1024
1285
  );
1025
- return this.getRequest(requestId);
1286
+ return this.getRequest(requestId2);
1026
1287
  }
1027
1288
  async requestSwap(args, opts = {}) {
1028
1289
  return this.withExpiryRetry(
@@ -1071,12 +1332,12 @@ var PayboxClient = class _PayboxClient {
1071
1332
  await this.requestAfterSign(response.request_id, opts.waitForApproval)
1072
1333
  );
1073
1334
  }
1074
- async waitWhileApproval(requestId, wait) {
1335
+ async waitWhileApproval(requestId2, wait) {
1075
1336
  const o = typeof wait === "object" ? wait : {};
1076
1337
  const interval = o.intervalMs ?? 2e3;
1077
1338
  const deadline = Date.now() + (o.timeoutMs ?? 3e5);
1078
1339
  for (; ; ) {
1079
- const r = await this.getRequest(requestId);
1340
+ const r = await this.getRequest(requestId2);
1080
1341
  if (r.status !== "pending_approval" || Date.now() > deadline) return r;
1081
1342
  await new Promise((res) => setTimeout(res, interval));
1082
1343
  }
@@ -1089,11 +1350,11 @@ var PayboxClient = class _PayboxClient {
1089
1350
  }
1090
1351
  return first;
1091
1352
  }
1092
- async signWithReconcile(requestId, sign) {
1353
+ async signWithReconcile(requestId2, sign) {
1093
1354
  try {
1094
1355
  await sign();
1095
1356
  } catch {
1096
- const reconciled = await this.getRequest(requestId);
1357
+ const reconciled = await this.getRequest(requestId2);
1097
1358
  if (reconciled.status !== "pending_signature") return;
1098
1359
  await sign();
1099
1360
  }
@@ -1145,6 +1406,34 @@ var PayboxClient = class _PayboxClient {
1145
1406
  invocation_id: args.invocationId
1146
1407
  }));
1147
1408
  }
1409
+ runPlugin(args, options = {}) {
1410
+ return this.executePlugin(args, options);
1411
+ }
1412
+ resumeRequest(requestId2, options = {}) {
1413
+ return this.executePlugin(requestId2, options);
1414
+ }
1415
+ executePlugin(start, options) {
1416
+ return executePlugin(start, options, (signal) => {
1417
+ const mcp = new McpTransport({
1418
+ baseUrl: this.baseUrl,
1419
+ bearer: () => this.bearer(),
1420
+ fetchImpl: (input, init) => {
1421
+ signal.throwIfAborted();
1422
+ return this.fetchImpl(input, { ...init, signal });
1423
+ }
1424
+ });
1425
+ const post = (path, body) => this.request("POST", path, { body, signal });
1426
+ const creds = this.signingCreds();
1427
+ return {
1428
+ callTool: (name, args) => mcp.callTool(name, args, name === "reopen_signing_window" ? "in-process" : void 0),
1429
+ getRequest: (id) => this.request("GET", `/agent/requests/${id}`, { signal }),
1430
+ sign: creds ? async (id, action, validate) => {
1431
+ if (action.type === "transactions") await signSwapRequest(post, id, action.plan, creds, validate);
1432
+ else await signWalletRequest(post, id, action.intent, creds, action.binding);
1433
+ } : void 0
1434
+ };
1435
+ });
1436
+ }
1148
1437
  async payX402(args, opts = {}) {
1149
1438
  return this.withExpiryRetry(
1150
1439
  async () => {
@@ -1199,8 +1488,8 @@ var PayboxClient = class _PayboxClient {
1199
1488
  await this.requestAfterSign(response.request_id, opts.waitForApproval)
1200
1489
  );
1201
1490
  }
1202
- claimPaymentCredentials(requestId) {
1203
- return this.request("POST", `/agent/requests/${requestId}/credentials`);
1491
+ claimPaymentCredentials(requestId2) {
1492
+ return this.request("POST", `/agent/requests/${requestId2}/credentials`);
1204
1493
  }
1205
1494
  requestAccountChange(note) {
1206
1495
  return this.request("POST", "/agent/account-change", { body: { note } });
@@ -1223,18 +1512,18 @@ var PayboxClient = class _PayboxClient {
1223
1512
  }
1224
1513
  });
1225
1514
  }
1226
- getRequest(requestId) {
1227
- return this.request("GET", `/agent/requests/${requestId}`);
1515
+ getRequest(requestId2) {
1516
+ return this.request("GET", `/agent/requests/${requestId2}`);
1228
1517
  }
1229
- requestAfterSign(requestId, wait) {
1230
- if (!wait) return this.getRequest(requestId);
1231
- return this.waitForRequest(requestId, typeof wait === "object" ? wait : {});
1518
+ requestAfterSign(requestId2, wait) {
1519
+ if (!wait) return this.getRequest(requestId2);
1520
+ return this.waitForRequest(requestId2, typeof wait === "object" ? wait : {});
1232
1521
  }
1233
- async waitForRequest(requestId, opts = {}) {
1522
+ async waitForRequest(requestId2, opts = {}) {
1234
1523
  const interval = opts.intervalMs ?? 2e3;
1235
1524
  const deadline = Date.now() + (opts.timeoutMs ?? 3e5);
1236
1525
  for (; ; ) {
1237
- const r = await this.getRequest(requestId);
1526
+ const r = await this.getRequest(requestId2);
1238
1527
  const pending = r.status === "pending_approval" || r.status === "pending_funding" || r.status === "pending_signature" || r.status === "pending_settlement" || r.status === "pending_confirmation";
1239
1528
  if (!pending || Date.now() > deadline) return r;
1240
1529
  await new Promise((res) => setTimeout(res, interval));
@@ -1262,4 +1551,4 @@ export {
1262
1551
  PayboxError,
1263
1552
  PayboxClient
1264
1553
  };
1265
- //# sourceMappingURL=chunk-OZ7KVOBT.js.map
1554
+ //# sourceMappingURL=chunk-YTHYNUMM.js.map