ton-provider-system 0.1.13 → 0.2.1
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.cjs +645 -218
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +241 -19
- package/dist/index.d.ts +241 -19
- package/dist/index.js +636 -219
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -557,183 +557,461 @@ function createRegistryFromData(data, logger) {
|
|
|
557
557
|
return new ProviderRegistry(mergedConfig, logger);
|
|
558
558
|
}
|
|
559
559
|
|
|
560
|
-
// src/
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
normalized = normalized.slice(0, -1);
|
|
560
|
+
// src/providers/base.ts
|
|
561
|
+
var BaseProvider = class {
|
|
562
|
+
constructor(provider) {
|
|
563
|
+
this.provider = provider;
|
|
565
564
|
}
|
|
566
|
-
|
|
567
|
-
|
|
565
|
+
/**
|
|
566
|
+
* Get the provider instance
|
|
567
|
+
*/
|
|
568
|
+
getProvider() {
|
|
569
|
+
return this.provider;
|
|
568
570
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
571
|
+
/**
|
|
572
|
+
* Build a JSON-RPC request body.
|
|
573
|
+
* Most providers use standard JSON-RPC 2.0, but some may need modifications.
|
|
574
|
+
*/
|
|
575
|
+
buildRequest(method, params = {}) {
|
|
576
|
+
return {
|
|
577
|
+
id: "1",
|
|
578
|
+
jsonrpc: "2.0",
|
|
579
|
+
method,
|
|
580
|
+
params
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Parse response from provider.
|
|
585
|
+
* Handles provider-specific response formats.
|
|
586
|
+
*/
|
|
587
|
+
parseResponse(data) {
|
|
588
|
+
if (data && typeof data === "object") {
|
|
589
|
+
const dataObj = data;
|
|
590
|
+
if ("ok" in dataObj) {
|
|
591
|
+
if (!dataObj.ok) {
|
|
592
|
+
const error = dataObj.error;
|
|
593
|
+
throw new Error(error || "API returned ok=false");
|
|
594
|
+
}
|
|
595
|
+
const result = dataObj.result;
|
|
596
|
+
return result || dataObj;
|
|
574
597
|
}
|
|
575
|
-
if (
|
|
576
|
-
return
|
|
598
|
+
if ("result" in dataObj) {
|
|
599
|
+
return dataObj.result;
|
|
577
600
|
}
|
|
578
|
-
|
|
601
|
+
if ("last" in dataObj || "@type" in dataObj) {
|
|
602
|
+
return dataObj;
|
|
603
|
+
}
|
|
604
|
+
if ("error" in dataObj) {
|
|
605
|
+
const errorObj = dataObj.error;
|
|
606
|
+
const errorMsg = typeof errorObj === "string" ? errorObj : errorObj?.message || errorObj?.code || String(errorObj);
|
|
607
|
+
throw new Error(`API error: ${errorMsg}`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return data;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Parse masterchain info from response.
|
|
614
|
+
* Validates the response structure and extracts seqno.
|
|
615
|
+
*/
|
|
616
|
+
parseMasterchainInfo(data) {
|
|
617
|
+
const info = this.parseResponse(data);
|
|
618
|
+
if (!info || typeof info !== "object") {
|
|
619
|
+
throw new Error("Invalid response structure");
|
|
620
|
+
}
|
|
621
|
+
const infoObj = info;
|
|
622
|
+
const seqno = infoObj.last?.seqno;
|
|
623
|
+
if (seqno === void 0 || seqno === null || seqno <= 0 || !Number.isInteger(seqno)) {
|
|
624
|
+
throw new Error(`Invalid seqno: ${seqno} (must be positive integer)`);
|
|
625
|
+
}
|
|
626
|
+
return info;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Validate provider configuration.
|
|
630
|
+
* Checks if required API keys are present, etc.
|
|
631
|
+
*/
|
|
632
|
+
validateConfig() {
|
|
633
|
+
return { valid: true };
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Get the normalized endpoint for this provider.
|
|
637
|
+
*/
|
|
638
|
+
getNormalizedEndpoint() {
|
|
639
|
+
return this.normalizeEndpoint(this.provider.endpointV2);
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Check if this provider requires an API key.
|
|
643
|
+
*/
|
|
644
|
+
requiresApiKey() {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Check if API key is present (if required).
|
|
649
|
+
*/
|
|
650
|
+
hasApiKey() {
|
|
651
|
+
return !!this.provider.apiKey;
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
// src/providers/chainstack.ts
|
|
656
|
+
var ChainstackProvider = class extends BaseProvider {
|
|
657
|
+
constructor(provider) {
|
|
658
|
+
super(provider);
|
|
659
|
+
}
|
|
660
|
+
normalizeEndpoint(endpoint) {
|
|
661
|
+
let normalized = endpoint.trim();
|
|
662
|
+
if (normalized.endsWith("/")) {
|
|
663
|
+
normalized = normalized.slice(0, -1);
|
|
664
|
+
}
|
|
665
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
666
|
+
return normalized;
|
|
667
|
+
}
|
|
668
|
+
if (normalized.endsWith("/api/v2")) {
|
|
579
669
|
return normalized + "/jsonRPC";
|
|
580
670
|
}
|
|
671
|
+
if (normalized.endsWith("/api/v3")) {
|
|
672
|
+
return normalized.replace("/api/v3", "/api/v2/jsonRPC");
|
|
673
|
+
}
|
|
674
|
+
return normalized;
|
|
581
675
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
676
|
+
buildHeaders() {
|
|
677
|
+
return {
|
|
678
|
+
"Content-Type": "application/json"
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
validateConfig() {
|
|
682
|
+
if (this.provider.endpointV2.includes("{key}")) {
|
|
683
|
+
return {
|
|
684
|
+
valid: false,
|
|
685
|
+
error: "Chainstack API key not resolved in endpoint URL"
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
return { valid: true };
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
// src/providers/tatum.ts
|
|
693
|
+
var TatumProvider = class extends BaseProvider {
|
|
694
|
+
constructor(provider) {
|
|
695
|
+
super(provider);
|
|
696
|
+
}
|
|
697
|
+
normalizeEndpoint(endpoint) {
|
|
698
|
+
let normalized = endpoint.trim();
|
|
699
|
+
if (normalized.endsWith("/")) {
|
|
700
|
+
normalized = normalized.slice(0, -1);
|
|
701
|
+
}
|
|
702
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
703
|
+
return normalized;
|
|
704
|
+
}
|
|
705
|
+
if (normalized.includes("gateway.tatum.io")) {
|
|
706
|
+
try {
|
|
707
|
+
const url = new URL(normalized);
|
|
708
|
+
if (!url.pathname || url.pathname === "/") {
|
|
709
|
+
return normalized + "/jsonRPC";
|
|
590
710
|
}
|
|
591
|
-
|
|
711
|
+
if (!url.pathname.toLowerCase().endsWith("/jsonrpc")) {
|
|
712
|
+
return normalized + "/jsonRPC";
|
|
713
|
+
}
|
|
714
|
+
} catch {
|
|
715
|
+
return normalized + "/jsonRPC";
|
|
592
716
|
}
|
|
593
|
-
|
|
717
|
+
}
|
|
718
|
+
return normalized;
|
|
719
|
+
}
|
|
720
|
+
buildHeaders() {
|
|
721
|
+
const headers = {
|
|
722
|
+
"Content-Type": "application/json"
|
|
723
|
+
};
|
|
724
|
+
if (this.provider.apiKey) {
|
|
725
|
+
headers["x-api-key"] = this.provider.apiKey;
|
|
726
|
+
}
|
|
727
|
+
return headers;
|
|
728
|
+
}
|
|
729
|
+
requiresApiKey() {
|
|
730
|
+
return true;
|
|
731
|
+
}
|
|
732
|
+
validateConfig() {
|
|
733
|
+
if (!this.provider.apiKey) {
|
|
734
|
+
return {
|
|
735
|
+
valid: false,
|
|
736
|
+
error: "Tatum provider requires API key (set TATUM_API_KEY_TESTNET or TATUM_API_KEY_MAINNET)"
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
return { valid: true };
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
// src/providers/onfinality.ts
|
|
744
|
+
var OnFinalityProvider = class extends BaseProvider {
|
|
745
|
+
constructor(provider) {
|
|
746
|
+
super(provider);
|
|
747
|
+
}
|
|
748
|
+
normalizeEndpoint(endpoint) {
|
|
749
|
+
let normalized = endpoint.trim();
|
|
750
|
+
if (normalized.endsWith("/")) {
|
|
751
|
+
normalized = normalized.slice(0, -1);
|
|
752
|
+
}
|
|
753
|
+
if (normalized.includes("onfinality.io")) {
|
|
754
|
+
try {
|
|
755
|
+
const url = new URL(normalized);
|
|
756
|
+
const baseUrl = normalized.split("?")[0];
|
|
757
|
+
if (!url.pathname || url.pathname === "/") {
|
|
758
|
+
if (this.provider.apiKey) {
|
|
759
|
+
return baseUrl.replace(/\/?$/, "/rpc");
|
|
760
|
+
}
|
|
761
|
+
return baseUrl.replace(/\/?$/, "/public");
|
|
762
|
+
}
|
|
763
|
+
if (url.pathname === "/rpc" || url.pathname === "/public") {
|
|
764
|
+
return baseUrl;
|
|
765
|
+
}
|
|
594
766
|
return baseUrl;
|
|
767
|
+
} catch {
|
|
768
|
+
if (normalized.includes("{key}")) {
|
|
769
|
+
return normalized.split("?")[0].replace(/\/?$/, "/public");
|
|
770
|
+
}
|
|
771
|
+
if (!normalized.includes("/rpc") && !normalized.includes("/public")) {
|
|
772
|
+
return normalized.split("?")[0] + "/public";
|
|
773
|
+
}
|
|
774
|
+
return normalized.split("?")[0];
|
|
595
775
|
}
|
|
596
|
-
return baseUrl;
|
|
597
|
-
} catch {
|
|
598
|
-
if (normalized.includes("{key}")) {
|
|
599
|
-
return normalized.split("?")[0].replace(/\/?$/, "/public");
|
|
600
|
-
}
|
|
601
|
-
if (!normalized.includes("/rpc") && !normalized.includes("/public")) {
|
|
602
|
-
return normalized.split("?")[0] + "/public";
|
|
603
|
-
}
|
|
604
|
-
return normalized.split("?")[0];
|
|
605
776
|
}
|
|
777
|
+
return normalized;
|
|
606
778
|
}
|
|
607
|
-
|
|
608
|
-
|
|
779
|
+
buildHeaders() {
|
|
780
|
+
const headers = {
|
|
781
|
+
"Content-Type": "application/json"
|
|
782
|
+
};
|
|
783
|
+
if (this.provider.apiKey) {
|
|
784
|
+
headers["apikey"] = this.provider.apiKey;
|
|
785
|
+
}
|
|
786
|
+
return headers;
|
|
609
787
|
}
|
|
610
|
-
|
|
611
|
-
|
|
788
|
+
parseResponse(data) {
|
|
789
|
+
if (typeof data === "string") {
|
|
790
|
+
if (data.includes("Backend error") || data.includes("backend error")) {
|
|
791
|
+
throw new Error(`OnFinality backend error: ${data}`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return super.parseResponse(data);
|
|
612
795
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
// src/providers/quicknode.ts
|
|
799
|
+
var QuickNodeProvider = class extends BaseProvider {
|
|
800
|
+
constructor(provider) {
|
|
801
|
+
super(provider);
|
|
802
|
+
}
|
|
803
|
+
normalizeEndpoint(endpoint) {
|
|
804
|
+
let normalized = endpoint.trim();
|
|
805
|
+
if (normalized.endsWith("/")) {
|
|
806
|
+
normalized = normalized.slice(0, -1);
|
|
807
|
+
}
|
|
808
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
809
|
+
return normalized;
|
|
810
|
+
}
|
|
811
|
+
if (normalized.includes("quiknode.pro")) {
|
|
812
|
+
try {
|
|
813
|
+
const url = new URL(normalized);
|
|
814
|
+
if (!url.pathname || url.pathname === "/") {
|
|
815
|
+
return normalized + "/jsonRPC";
|
|
816
|
+
}
|
|
817
|
+
if (!url.pathname.toLowerCase().endsWith("/jsonrpc")) {
|
|
818
|
+
return normalized + "/jsonRPC";
|
|
819
|
+
}
|
|
820
|
+
} catch {
|
|
617
821
|
return normalized + "/jsonRPC";
|
|
618
822
|
}
|
|
619
|
-
|
|
823
|
+
}
|
|
824
|
+
return normalized;
|
|
825
|
+
}
|
|
826
|
+
buildHeaders() {
|
|
827
|
+
return {
|
|
828
|
+
"Content-Type": "application/json"
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
validateConfig() {
|
|
832
|
+
if (this.provider.endpointV2.includes("{key}")) {
|
|
833
|
+
return {
|
|
834
|
+
valid: false,
|
|
835
|
+
error: "QuickNode API key not resolved in endpoint URL"
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
return { valid: true };
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
// src/providers/getblock.ts
|
|
843
|
+
var GetBlockProvider = class extends BaseProvider {
|
|
844
|
+
constructor(provider) {
|
|
845
|
+
super(provider);
|
|
846
|
+
}
|
|
847
|
+
normalizeEndpoint(endpoint) {
|
|
848
|
+
let normalized = endpoint.trim();
|
|
849
|
+
if (normalized.endsWith("/")) {
|
|
850
|
+
normalized = normalized.slice(0, -1);
|
|
851
|
+
}
|
|
852
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
853
|
+
return normalized;
|
|
854
|
+
}
|
|
855
|
+
if (normalized.includes("getblock.io")) {
|
|
856
|
+
try {
|
|
857
|
+
const url = new URL(normalized);
|
|
858
|
+
if (!url.pathname || url.pathname === "/") {
|
|
859
|
+
return normalized + "/jsonRPC";
|
|
860
|
+
}
|
|
861
|
+
if (!url.pathname.toLowerCase().endsWith("/jsonrpc")) {
|
|
862
|
+
return normalized + "/jsonRPC";
|
|
863
|
+
}
|
|
864
|
+
} catch {
|
|
620
865
|
return normalized + "/jsonRPC";
|
|
621
866
|
}
|
|
622
|
-
} catch {
|
|
623
|
-
return normalized + "/jsonRPC";
|
|
624
867
|
}
|
|
868
|
+
return normalized;
|
|
625
869
|
}
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
870
|
+
buildHeaders() {
|
|
871
|
+
const headers = {
|
|
872
|
+
"Content-Type": "application/json"
|
|
873
|
+
};
|
|
874
|
+
if (this.provider.apiKey) {
|
|
875
|
+
headers["x-api-key"] = this.provider.apiKey;
|
|
630
876
|
}
|
|
631
|
-
|
|
632
|
-
}
|
|
633
|
-
return normalized;
|
|
634
|
-
}
|
|
635
|
-
function toV2Base(endpoint) {
|
|
636
|
-
let normalized = endpoint.trim();
|
|
637
|
-
if (normalized.endsWith("/")) {
|
|
638
|
-
normalized = normalized.slice(0, -1);
|
|
877
|
+
return headers;
|
|
639
878
|
}
|
|
640
|
-
|
|
641
|
-
|
|
879
|
+
requiresApiKey() {
|
|
880
|
+
return true;
|
|
642
881
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
882
|
+
validateConfig() {
|
|
883
|
+
if (!this.provider.apiKey) {
|
|
884
|
+
return {
|
|
885
|
+
valid: false,
|
|
886
|
+
error: "GetBlock provider requires API key"
|
|
887
|
+
};
|
|
648
888
|
}
|
|
889
|
+
return { valid: true };
|
|
649
890
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
function getBaseUrl(endpoint) {
|
|
657
|
-
try {
|
|
658
|
-
const url = new URL(endpoint);
|
|
659
|
-
return `${url.protocol}//${url.host}`;
|
|
660
|
-
} catch {
|
|
661
|
-
return endpoint;
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
// src/providers/toncenter.ts
|
|
894
|
+
var TonCenterProvider = class extends BaseProvider {
|
|
895
|
+
constructor(provider) {
|
|
896
|
+
super(provider);
|
|
662
897
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
898
|
+
normalizeEndpoint(endpoint) {
|
|
899
|
+
let normalized = endpoint.trim();
|
|
900
|
+
if (normalized.endsWith("/")) {
|
|
901
|
+
normalized = normalized.slice(0, -1);
|
|
902
|
+
}
|
|
903
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
904
|
+
return normalized;
|
|
905
|
+
}
|
|
906
|
+
if (normalized.endsWith("/api/v2")) {
|
|
907
|
+
return normalized + "/jsonRPC";
|
|
908
|
+
}
|
|
909
|
+
if (normalized.endsWith("/api/v3")) {
|
|
910
|
+
return normalized.replace("/api/v3", "/api/v2/jsonRPC");
|
|
911
|
+
}
|
|
912
|
+
return normalized;
|
|
670
913
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
return parsed.hostname.includes("quiknode.pro");
|
|
676
|
-
} catch {
|
|
677
|
-
return false;
|
|
914
|
+
buildHeaders() {
|
|
915
|
+
return {
|
|
916
|
+
"Content-Type": "application/json"
|
|
917
|
+
};
|
|
678
918
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
try {
|
|
682
|
-
const parsed = new URL(url.trim());
|
|
683
|
-
return parsed.hostname.includes("toncenter.com");
|
|
684
|
-
} catch {
|
|
919
|
+
// TON Center API key is optional (1 RPS without key, 10 RPS with key)
|
|
920
|
+
requiresApiKey() {
|
|
685
921
|
return false;
|
|
686
922
|
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
return false;
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
// src/providers/orbs.ts
|
|
926
|
+
var OrbsProvider = class extends BaseProvider {
|
|
927
|
+
constructor(provider) {
|
|
928
|
+
super(provider);
|
|
694
929
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
const base = toV2Base(baseEndpoint);
|
|
710
|
-
return `${base}/getAddressInformation?address=${encodeURIComponent(address)}`;
|
|
711
|
-
}
|
|
712
|
-
function detectNetworkFromEndpoint(endpoint) {
|
|
713
|
-
const lower = endpoint.toLowerCase();
|
|
714
|
-
if (lower.includes("testnet") || lower.includes("test") || lower.includes("sandbox")) {
|
|
715
|
-
return "testnet";
|
|
930
|
+
normalizeEndpoint(endpoint) {
|
|
931
|
+
let normalized = endpoint.trim();
|
|
932
|
+
if (normalized.endsWith("/")) {
|
|
933
|
+
normalized = normalized.slice(0, -1);
|
|
934
|
+
}
|
|
935
|
+
if (normalized.endsWith("/api/v2")) {
|
|
936
|
+
return normalized;
|
|
937
|
+
}
|
|
938
|
+
return normalized;
|
|
939
|
+
}
|
|
940
|
+
buildHeaders() {
|
|
941
|
+
return {
|
|
942
|
+
"Content-Type": "application/json"
|
|
943
|
+
};
|
|
716
944
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
945
|
+
/**
|
|
946
|
+
* Get dynamic endpoint from Orbs TON Access.
|
|
947
|
+
* This should be called before making requests.
|
|
948
|
+
*/
|
|
949
|
+
async getDynamicEndpoint() {
|
|
950
|
+
if (!this.provider.isDynamic) {
|
|
951
|
+
return this.normalizeEndpoint(this.provider.endpointV2);
|
|
952
|
+
}
|
|
953
|
+
try {
|
|
954
|
+
const { getHttpEndpoint } = await import('@orbs-network/ton-access');
|
|
955
|
+
const endpoint = await getHttpEndpoint({ network: this.provider.network });
|
|
956
|
+
return this.normalizeEndpoint(endpoint);
|
|
957
|
+
} catch (error) {
|
|
958
|
+
return this.normalizeEndpoint(this.provider.endpointV2);
|
|
959
|
+
}
|
|
720
960
|
}
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
function isValidHttpUrl(str) {
|
|
724
|
-
try {
|
|
725
|
-
const url = new URL(str);
|
|
726
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
|
727
|
-
} catch {
|
|
961
|
+
requiresApiKey() {
|
|
728
962
|
return false;
|
|
729
963
|
}
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
964
|
+
};
|
|
965
|
+
|
|
966
|
+
// src/providers/index.ts
|
|
967
|
+
var GenericProvider = class extends BaseProvider {
|
|
968
|
+
normalizeEndpoint(endpoint) {
|
|
969
|
+
let normalized = endpoint.trim();
|
|
970
|
+
if (normalized.endsWith("/")) {
|
|
971
|
+
normalized = normalized.slice(0, -1);
|
|
972
|
+
}
|
|
973
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
974
|
+
return normalized;
|
|
975
|
+
}
|
|
976
|
+
try {
|
|
977
|
+
const url = new URL(normalized);
|
|
978
|
+
if (!url.pathname || url.pathname === "/") {
|
|
979
|
+
return normalized + "/jsonRPC";
|
|
980
|
+
}
|
|
981
|
+
} catch {
|
|
982
|
+
}
|
|
983
|
+
return normalized;
|
|
984
|
+
}
|
|
985
|
+
buildHeaders() {
|
|
986
|
+
const headers = {
|
|
987
|
+
"Content-Type": "application/json"
|
|
988
|
+
};
|
|
989
|
+
if (this.provider.apiKey) {
|
|
990
|
+
headers["x-api-key"] = this.provider.apiKey;
|
|
991
|
+
}
|
|
992
|
+
return headers;
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
function createProvider(provider) {
|
|
996
|
+
switch (provider.type) {
|
|
997
|
+
case "chainstack":
|
|
998
|
+
return new ChainstackProvider(provider);
|
|
999
|
+
case "tatum":
|
|
1000
|
+
return new TatumProvider(provider);
|
|
1001
|
+
case "onfinality":
|
|
1002
|
+
return new OnFinalityProvider(provider);
|
|
1003
|
+
case "quicknode":
|
|
1004
|
+
return new QuickNodeProvider(provider);
|
|
1005
|
+
case "getblock":
|
|
1006
|
+
return new GetBlockProvider(provider);
|
|
1007
|
+
case "toncenter":
|
|
1008
|
+
return new TonCenterProvider(provider);
|
|
1009
|
+
case "orbs":
|
|
1010
|
+
return new OrbsProvider(provider);
|
|
1011
|
+
case "custom":
|
|
1012
|
+
return new GenericProvider(provider);
|
|
1013
|
+
default:
|
|
1014
|
+
return new GenericProvider(provider);
|
|
737
1015
|
}
|
|
738
1016
|
}
|
|
739
1017
|
|
|
@@ -793,21 +1071,25 @@ var HealthChecker = class {
|
|
|
793
1071
|
if (!endpoint) {
|
|
794
1072
|
throw new Error("No valid endpoint available");
|
|
795
1073
|
}
|
|
796
|
-
|
|
797
|
-
|
|
1074
|
+
const providerImpl = createProvider(provider);
|
|
1075
|
+
const validation = providerImpl.validateConfig();
|
|
1076
|
+
if (!validation.valid) {
|
|
1077
|
+
throw new Error(validation.error || "Provider configuration invalid");
|
|
798
1078
|
}
|
|
799
|
-
|
|
1079
|
+
const normalizedEndpoint = providerImpl.normalizeEndpoint(endpoint);
|
|
800
1080
|
if (provider.type === "onfinality") {
|
|
801
1081
|
this.logger.debug(`OnFinality endpoint: ${endpoint} -> ${normalizedEndpoint}, API key: ${provider.apiKey ? "set" : "not set"}`);
|
|
802
1082
|
}
|
|
803
1083
|
let info;
|
|
804
1084
|
try {
|
|
805
|
-
info = await this.callGetMasterchainInfo(normalizedEndpoint, provider);
|
|
1085
|
+
info = await this.callGetMasterchainInfo(normalizedEndpoint, provider, providerImpl);
|
|
806
1086
|
} catch (error) {
|
|
807
1087
|
if (provider.type === "onfinality" && normalizedEndpoint.includes("/rpc") && provider.apiKey && error.message?.includes("backend error")) {
|
|
808
1088
|
this.logger.debug(`OnFinality /rpc failed, retrying with /public endpoint`);
|
|
809
1089
|
const publicEndpoint = normalizedEndpoint.replace("/rpc", "/public");
|
|
810
|
-
|
|
1090
|
+
const publicProvider = { ...provider, apiKey: void 0 };
|
|
1091
|
+
const publicProviderImpl = createProvider(publicProvider);
|
|
1092
|
+
info = await this.callGetMasterchainInfo(publicEndpoint, publicProvider, publicProviderImpl);
|
|
811
1093
|
} else {
|
|
812
1094
|
throw error;
|
|
813
1095
|
}
|
|
@@ -953,14 +1235,17 @@ var HealthChecker = class {
|
|
|
953
1235
|
}
|
|
954
1236
|
/**
|
|
955
1237
|
* Mark a provider as degraded (e.g., on 429 error)
|
|
1238
|
+
*
|
|
1239
|
+
* Providers marked as degraded have failed health checks (e.g., rate limit errors)
|
|
1240
|
+
* and should not be selected. The system will failover to the next available provider.
|
|
956
1241
|
*/
|
|
957
1242
|
markDegraded(providerId, network, error) {
|
|
958
1243
|
const key = this.getResultKey(providerId, network);
|
|
959
1244
|
const existing = this.results.get(key);
|
|
960
1245
|
const result = existing ? {
|
|
961
1246
|
...existing,
|
|
962
|
-
success:
|
|
963
|
-
// Degraded providers
|
|
1247
|
+
success: false,
|
|
1248
|
+
// Degraded providers with errors should not be selected
|
|
964
1249
|
status: "degraded",
|
|
965
1250
|
error: error || "Marked as degraded",
|
|
966
1251
|
lastTested: /* @__PURE__ */ new Date(),
|
|
@@ -968,8 +1253,8 @@ var HealthChecker = class {
|
|
|
968
1253
|
} : {
|
|
969
1254
|
id: providerId,
|
|
970
1255
|
network,
|
|
971
|
-
success:
|
|
972
|
-
// Degraded providers
|
|
1256
|
+
success: false,
|
|
1257
|
+
// Degraded providers with errors should not be selected
|
|
973
1258
|
status: "degraded",
|
|
974
1259
|
latencyMs: null,
|
|
975
1260
|
seqno: null,
|
|
@@ -1032,44 +1317,19 @@ var HealthChecker = class {
|
|
|
1032
1317
|
}
|
|
1033
1318
|
return provider.endpointV2 || provider.endpointV3 || null;
|
|
1034
1319
|
}
|
|
1035
|
-
/**
|
|
1036
|
-
* Normalize endpoint for provider-specific requirements
|
|
1037
|
-
*
|
|
1038
|
-
* Note: normalizeV2Endpoint now handles all provider-specific cases correctly,
|
|
1039
|
-
* including Tatum (/jsonRPC), OnFinality (/public or /rpc), QuickNode, and GetBlock.
|
|
1040
|
-
*/
|
|
1041
|
-
normalizeEndpointForProvider(provider, endpoint) {
|
|
1042
|
-
if (provider.type === "tatum" && endpoint.includes("api.tatum.io/v3/blockchain/node")) {
|
|
1043
|
-
const network = provider.network === "testnet" ? "testnet" : "mainnet";
|
|
1044
|
-
endpoint = `https://ton-${network}.gateway.tatum.io`;
|
|
1045
|
-
}
|
|
1046
|
-
return normalizeV2Endpoint(endpoint);
|
|
1047
|
-
}
|
|
1048
1320
|
/**
|
|
1049
1321
|
* Call getMasterchainInfo API with provider-specific handling
|
|
1050
1322
|
*/
|
|
1051
|
-
async callGetMasterchainInfo(endpoint, provider) {
|
|
1323
|
+
async callGetMasterchainInfo(endpoint, provider, providerImpl) {
|
|
1052
1324
|
const controller = new AbortController();
|
|
1053
1325
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeoutMs);
|
|
1054
|
-
const headers =
|
|
1055
|
-
|
|
1056
|
-
};
|
|
1057
|
-
if (provider.type === "tatum" && provider.apiKey) {
|
|
1058
|
-
headers["x-api-key"] = provider.apiKey;
|
|
1059
|
-
}
|
|
1060
|
-
if (provider.type === "onfinality" && provider.apiKey) {
|
|
1061
|
-
headers["apikey"] = provider.apiKey;
|
|
1062
|
-
}
|
|
1326
|
+
const headers = providerImpl.buildHeaders();
|
|
1327
|
+
const requestBody = providerImpl.buildRequest("getMasterchainInfo", {});
|
|
1063
1328
|
try {
|
|
1064
1329
|
const response = await fetch(endpoint, {
|
|
1065
1330
|
method: "POST",
|
|
1066
1331
|
headers,
|
|
1067
|
-
body: JSON.stringify(
|
|
1068
|
-
id: "1",
|
|
1069
|
-
jsonrpc: "2.0",
|
|
1070
|
-
method: "getMasterchainInfo",
|
|
1071
|
-
params: {}
|
|
1072
|
-
}),
|
|
1332
|
+
body: JSON.stringify(requestBody),
|
|
1073
1333
|
signal: controller.signal
|
|
1074
1334
|
});
|
|
1075
1335
|
clearTimeout(timeoutId);
|
|
@@ -1095,40 +1355,7 @@ var HealthChecker = class {
|
|
|
1095
1355
|
}
|
|
1096
1356
|
}
|
|
1097
1357
|
data = await response.json();
|
|
1098
|
-
|
|
1099
|
-
if (data && typeof data === "object") {
|
|
1100
|
-
const dataObj = data;
|
|
1101
|
-
if ("ok" in dataObj) {
|
|
1102
|
-
if (!dataObj.ok) {
|
|
1103
|
-
const error = dataObj.error;
|
|
1104
|
-
throw new Error(error || "API returned ok=false");
|
|
1105
|
-
}
|
|
1106
|
-
const result = dataObj.result;
|
|
1107
|
-
info = result || dataObj;
|
|
1108
|
-
} else if ("result" in dataObj) {
|
|
1109
|
-
info = dataObj.result;
|
|
1110
|
-
} else if ("last" in dataObj || "@type" in dataObj) {
|
|
1111
|
-
info = dataObj;
|
|
1112
|
-
} else if ("error" in dataObj) {
|
|
1113
|
-
const errorObj = dataObj.error;
|
|
1114
|
-
const errorMsg = typeof errorObj === "string" ? errorObj : errorObj?.message || errorObj?.code || String(errorObj);
|
|
1115
|
-
throw new Error(`API error: ${errorMsg}`);
|
|
1116
|
-
} else {
|
|
1117
|
-
throw new Error(`Unknown response format from ${provider.type}`);
|
|
1118
|
-
}
|
|
1119
|
-
} else {
|
|
1120
|
-
throw new Error(`Invalid response type: ${typeof data}`);
|
|
1121
|
-
}
|
|
1122
|
-
if (!info || typeof info !== "object") {
|
|
1123
|
-
this.logger.debug(`Invalid response structure from ${provider.type}: ${JSON.stringify(data)}`);
|
|
1124
|
-
throw new Error("Invalid response structure");
|
|
1125
|
-
}
|
|
1126
|
-
const infoObj = info;
|
|
1127
|
-
const seqno = infoObj.last?.seqno;
|
|
1128
|
-
if (seqno === void 0 || seqno === null || seqno <= 0 || !Number.isInteger(seqno)) {
|
|
1129
|
-
this.logger.debug(`Invalid seqno from ${provider.type}:`, { seqno, info });
|
|
1130
|
-
throw new Error(`Invalid seqno: ${seqno} (must be positive integer)`);
|
|
1131
|
-
}
|
|
1358
|
+
const info = providerImpl.parseMasterchainInfo(data);
|
|
1132
1359
|
return info;
|
|
1133
1360
|
} catch (error) {
|
|
1134
1361
|
clearTimeout(timeoutId);
|
|
@@ -1988,6 +2215,193 @@ function createSelector(registry, healthChecker, config, logger, adapter = "node
|
|
|
1988
2215
|
return new ProviderSelector(registry, healthChecker, config, logger, adapter);
|
|
1989
2216
|
}
|
|
1990
2217
|
|
|
2218
|
+
// src/utils/endpoint.ts
|
|
2219
|
+
function normalizeV2Endpoint(endpoint, provider) {
|
|
2220
|
+
if (provider) {
|
|
2221
|
+
const providerImpl = createProvider(provider);
|
|
2222
|
+
return providerImpl.normalizeEndpoint(endpoint);
|
|
2223
|
+
}
|
|
2224
|
+
return normalizeV2EndpointFallback(endpoint);
|
|
2225
|
+
}
|
|
2226
|
+
function normalizeV2EndpointFallback(endpoint) {
|
|
2227
|
+
let normalized = endpoint.trim();
|
|
2228
|
+
if (normalized.endsWith("/")) {
|
|
2229
|
+
normalized = normalized.slice(0, -1);
|
|
2230
|
+
}
|
|
2231
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
2232
|
+
return normalized;
|
|
2233
|
+
}
|
|
2234
|
+
if (normalized.includes("gateway.tatum.io")) {
|
|
2235
|
+
try {
|
|
2236
|
+
const url = new URL(normalized);
|
|
2237
|
+
if (!url.pathname || url.pathname === "/") {
|
|
2238
|
+
return normalized + "/jsonRPC";
|
|
2239
|
+
}
|
|
2240
|
+
if (!url.pathname.toLowerCase().endsWith("/jsonrpc")) {
|
|
2241
|
+
return normalized + "/jsonRPC";
|
|
2242
|
+
}
|
|
2243
|
+
} catch {
|
|
2244
|
+
return normalized + "/jsonRPC";
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
if (normalized.includes("onfinality.io")) {
|
|
2248
|
+
try {
|
|
2249
|
+
const url = new URL(normalized);
|
|
2250
|
+
const baseUrl = normalized.split("?")[0];
|
|
2251
|
+
if (!url.pathname || url.pathname === "/") {
|
|
2252
|
+
const apikey = url.searchParams.get("apikey");
|
|
2253
|
+
if (apikey && apikey !== "{key}" && apikey.length > 0) {
|
|
2254
|
+
return baseUrl.replace(/\/?$/, "/rpc");
|
|
2255
|
+
}
|
|
2256
|
+
return baseUrl.replace(/\/?$/, "/public");
|
|
2257
|
+
}
|
|
2258
|
+
if (url.pathname === "/rpc" || url.pathname === "/public") {
|
|
2259
|
+
return baseUrl;
|
|
2260
|
+
}
|
|
2261
|
+
return baseUrl;
|
|
2262
|
+
} catch {
|
|
2263
|
+
if (normalized.includes("{key}")) {
|
|
2264
|
+
return normalized.split("?")[0].replace(/\/?$/, "/public");
|
|
2265
|
+
}
|
|
2266
|
+
if (!normalized.includes("/rpc") && !normalized.includes("/public")) {
|
|
2267
|
+
return normalized.split("?")[0] + "/public";
|
|
2268
|
+
}
|
|
2269
|
+
return normalized.split("?")[0];
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
if (normalized.endsWith("/api/v2")) {
|
|
2273
|
+
return normalized + "/jsonRPC";
|
|
2274
|
+
}
|
|
2275
|
+
if (normalized.endsWith("/api/v3")) {
|
|
2276
|
+
return normalized.replace("/api/v3", "/api/v2/jsonRPC");
|
|
2277
|
+
}
|
|
2278
|
+
if (normalized.includes("quiknode.pro") || normalized.includes("getblock.io")) {
|
|
2279
|
+
try {
|
|
2280
|
+
const url = new URL(normalized);
|
|
2281
|
+
if (!url.pathname || url.pathname === "/") {
|
|
2282
|
+
return normalized + "/jsonRPC";
|
|
2283
|
+
}
|
|
2284
|
+
if (!url.pathname.toLowerCase().endsWith("/jsonrpc")) {
|
|
2285
|
+
return normalized + "/jsonRPC";
|
|
2286
|
+
}
|
|
2287
|
+
} catch {
|
|
2288
|
+
return normalized + "/jsonRPC";
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
try {
|
|
2292
|
+
const url = new URL(normalized);
|
|
2293
|
+
if (!url.pathname || url.pathname === "/") {
|
|
2294
|
+
return normalized + "/jsonRPC";
|
|
2295
|
+
}
|
|
2296
|
+
} catch {
|
|
2297
|
+
}
|
|
2298
|
+
return normalized;
|
|
2299
|
+
}
|
|
2300
|
+
function toV2Base(endpoint) {
|
|
2301
|
+
let normalized = endpoint.trim();
|
|
2302
|
+
if (normalized.endsWith("/")) {
|
|
2303
|
+
normalized = normalized.slice(0, -1);
|
|
2304
|
+
}
|
|
2305
|
+
if (normalized.toLowerCase().endsWith("/jsonrpc")) {
|
|
2306
|
+
normalized = normalized.slice(0, -8);
|
|
2307
|
+
}
|
|
2308
|
+
normalized = normalized.replace(/\/api\/v3\b/, "/api/v2");
|
|
2309
|
+
if (!normalized.endsWith("/api/v2")) {
|
|
2310
|
+
if (normalized.includes("/api/v2")) {
|
|
2311
|
+
const idx = normalized.indexOf("/api/v2");
|
|
2312
|
+
normalized = normalized.slice(0, idx + 7);
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
return normalized;
|
|
2316
|
+
}
|
|
2317
|
+
function toV3Base(endpoint) {
|
|
2318
|
+
const normalized = toV2Base(endpoint);
|
|
2319
|
+
return normalized.replace("/api/v2", "/api/v3");
|
|
2320
|
+
}
|
|
2321
|
+
function getBaseUrl(endpoint) {
|
|
2322
|
+
try {
|
|
2323
|
+
const url = new URL(endpoint);
|
|
2324
|
+
return `${url.protocol}//${url.host}`;
|
|
2325
|
+
} catch {
|
|
2326
|
+
return endpoint;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
function isChainstackUrl(url) {
|
|
2330
|
+
try {
|
|
2331
|
+
const parsed = new URL(url.trim());
|
|
2332
|
+
return parsed.hostname.includes("chainstack.com");
|
|
2333
|
+
} catch {
|
|
2334
|
+
return false;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
function isQuickNodeUrl(url) {
|
|
2338
|
+
try {
|
|
2339
|
+
const parsed = new URL(url.trim());
|
|
2340
|
+
return parsed.hostname.includes("quiknode.pro");
|
|
2341
|
+
} catch {
|
|
2342
|
+
return false;
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
function isTonCenterUrl(url) {
|
|
2346
|
+
try {
|
|
2347
|
+
const parsed = new URL(url.trim());
|
|
2348
|
+
return parsed.hostname.includes("toncenter.com");
|
|
2349
|
+
} catch {
|
|
2350
|
+
return false;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
function isOrbsUrl(url) {
|
|
2354
|
+
try {
|
|
2355
|
+
const parsed = new URL(url.trim());
|
|
2356
|
+
return parsed.hostname.includes("orbs.network") || parsed.hostname.includes("ton-access");
|
|
2357
|
+
} catch {
|
|
2358
|
+
return false;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
function buildRestUrl(baseEndpoint, method) {
|
|
2362
|
+
const base = toV2Base(baseEndpoint);
|
|
2363
|
+
return `${base}/${method}`;
|
|
2364
|
+
}
|
|
2365
|
+
function buildGetAddressStateUrl(baseEndpoint, address) {
|
|
2366
|
+
const base = toV2Base(baseEndpoint);
|
|
2367
|
+
return `${base}/getAddressState?address=${encodeURIComponent(address)}`;
|
|
2368
|
+
}
|
|
2369
|
+
function buildGetAddressBalanceUrl(baseEndpoint, address) {
|
|
2370
|
+
const base = toV2Base(baseEndpoint);
|
|
2371
|
+
return `${base}/getAddressBalance?address=${encodeURIComponent(address)}`;
|
|
2372
|
+
}
|
|
2373
|
+
function buildGetAddressInfoUrl(baseEndpoint, address) {
|
|
2374
|
+
const base = toV2Base(baseEndpoint);
|
|
2375
|
+
return `${base}/getAddressInformation?address=${encodeURIComponent(address)}`;
|
|
2376
|
+
}
|
|
2377
|
+
function detectNetworkFromEndpoint(endpoint) {
|
|
2378
|
+
const lower = endpoint.toLowerCase();
|
|
2379
|
+
if (lower.includes("testnet") || lower.includes("test") || lower.includes("sandbox")) {
|
|
2380
|
+
return "testnet";
|
|
2381
|
+
}
|
|
2382
|
+
if (lower.includes("mainnet") || lower.includes("main") || // TonCenter mainnet doesn't have 'mainnet' in URL
|
|
2383
|
+
lower.includes("toncenter.com") && !lower.includes("testnet")) {
|
|
2384
|
+
return "mainnet";
|
|
2385
|
+
}
|
|
2386
|
+
return null;
|
|
2387
|
+
}
|
|
2388
|
+
function isValidHttpUrl(str) {
|
|
2389
|
+
try {
|
|
2390
|
+
const url = new URL(str);
|
|
2391
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
2392
|
+
} catch {
|
|
2393
|
+
return false;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
function isValidWsUrl(str) {
|
|
2397
|
+
try {
|
|
2398
|
+
const url = new URL(str);
|
|
2399
|
+
return url.protocol === "ws:" || url.protocol === "wss:";
|
|
2400
|
+
} catch {
|
|
2401
|
+
return false;
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
|
|
1991
2405
|
// src/core/manager.ts
|
|
1992
2406
|
var consoleLogger5 = {
|
|
1993
2407
|
debug: (msg, data) => console.debug(`[ProviderManager] ${msg}`, data || ""),
|
|
@@ -2186,17 +2600,20 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2186
2600
|
this.options.logger.warn("No providers available, using fallback");
|
|
2187
2601
|
return this.getFallbackEndpoint();
|
|
2188
2602
|
}
|
|
2189
|
-
|
|
2603
|
+
const activeProviderId = this.selector.getActiveProviderId(this.network);
|
|
2604
|
+
if (!activeProviderId) {
|
|
2605
|
+
this.selector.getBestProvider(this.network);
|
|
2606
|
+
}
|
|
2190
2607
|
if (provider.isDynamic && provider.type === "orbs") {
|
|
2191
2608
|
try {
|
|
2192
2609
|
const { getHttpEndpoint } = await import('@orbs-network/ton-access');
|
|
2193
2610
|
const endpoint = await getHttpEndpoint({ network: this.network });
|
|
2194
|
-
return normalizeV2Endpoint(endpoint);
|
|
2611
|
+
return normalizeV2Endpoint(endpoint, provider);
|
|
2195
2612
|
} catch (error) {
|
|
2196
2613
|
this.options.logger.warn(`Failed to get Orbs endpoint: ${error.message}`);
|
|
2197
2614
|
}
|
|
2198
2615
|
}
|
|
2199
|
-
return normalizeV2Endpoint(provider.endpointV2);
|
|
2616
|
+
return normalizeV2Endpoint(provider.endpointV2, provider);
|
|
2200
2617
|
}
|
|
2201
2618
|
/**
|
|
2202
2619
|
* Get endpoint with rate limiting
|
|
@@ -2219,11 +2636,11 @@ var _ProviderManager = class _ProviderManager {
|
|
|
2219
2636
|
this.options.logger.warn(`Rate limit timeout for ${provider.id}`);
|
|
2220
2637
|
const next = this.selector.getNextProvider(this.network, [provider.id]);
|
|
2221
2638
|
if (next) {
|
|
2222
|
-
return normalizeV2Endpoint(next.endpointV2);
|
|
2639
|
+
return normalizeV2Endpoint(next.endpointV2, next);
|
|
2223
2640
|
}
|
|
2224
2641
|
return this.getFallbackEndpoint();
|
|
2225
2642
|
}
|
|
2226
|
-
return normalizeV2Endpoint(provider.endpointV2);
|
|
2643
|
+
return normalizeV2Endpoint(provider.endpointV2, provider);
|
|
2227
2644
|
}
|
|
2228
2645
|
/**
|
|
2229
2646
|
* Get current active provider
|
|
@@ -3083,18 +3500,24 @@ async function createBrowserAdapterForNetwork(network, configPath, logger) {
|
|
|
3083
3500
|
}
|
|
3084
3501
|
|
|
3085
3502
|
exports.ApiVersionSchema = ApiVersionSchema;
|
|
3503
|
+
exports.BaseProvider = BaseProvider;
|
|
3086
3504
|
exports.BrowserAdapter = BrowserAdapter;
|
|
3087
3505
|
exports.CHAINSTACK_RATE_LIMIT = CHAINSTACK_RATE_LIMIT;
|
|
3506
|
+
exports.ChainstackProvider = ChainstackProvider;
|
|
3088
3507
|
exports.ConfigError = ConfigError;
|
|
3089
3508
|
exports.DEFAULT_CONTRACT_TIMEOUT_MS = DEFAULT_CONTRACT_TIMEOUT_MS;
|
|
3090
3509
|
exports.DEFAULT_HEALTH_CHECK_TIMEOUT_MS = DEFAULT_HEALTH_CHECK_TIMEOUT_MS;
|
|
3091
3510
|
exports.DEFAULT_PROVIDERS = DEFAULT_PROVIDERS;
|
|
3092
3511
|
exports.DEFAULT_PROVIDER_TIMEOUT_MS = DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
3093
3512
|
exports.DEFAULT_RATE_LIMIT = DEFAULT_RATE_LIMIT;
|
|
3513
|
+
exports.GenericProvider = GenericProvider;
|
|
3514
|
+
exports.GetBlockProvider = GetBlockProvider;
|
|
3094
3515
|
exports.HealthChecker = HealthChecker;
|
|
3095
3516
|
exports.NetworkSchema = NetworkSchema;
|
|
3096
3517
|
exports.NodeAdapter = NodeAdapter;
|
|
3097
3518
|
exports.ORBS_RATE_LIMIT = ORBS_RATE_LIMIT;
|
|
3519
|
+
exports.OnFinalityProvider = OnFinalityProvider;
|
|
3520
|
+
exports.OrbsProvider = OrbsProvider;
|
|
3098
3521
|
exports.ProviderConfigSchema = ProviderConfigSchema;
|
|
3099
3522
|
exports.ProviderError = ProviderError;
|
|
3100
3523
|
exports.ProviderManager = ProviderManager;
|
|
@@ -3102,11 +3525,14 @@ exports.ProviderRegistry = ProviderRegistry;
|
|
|
3102
3525
|
exports.ProviderSelector = ProviderSelector;
|
|
3103
3526
|
exports.ProviderTypeSchema = ProviderTypeSchema;
|
|
3104
3527
|
exports.QUICKNODE_RATE_LIMIT = QUICKNODE_RATE_LIMIT;
|
|
3528
|
+
exports.QuickNodeProvider = QuickNodeProvider;
|
|
3105
3529
|
exports.RateLimitError = RateLimitError;
|
|
3106
3530
|
exports.RateLimiterManager = RateLimiterManager;
|
|
3107
3531
|
exports.RpcConfigSchema = RpcConfigSchema;
|
|
3532
|
+
exports.TatumProvider = TatumProvider;
|
|
3108
3533
|
exports.TimeoutError = TimeoutError;
|
|
3109
3534
|
exports.TokenBucketRateLimiter = TokenBucketRateLimiter;
|
|
3535
|
+
exports.TonCenterProvider = TonCenterProvider;
|
|
3110
3536
|
exports.buildGetAddressBalanceUrl = buildGetAddressBalanceUrl;
|
|
3111
3537
|
exports.buildGetAddressInfoUrl = buildGetAddressInfoUrl;
|
|
3112
3538
|
exports.buildGetAddressStateUrl = buildGetAddressStateUrl;
|
|
@@ -3118,6 +3544,7 @@ exports.createDefaultRegistry = createDefaultRegistry;
|
|
|
3118
3544
|
exports.createEmptyConfig = createEmptyConfig;
|
|
3119
3545
|
exports.createHealthChecker = createHealthChecker;
|
|
3120
3546
|
exports.createNodeAdapter = createNodeAdapter;
|
|
3547
|
+
exports.createProvider = createProvider;
|
|
3121
3548
|
exports.createProviderManager = createProviderManager;
|
|
3122
3549
|
exports.createRateLimiter = createRateLimiter;
|
|
3123
3550
|
exports.createRateLimiterManager = createRateLimiterManager;
|