@bosonprotocol/x402-client 0.1.1-alpha-1 → 0.2.0-alpha-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.
@@ -1,7 +1,7 @@
1
1
  import { P as Policy, X as X402bClientConfig, E as ExchangeSummary, S as Signer } from './types-DLOroMb1.js';
2
2
  export { F as FulfillmentConfig, R as RedeemMode, T as TokenDomainResolver } from './types-DLOroMb1.js';
3
- import { EscrowPaymentRequirements, BosonCommitActionId, BosonMetaTx, Hex as Hex$1 } from '@bosonprotocol/x402-core/schemes/escrow';
4
- import { ActionId } from '@bosonprotocol/x402-core/state-machine';
3
+ import { EscrowPaymentRequirements, BosonCommitActionId, BosonMetaTx, Hex as Hex$1, NextAction, EscrowNextActions } from '@bosonprotocol/x402-core/schemes/escrow';
4
+ import { ActionId, ExchangeState, DisputeState } from '@bosonprotocol/x402-core/state-machine';
5
5
  import { Address, Hex } from 'viem';
6
6
  import '@bosonprotocol/x402-core/eip712/token-auth';
7
7
 
@@ -28,6 +28,11 @@ declare class MaxAmountExceededError extends Error {
28
28
  */
29
29
  declare function pickAction(requirements: EscrowPaymentRequirements, policy?: Policy): BosonCommitActionId;
30
30
 
31
+ /** Decode a base64-encoded string to UTF-8. */
32
+ declare function decodeBase64(value: string): string;
33
+ /** Encode a UTF-8 string as base64. */
34
+ declare function encodeBase64(value: string): string;
35
+
31
36
  interface ResolvedFulfillment {
32
37
  option: string;
33
38
  /**
@@ -121,6 +126,84 @@ interface SignedPostCommitAction {
121
126
  signedPayload: Hex$1;
122
127
  }
123
128
 
129
+ /** Channels this submitter drives over HTTP. */
130
+ type SubmitChannel = "server" | "facilitator";
131
+ /**
132
+ * Why a channel attempt didn't yield a 2xx. `"no-endpoint"` is a
133
+ * configuration gap (channel advertised, but no URL listed under
134
+ * `action.endpoints`) — distinct from a real transport-level
135
+ * `"network"` failure so callers branching on `reason` can tell the
136
+ * two apart. `"invalid-response"` covers 2xx replies whose body
137
+ * doesn't match the channel's expected shape — the server replied
138
+ * but with something we can't make sense of, treated as a
139
+ * recoverable failure (the next channel is tried).
140
+ */
141
+ type ChannelFailureReason = "5xx" | "4xx" | "network" | "timeout" | "no-endpoint" | "invalid-response";
142
+ /** Per-channel attempt record — every walk-step appended to `attempts[]`. */
143
+ type ChannelAttempt = {
144
+ channel: SubmitChannel;
145
+ ok: true;
146
+ status: number;
147
+ } | {
148
+ channel: SubmitChannel;
149
+ ok: false;
150
+ reason: ChannelFailureReason;
151
+ status?: number;
152
+ message?: string;
153
+ };
154
+ /** Caller passes `{ option, data }` for the redeem-only fulfillment payload. */
155
+ interface FulfillmentRequest {
156
+ option: string;
157
+ data: Record<string, unknown> | null;
158
+ }
159
+ interface SubmitArgs {
160
+ action: NextAction;
161
+ signed: SignedPostCommitAction;
162
+ exchangeId: string;
163
+ /** CAIP-2 (e.g. `"eip155:31337"`). Required by the facilitator route. */
164
+ network: string;
165
+ /** Escrow contract address. Required by the facilitator route. */
166
+ escrowAddress: Address;
167
+ /** Redeem-only — forwarded to the `server` channel body; ignored by `facilitator`. */
168
+ fulfillment?: FulfillmentRequest;
169
+ /** Defaults to `globalThis.fetch`. */
170
+ fetch?: typeof globalThis.fetch;
171
+ /** Per-channel timeout in milliseconds. Defaults to 10000. */
172
+ timeoutMs?: number;
173
+ }
174
+ interface SubmitResult {
175
+ txHash: Hex;
176
+ newExchangeState: ExchangeState;
177
+ newDisputeState?: DisputeState;
178
+ /** Present only when the `server` channel handled the action. */
179
+ nextActions?: EscrowNextActions;
180
+ channelUsed: SubmitChannel;
181
+ attempts: readonly ChannelAttempt[];
182
+ }
183
+ /** Thrown when no advertised channel matches one this submitter can drive. */
184
+ declare class NoCompatibleChannelError extends Error {
185
+ readonly actionId: string;
186
+ readonly advertisedChannels: readonly string[];
187
+ constructor(actionId: string, advertisedChannels: readonly string[]);
188
+ }
189
+ /**
190
+ * Thrown when every attempted channel failed. Carries the per-channel
191
+ * attempt log so callers can branch on the final cause (e.g. 4xx from
192
+ * the server → buyer payload bug; 5xx from both → outage).
193
+ */
194
+ declare class AllChannelsFailedError extends Error {
195
+ readonly attempts: readonly ChannelAttempt[];
196
+ constructor(actionId: string, attempts: readonly ChannelAttempt[]);
197
+ }
198
+ /**
199
+ * Submit a signed post-commit action through the first responsive HTTP
200
+ * channel advertised on `action.channels`. Returns the normalized result
201
+ * on first 2xx; throws `NoCompatibleChannelError` when no submittable
202
+ * channel is advertised, or `AllChannelsFailedError` when every attempt
203
+ * failed.
204
+ */
205
+ declare function submitAction(args: SubmitArgs): Promise<SubmitResult>;
206
+
124
207
  type BigNumberish = string | number | bigint;
125
208
  /**
126
209
  * Resolution targets accepted by the "withdraw all" helper. Either
@@ -165,6 +248,27 @@ interface SignedWithdrawFunds {
165
248
  tokenAmounts: readonly string[];
166
249
  }
167
250
 
251
+ /**
252
+ * Args for `client.submitAction`. Layered over `SignActionArgs`: the
253
+ * client signs the meta-tx, then resolves the matching `NextAction`
254
+ * entry on `priorNextActions` and walks its `channels[]` (server →
255
+ * facilitator) until the first 2xx. See `submit.ts` for the channel
256
+ * walk semantics; see `signAction` for the signing args.
257
+ */
258
+ type SubmitActionArgs = SignActionArgs & {
259
+ /**
260
+ * The `nextActions` envelope returned by the prior server response.
261
+ * Used to read `channels[]` + `endpoints[channel]` for the entry
262
+ * matching `actionId`.
263
+ */
264
+ priorNextActions: EscrowNextActions;
265
+ /** Redeem-only fulfillment payload — forwarded to the `server` channel body. */
266
+ fulfillment?: FulfillmentRequest;
267
+ /** Override the default `globalThis.fetch`. Useful for tests / custom transports. */
268
+ fetch?: typeof globalThis.fetch;
269
+ /** Per-channel timeout in milliseconds. Default 10000. */
270
+ timeoutMs?: number;
271
+ };
168
272
  interface X402bClient {
169
273
  /**
170
274
  * Consume a parsed escrow PaymentRequirements and return the base64
@@ -188,6 +292,25 @@ interface X402bClient {
188
292
  * of MVP.
189
293
  */
190
294
  signAction(args: SignActionArgs): Promise<SignedPostCommitAction>;
295
+ /**
296
+ * Sign a buyer post-commit action via {@link X402bClient.signAction} and
297
+ * submit it through the first responsive HTTP channel the seller
298
+ * advertised on the matching `nextActions.next[]` entry. Order is taken
299
+ * from `priorNextActions` (the envelope from the prior server response);
300
+ * the walk is intersected with `["server", "facilitator"]` — `onchain` /
301
+ * `mcp` / `xmtp` channels are out of scope for this method.
302
+ *
303
+ * Falls back to the next channel on **5xx / network error / timeout**.
304
+ * Stops and throws on **4xx** (a buyer-side payload error fallback
305
+ * can't fix — masking it would hide bugs). Throws
306
+ * `NoCompatibleChannelError` when the matching entry advertises only
307
+ * non-HTTP channels, and `AllChannelsFailedError` when every attempt
308
+ * failed.
309
+ *
310
+ * Pre-existing callers that prefer to keep submission outside the SDK
311
+ * can still use `signAction` + their own dispatch.
312
+ */
313
+ submitAction(args: SubmitActionArgs): Promise<SubmitResult>;
191
314
  /**
192
315
  * Sign a `withdrawFunds(entityId, tokenList, tokenAmounts)` meta-tx.
193
316
  * Caller-resolved entity + tokens snapshot — see
@@ -237,4 +360,4 @@ interface Web3LibAdapterLike {
237
360
  */
238
361
  declare function signerFromEthersAdapter(adapter: Web3LibAdapterLike): Signer;
239
362
 
240
- export { ExchangeSummary, FulfillmentValidationError, MaxAmountExceededError, NoCompatibleActionError, Policy, type ResolveDisputeArgs, type ResolvedFulfillment, type SignActionArgs, type SignWithdrawAllAvailableFundsArgs, type SignWithdrawFundsArgs, type SignedPostCommitAction, type SignedWithdrawFunds, Signer, type SimplePostCommitArgs, UnsupportedSchemeError, UnsupportedTokenAuthError, type Web3LibAdapterLike, type WithdrawEntitySelector, type X402bClient, X402bClientConfig, createX402bClient, parseChainId, parsePaymentResponse, pickAction, resolveFulfillment, signerFromEthersAdapter };
363
+ export { AllChannelsFailedError, type ChannelAttempt, type ChannelFailureReason, ExchangeSummary, type FulfillmentRequest, FulfillmentValidationError, MaxAmountExceededError, NoCompatibleActionError, NoCompatibleChannelError, Policy, type ResolveDisputeArgs, type ResolvedFulfillment, type SignActionArgs, type SignWithdrawAllAvailableFundsArgs, type SignWithdrawFundsArgs, type SignedPostCommitAction, type SignedWithdrawFunds, Signer, type SimplePostCommitArgs, type SubmitActionArgs, type SubmitArgs, type SubmitChannel, type SubmitResult, UnsupportedSchemeError, UnsupportedTokenAuthError, type Web3LibAdapterLike, type WithdrawEntitySelector, type X402bClient, X402bClientConfig, createX402bClient, decodeBase64, encodeBase64, parseChainId, parsePaymentResponse, pickAction, resolveFulfillment, signerFromEthersAdapter, submitAction };
package/dist/cjs/index.js CHANGED
@@ -4,6 +4,7 @@ var Ajv = require('ajv');
4
4
  var coreSdk = require('@bosonprotocol/core-sdk');
5
5
  var escrow = require('@bosonprotocol/x402-core/schemes/escrow');
6
6
  var codec = require('@bosonprotocol/x402-evm/codec');
7
+ var stateMachine = require('@bosonprotocol/x402-core/state-machine');
7
8
  var viem = require('viem');
8
9
  var tokenAuth = require('@bosonprotocol/x402-core/eip712/token-auth');
9
10
 
@@ -72,6 +73,30 @@ function pickAction(requirements, policy) {
72
73
  `no commit-time action ('${FLOW_A}' or '${FLOW_B}') with 'server' channel found in requirements.actions.next`
73
74
  );
74
75
  }
76
+
77
+ // src/base64.ts
78
+ function decodeBase64(value) {
79
+ if (typeof Buffer !== "undefined") {
80
+ return Buffer.from(value, "base64").toString("utf8");
81
+ }
82
+ const binary = atob(value);
83
+ const bytes = new Uint8Array(binary.length);
84
+ for (let i = 0; i < binary.length; i++) {
85
+ bytes[i] = binary.charCodeAt(i);
86
+ }
87
+ return new TextDecoder().decode(bytes);
88
+ }
89
+ function encodeBase64(value) {
90
+ if (typeof Buffer !== "undefined") {
91
+ return Buffer.from(value, "utf8").toString("base64");
92
+ }
93
+ const bytes = new TextEncoder().encode(value);
94
+ let binary = "";
95
+ for (const b of bytes) {
96
+ binary += String.fromCharCode(b);
97
+ }
98
+ return btoa(binary);
99
+ }
75
100
  function resolveFulfillment(requirements, config) {
76
101
  const required = requirements.fulfillment?.required ?? false;
77
102
  if (!required) {
@@ -244,17 +269,6 @@ function isClientStateShape(v) {
244
269
  }
245
270
  return true;
246
271
  }
247
- function decodeBase64(value) {
248
- if (typeof Buffer !== "undefined") {
249
- return Buffer.from(value, "base64").toString("utf8");
250
- }
251
- const binary = atob(value);
252
- const bytes = new Uint8Array(binary.length);
253
- for (let i = 0; i < binary.length; i++) {
254
- bytes[i] = binary.charCodeAt(i);
255
- }
256
- return new TextDecoder().decode(bytes);
257
- }
258
272
  function pickString(obj, keys) {
259
273
  for (const key of keys) {
260
274
  const v = obj[key];
@@ -297,16 +311,7 @@ function assemblePayload({
297
311
  }
298
312
  function assembleAndEncodePayload(args) {
299
313
  const payload = assemblePayload(args);
300
- const json = JSON.stringify(payload);
301
- if (typeof Buffer !== "undefined") {
302
- return Buffer.from(json, "utf8").toString("base64");
303
- }
304
- const bytes = new TextEncoder().encode(json);
305
- let binary = "";
306
- for (const b of bytes) {
307
- binary += String.fromCharCode(b);
308
- }
309
- return btoa(binary);
314
+ return encodeBase64(JSON.stringify(payload));
310
315
  }
311
316
 
312
317
  // src/utils/crypto.ts
@@ -425,6 +430,235 @@ async function callSignMetaTx(coreSdk, args, nonce) {
425
430
  }
426
431
  }
427
432
  }
433
+ var SUBMIT_CHANNELS = ["server", "facilitator"];
434
+ var NoCompatibleChannelError = class extends Error {
435
+ constructor(actionId, advertisedChannels) {
436
+ super(
437
+ `x402-client: action '${actionId}' advertises channels [${advertisedChannels.join(", ")}] but none are submittable over HTTP (server / facilitator).`
438
+ );
439
+ this.name = "NoCompatibleChannelError";
440
+ this.actionId = actionId;
441
+ this.advertisedChannels = advertisedChannels;
442
+ }
443
+ };
444
+ var AllChannelsFailedError = class extends Error {
445
+ constructor(actionId, attempts) {
446
+ super(
447
+ `x402-client: action '${actionId}' failed on every attempted channel \u2014 ${attempts.map((a) => formatAttempt(a)).join("; ")}`
448
+ );
449
+ this.name = "AllChannelsFailedError";
450
+ this.attempts = attempts;
451
+ }
452
+ };
453
+ function formatAttempt(a) {
454
+ if (a.ok) return `${a.channel}=ok(${a.status})`;
455
+ const tail = a.status !== void 0 ? `(${a.status})` : "";
456
+ return `${a.channel}=${a.reason}${tail}`;
457
+ }
458
+ async function submitAction(args) {
459
+ const fetcher = args.fetch ?? globalThis.fetch.bind(globalThis);
460
+ const timeoutMs = args.timeoutMs ?? 1e4;
461
+ const ordered = orderedChannels(args.action);
462
+ if (ordered.length === 0) {
463
+ throw new NoCompatibleChannelError(args.action.id, args.action.channels);
464
+ }
465
+ const attempts = [];
466
+ for (const channel of ordered) {
467
+ const endpoint = args.action.endpoints?.[channel];
468
+ if (endpoint === void 0) {
469
+ attempts.push({
470
+ channel,
471
+ ok: false,
472
+ reason: "no-endpoint",
473
+ message: `no endpoint advertised for channel '${channel}'`
474
+ });
475
+ continue;
476
+ }
477
+ const outcome = await attemptChannel({
478
+ channel,
479
+ endpoint,
480
+ args,
481
+ fetcher,
482
+ timeoutMs
483
+ });
484
+ attempts.push(outcome.attempt);
485
+ if (outcome.attempt.ok && outcome.result !== void 0) {
486
+ return { ...outcome.result, attempts };
487
+ }
488
+ if (!outcome.attempt.ok && outcome.attempt.reason === "4xx") {
489
+ throw new AllChannelsFailedError(args.action.id, attempts);
490
+ }
491
+ }
492
+ throw new AllChannelsFailedError(args.action.id, attempts);
493
+ }
494
+ function orderedChannels(action) {
495
+ const seen = /* @__PURE__ */ new Set();
496
+ const out = [];
497
+ for (const c of action.channels) {
498
+ if (SUBMIT_CHANNELS.includes(c) && !seen.has(c)) {
499
+ seen.add(c);
500
+ out.push(c);
501
+ }
502
+ }
503
+ return out;
504
+ }
505
+ async function attemptChannel(input) {
506
+ const { channel, endpoint, args, fetcher, timeoutMs } = input;
507
+ const body = channel === "server" ? buildServerBody(args) : buildFacilitatorBody(args);
508
+ let res;
509
+ try {
510
+ res = await fetchWithTimeout(fetcher, endpoint, body, timeoutMs);
511
+ } catch (e) {
512
+ const reason = isTimeout(e) ? "timeout" : "network";
513
+ return {
514
+ attempt: {
515
+ channel,
516
+ ok: false,
517
+ reason,
518
+ message: e instanceof Error ? e.message : String(e)
519
+ }
520
+ };
521
+ }
522
+ const parsed = await res.json().catch(() => null);
523
+ if (res.status >= 500) {
524
+ return {
525
+ attempt: { channel, ok: false, reason: "5xx", status: res.status }
526
+ };
527
+ }
528
+ if (!res.ok) {
529
+ return {
530
+ attempt: { channel, ok: false, reason: "4xx", status: res.status }
531
+ };
532
+ }
533
+ if (parsed === null || typeof parsed !== "object") {
534
+ return {
535
+ attempt: {
536
+ channel,
537
+ ok: false,
538
+ reason: "invalid-response",
539
+ status: res.status,
540
+ message: "response body is not a JSON object"
541
+ }
542
+ };
543
+ }
544
+ try {
545
+ const result = channel === "server" ? parseServerResult(parsed) : parseFacilitatorResult(parsed);
546
+ return {
547
+ attempt: { channel, ok: true, status: res.status },
548
+ result: { ...result, channelUsed: channel }
549
+ };
550
+ } catch (e) {
551
+ return {
552
+ attempt: {
553
+ channel,
554
+ ok: false,
555
+ reason: "invalid-response",
556
+ status: res.status,
557
+ message: e instanceof Error ? e.message : String(e)
558
+ }
559
+ };
560
+ }
561
+ }
562
+ function buildServerBody(args) {
563
+ const body = {
564
+ exchangeId: args.exchangeId,
565
+ signedPayload: args.signed.signedPayload
566
+ };
567
+ if (args.action.id === "boson-redeem" && args.fulfillment !== void 0) {
568
+ body.fulfillment = args.fulfillment;
569
+ }
570
+ return body;
571
+ }
572
+ function buildFacilitatorBody(args) {
573
+ return {
574
+ action: args.action.id,
575
+ exchangeId: args.exchangeId,
576
+ network: args.network,
577
+ escrowAddress: args.escrowAddress,
578
+ signedPayload: args.signed.signedPayload
579
+ };
580
+ }
581
+ async function fetchWithTimeout(fetcher, endpoint, body, timeoutMs) {
582
+ const controller = new AbortController();
583
+ const timer = setTimeout(() => controller.abort(new TimeoutError(timeoutMs)), timeoutMs);
584
+ try {
585
+ return await fetcher(endpoint, {
586
+ method: "POST",
587
+ headers: { "content-type": "application/json" },
588
+ body: JSON.stringify(body),
589
+ signal: controller.signal
590
+ });
591
+ } finally {
592
+ clearTimeout(timer);
593
+ }
594
+ }
595
+ var TimeoutError = class extends Error {
596
+ constructor(timeoutMs) {
597
+ super(`x402-client/submit: channel attempt timed out after ${timeoutMs}ms`);
598
+ this.isTimeout = true;
599
+ this.name = "TimeoutError";
600
+ }
601
+ };
602
+ function isTimeout(e) {
603
+ if (e instanceof TimeoutError) return true;
604
+ if (typeof e !== "object" || e === null) return false;
605
+ const obj = e;
606
+ if (obj.isTimeout === true) return true;
607
+ if (obj.name === "AbortError" || obj.name === "TimeoutError") return true;
608
+ if (typeof obj.cause === "object" && obj.cause !== null) {
609
+ const cause = obj.cause;
610
+ if (cause.isTimeout === true) return true;
611
+ if (cause.name === "TimeoutError") return true;
612
+ }
613
+ return false;
614
+ }
615
+ function parseServerResult(body) {
616
+ if (typeof body !== "object" || body === null) {
617
+ throw new Error("server response body is not an object");
618
+ }
619
+ const raw = body;
620
+ const txHash = raw.txHash;
621
+ const exchangeState = raw.nextActions?.exchangeState;
622
+ if (!isHexHash(txHash) || !isExchangeState(exchangeState)) {
623
+ throw new Error("server response missing txHash or nextActions.exchangeState");
624
+ }
625
+ const out = {
626
+ txHash,
627
+ newExchangeState: exchangeState,
628
+ nextActions: raw.nextActions
629
+ };
630
+ if (isDisputeState(raw.nextActions?.disputeState)) {
631
+ out.newDisputeState = raw.nextActions.disputeState;
632
+ }
633
+ return out;
634
+ }
635
+ function parseFacilitatorResult(body) {
636
+ if (typeof body !== "object" || body === null) {
637
+ throw new Error("facilitator response body is not an object");
638
+ }
639
+ const raw = body;
640
+ if (raw.ok !== true || !isHexHash(raw.txHash) || !isExchangeState(raw.newExchangeState)) {
641
+ throw new Error("facilitator response missing ok/txHash/newExchangeState");
642
+ }
643
+ const out = {
644
+ txHash: raw.txHash,
645
+ newExchangeState: raw.newExchangeState
646
+ };
647
+ if (isDisputeState(raw.newDisputeState)) {
648
+ out.newDisputeState = raw.newDisputeState;
649
+ }
650
+ return out;
651
+ }
652
+ var TX_HASH_RE = /^0x[0-9a-fA-F]{64}$/;
653
+ function isHexHash(v) {
654
+ return typeof v === "string" && TX_HASH_RE.test(v);
655
+ }
656
+ function isExchangeState(v) {
657
+ return typeof v === "string" && Object.values(stateMachine.ExchangeState).includes(v);
658
+ }
659
+ function isDisputeState(v) {
660
+ return typeof v === "string" && Object.values(stateMachine.DisputeState).includes(v);
661
+ }
428
662
  function normalizeEntityId(value) {
429
663
  if (typeof value === "bigint") {
430
664
  if (value < 0n) throw new Error(`entityId must be non-negative, got ${value.toString()}`);
@@ -848,6 +1082,26 @@ function createX402bClient(config) {
848
1082
  signAction(args) {
849
1083
  return signPostCommitAction(args, { buildCoreSdk, getBuyerAddress });
850
1084
  },
1085
+ async submitAction(args) {
1086
+ const signed = await signPostCommitAction(args, { buildCoreSdk, getBuyerAddress });
1087
+ const action = args.priorNextActions.next.find((entry) => entry.id === args.actionId);
1088
+ if (action === void 0) {
1089
+ throw new Error(
1090
+ `x402-client/submitAction: actionId '${args.actionId}' is not present in priorNextActions.next[]`
1091
+ );
1092
+ }
1093
+ const submitArgs = {
1094
+ action,
1095
+ signed,
1096
+ exchangeId: String(args.exchangeId),
1097
+ network: args.network,
1098
+ escrowAddress: args.escrowAddress,
1099
+ fulfillment: args.fulfillment,
1100
+ fetch: args.fetch,
1101
+ timeoutMs: args.timeoutMs
1102
+ };
1103
+ return submitAction(submitArgs);
1104
+ },
851
1105
  signWithdrawFunds(args) {
852
1106
  return signWithdrawFunds(args, { buildCoreSdk, getSignerAddress: getBuyerAddress });
853
1107
  },
@@ -908,16 +1162,21 @@ function deriveEip712DomainType(domain) {
908
1162
  return fields;
909
1163
  }
910
1164
 
1165
+ exports.AllChannelsFailedError = AllChannelsFailedError;
911
1166
  exports.FulfillmentValidationError = FulfillmentValidationError;
912
1167
  exports.MaxAmountExceededError = MaxAmountExceededError;
913
1168
  exports.NoCompatibleActionError = NoCompatibleActionError;
1169
+ exports.NoCompatibleChannelError = NoCompatibleChannelError;
914
1170
  exports.UnsupportedSchemeError = UnsupportedSchemeError;
915
1171
  exports.UnsupportedTokenAuthError = UnsupportedTokenAuthError;
916
1172
  exports.createX402bClient = createX402bClient;
1173
+ exports.decodeBase64 = decodeBase64;
1174
+ exports.encodeBase64 = encodeBase64;
917
1175
  exports.parseChainId = parseChainId;
918
1176
  exports.parsePaymentResponse = parsePaymentResponse;
919
1177
  exports.pickAction = pickAction;
920
1178
  exports.resolveFulfillment = resolveFulfillment;
921
1179
  exports.signerFromEthersAdapter = signerFromEthersAdapter;
1180
+ exports.submitAction = submitAction;
922
1181
  //# sourceMappingURL=index.js.map
923
1182
  //# sourceMappingURL=index.js.map