moltspay 0.8.14 → 0.9.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/dist/index.js CHANGED
@@ -2905,7 +2905,7 @@ function alphabet(letters) {
2905
2905
  };
2906
2906
  }
2907
2907
  // @__NO_SIDE_EFFECTS__
2908
- function join4(separator = "") {
2908
+ function join5(separator = "") {
2909
2909
  astr("join", separator);
2910
2910
  return {
2911
2911
  encode: (from) => {
@@ -3112,10 +3112,10 @@ var init_esm = __esm({
3112
3112
  convertRadix2,
3113
3113
  radix,
3114
3114
  radix2,
3115
- join: join4,
3115
+ join: join5,
3116
3116
  padding
3117
3117
  };
3118
- genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join4(""));
3118
+ genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join5(""));
3119
3119
  base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
3120
3120
  createBase58check = (sha2566) => /* @__PURE__ */ chain(checksum(4, (data) => sha2566(sha2566(data))), base58);
3121
3121
  }
@@ -3263,14 +3263,14 @@ var init_esm2 = __esm({
3263
3263
  }
3264
3264
  this.pubHash = hash160(this.pubKey);
3265
3265
  }
3266
- derive(path3) {
3267
- if (!/^[mM]'?/.test(path3)) {
3266
+ derive(path4) {
3267
+ if (!/^[mM]'?/.test(path4)) {
3268
3268
  throw new Error('Path must start with "m" or "M"');
3269
3269
  }
3270
- if (/^[mM]'?$/.test(path3)) {
3270
+ if (/^[mM]'?$/.test(path4)) {
3271
3271
  return this;
3272
3272
  }
3273
- const parts = path3.replace(/^[mM]'?\//, "").split("/");
3273
+ const parts = path4.replace(/^[mM]'?\//, "").split("/");
3274
3274
  let child = this;
3275
3275
  for (const c of parts) {
3276
3276
  const m = /^(\d+)('?)$/.exec(c);
@@ -9631,8 +9631,8 @@ var init_privateKeyToAccount = __esm({
9631
9631
  });
9632
9632
 
9633
9633
  // node_modules/viem/_esm/accounts/hdKeyToAccount.js
9634
- function hdKeyToAccount(hdKey_, { accountIndex = 0, addressIndex = 0, changeIndex = 0, path: path3, ...options } = {}) {
9635
- const hdKey = hdKey_.derive(path3 || `m/44'/60'/${accountIndex}'/${changeIndex}/${addressIndex}`);
9634
+ function hdKeyToAccount(hdKey_, { accountIndex = 0, addressIndex = 0, changeIndex = 0, path: path4, ...options } = {}) {
9635
+ const hdKey = hdKey_.derive(path4 || `m/44'/60'/${accountIndex}'/${changeIndex}/${addressIndex}`);
9636
9636
  const account = privateKeyToAccount(toHex(hdKey.privateKey), options);
9637
9637
  return {
9638
9638
  ...account,
@@ -30342,15 +30342,20 @@ var init_accounts = __esm({
30342
30342
  // src/index.ts
30343
30343
  var index_exports = {};
30344
30344
  __export(index_exports, {
30345
+ BaseFacilitator: () => BaseFacilitator,
30346
+ CDPFacilitator: () => CDPFacilitator,
30345
30347
  CDPWallet: () => CDPWallet,
30346
30348
  CHAINS: () => CHAINS,
30347
30349
  ERC20_ABI: () => ERC20_ABI,
30350
+ FacilitatorRegistry: () => FacilitatorRegistry,
30348
30351
  MoltsPayClient: () => MoltsPayClient,
30349
30352
  MoltsPayServer: () => MoltsPayServer,
30353
+ createRegistry: () => createRegistry,
30350
30354
  createWallet: () => createWallet,
30351
30355
  getCDPWalletAddress: () => getCDPWalletAddress,
30352
30356
  getChain: () => getChain,
30353
30357
  getChainById: () => getChainById,
30358
+ getDefaultRegistry: () => getDefaultRegistry,
30354
30359
  getTransactionStatus: () => getTransactionStatus,
30355
30360
  getWalletAddress: () => getWalletAddress,
30356
30361
  initCDPWallet: () => initCDPWallet,
@@ -30367,20 +30372,478 @@ init_cjs_shims();
30367
30372
 
30368
30373
  // src/server/index.ts
30369
30374
  init_cjs_shims();
30370
- var import_fs = require("fs");
30375
+ var import_fs2 = require("fs");
30371
30376
  var import_http = require("http");
30377
+ var path2 = __toESM(require("path"));
30378
+
30379
+ // src/facilitators/index.ts
30380
+ init_cjs_shims();
30381
+
30382
+ // src/facilitators/interface.ts
30383
+ init_cjs_shims();
30384
+ var BaseFacilitator = class {
30385
+ supportsNetwork(network) {
30386
+ return this.supportedNetworks.includes(network);
30387
+ }
30388
+ };
30389
+
30390
+ // src/facilitators/cdp.ts
30391
+ init_cjs_shims();
30392
+ var import_fs = require("fs");
30372
30393
  var path = __toESM(require("path"));
30394
+ var X402_VERSION = 2;
30395
+ var CDP_MAINNET_URL = "https://api.cdp.coinbase.com/platform/v2/x402";
30396
+ var CDP_TESTNET_URL = "https://www.x402.org/facilitator";
30397
+ function loadEnvFile() {
30398
+ const envPaths = [
30399
+ path.join(process.cwd(), ".env"),
30400
+ path.join(process.env.HOME || "", ".moltspay", ".env")
30401
+ ];
30402
+ for (const envPath of envPaths) {
30403
+ if ((0, import_fs.existsSync)(envPath)) {
30404
+ try {
30405
+ const content = (0, import_fs.readFileSync)(envPath, "utf-8");
30406
+ for (const line of content.split("\n")) {
30407
+ const trimmed = line.trim();
30408
+ if (!trimmed || trimmed.startsWith("#")) continue;
30409
+ const eqIndex = trimmed.indexOf("=");
30410
+ if (eqIndex === -1) continue;
30411
+ const key = trimmed.slice(0, eqIndex).trim();
30412
+ let value = trimmed.slice(eqIndex + 1).trim();
30413
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
30414
+ value = value.slice(1, -1);
30415
+ }
30416
+ if (!process.env[key]) {
30417
+ process.env[key] = value;
30418
+ }
30419
+ }
30420
+ break;
30421
+ } catch {
30422
+ }
30423
+ }
30424
+ }
30425
+ }
30426
+ var CDPFacilitator = class extends BaseFacilitator {
30427
+ name = "cdp";
30428
+ displayName = "Coinbase CDP";
30429
+ supportedNetworks;
30430
+ endpoint;
30431
+ useMainnet;
30432
+ apiKeyId;
30433
+ apiKeySecret;
30434
+ constructor(config = {}) {
30435
+ super();
30436
+ loadEnvFile();
30437
+ this.useMainnet = config.useMainnet ?? process.env.USE_MAINNET?.toLowerCase() === "true";
30438
+ this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
30439
+ this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
30440
+ this.endpoint = this.useMainnet ? CDP_MAINNET_URL : CDP_TESTNET_URL;
30441
+ this.supportedNetworks = this.useMainnet ? ["eip155:8453"] : ["eip155:8453", "eip155:84532"];
30442
+ if (this.useMainnet && (!this.apiKeyId || !this.apiKeySecret)) {
30443
+ console.warn("[CDPFacilitator] WARNING: Mainnet mode but missing CDP credentials!");
30444
+ console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
30445
+ }
30446
+ }
30447
+ /**
30448
+ * Get auth headers for CDP API requests
30449
+ */
30450
+ async getAuthHeaders(method, urlPath, body) {
30451
+ if (!this.useMainnet) {
30452
+ return {};
30453
+ }
30454
+ if (!this.apiKeyId || !this.apiKeySecret) {
30455
+ throw new Error("CDP credentials required for mainnet");
30456
+ }
30457
+ try {
30458
+ const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
30459
+ return await getAuthHeaders({
30460
+ apiKeyId: this.apiKeyId,
30461
+ apiKeySecret: this.apiKeySecret,
30462
+ requestMethod: method,
30463
+ requestHost: "api.cdp.coinbase.com",
30464
+ requestPath: urlPath,
30465
+ requestBody: body
30466
+ });
30467
+ } catch (err) {
30468
+ throw new Error(`Failed to generate CDP auth: ${err.message}`);
30469
+ }
30470
+ }
30471
+ /**
30472
+ * Health check - verify facilitator is reachable
30473
+ */
30474
+ async healthCheck() {
30475
+ const start = Date.now();
30476
+ try {
30477
+ const controller = new AbortController();
30478
+ const timeout = setTimeout(() => controller.abort(), 5e3);
30479
+ const response = await fetch(this.endpoint.replace("/x402", ""), {
30480
+ method: "HEAD",
30481
+ signal: controller.signal
30482
+ }).catch(() => null);
30483
+ clearTimeout(timeout);
30484
+ const latencyMs = Date.now() - start;
30485
+ return {
30486
+ healthy: response !== null,
30487
+ latencyMs
30488
+ };
30489
+ } catch (err) {
30490
+ return {
30491
+ healthy: false,
30492
+ error: err.message,
30493
+ latencyMs: Date.now() - start
30494
+ };
30495
+ }
30496
+ }
30497
+ /**
30498
+ * Verify payment signature with facilitator
30499
+ */
30500
+ async verify(paymentPayload, requirements) {
30501
+ try {
30502
+ const requestBody = {
30503
+ x402Version: X402_VERSION,
30504
+ paymentPayload,
30505
+ paymentRequirements: requirements
30506
+ };
30507
+ const headers = {
30508
+ "Content-Type": "application/json"
30509
+ };
30510
+ if (this.useMainnet) {
30511
+ const authHeaders = await this.getAuthHeaders(
30512
+ "POST",
30513
+ "/platform/v2/x402/verify",
30514
+ requestBody
30515
+ );
30516
+ Object.assign(headers, authHeaders);
30517
+ }
30518
+ const response = await fetch(`${this.endpoint}/verify`, {
30519
+ method: "POST",
30520
+ headers,
30521
+ body: JSON.stringify(requestBody)
30522
+ });
30523
+ const result = await response.json();
30524
+ if (!response.ok || !result.isValid) {
30525
+ return {
30526
+ valid: false,
30527
+ error: result.invalidReason || result.error || "Verification failed",
30528
+ details: result
30529
+ };
30530
+ }
30531
+ return { valid: true, details: result };
30532
+ } catch (err) {
30533
+ return {
30534
+ valid: false,
30535
+ error: `Facilitator error: ${err.message}`
30536
+ };
30537
+ }
30538
+ }
30539
+ /**
30540
+ * Settle payment on-chain via facilitator
30541
+ */
30542
+ async settle(paymentPayload, requirements) {
30543
+ try {
30544
+ const requestBody = {
30545
+ x402Version: X402_VERSION,
30546
+ paymentPayload,
30547
+ paymentRequirements: requirements
30548
+ };
30549
+ const headers = {
30550
+ "Content-Type": "application/json"
30551
+ };
30552
+ if (this.useMainnet) {
30553
+ const authHeaders = await this.getAuthHeaders(
30554
+ "POST",
30555
+ "/platform/v2/x402/settle",
30556
+ requestBody
30557
+ );
30558
+ Object.assign(headers, authHeaders);
30559
+ }
30560
+ const response = await fetch(`${this.endpoint}/settle`, {
30561
+ method: "POST",
30562
+ headers,
30563
+ body: JSON.stringify(requestBody)
30564
+ });
30565
+ const result = await response.json();
30566
+ if (!response.ok || !result.success) {
30567
+ return {
30568
+ success: false,
30569
+ error: result.error || result.errorReason || "Settlement failed"
30570
+ };
30571
+ }
30572
+ return {
30573
+ success: true,
30574
+ transaction: result.transaction,
30575
+ status: result.status || "settled"
30576
+ };
30577
+ } catch (err) {
30578
+ return {
30579
+ success: false,
30580
+ error: `Settlement error: ${err.message}`
30581
+ };
30582
+ }
30583
+ }
30584
+ /**
30585
+ * Get CDP fee information
30586
+ */
30587
+ async getFee() {
30588
+ return {
30589
+ perTx: 1e-3,
30590
+ currency: "USD",
30591
+ freeQuota: 1e3
30592
+ };
30593
+ }
30594
+ /**
30595
+ * Get configuration summary (for logging)
30596
+ */
30597
+ getConfigSummary() {
30598
+ const mode = this.useMainnet ? "mainnet" : "testnet";
30599
+ const hasCredentials = !!(this.apiKeyId && this.apiKeySecret);
30600
+ return `CDP Facilitator (${mode}, credentials: ${hasCredentials ? "yes" : "no"})`;
30601
+ }
30602
+ };
30603
+
30604
+ // src/facilitators/registry.ts
30605
+ init_cjs_shims();
30606
+ var FacilitatorRegistry = class {
30607
+ factories = /* @__PURE__ */ new Map();
30608
+ instances = /* @__PURE__ */ new Map();
30609
+ selection;
30610
+ roundRobinIndex = 0;
30611
+ constructor(selection) {
30612
+ this.registerFactory("cdp", (config) => new CDPFacilitator(config));
30613
+ this.selection = selection || { primary: "cdp", strategy: "failover" };
30614
+ }
30615
+ /**
30616
+ * Register a new facilitator factory
30617
+ */
30618
+ registerFactory(name, factory) {
30619
+ this.factories.set(name, factory);
30620
+ }
30621
+ /**
30622
+ * Get or create a facilitator instance
30623
+ */
30624
+ get(name, config) {
30625
+ if (this.instances.has(name)) {
30626
+ return this.instances.get(name);
30627
+ }
30628
+ const factory = this.factories.get(name);
30629
+ if (!factory) {
30630
+ throw new Error(`Unknown facilitator: ${name}. Available: ${Array.from(this.factories.keys()).join(", ")}`);
30631
+ }
30632
+ const mergedConfig = {
30633
+ ...this.selection.config?.[name],
30634
+ ...config
30635
+ };
30636
+ const instance = factory(mergedConfig);
30637
+ this.instances.set(name, instance);
30638
+ return instance;
30639
+ }
30640
+ /**
30641
+ * Get all configured facilitator names
30642
+ */
30643
+ getConfiguredNames() {
30644
+ const names = [this.selection.primary];
30645
+ if (this.selection.fallback) {
30646
+ names.push(...this.selection.fallback);
30647
+ }
30648
+ return names;
30649
+ }
30650
+ /**
30651
+ * Get list of facilitators based on selection strategy
30652
+ */
30653
+ async getOrderedFacilitators(network) {
30654
+ const names = this.getConfiguredNames();
30655
+ const facilitators = [];
30656
+ for (const name of names) {
30657
+ try {
30658
+ const f = this.get(name);
30659
+ if (f.supportsNetwork(network)) {
30660
+ facilitators.push(f);
30661
+ }
30662
+ } catch (err) {
30663
+ console.warn(`[Registry] Failed to get facilitator ${name}:`, err);
30664
+ }
30665
+ }
30666
+ if (facilitators.length === 0) {
30667
+ throw new Error(`No facilitators available for network: ${network}`);
30668
+ }
30669
+ switch (this.selection.strategy) {
30670
+ case "random":
30671
+ return this.shuffle(facilitators);
30672
+ case "roundrobin":
30673
+ this.roundRobinIndex = (this.roundRobinIndex + 1) % facilitators.length;
30674
+ return [
30675
+ ...facilitators.slice(this.roundRobinIndex),
30676
+ ...facilitators.slice(0, this.roundRobinIndex)
30677
+ ];
30678
+ case "cheapest":
30679
+ return this.sortByCheapest(facilitators);
30680
+ case "fastest":
30681
+ return this.sortByFastest(facilitators);
30682
+ case "failover":
30683
+ default:
30684
+ return facilitators;
30685
+ }
30686
+ }
30687
+ shuffle(array) {
30688
+ const result = [...array];
30689
+ for (let i = result.length - 1; i > 0; i--) {
30690
+ const j = Math.floor(Math.random() * (i + 1));
30691
+ [result[i], result[j]] = [result[j], result[i]];
30692
+ }
30693
+ return result;
30694
+ }
30695
+ async sortByCheapest(facilitators) {
30696
+ const withFees = await Promise.all(
30697
+ facilitators.map(async (f) => {
30698
+ try {
30699
+ const fee = await f.getFee?.();
30700
+ return { facilitator: f, perTx: fee?.perTx ?? Infinity };
30701
+ } catch {
30702
+ return { facilitator: f, perTx: Infinity };
30703
+ }
30704
+ })
30705
+ );
30706
+ withFees.sort((a, b) => a.perTx - b.perTx);
30707
+ return withFees.map((w) => w.facilitator);
30708
+ }
30709
+ async sortByFastest(facilitators) {
30710
+ const withLatency = await Promise.all(
30711
+ facilitators.map(async (f) => {
30712
+ try {
30713
+ const health = await f.healthCheck();
30714
+ return { facilitator: f, latency: health.latencyMs ?? Infinity };
30715
+ } catch {
30716
+ return { facilitator: f, latency: Infinity };
30717
+ }
30718
+ })
30719
+ );
30720
+ withLatency.sort((a, b) => a.latency - b.latency);
30721
+ return withLatency.map((w) => w.facilitator);
30722
+ }
30723
+ /**
30724
+ * Verify payment using configured facilitators
30725
+ */
30726
+ async verify(paymentPayload, requirements) {
30727
+ const network = paymentPayload.accepted?.network || paymentPayload.network || requirements.network;
30728
+ const facilitators = await this.getOrderedFacilitators(network);
30729
+ let lastError;
30730
+ for (const f of facilitators) {
30731
+ try {
30732
+ console.log(`[Registry] Trying ${f.name} for verify...`);
30733
+ const result = await f.verify(paymentPayload, requirements);
30734
+ if (result.valid) {
30735
+ console.log(`[Registry] ${f.name} verify succeeded`);
30736
+ return { ...result, facilitator: f.name };
30737
+ }
30738
+ lastError = result.error;
30739
+ console.log(`[Registry] ${f.name} verify failed: ${result.error}`);
30740
+ if (this.selection.strategy === "failover" && !this.isTransientError(result.error)) {
30741
+ break;
30742
+ }
30743
+ } catch (err) {
30744
+ lastError = err.message;
30745
+ console.error(`[Registry] ${f.name} error:`, err.message);
30746
+ }
30747
+ }
30748
+ return {
30749
+ valid: false,
30750
+ error: lastError || "All facilitators failed",
30751
+ facilitator: "none"
30752
+ };
30753
+ }
30754
+ /**
30755
+ * Settle payment using configured facilitators
30756
+ */
30757
+ async settle(paymentPayload, requirements) {
30758
+ const network = paymentPayload.accepted?.network || paymentPayload.network || requirements.network;
30759
+ const facilitators = await this.getOrderedFacilitators(network);
30760
+ let lastError;
30761
+ for (const f of facilitators) {
30762
+ try {
30763
+ console.log(`[Registry] Trying ${f.name} for settle...`);
30764
+ const result = await f.settle(paymentPayload, requirements);
30765
+ if (result.success) {
30766
+ console.log(`[Registry] ${f.name} settle succeeded: ${result.transaction}`);
30767
+ return { ...result, facilitator: f.name };
30768
+ }
30769
+ lastError = result.error;
30770
+ console.log(`[Registry] ${f.name} settle failed: ${result.error}`);
30771
+ } catch (err) {
30772
+ lastError = err.message;
30773
+ console.error(`[Registry] ${f.name} error:`, err.message);
30774
+ }
30775
+ }
30776
+ return {
30777
+ success: false,
30778
+ error: lastError || "All facilitators failed",
30779
+ facilitator: "none"
30780
+ };
30781
+ }
30782
+ /**
30783
+ * Check health of all configured facilitators
30784
+ */
30785
+ async healthCheckAll() {
30786
+ const results = {};
30787
+ for (const name of this.getConfiguredNames()) {
30788
+ try {
30789
+ const f = this.get(name);
30790
+ results[name] = await f.healthCheck();
30791
+ } catch (err) {
30792
+ results[name] = { healthy: false, error: err.message };
30793
+ }
30794
+ }
30795
+ return results;
30796
+ }
30797
+ /**
30798
+ * Check if an error is transient (network/server issue) vs permanent (bad request)
30799
+ */
30800
+ isTransientError(error) {
30801
+ if (!error) return true;
30802
+ const transientPatterns = [
30803
+ /timeout/i,
30804
+ /network/i,
30805
+ /connection/i,
30806
+ /ECONNREFUSED/i,
30807
+ /ETIMEDOUT/i,
30808
+ /503/,
30809
+ /502/,
30810
+ /500/
30811
+ ];
30812
+ return transientPatterns.some((p) => p.test(error));
30813
+ }
30814
+ /**
30815
+ * Update selection configuration
30816
+ */
30817
+ setSelection(selection) {
30818
+ this.selection = selection;
30819
+ this.instances.clear();
30820
+ }
30821
+ /**
30822
+ * Get current selection configuration
30823
+ */
30824
+ getSelection() {
30825
+ return { ...this.selection };
30826
+ }
30827
+ };
30828
+ var defaultRegistry = null;
30829
+ function getDefaultRegistry() {
30830
+ if (!defaultRegistry) {
30831
+ defaultRegistry = new FacilitatorRegistry();
30832
+ }
30833
+ return defaultRegistry;
30834
+ }
30835
+ function createRegistry(selection) {
30836
+ return new FacilitatorRegistry(selection);
30837
+ }
30373
30838
 
30374
30839
  // src/server/types.ts
30375
30840
  init_cjs_shims();
30376
30841
 
30377
30842
  // src/server/index.ts
30378
- var X402_VERSION = 2;
30843
+ var X402_VERSION2 = 2;
30379
30844
  var PAYMENT_REQUIRED_HEADER = "x-payment-required";
30380
30845
  var PAYMENT_HEADER = "x-payment";
30381
30846
  var PAYMENT_RESPONSE_HEADER = "x-payment-response";
30382
- var FACILITATOR_TESTNET = "https://www.x402.org/facilitator";
30383
- var FACILITATOR_MAINNET = "https://api.cdp.coinbase.com/platform/v2/x402";
30384
30847
  var USDC_ADDRESSES = {
30385
30848
  "eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
30386
30849
  // Base mainnet
@@ -30391,15 +30854,15 @@ var USDC_DOMAIN = {
30391
30854
  name: "USD Coin",
30392
30855
  version: "2"
30393
30856
  };
30394
- function loadEnvFiles() {
30857
+ function loadEnvFile2() {
30395
30858
  const envPaths = [
30396
- path.join(process.cwd(), ".env"),
30397
- path.join(process.env.HOME || "", ".moltspay", ".env")
30859
+ path2.join(process.cwd(), ".env"),
30860
+ path2.join(process.env.HOME || "", ".moltspay", ".env")
30398
30861
  ];
30399
30862
  for (const envPath of envPaths) {
30400
- if ((0, import_fs.existsSync)(envPath)) {
30863
+ if ((0, import_fs2.existsSync)(envPath)) {
30401
30864
  try {
30402
- const content = (0, import_fs.readFileSync)(envPath, "utf-8");
30865
+ const content = (0, import_fs2.readFileSync)(envPath, "utf-8");
30403
30866
  for (const line of content.split("\n")) {
30404
30867
  const trimmed = line.trim();
30405
30868
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -30416,77 +30879,44 @@ function loadEnvFiles() {
30416
30879
  }
30417
30880
  console.log(`[MoltsPay] Loaded config from ${envPath}`);
30418
30881
  break;
30419
- } catch (err) {
30420
- console.warn(`[MoltsPay] Failed to load ${envPath}:`, err);
30882
+ } catch {
30421
30883
  }
30422
30884
  }
30423
30885
  }
30424
30886
  }
30425
- function getCDPConfig() {
30426
- loadEnvFiles();
30427
- return {
30428
- useMainnet: process.env.USE_MAINNET?.toLowerCase() === "true",
30429
- apiKeyId: process.env.CDP_API_KEY_ID,
30430
- apiKeySecret: process.env.CDP_API_KEY_SECRET
30431
- };
30432
- }
30433
- async function getCDPAuthHeaders(method, urlPath, body) {
30434
- const config = getCDPConfig();
30435
- if (!config.apiKeyId || !config.apiKeySecret) {
30436
- throw new Error("CDP_API_KEY_ID and CDP_API_KEY_SECRET required for mainnet");
30437
- }
30438
- try {
30439
- const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
30440
- const headers = await getAuthHeaders({
30441
- apiKeyId: config.apiKeyId,
30442
- apiKeySecret: config.apiKeySecret,
30443
- requestMethod: method,
30444
- requestHost: "api.cdp.coinbase.com",
30445
- requestPath: urlPath,
30446
- requestBody: body
30447
- });
30448
- return headers;
30449
- } catch (err) {
30450
- console.error("[MoltsPay] Failed to generate CDP auth headers:", err.message);
30451
- throw err;
30452
- }
30453
- }
30454
30887
  var MoltsPayServer = class {
30455
30888
  manifest;
30456
30889
  skills = /* @__PURE__ */ new Map();
30457
30890
  options;
30458
- cdpConfig;
30459
- facilitatorUrl;
30891
+ registry;
30460
30892
  networkId;
30893
+ useMainnet;
30461
30894
  constructor(servicesPath, options = {}) {
30462
- this.cdpConfig = getCDPConfig();
30463
- const content = (0, import_fs.readFileSync)(servicesPath, "utf-8");
30895
+ loadEnvFile2();
30896
+ const content = (0, import_fs2.readFileSync)(servicesPath, "utf-8");
30464
30897
  this.manifest = JSON.parse(content);
30465
30898
  this.options = {
30466
30899
  port: options.port || 3e3,
30467
- host: options.host || "0.0.0.0"
30900
+ host: options.host || "0.0.0.0",
30901
+ ...options
30468
30902
  };
30469
- if (this.cdpConfig.useMainnet) {
30470
- if (!this.cdpConfig.apiKeyId || !this.cdpConfig.apiKeySecret) {
30471
- console.warn("[MoltsPay] WARNING: USE_MAINNET=true but CDP keys not set!");
30472
- console.warn("[MoltsPay] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env");
30903
+ this.useMainnet = process.env.USE_MAINNET?.toLowerCase() === "true";
30904
+ this.networkId = this.useMainnet ? "eip155:8453" : "eip155:84532";
30905
+ const facilitatorConfig = options.facilitators || {
30906
+ primary: "cdp",
30907
+ strategy: "failover",
30908
+ config: {
30909
+ cdp: { useMainnet: this.useMainnet }
30473
30910
  }
30474
- this.facilitatorUrl = FACILITATOR_MAINNET;
30475
- this.networkId = "eip155:8453";
30476
- } else {
30477
- this.facilitatorUrl = options.facilitatorUrl || FACILITATOR_TESTNET;
30478
- this.networkId = "eip155:84532";
30479
- }
30480
- const networkName = this.cdpConfig.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
30481
- const facilitatorName = this.cdpConfig.useMainnet ? "CDP" : "x402.org";
30911
+ };
30912
+ this.registry = new FacilitatorRegistry(facilitatorConfig);
30913
+ const primaryFacilitator = this.registry.get(facilitatorConfig.primary);
30914
+ const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
30482
30915
  console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
30483
30916
  console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
30484
30917
  console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
30485
30918
  console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
30486
- console.log(`[MoltsPay] Facilitator: ${facilitatorName} (${this.facilitatorUrl})`);
30487
- if (this.cdpConfig.useMainnet && this.cdpConfig.apiKeyId) {
30488
- console.log(`[MoltsPay] CDP API Key: ${this.cdpConfig.apiKeyId.slice(0, 8)}...`);
30489
- }
30919
+ console.log(`[MoltsPay] Facilitator: ${primaryFacilitator.displayName} (${facilitatorConfig.strategy || "failover"})`);
30490
30920
  console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
30491
30921
  }
30492
30922
  /**
@@ -30512,6 +30942,7 @@ var MoltsPayServer = class {
30512
30942
  console.log(`[MoltsPay] Endpoints:`);
30513
30943
  console.log(` GET /services - List available services`);
30514
30944
  console.log(` POST /execute - Execute service (x402 payment)`);
30945
+ console.log(` GET /health - Health check (incl. facilitators)`);
30515
30946
  });
30516
30947
  }
30517
30948
  /**
@@ -30532,6 +30963,9 @@ var MoltsPayServer = class {
30532
30963
  if (url.pathname === "/services" && req.method === "GET") {
30533
30964
  return this.handleGetServices(res);
30534
30965
  }
30966
+ if (url.pathname === "/health" && req.method === "GET") {
30967
+ return await this.handleHealthCheck(res);
30968
+ }
30535
30969
  if (url.pathname === "/execute" && req.method === "POST") {
30536
30970
  const body = await this.readBody(req);
30537
30971
  const paymentHeader = req.headers[PAYMENT_HEADER];
@@ -30557,18 +30991,37 @@ var MoltsPayServer = class {
30557
30991
  output: s.output,
30558
30992
  available: this.skills.has(s.id)
30559
30993
  }));
30994
+ const selection = this.registry.getSelection();
30560
30995
  this.sendJson(res, 200, {
30561
30996
  provider: this.manifest.provider,
30562
30997
  services,
30563
30998
  x402: {
30564
- version: X402_VERSION,
30999
+ version: X402_VERSION2,
30565
31000
  network: this.networkId,
30566
31001
  schemes: ["exact"],
30567
- facilitator: this.cdpConfig.useMainnet ? "cdp" : "x402.org",
30568
- mainnet: this.cdpConfig.useMainnet
31002
+ facilitators: {
31003
+ primary: selection.primary,
31004
+ fallback: selection.fallback,
31005
+ strategy: selection.strategy
31006
+ },
31007
+ mainnet: this.useMainnet
30569
31008
  }
30570
31009
  });
30571
31010
  }
31011
+ /**
31012
+ * GET /health - Health check endpoint
31013
+ */
31014
+ async handleHealthCheck(res) {
31015
+ const facilitatorHealth = await this.registry.healthCheckAll();
31016
+ const allHealthy = Object.values(facilitatorHealth).every((h) => h.healthy);
31017
+ this.sendJson(res, allHealthy ? 200 : 503, {
31018
+ status: allHealthy ? "healthy" : "degraded",
31019
+ network: this.networkId,
31020
+ facilitators: facilitatorHealth,
31021
+ services: this.manifest.services.length,
31022
+ registered: this.skills.size
31023
+ });
31024
+ }
30572
31025
  /**
30573
31026
  * POST /execute - Execute service with x402 payment
30574
31027
  */
@@ -30600,11 +31053,16 @@ var MoltsPayServer = class {
30600
31053
  if (!validation.valid) {
30601
31054
  return this.sendJson(res, 402, { error: validation.error });
30602
31055
  }
30603
- console.log(`[MoltsPay] Verifying payment with facilitator...`);
30604
- const verifyResult = await this.verifyWithFacilitator(payment, skill.config);
31056
+ const requirements = this.buildPaymentRequirements(skill.config);
31057
+ console.log(`[MoltsPay] Verifying payment...`);
31058
+ const verifyResult = await this.registry.verify(payment, requirements);
30605
31059
  if (!verifyResult.valid) {
30606
- return this.sendJson(res, 402, { error: `Payment verification failed: ${verifyResult.error}` });
31060
+ return this.sendJson(res, 402, {
31061
+ error: `Payment verification failed: ${verifyResult.error}`,
31062
+ facilitator: verifyResult.facilitator
31063
+ });
30607
31064
  }
31065
+ console.log(`[MoltsPay] Verified by ${verifyResult.facilitator}`);
30608
31066
  console.log(`[MoltsPay] Executing skill: ${service}`);
30609
31067
  let result;
30610
31068
  try {
@@ -30619,17 +31077,18 @@ var MoltsPayServer = class {
30619
31077
  console.log(`[MoltsPay] Skill succeeded, settling payment...`);
30620
31078
  let settlement = null;
30621
31079
  try {
30622
- settlement = await this.settleWithFacilitator(payment, skill.config);
30623
- console.log(`[MoltsPay] Payment settled: ${settlement.transaction || "pending"}`);
31080
+ settlement = await this.registry.settle(payment, requirements);
31081
+ console.log(`[MoltsPay] Payment settled by ${settlement.facilitator}: ${settlement.transaction || "pending"}`);
30624
31082
  } catch (err) {
30625
31083
  console.error("[MoltsPay] Settlement failed:", err.message);
30626
31084
  }
30627
31085
  const responseHeaders = {};
30628
- if (settlement) {
31086
+ if (settlement?.success) {
30629
31087
  const responsePayload = {
30630
31088
  success: true,
30631
31089
  transaction: settlement.transaction,
30632
- network: payment.network
31090
+ network: payment.network || payment.accepted?.network,
31091
+ facilitator: settlement.facilitator
30633
31092
  };
30634
31093
  responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(
30635
31094
  JSON.stringify(responsePayload)
@@ -30638,7 +31097,7 @@ var MoltsPayServer = class {
30638
31097
  this.sendJson(res, 200, {
30639
31098
  success: true,
30640
31099
  result,
30641
- payment: settlement ? { transaction: settlement.transaction, status: "settled" } : { status: "pending" }
31100
+ payment: settlement?.success ? { transaction: settlement.transaction, status: "settled", facilitator: settlement.facilitator } : { status: "pending" }
30642
31101
  }, responseHeaders);
30643
31102
  }
30644
31103
  /**
@@ -30647,7 +31106,7 @@ var MoltsPayServer = class {
30647
31106
  sendPaymentRequired(config, res) {
30648
31107
  const requirements = this.buildPaymentRequirements(config);
30649
31108
  const paymentRequired = {
30650
- x402Version: X402_VERSION,
31109
+ x402Version: X402_VERSION2,
30651
31110
  accepts: [requirements],
30652
31111
  resource: {
30653
31112
  url: `/execute?service=${config.id}`,
@@ -30670,7 +31129,7 @@ var MoltsPayServer = class {
30670
31129
  * Basic payment validation
30671
31130
  */
30672
31131
  validatePayment(payment, config) {
30673
- if (payment.x402Version !== X402_VERSION) {
31132
+ if (payment.x402Version !== X402_VERSION2) {
30674
31133
  return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };
30675
31134
  }
30676
31135
  const scheme = payment.accepted?.scheme || payment.scheme;
@@ -30684,7 +31143,7 @@ var MoltsPayServer = class {
30684
31143
  return { valid: true };
30685
31144
  }
30686
31145
  /**
30687
- * Build complete payment requirements for facilitator
31146
+ * Build payment requirements for facilitator
30688
31147
  */
30689
31148
  buildPaymentRequirements(config) {
30690
31149
  const amountInUnits = Math.floor(config.price * 1e6).toString();
@@ -30699,77 +31158,6 @@ var MoltsPayServer = class {
30699
31158
  extra: USDC_DOMAIN
30700
31159
  };
30701
31160
  }
30702
- /**
30703
- * Verify payment with facilitator (testnet or CDP)
30704
- */
30705
- async verifyWithFacilitator(payment, config) {
30706
- try {
30707
- const requirements = this.buildPaymentRequirements(config);
30708
- const requestBody = {
30709
- x402Version: X402_VERSION,
30710
- // Required at top level for CDP
30711
- paymentPayload: payment,
30712
- paymentRequirements: requirements
30713
- };
30714
- console.log("[MoltsPay] Verify request:", JSON.stringify(requestBody, null, 2));
30715
- let headers = { "Content-Type": "application/json" };
30716
- if (this.cdpConfig.useMainnet) {
30717
- const authHeaders = await getCDPAuthHeaders(
30718
- "POST",
30719
- "/platform/v2/x402/verify",
30720
- requestBody
30721
- );
30722
- headers = { ...headers, ...authHeaders };
30723
- }
30724
- const response = await fetch(`${this.facilitatorUrl}/verify`, {
30725
- method: "POST",
30726
- headers,
30727
- body: JSON.stringify(requestBody)
30728
- });
30729
- const result = await response.json();
30730
- console.log("[MoltsPay] Verify response:", JSON.stringify(result, null, 2));
30731
- if (!response.ok || !result.isValid) {
30732
- return { valid: false, error: result.invalidReason || result.error || "Verification failed" };
30733
- }
30734
- return { valid: true };
30735
- } catch (err) {
30736
- return { valid: false, error: `Facilitator error: ${err.message}` };
30737
- }
30738
- }
30739
- /**
30740
- * Settle payment with facilitator (execute on-chain transfer)
30741
- */
30742
- async settleWithFacilitator(payment, config) {
30743
- const requirements = this.buildPaymentRequirements(config);
30744
- const requestBody = {
30745
- x402Version: X402_VERSION,
30746
- // Required at top level for CDP
30747
- paymentPayload: payment,
30748
- paymentRequirements: requirements
30749
- };
30750
- let headers = { "Content-Type": "application/json" };
30751
- if (this.cdpConfig.useMainnet) {
30752
- const authHeaders = await getCDPAuthHeaders(
30753
- "POST",
30754
- "/platform/v2/x402/settle",
30755
- requestBody
30756
- );
30757
- headers = { ...headers, ...authHeaders };
30758
- }
30759
- const response = await fetch(`${this.facilitatorUrl}/settle`, {
30760
- method: "POST",
30761
- headers,
30762
- body: JSON.stringify(requestBody)
30763
- });
30764
- const result = await response.json();
30765
- if (!response.ok || !result.success) {
30766
- throw new Error(result.error || result.errorReason || "Settlement failed");
30767
- }
30768
- return {
30769
- transaction: result.transaction,
30770
- status: result.status || "settled"
30771
- };
30772
- }
30773
31161
  async readBody(req) {
30774
31162
  return new Promise((resolve, reject) => {
30775
31163
  let body = "";
@@ -30796,7 +31184,7 @@ var MoltsPayServer = class {
30796
31184
 
30797
31185
  // src/client/index.ts
30798
31186
  init_cjs_shims();
30799
- var import_fs2 = require("fs");
31187
+ var import_fs3 = require("fs");
30800
31188
  var import_os = require("os");
30801
31189
  var import_path = require("path");
30802
31190
  var import_ethers = require("ethers");
@@ -30883,7 +31271,7 @@ var ERC20_ABI = [
30883
31271
  init_cjs_shims();
30884
31272
 
30885
31273
  // src/client/index.ts
30886
- var X402_VERSION2 = 2;
31274
+ var X402_VERSION3 = 2;
30887
31275
  var PAYMENT_REQUIRED_HEADER2 = "x-payment-required";
30888
31276
  var PAYMENT_HEADER2 = "x-payment";
30889
31277
  var DEFAULT_CONFIG = {
@@ -31009,7 +31397,7 @@ var MoltsPayClient = class {
31009
31397
  }
31010
31398
  const authorization = await this.signEIP3009(payTo, amount, chain2);
31011
31399
  const payload = {
31012
- x402Version: X402_VERSION2,
31400
+ x402Version: X402_VERSION3,
31013
31401
  payload: authorization,
31014
31402
  // v2 requires 'accepted' field with the requirements being fulfilled
31015
31403
  accepted: {
@@ -31107,25 +31495,25 @@ var MoltsPayClient = class {
31107
31495
  // --- Config & Wallet Management ---
31108
31496
  loadConfig() {
31109
31497
  const configPath = (0, import_path.join)(this.configDir, "config.json");
31110
- if ((0, import_fs2.existsSync)(configPath)) {
31111
- const content = (0, import_fs2.readFileSync)(configPath, "utf-8");
31498
+ if ((0, import_fs3.existsSync)(configPath)) {
31499
+ const content = (0, import_fs3.readFileSync)(configPath, "utf-8");
31112
31500
  return { ...DEFAULT_CONFIG, ...JSON.parse(content) };
31113
31501
  }
31114
31502
  return { ...DEFAULT_CONFIG };
31115
31503
  }
31116
31504
  saveConfig() {
31117
- (0, import_fs2.mkdirSync)(this.configDir, { recursive: true });
31505
+ (0, import_fs3.mkdirSync)(this.configDir, { recursive: true });
31118
31506
  const configPath = (0, import_path.join)(this.configDir, "config.json");
31119
- (0, import_fs2.writeFileSync)(configPath, JSON.stringify(this.config, null, 2));
31507
+ (0, import_fs3.writeFileSync)(configPath, JSON.stringify(this.config, null, 2));
31120
31508
  }
31121
31509
  /**
31122
31510
  * Load spending data from disk
31123
31511
  */
31124
31512
  loadSpending() {
31125
31513
  const spendingPath = (0, import_path.join)(this.configDir, "spending.json");
31126
- if ((0, import_fs2.existsSync)(spendingPath)) {
31514
+ if ((0, import_fs3.existsSync)(spendingPath)) {
31127
31515
  try {
31128
- const data = JSON.parse((0, import_fs2.readFileSync)(spendingPath, "utf-8"));
31516
+ const data = JSON.parse((0, import_fs3.readFileSync)(spendingPath, "utf-8"));
31129
31517
  const today = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0);
31130
31518
  if (data.date && data.date === today) {
31131
31519
  this.todaySpending = data.amount || 0;
@@ -31144,29 +31532,29 @@ var MoltsPayClient = class {
31144
31532
  * Save spending data to disk
31145
31533
  */
31146
31534
  saveSpending() {
31147
- (0, import_fs2.mkdirSync)(this.configDir, { recursive: true });
31535
+ (0, import_fs3.mkdirSync)(this.configDir, { recursive: true });
31148
31536
  const spendingPath = (0, import_path.join)(this.configDir, "spending.json");
31149
31537
  const data = {
31150
31538
  date: this.lastSpendingReset || (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0),
31151
31539
  amount: this.todaySpending,
31152
31540
  updatedAt: Date.now()
31153
31541
  };
31154
- (0, import_fs2.writeFileSync)(spendingPath, JSON.stringify(data, null, 2));
31542
+ (0, import_fs3.writeFileSync)(spendingPath, JSON.stringify(data, null, 2));
31155
31543
  }
31156
31544
  loadWallet() {
31157
31545
  const walletPath = (0, import_path.join)(this.configDir, "wallet.json");
31158
- if ((0, import_fs2.existsSync)(walletPath)) {
31546
+ if ((0, import_fs3.existsSync)(walletPath)) {
31159
31547
  try {
31160
- const stats = (0, import_fs2.statSync)(walletPath);
31548
+ const stats = (0, import_fs3.statSync)(walletPath);
31161
31549
  const mode = stats.mode & 511;
31162
31550
  if (mode !== 384) {
31163
31551
  console.warn(`[MoltsPay] WARNING: wallet.json has insecure permissions (${mode.toString(8)})`);
31164
31552
  console.warn(`[MoltsPay] Fixing permissions to 0600...`);
31165
- (0, import_fs2.chmodSync)(walletPath, 384);
31553
+ (0, import_fs3.chmodSync)(walletPath, 384);
31166
31554
  }
31167
31555
  } catch (err) {
31168
31556
  }
31169
- const content = (0, import_fs2.readFileSync)(walletPath, "utf-8");
31557
+ const content = (0, import_fs3.readFileSync)(walletPath, "utf-8");
31170
31558
  return JSON.parse(content);
31171
31559
  }
31172
31560
  return null;
@@ -31175,7 +31563,7 @@ var MoltsPayClient = class {
31175
31563
  * Initialize a new wallet (called by CLI)
31176
31564
  */
31177
31565
  static init(configDir, options) {
31178
- (0, import_fs2.mkdirSync)(configDir, { recursive: true });
31566
+ (0, import_fs3.mkdirSync)(configDir, { recursive: true });
31179
31567
  const wallet = import_ethers.Wallet.createRandom();
31180
31568
  const walletData = {
31181
31569
  address: wallet.address,
@@ -31183,7 +31571,7 @@ var MoltsPayClient = class {
31183
31571
  createdAt: Date.now()
31184
31572
  };
31185
31573
  const walletPath = (0, import_path.join)(configDir, "wallet.json");
31186
- (0, import_fs2.writeFileSync)(walletPath, JSON.stringify(walletData, null, 2), { mode: 384 });
31574
+ (0, import_fs3.writeFileSync)(walletPath, JSON.stringify(walletData, null, 2), { mode: 384 });
31187
31575
  const config = {
31188
31576
  chain: options.chain,
31189
31577
  limits: {
@@ -31192,7 +31580,7 @@ var MoltsPayClient = class {
31192
31580
  }
31193
31581
  };
31194
31582
  const configPath = (0, import_path.join)(configDir, "config.json");
31195
- (0, import_fs2.writeFileSync)(configPath, JSON.stringify(config, null, 2));
31583
+ (0, import_fs3.writeFileSync)(configPath, JSON.stringify(config, null, 2));
31196
31584
  return { address: wallet.address, configDir };
31197
31585
  }
31198
31586
  /**
@@ -31230,7 +31618,7 @@ var import_ethers2 = require("ethers");
31230
31618
  // src/wallet/createWallet.ts
31231
31619
  init_cjs_shims();
31232
31620
  var import_ethers3 = require("ethers");
31233
- var import_fs3 = require("fs");
31621
+ var import_fs4 = require("fs");
31234
31622
  var import_path2 = require("path");
31235
31623
  var import_crypto = require("crypto");
31236
31624
  var DEFAULT_STORAGE_DIR = (0, import_path2.join)(process.env.HOME || "~", ".moltspay");
@@ -31257,9 +31645,9 @@ function decryptPrivateKey(encrypted, password, iv, salt) {
31257
31645
  }
31258
31646
  function createWallet(options = {}) {
31259
31647
  const storagePath = options.storagePath || (0, import_path2.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
31260
- if ((0, import_fs3.existsSync)(storagePath) && !options.overwrite) {
31648
+ if ((0, import_fs4.existsSync)(storagePath) && !options.overwrite) {
31261
31649
  try {
31262
- const existing = JSON.parse((0, import_fs3.readFileSync)(storagePath, "utf8"));
31650
+ const existing = JSON.parse((0, import_fs4.readFileSync)(storagePath, "utf8"));
31263
31651
  return {
31264
31652
  success: true,
31265
31653
  address: existing.address,
@@ -31291,10 +31679,10 @@ function createWallet(options = {}) {
31291
31679
  walletData.privateKey = wallet.privateKey;
31292
31680
  }
31293
31681
  const dir = (0, import_path2.dirname)(storagePath);
31294
- if (!(0, import_fs3.existsSync)(dir)) {
31295
- (0, import_fs3.mkdirSync)(dir, { recursive: true });
31682
+ if (!(0, import_fs4.existsSync)(dir)) {
31683
+ (0, import_fs4.mkdirSync)(dir, { recursive: true });
31296
31684
  }
31297
- (0, import_fs3.writeFileSync)(storagePath, JSON.stringify(walletData, null, 2), { mode: 384 });
31685
+ (0, import_fs4.writeFileSync)(storagePath, JSON.stringify(walletData, null, 2), { mode: 384 });
31298
31686
  return {
31299
31687
  success: true,
31300
31688
  address: wallet.address,
@@ -31310,11 +31698,11 @@ function createWallet(options = {}) {
31310
31698
  }
31311
31699
  function loadWallet(options = {}) {
31312
31700
  const storagePath = options.storagePath || (0, import_path2.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
31313
- if (!(0, import_fs3.existsSync)(storagePath)) {
31701
+ if (!(0, import_fs4.existsSync)(storagePath)) {
31314
31702
  return { success: false, error: "Wallet not found. Run createWallet() first." };
31315
31703
  }
31316
31704
  try {
31317
- const data = JSON.parse((0, import_fs3.readFileSync)(storagePath, "utf8"));
31705
+ const data = JSON.parse((0, import_fs4.readFileSync)(storagePath, "utf8"));
31318
31706
  if (data.encrypted) {
31319
31707
  if (!options.password) {
31320
31708
  return { success: false, error: "Wallet is encrypted. Password required." };
@@ -31329,20 +31717,20 @@ function loadWallet(options = {}) {
31329
31717
  }
31330
31718
  }
31331
31719
  function getWalletAddress(storagePath) {
31332
- const path3 = storagePath || (0, import_path2.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
31333
- if (!(0, import_fs3.existsSync)(path3)) {
31720
+ const path4 = storagePath || (0, import_path2.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
31721
+ if (!(0, import_fs4.existsSync)(path4)) {
31334
31722
  return null;
31335
31723
  }
31336
31724
  try {
31337
- const data = JSON.parse((0, import_fs3.readFileSync)(path3, "utf8"));
31725
+ const data = JSON.parse((0, import_fs4.readFileSync)(path4, "utf8"));
31338
31726
  return data.address;
31339
31727
  } catch {
31340
31728
  return null;
31341
31729
  }
31342
31730
  }
31343
31731
  function walletExists(storagePath) {
31344
- const path3 = storagePath || (0, import_path2.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
31345
- return (0, import_fs3.existsSync)(path3);
31732
+ const path4 = storagePath || (0, import_path2.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
31733
+ return (0, import_fs4.existsSync)(path4);
31346
31734
  }
31347
31735
 
31348
31736
  // src/verify/index.ts
@@ -31485,8 +31873,8 @@ async function waitForTransaction(txHash, chain2 = "base", confirmations = 1, ti
31485
31873
  // src/cdp/index.ts
31486
31874
  init_cjs_shims();
31487
31875
  var fs = __toESM(require("fs"));
31488
- var path2 = __toESM(require("path"));
31489
- var DEFAULT_STORAGE_DIR2 = path2.join(process.env.HOME || ".", ".moltspay");
31876
+ var path3 = __toESM(require("path"));
31877
+ var DEFAULT_STORAGE_DIR2 = path3.join(process.env.HOME || ".", ".moltspay");
31490
31878
  var CDP_CONFIG_FILE = "cdp-wallet.json";
31491
31879
  function isCDPAvailable() {
31492
31880
  try {
@@ -31508,7 +31896,7 @@ function getCDPCredentials(config) {
31508
31896
  async function initCDPWallet(config = {}) {
31509
31897
  const storageDir = config.storageDir || DEFAULT_STORAGE_DIR2;
31510
31898
  const chain2 = config.chain || "base";
31511
- const storagePath = path2.join(storageDir, CDP_CONFIG_FILE);
31899
+ const storagePath = path3.join(storageDir, CDP_CONFIG_FILE);
31512
31900
  if (fs.existsSync(storagePath)) {
31513
31901
  try {
31514
31902
  const data = JSON.parse(fs.readFileSync(storagePath, "utf-8"));
@@ -31570,7 +31958,7 @@ async function initCDPWallet(config = {}) {
31570
31958
  }
31571
31959
  function loadCDPWallet(config = {}) {
31572
31960
  const storageDir = config.storageDir || DEFAULT_STORAGE_DIR2;
31573
- const storagePath = path2.join(storageDir, CDP_CONFIG_FILE);
31961
+ const storagePath = path3.join(storageDir, CDP_CONFIG_FILE);
31574
31962
  if (!fs.existsSync(storagePath)) {
31575
31963
  return null;
31576
31964
  }
@@ -31689,15 +32077,20 @@ var CDPWallet = class {
31689
32077
  };
31690
32078
  // Annotate the CommonJS export names for ESM import in node:
31691
32079
  0 && (module.exports = {
32080
+ BaseFacilitator,
32081
+ CDPFacilitator,
31692
32082
  CDPWallet,
31693
32083
  CHAINS,
31694
32084
  ERC20_ABI,
32085
+ FacilitatorRegistry,
31695
32086
  MoltsPayClient,
31696
32087
  MoltsPayServer,
32088
+ createRegistry,
31697
32089
  createWallet,
31698
32090
  getCDPWalletAddress,
31699
32091
  getChain,
31700
32092
  getChainById,
32093
+ getDefaultRegistry,
31701
32094
  getTransactionStatus,
31702
32095
  getWalletAddress,
31703
32096
  initCDPWallet,