pmxtjs 2.34.1 → 2.34.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -335,6 +335,51 @@ export class Exchange {
335
335
  }
336
336
  return headers;
337
337
  }
338
+ /**
339
+ * Resolve the current sidecar base URL.
340
+ *
341
+ * For hosted mode the configured basePath is returned as-is.
342
+ * For local mode the port is re-read from the lock file on every
343
+ * call so we pick up sidecar restarts that land on a different port.
344
+ */
345
+ resolveBaseUrl() {
346
+ if (this.isHosted)
347
+ return this.config.basePath;
348
+ const port = this.serverManager.getRunningPort();
349
+ return `http://localhost:${port}`;
350
+ }
351
+ /**
352
+ * Execute a fetch with retry on connection failures.
353
+ *
354
+ * Only retries on connection-level errors (ECONNREFUSED, ECONNRESET) —
355
+ * never on HTTP responses (4xx, 5xx). On first connection failure,
356
+ * attempts to restart the sidecar.
357
+ */
358
+ async fetchWithRetry(input, init) {
359
+ const delays = [200, 500, 1000];
360
+ let lastError;
361
+ for (let attempt = 0; attempt <= delays.length; attempt++) {
362
+ try {
363
+ return await fetch(input, init);
364
+ }
365
+ catch (error) {
366
+ lastError = error;
367
+ if (attempt >= delays.length)
368
+ break;
369
+ // Connection failed — try to restart the sidecar on first failure
370
+ if (attempt === 0 && !this.isHosted) {
371
+ try {
372
+ await this.serverManager.ensureServerRunning();
373
+ }
374
+ catch {
375
+ // Restart failed — continue retrying anyway
376
+ }
377
+ }
378
+ await new Promise(resolve => setTimeout(resolve, delays[attempt]));
379
+ }
380
+ }
381
+ throw lastError;
382
+ }
338
383
  // Low-Level API Access
339
384
  /**
340
385
  * Call an exchange-specific REST endpoint by its operationId.
@@ -354,12 +399,12 @@ export class Exchange {
354
399
  async callApi(operationId, params) {
355
400
  await this.initPromise;
356
401
  try {
357
- const url = `${this.config.basePath}/api/${this.exchangeName}/callApi`;
402
+ const url = `${this.resolveBaseUrl()}/api/${this.exchangeName}/callApi`;
358
403
  const requestBody = {
359
404
  args: [operationId, params],
360
405
  credentials: this.getCredentials()
361
406
  };
362
- const response = await fetch(url, {
407
+ const response = await this.fetchWithRetry(url, {
363
408
  method: 'POST',
364
409
  headers: {
365
410
  'Content-Type': 'application/json',
@@ -403,12 +448,13 @@ export class Exchange {
403
448
  * @internal — shared transport used by every generated read method.
404
449
  */
405
450
  async sidecarReadRequest(methodName, query, args) {
406
- const baseUrl = `${this.config.basePath}/api/${this.exchangeName}/${methodName}`;
451
+ const resolvedBase = this.resolveBaseUrl();
452
+ const baseUrl = `${resolvedBase}/api/${this.exchangeName}/${methodName}`;
407
453
  const hasCredentials = this.getCredentials() !== undefined;
408
454
  if (!hasCredentials && !this._getReadsUnsupported && !queryHasNestedObject(query)) {
409
455
  const qs = buildSidecarQueryString(query);
410
456
  const getUrl = qs ? `${baseUrl}?${qs}` : baseUrl;
411
- const response = await fetch(getUrl, {
457
+ const response = await this.fetchWithRetry(getUrl, {
412
458
  method: 'GET',
413
459
  headers: this.getAuthHeaders(),
414
460
  });
@@ -431,7 +477,7 @@ export class Exchange {
431
477
  }
432
478
  }
433
479
  // POST fallback — identical to the original per-method template.
434
- const response = await fetch(baseUrl, {
480
+ const response = await this.fetchWithRetry(baseUrl, {
435
481
  method: 'POST',
436
482
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
437
483
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
@@ -451,14 +497,17 @@ export class Exchange {
451
497
  try {
452
498
  const args = [];
453
499
  args.push(reload);
454
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/loadMarkets`, {
500
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/loadMarkets`, {
455
501
  method: 'POST',
456
502
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
457
503
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
458
504
  });
459
505
  if (!response.ok) {
460
- const error = await response.json().catch(() => ({}));
461
- throw new Error(error.error?.message || response.statusText);
506
+ const body = await response.json().catch(() => ({}));
507
+ if (body.error && typeof body.error === "object") {
508
+ throw fromServerError(body.error);
509
+ }
510
+ throw new PmxtError(body.error?.message || response.statusText);
462
511
  }
463
512
  const json = await response.json();
464
513
  const data = this.handleResponse(json);
@@ -469,7 +518,9 @@ export class Exchange {
469
518
  return result;
470
519
  }
471
520
  catch (error) {
472
- throw new Error(`Failed to loadMarkets: ${error}`);
521
+ if (error instanceof PmxtError)
522
+ throw error;
523
+ throw new PmxtError(`Failed to loadMarkets: ${error}`);
473
524
  }
474
525
  }
475
526
  async fetchMarkets(params) {
@@ -478,21 +529,26 @@ export class Exchange {
478
529
  const args = [];
479
530
  if (params !== undefined)
480
531
  args.push(params);
481
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchMarkets`, {
532
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchMarkets`, {
482
533
  method: 'POST',
483
534
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
484
535
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
485
536
  });
486
537
  if (!response.ok) {
487
- const error = await response.json().catch(() => ({}));
488
- throw new Error(error.error?.message || response.statusText);
538
+ const body = await response.json().catch(() => ({}));
539
+ if (body.error && typeof body.error === "object") {
540
+ throw fromServerError(body.error);
541
+ }
542
+ throw new PmxtError(body.error?.message || response.statusText);
489
543
  }
490
544
  const json = await response.json();
491
545
  const data = this.handleResponse(json);
492
546
  return data.map(convertMarket);
493
547
  }
494
548
  catch (error) {
495
- throw new Error(`Failed to fetchMarkets: ${error}`);
549
+ if (error instanceof PmxtError)
550
+ throw error;
551
+ throw new PmxtError(`Failed to fetchMarkets: ${error}`);
496
552
  }
497
553
  }
498
554
  async fetchMarketsPaginated(params) {
@@ -501,14 +557,17 @@ export class Exchange {
501
557
  const args = [];
502
558
  if (params !== undefined)
503
559
  args.push(params);
504
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchMarketsPaginated`, {
560
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchMarketsPaginated`, {
505
561
  method: 'POST',
506
562
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
507
563
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
508
564
  });
509
565
  if (!response.ok) {
510
- const error = await response.json().catch(() => ({}));
511
- throw new Error(error.error?.message || response.statusText);
566
+ const body = await response.json().catch(() => ({}));
567
+ if (body.error && typeof body.error === "object") {
568
+ throw fromServerError(body.error);
569
+ }
570
+ throw new PmxtError(body.error?.message || response.statusText);
512
571
  }
513
572
  const json = await response.json();
514
573
  const data = this.handleResponse(json);
@@ -519,7 +578,9 @@ export class Exchange {
519
578
  };
520
579
  }
521
580
  catch (error) {
522
- throw new Error(`Failed to fetchMarketsPaginated: ${error}`);
581
+ if (error instanceof PmxtError)
582
+ throw error;
583
+ throw new PmxtError(`Failed to fetchMarketsPaginated: ${error}`);
523
584
  }
524
585
  }
525
586
  async fetchEvents(params) {
@@ -528,21 +589,26 @@ export class Exchange {
528
589
  const args = [];
529
590
  if (params !== undefined)
530
591
  args.push(params);
531
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchEvents`, {
592
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchEvents`, {
532
593
  method: 'POST',
533
594
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
534
595
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
535
596
  });
536
597
  if (!response.ok) {
537
- const error = await response.json().catch(() => ({}));
538
- throw new Error(error.error?.message || response.statusText);
598
+ const body = await response.json().catch(() => ({}));
599
+ if (body.error && typeof body.error === "object") {
600
+ throw fromServerError(body.error);
601
+ }
602
+ throw new PmxtError(body.error?.message || response.statusText);
539
603
  }
540
604
  const json = await response.json();
541
605
  const data = this.handleResponse(json);
542
606
  return data.map(convertEvent);
543
607
  }
544
608
  catch (error) {
545
- throw new Error(`Failed to fetchEvents: ${error}`);
609
+ if (error instanceof PmxtError)
610
+ throw error;
611
+ throw new PmxtError(`Failed to fetchEvents: ${error}`);
546
612
  }
547
613
  }
548
614
  async fetchMarket(params) {
@@ -551,21 +617,26 @@ export class Exchange {
551
617
  const args = [];
552
618
  if (params !== undefined)
553
619
  args.push(params);
554
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchMarket`, {
620
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchMarket`, {
555
621
  method: 'POST',
556
622
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
557
623
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
558
624
  });
559
625
  if (!response.ok) {
560
- const error = await response.json().catch(() => ({}));
561
- throw new Error(error.error?.message || response.statusText);
626
+ const body = await response.json().catch(() => ({}));
627
+ if (body.error && typeof body.error === "object") {
628
+ throw fromServerError(body.error);
629
+ }
630
+ throw new PmxtError(body.error?.message || response.statusText);
562
631
  }
563
632
  const json = await response.json();
564
633
  const data = this.handleResponse(json);
565
634
  return convertMarket(data);
566
635
  }
567
636
  catch (error) {
568
- throw new Error(`Failed to fetchMarket: ${error}`);
637
+ if (error instanceof PmxtError)
638
+ throw error;
639
+ throw new PmxtError(`Failed to fetchMarket: ${error}`);
569
640
  }
570
641
  }
571
642
  async fetchEvent(params) {
@@ -574,21 +645,26 @@ export class Exchange {
574
645
  const args = [];
575
646
  if (params !== undefined)
576
647
  args.push(params);
577
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchEvent`, {
648
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchEvent`, {
578
649
  method: 'POST',
579
650
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
580
651
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
581
652
  });
582
653
  if (!response.ok) {
583
- const error = await response.json().catch(() => ({}));
584
- throw new Error(error.error?.message || response.statusText);
654
+ const body = await response.json().catch(() => ({}));
655
+ if (body.error && typeof body.error === "object") {
656
+ throw fromServerError(body.error);
657
+ }
658
+ throw new PmxtError(body.error?.message || response.statusText);
585
659
  }
586
660
  const json = await response.json();
587
661
  const data = this.handleResponse(json);
588
662
  return convertEvent(data);
589
663
  }
590
664
  catch (error) {
591
- throw new Error(`Failed to fetchEvent: ${error}`);
665
+ if (error instanceof PmxtError)
666
+ throw error;
667
+ throw new PmxtError(`Failed to fetchEvent: ${error}`);
592
668
  }
593
669
  }
594
670
  async fetchOrderBook(id) {
@@ -596,21 +672,26 @@ export class Exchange {
596
672
  try {
597
673
  const args = [];
598
674
  args.push(id);
599
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchOrderBook`, {
675
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchOrderBook`, {
600
676
  method: 'POST',
601
677
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
602
678
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
603
679
  });
604
680
  if (!response.ok) {
605
- const error = await response.json().catch(() => ({}));
606
- throw new Error(error.error?.message || response.statusText);
681
+ const body = await response.json().catch(() => ({}));
682
+ if (body.error && typeof body.error === "object") {
683
+ throw fromServerError(body.error);
684
+ }
685
+ throw new PmxtError(body.error?.message || response.statusText);
607
686
  }
608
687
  const json = await response.json();
609
688
  const data = this.handleResponse(json);
610
689
  return convertOrderBook(data);
611
690
  }
612
691
  catch (error) {
613
- throw new Error(`Failed to fetchOrderBook: ${error}`);
692
+ if (error instanceof PmxtError)
693
+ throw error;
694
+ throw new PmxtError(`Failed to fetchOrderBook: ${error}`);
614
695
  }
615
696
  }
616
697
  async submitOrder(built) {
@@ -618,21 +699,26 @@ export class Exchange {
618
699
  try {
619
700
  const args = [];
620
701
  args.push(built);
621
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/submitOrder`, {
702
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/submitOrder`, {
622
703
  method: 'POST',
623
704
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
624
705
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
625
706
  });
626
707
  if (!response.ok) {
627
- const error = await response.json().catch(() => ({}));
628
- throw new Error(error.error?.message || response.statusText);
708
+ const body = await response.json().catch(() => ({}));
709
+ if (body.error && typeof body.error === "object") {
710
+ throw fromServerError(body.error);
711
+ }
712
+ throw new PmxtError(body.error?.message || response.statusText);
629
713
  }
630
714
  const json = await response.json();
631
715
  const data = this.handleResponse(json);
632
716
  return convertOrder(data);
633
717
  }
634
718
  catch (error) {
635
- throw new Error(`Failed to submitOrder: ${error}`);
719
+ if (error instanceof PmxtError)
720
+ throw error;
721
+ throw new PmxtError(`Failed to submitOrder: ${error}`);
636
722
  }
637
723
  }
638
724
  async cancelOrder(orderId) {
@@ -640,21 +726,26 @@ export class Exchange {
640
726
  try {
641
727
  const args = [];
642
728
  args.push(orderId);
643
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/cancelOrder`, {
729
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/cancelOrder`, {
644
730
  method: 'POST',
645
731
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
646
732
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
647
733
  });
648
734
  if (!response.ok) {
649
- const error = await response.json().catch(() => ({}));
650
- throw new Error(error.error?.message || response.statusText);
735
+ const body = await response.json().catch(() => ({}));
736
+ if (body.error && typeof body.error === "object") {
737
+ throw fromServerError(body.error);
738
+ }
739
+ throw new PmxtError(body.error?.message || response.statusText);
651
740
  }
652
741
  const json = await response.json();
653
742
  const data = this.handleResponse(json);
654
743
  return convertOrder(data);
655
744
  }
656
745
  catch (error) {
657
- throw new Error(`Failed to cancelOrder: ${error}`);
746
+ if (error instanceof PmxtError)
747
+ throw error;
748
+ throw new PmxtError(`Failed to cancelOrder: ${error}`);
658
749
  }
659
750
  }
660
751
  async fetchOrder(orderId) {
@@ -662,21 +753,26 @@ export class Exchange {
662
753
  try {
663
754
  const args = [];
664
755
  args.push(orderId);
665
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchOrder`, {
756
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchOrder`, {
666
757
  method: 'POST',
667
758
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
668
759
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
669
760
  });
670
761
  if (!response.ok) {
671
- const error = await response.json().catch(() => ({}));
672
- throw new Error(error.error?.message || response.statusText);
762
+ const body = await response.json().catch(() => ({}));
763
+ if (body.error && typeof body.error === "object") {
764
+ throw fromServerError(body.error);
765
+ }
766
+ throw new PmxtError(body.error?.message || response.statusText);
673
767
  }
674
768
  const json = await response.json();
675
769
  const data = this.handleResponse(json);
676
770
  return convertOrder(data);
677
771
  }
678
772
  catch (error) {
679
- throw new Error(`Failed to fetchOrder: ${error}`);
773
+ if (error instanceof PmxtError)
774
+ throw error;
775
+ throw new PmxtError(`Failed to fetchOrder: ${error}`);
680
776
  }
681
777
  }
682
778
  async fetchOpenOrders(marketId) {
@@ -685,21 +781,26 @@ export class Exchange {
685
781
  const args = [];
686
782
  if (marketId !== undefined)
687
783
  args.push(marketId);
688
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchOpenOrders`, {
784
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchOpenOrders`, {
689
785
  method: 'POST',
690
786
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
691
787
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
692
788
  });
693
789
  if (!response.ok) {
694
- const error = await response.json().catch(() => ({}));
695
- throw new Error(error.error?.message || response.statusText);
790
+ const body = await response.json().catch(() => ({}));
791
+ if (body.error && typeof body.error === "object") {
792
+ throw fromServerError(body.error);
793
+ }
794
+ throw new PmxtError(body.error?.message || response.statusText);
696
795
  }
697
796
  const json = await response.json();
698
797
  const data = this.handleResponse(json);
699
798
  return data.map(convertOrder);
700
799
  }
701
800
  catch (error) {
702
- throw new Error(`Failed to fetchOpenOrders: ${error}`);
801
+ if (error instanceof PmxtError)
802
+ throw error;
803
+ throw new PmxtError(`Failed to fetchOpenOrders: ${error}`);
703
804
  }
704
805
  }
705
806
  async fetchMyTrades(params) {
@@ -708,21 +809,26 @@ export class Exchange {
708
809
  const args = [];
709
810
  if (params !== undefined)
710
811
  args.push(params);
711
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchMyTrades`, {
812
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchMyTrades`, {
712
813
  method: 'POST',
713
814
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
714
815
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
715
816
  });
716
817
  if (!response.ok) {
717
- const error = await response.json().catch(() => ({}));
718
- throw new Error(error.error?.message || response.statusText);
818
+ const body = await response.json().catch(() => ({}));
819
+ if (body.error && typeof body.error === "object") {
820
+ throw fromServerError(body.error);
821
+ }
822
+ throw new PmxtError(body.error?.message || response.statusText);
719
823
  }
720
824
  const json = await response.json();
721
825
  const data = this.handleResponse(json);
722
826
  return data.map(convertUserTrade);
723
827
  }
724
828
  catch (error) {
725
- throw new Error(`Failed to fetchMyTrades: ${error}`);
829
+ if (error instanceof PmxtError)
830
+ throw error;
831
+ throw new PmxtError(`Failed to fetchMyTrades: ${error}`);
726
832
  }
727
833
  }
728
834
  async fetchClosedOrders(params) {
@@ -731,21 +837,26 @@ export class Exchange {
731
837
  const args = [];
732
838
  if (params !== undefined)
733
839
  args.push(params);
734
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchClosedOrders`, {
840
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchClosedOrders`, {
735
841
  method: 'POST',
736
842
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
737
843
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
738
844
  });
739
845
  if (!response.ok) {
740
- const error = await response.json().catch(() => ({}));
741
- throw new Error(error.error?.message || response.statusText);
846
+ const body = await response.json().catch(() => ({}));
847
+ if (body.error && typeof body.error === "object") {
848
+ throw fromServerError(body.error);
849
+ }
850
+ throw new PmxtError(body.error?.message || response.statusText);
742
851
  }
743
852
  const json = await response.json();
744
853
  const data = this.handleResponse(json);
745
854
  return data.map(convertOrder);
746
855
  }
747
856
  catch (error) {
748
- throw new Error(`Failed to fetchClosedOrders: ${error}`);
857
+ if (error instanceof PmxtError)
858
+ throw error;
859
+ throw new PmxtError(`Failed to fetchClosedOrders: ${error}`);
749
860
  }
750
861
  }
751
862
  async fetchAllOrders(params) {
@@ -754,21 +865,26 @@ export class Exchange {
754
865
  const args = [];
755
866
  if (params !== undefined)
756
867
  args.push(params);
757
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchAllOrders`, {
868
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchAllOrders`, {
758
869
  method: 'POST',
759
870
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
760
871
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
761
872
  });
762
873
  if (!response.ok) {
763
- const error = await response.json().catch(() => ({}));
764
- throw new Error(error.error?.message || response.statusText);
874
+ const body = await response.json().catch(() => ({}));
875
+ if (body.error && typeof body.error === "object") {
876
+ throw fromServerError(body.error);
877
+ }
878
+ throw new PmxtError(body.error?.message || response.statusText);
765
879
  }
766
880
  const json = await response.json();
767
881
  const data = this.handleResponse(json);
768
882
  return data.map(convertOrder);
769
883
  }
770
884
  catch (error) {
771
- throw new Error(`Failed to fetchAllOrders: ${error}`);
885
+ if (error instanceof PmxtError)
886
+ throw error;
887
+ throw new PmxtError(`Failed to fetchAllOrders: ${error}`);
772
888
  }
773
889
  }
774
890
  async fetchPositions(address) {
@@ -777,21 +893,26 @@ export class Exchange {
777
893
  const args = [];
778
894
  if (address !== undefined)
779
895
  args.push(address);
780
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchPositions`, {
896
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchPositions`, {
781
897
  method: 'POST',
782
898
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
783
899
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
784
900
  });
785
901
  if (!response.ok) {
786
- const error = await response.json().catch(() => ({}));
787
- throw new Error(error.error?.message || response.statusText);
902
+ const body = await response.json().catch(() => ({}));
903
+ if (body.error && typeof body.error === "object") {
904
+ throw fromServerError(body.error);
905
+ }
906
+ throw new PmxtError(body.error?.message || response.statusText);
788
907
  }
789
908
  const json = await response.json();
790
909
  const data = this.handleResponse(json);
791
910
  return data.map(convertPosition);
792
911
  }
793
912
  catch (error) {
794
- throw new Error(`Failed to fetchPositions: ${error}`);
913
+ if (error instanceof PmxtError)
914
+ throw error;
915
+ throw new PmxtError(`Failed to fetchPositions: ${error}`);
795
916
  }
796
917
  }
797
918
  async fetchBalance(address) {
@@ -800,21 +921,26 @@ export class Exchange {
800
921
  const args = [];
801
922
  if (address !== undefined)
802
923
  args.push(address);
803
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/fetchBalance`, {
924
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchBalance`, {
804
925
  method: 'POST',
805
926
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
806
927
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
807
928
  });
808
929
  if (!response.ok) {
809
- const error = await response.json().catch(() => ({}));
810
- throw new Error(error.error?.message || response.statusText);
930
+ const body = await response.json().catch(() => ({}));
931
+ if (body.error && typeof body.error === "object") {
932
+ throw fromServerError(body.error);
933
+ }
934
+ throw new PmxtError(body.error?.message || response.statusText);
811
935
  }
812
936
  const json = await response.json();
813
937
  const data = this.handleResponse(json);
814
938
  return data.map(convertBalance);
815
939
  }
816
940
  catch (error) {
817
- throw new Error(`Failed to fetchBalance: ${error}`);
941
+ if (error instanceof PmxtError)
942
+ throw error;
943
+ throw new PmxtError(`Failed to fetchBalance: ${error}`);
818
944
  }
819
945
  }
820
946
  async unwatchOrderBook(id) {
@@ -822,20 +948,25 @@ export class Exchange {
822
948
  try {
823
949
  const args = [];
824
950
  args.push(id);
825
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/unwatchOrderBook`, {
951
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/unwatchOrderBook`, {
826
952
  method: 'POST',
827
953
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
828
954
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
829
955
  });
830
956
  if (!response.ok) {
831
- const error = await response.json().catch(() => ({}));
832
- throw new Error(error.error?.message || response.statusText);
957
+ const body = await response.json().catch(() => ({}));
958
+ if (body.error && typeof body.error === "object") {
959
+ throw fromServerError(body.error);
960
+ }
961
+ throw new PmxtError(body.error?.message || response.statusText);
833
962
  }
834
963
  const json = await response.json();
835
964
  this.handleResponse(json);
836
965
  }
837
966
  catch (error) {
838
- throw new Error(`Failed to unwatchOrderBook: ${error}`);
967
+ if (error instanceof PmxtError)
968
+ throw error;
969
+ throw new PmxtError(`Failed to unwatchOrderBook: ${error}`);
839
970
  }
840
971
  }
841
972
  async unwatchAddress(address) {
@@ -843,40 +974,207 @@ export class Exchange {
843
974
  try {
844
975
  const args = [];
845
976
  args.push(address);
846
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/unwatchAddress`, {
977
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/unwatchAddress`, {
847
978
  method: 'POST',
848
979
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
849
980
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
850
981
  });
851
982
  if (!response.ok) {
852
- const error = await response.json().catch(() => ({}));
853
- throw new Error(error.error?.message || response.statusText);
983
+ const body = await response.json().catch(() => ({}));
984
+ if (body.error && typeof body.error === "object") {
985
+ throw fromServerError(body.error);
986
+ }
987
+ throw new PmxtError(body.error?.message || response.statusText);
854
988
  }
855
989
  const json = await response.json();
856
990
  this.handleResponse(json);
857
991
  }
858
992
  catch (error) {
859
- throw new Error(`Failed to unwatchAddress: ${error}`);
993
+ if (error instanceof PmxtError)
994
+ throw error;
995
+ throw new PmxtError(`Failed to unwatchAddress: ${error}`);
860
996
  }
861
997
  }
862
998
  async close() {
863
999
  await this.initPromise;
864
1000
  try {
865
1001
  const args = [];
866
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/close`, {
1002
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/close`, {
867
1003
  method: 'POST',
868
1004
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
869
1005
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
870
1006
  });
871
1007
  if (!response.ok) {
872
- const error = await response.json().catch(() => ({}));
873
- throw new Error(error.error?.message || response.statusText);
1008
+ const body = await response.json().catch(() => ({}));
1009
+ if (body.error && typeof body.error === "object") {
1010
+ throw fromServerError(body.error);
1011
+ }
1012
+ throw new PmxtError(body.error?.message || response.statusText);
874
1013
  }
875
1014
  const json = await response.json();
876
1015
  this.handleResponse(json);
877
1016
  }
878
1017
  catch (error) {
879
- throw new Error(`Failed to close: ${error}`);
1018
+ if (error instanceof PmxtError)
1019
+ throw error;
1020
+ throw new PmxtError(`Failed to close: ${error}`);
1021
+ }
1022
+ }
1023
+ async fetchMarketMatches(params) {
1024
+ await this.initPromise;
1025
+ try {
1026
+ const args = [];
1027
+ args.push(params);
1028
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchMarketMatches`, {
1029
+ method: 'POST',
1030
+ headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1031
+ body: JSON.stringify({ args, credentials: this.getCredentials() }),
1032
+ });
1033
+ if (!response.ok) {
1034
+ const body = await response.json().catch(() => ({}));
1035
+ if (body.error && typeof body.error === "object") {
1036
+ throw fromServerError(body.error);
1037
+ }
1038
+ throw new PmxtError(body.error?.message || response.statusText);
1039
+ }
1040
+ const json = await response.json();
1041
+ return this.handleResponse(json);
1042
+ }
1043
+ catch (error) {
1044
+ if (error instanceof PmxtError)
1045
+ throw error;
1046
+ throw new PmxtError(`Failed to fetchMarketMatches: ${error}`);
1047
+ }
1048
+ }
1049
+ async fetchMatches(params) {
1050
+ await this.initPromise;
1051
+ try {
1052
+ const args = [];
1053
+ args.push(params);
1054
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchMatches`, {
1055
+ method: 'POST',
1056
+ headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1057
+ body: JSON.stringify({ args, credentials: this.getCredentials() }),
1058
+ });
1059
+ if (!response.ok) {
1060
+ const body = await response.json().catch(() => ({}));
1061
+ if (body.error && typeof body.error === "object") {
1062
+ throw fromServerError(body.error);
1063
+ }
1064
+ throw new PmxtError(body.error?.message || response.statusText);
1065
+ }
1066
+ const json = await response.json();
1067
+ return this.handleResponse(json);
1068
+ }
1069
+ catch (error) {
1070
+ if (error instanceof PmxtError)
1071
+ throw error;
1072
+ throw new PmxtError(`Failed to fetchMatches: ${error}`);
1073
+ }
1074
+ }
1075
+ async fetchEventMatches(params) {
1076
+ await this.initPromise;
1077
+ try {
1078
+ const args = [];
1079
+ args.push(params);
1080
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchEventMatches`, {
1081
+ method: 'POST',
1082
+ headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1083
+ body: JSON.stringify({ args, credentials: this.getCredentials() }),
1084
+ });
1085
+ if (!response.ok) {
1086
+ const body = await response.json().catch(() => ({}));
1087
+ if (body.error && typeof body.error === "object") {
1088
+ throw fromServerError(body.error);
1089
+ }
1090
+ throw new PmxtError(body.error?.message || response.statusText);
1091
+ }
1092
+ const json = await response.json();
1093
+ return this.handleResponse(json);
1094
+ }
1095
+ catch (error) {
1096
+ if (error instanceof PmxtError)
1097
+ throw error;
1098
+ throw new PmxtError(`Failed to fetchEventMatches: ${error}`);
1099
+ }
1100
+ }
1101
+ async compareMarketPrices(params) {
1102
+ await this.initPromise;
1103
+ try {
1104
+ const args = [];
1105
+ args.push(params);
1106
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/compareMarketPrices`, {
1107
+ method: 'POST',
1108
+ headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1109
+ body: JSON.stringify({ args, credentials: this.getCredentials() }),
1110
+ });
1111
+ if (!response.ok) {
1112
+ const body = await response.json().catch(() => ({}));
1113
+ if (body.error && typeof body.error === "object") {
1114
+ throw fromServerError(body.error);
1115
+ }
1116
+ throw new PmxtError(body.error?.message || response.statusText);
1117
+ }
1118
+ const json = await response.json();
1119
+ return this.handleResponse(json);
1120
+ }
1121
+ catch (error) {
1122
+ if (error instanceof PmxtError)
1123
+ throw error;
1124
+ throw new PmxtError(`Failed to compareMarketPrices: ${error}`);
1125
+ }
1126
+ }
1127
+ async fetchHedges(params) {
1128
+ await this.initPromise;
1129
+ try {
1130
+ const args = [];
1131
+ args.push(params);
1132
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchHedges`, {
1133
+ method: 'POST',
1134
+ headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1135
+ body: JSON.stringify({ args, credentials: this.getCredentials() }),
1136
+ });
1137
+ if (!response.ok) {
1138
+ const body = await response.json().catch(() => ({}));
1139
+ if (body.error && typeof body.error === "object") {
1140
+ throw fromServerError(body.error);
1141
+ }
1142
+ throw new PmxtError(body.error?.message || response.statusText);
1143
+ }
1144
+ const json = await response.json();
1145
+ return this.handleResponse(json);
1146
+ }
1147
+ catch (error) {
1148
+ if (error instanceof PmxtError)
1149
+ throw error;
1150
+ throw new PmxtError(`Failed to fetchHedges: ${error}`);
1151
+ }
1152
+ }
1153
+ async fetchArbitrage(params) {
1154
+ await this.initPromise;
1155
+ try {
1156
+ const args = [];
1157
+ if (params !== undefined)
1158
+ args.push(params);
1159
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/fetchArbitrage`, {
1160
+ method: 'POST',
1161
+ headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1162
+ body: JSON.stringify({ args, credentials: this.getCredentials() }),
1163
+ });
1164
+ if (!response.ok) {
1165
+ const body = await response.json().catch(() => ({}));
1166
+ if (body.error && typeof body.error === "object") {
1167
+ throw fromServerError(body.error);
1168
+ }
1169
+ throw new PmxtError(body.error?.message || response.statusText);
1170
+ }
1171
+ const json = await response.json();
1172
+ return this.handleResponse(json);
1173
+ }
1174
+ catch (error) {
1175
+ if (error instanceof PmxtError)
1176
+ throw error;
1177
+ throw new PmxtError(`Failed to fetchArbitrage: ${error}`);
880
1178
  }
881
1179
  }
882
1180
  // END GENERATED METHODS
@@ -981,7 +1279,7 @@ export class Exchange {
981
1279
  if (limit !== undefined) {
982
1280
  args.push(limit);
983
1281
  }
984
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/watchOrderBook`, {
1282
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/watchOrderBook`, {
985
1283
  method: 'POST',
986
1284
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
987
1285
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
@@ -1040,7 +1338,7 @@ export class Exchange {
1040
1338
  if (limit !== undefined) {
1041
1339
  args.push(limit);
1042
1340
  }
1043
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/watchTrades`, {
1341
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/watchTrades`, {
1044
1342
  method: 'POST',
1045
1343
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1046
1344
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
@@ -1090,7 +1388,7 @@ export class Exchange {
1090
1388
  if (types !== undefined) {
1091
1389
  args.push(types);
1092
1390
  }
1093
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/watchAddress`, {
1391
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/watchAddress`, {
1094
1392
  method: 'POST',
1095
1393
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1096
1394
  body: JSON.stringify({ args, credentials: this.getCredentials() }),
@@ -1178,7 +1476,7 @@ export class Exchange {
1178
1476
  if (params.fee !== undefined) {
1179
1477
  paramsDict.fee = params.fee;
1180
1478
  }
1181
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/buildOrder`, {
1479
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/buildOrder`, {
1182
1480
  method: 'POST',
1183
1481
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1184
1482
  body: JSON.stringify({ args: [paramsDict], credentials: this.getCredentials() }),
@@ -1248,7 +1546,7 @@ export class Exchange {
1248
1546
  if (params.fee !== undefined) {
1249
1547
  paramsDict.fee = params.fee;
1250
1548
  }
1251
- const response = await fetch(`${this.config.basePath}/api/${this.exchangeName}/createOrder`, {
1549
+ const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/createOrder`, {
1252
1550
  method: 'POST',
1253
1551
  headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
1254
1552
  body: JSON.stringify({ args: [paramsDict], credentials: this.getCredentials() }),
@@ -1302,8 +1600,8 @@ export class Exchange {
1302
1600
  if (credentials) {
1303
1601
  body.credentials = credentials;
1304
1602
  }
1305
- const url = `${this.config.basePath}/api/${this.exchangeName}/getExecutionPriceDetailed`;
1306
- const response = await fetch(url, {
1603
+ const url = `${this.resolveBaseUrl()}/api/${this.exchangeName}/getExecutionPriceDetailed`;
1604
+ const response = await this.fetchWithRetry(url, {
1307
1605
  method: 'POST',
1308
1606
  headers: {
1309
1607
  'Content-Type': 'application/json',