opentool 0.17.1 → 0.18.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/adapters/hyperliquid/browser.d.ts +1 -1
- package/dist/adapters/hyperliquid/browser.js +866 -701
- package/dist/adapters/hyperliquid/browser.js.map +1 -1
- package/dist/adapters/hyperliquid/index.d.ts +2 -2
- package/dist/adapters/hyperliquid/index.js +205 -38
- package/dist/adapters/hyperliquid/index.js.map +1 -1
- package/dist/{browser-DA4UUBo1.d.ts → browser-CnpOj35m.d.ts} +66 -17
- package/dist/index.d.ts +1 -1
- package/dist/index.js +204 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/base/package.json +1 -1
|
@@ -681,344 +681,775 @@ function assertPositiveNumber(value, label) {
|
|
|
681
681
|
}
|
|
682
682
|
}
|
|
683
683
|
|
|
684
|
-
// src/adapters/hyperliquid/
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
});
|
|
692
|
-
const data = await response.json().catch(() => null);
|
|
693
|
-
if (!response.ok) {
|
|
694
|
-
throw new HyperliquidApiError(
|
|
695
|
-
"Hyperliquid info request failed.",
|
|
696
|
-
data ?? { status: response.status }
|
|
697
|
-
);
|
|
698
|
-
}
|
|
699
|
-
return data;
|
|
684
|
+
// src/adapters/hyperliquid/symbols.ts
|
|
685
|
+
var UNKNOWN_SYMBOL2 = "UNKNOWN";
|
|
686
|
+
function extractHyperliquidDex(symbol) {
|
|
687
|
+
const idx = symbol.indexOf(":");
|
|
688
|
+
if (idx <= 0) return null;
|
|
689
|
+
const dex = symbol.slice(0, idx).trim().toLowerCase();
|
|
690
|
+
return dex || null;
|
|
700
691
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
return
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
return fetchHyperliquidAssetCtxs(this.environment);
|
|
719
|
-
}
|
|
720
|
-
spotAssetCtxs() {
|
|
721
|
-
return fetchHyperliquidSpotAssetCtxs(this.environment);
|
|
722
|
-
}
|
|
723
|
-
openOrders(user) {
|
|
724
|
-
return fetchHyperliquidOpenOrders({ user, environment: this.environment });
|
|
725
|
-
}
|
|
726
|
-
frontendOpenOrders(user) {
|
|
727
|
-
return fetchHyperliquidFrontendOpenOrders({
|
|
728
|
-
user,
|
|
729
|
-
environment: this.environment
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
orderStatus(user, oid) {
|
|
733
|
-
return fetchHyperliquidOrderStatus({
|
|
734
|
-
user,
|
|
735
|
-
oid,
|
|
736
|
-
environment: this.environment
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
historicalOrders(user) {
|
|
740
|
-
return fetchHyperliquidHistoricalOrders({
|
|
741
|
-
user,
|
|
742
|
-
environment: this.environment
|
|
743
|
-
});
|
|
744
|
-
}
|
|
745
|
-
userFills(user) {
|
|
746
|
-
return fetchHyperliquidUserFills({ user, environment: this.environment });
|
|
747
|
-
}
|
|
748
|
-
userFillsByTime(user, startTime, endTime) {
|
|
749
|
-
return fetchHyperliquidUserFillsByTime({
|
|
750
|
-
user,
|
|
751
|
-
startTime,
|
|
752
|
-
endTime,
|
|
753
|
-
environment: this.environment
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
userRateLimit(user) {
|
|
757
|
-
return fetchHyperliquidUserRateLimit({
|
|
758
|
-
user,
|
|
759
|
-
environment: this.environment
|
|
760
|
-
});
|
|
692
|
+
function parseHyperliquidSymbol(value) {
|
|
693
|
+
if (!value) return null;
|
|
694
|
+
const trimmed = value.trim();
|
|
695
|
+
if (!trimmed) return null;
|
|
696
|
+
if (trimmed.startsWith("@")) {
|
|
697
|
+
return {
|
|
698
|
+
raw: trimmed,
|
|
699
|
+
kind: "spotIndex",
|
|
700
|
+
normalized: trimmed,
|
|
701
|
+
routeTicker: trimmed,
|
|
702
|
+
displaySymbol: trimmed,
|
|
703
|
+
base: null,
|
|
704
|
+
quote: null,
|
|
705
|
+
pair: null,
|
|
706
|
+
dex: null,
|
|
707
|
+
leverageMode: "cross"
|
|
708
|
+
};
|
|
761
709
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
710
|
+
const dex = extractHyperliquidDex(trimmed);
|
|
711
|
+
const pair = resolveHyperliquidPair(trimmed);
|
|
712
|
+
const base = normalizeHyperliquidBaseSymbol(trimmed);
|
|
713
|
+
if (dex) {
|
|
714
|
+
if (!base) return null;
|
|
715
|
+
return {
|
|
716
|
+
raw: trimmed,
|
|
717
|
+
kind: "perp",
|
|
718
|
+
normalized: `${dex}:${base}`,
|
|
719
|
+
routeTicker: `${dex}:${base}`,
|
|
720
|
+
displaySymbol: `${dex.toUpperCase()}:${base}-USDC`,
|
|
721
|
+
base,
|
|
722
|
+
quote: null,
|
|
723
|
+
pair: null,
|
|
724
|
+
dex,
|
|
725
|
+
leverageMode: "isolated"
|
|
726
|
+
};
|
|
768
727
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
728
|
+
if (pair) {
|
|
729
|
+
const [pairBase, pairQuote] = pair.split("/");
|
|
730
|
+
return {
|
|
731
|
+
raw: trimmed,
|
|
732
|
+
kind: "spot",
|
|
733
|
+
normalized: pair,
|
|
734
|
+
routeTicker: pair.replace("/", "-"),
|
|
735
|
+
displaySymbol: pair.replace("/", "-"),
|
|
736
|
+
base: pairBase ?? null,
|
|
737
|
+
quote: pairQuote ?? null,
|
|
738
|
+
pair,
|
|
739
|
+
dex: null,
|
|
740
|
+
leverageMode: "cross"
|
|
741
|
+
};
|
|
774
742
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
743
|
+
if (!base) return null;
|
|
744
|
+
return {
|
|
745
|
+
raw: trimmed,
|
|
746
|
+
kind: "perp",
|
|
747
|
+
normalized: base,
|
|
748
|
+
routeTicker: base,
|
|
749
|
+
displaySymbol: `${base}-USDC`,
|
|
750
|
+
base,
|
|
751
|
+
quote: null,
|
|
752
|
+
pair: null,
|
|
753
|
+
dex: null,
|
|
754
|
+
leverageMode: "cross"
|
|
755
|
+
};
|
|
781
756
|
}
|
|
782
|
-
|
|
783
|
-
|
|
757
|
+
function normalizeHyperliquidQuoteSymbol(value) {
|
|
758
|
+
if (typeof value !== "string") return null;
|
|
759
|
+
const trimmed = value.trim();
|
|
760
|
+
if (!trimmed) return null;
|
|
761
|
+
return canonicalizeHyperliquidTokenCase(trimmed).toUpperCase();
|
|
784
762
|
}
|
|
785
|
-
|
|
786
|
-
|
|
763
|
+
function normalizeSpotTokenName2(value) {
|
|
764
|
+
const raw = (value ?? "").trim();
|
|
765
|
+
if (!raw) return "";
|
|
766
|
+
if (raw.endsWith("0") && raw.length > 1) {
|
|
767
|
+
return raw.slice(0, -1);
|
|
768
|
+
}
|
|
769
|
+
return raw;
|
|
787
770
|
}
|
|
788
|
-
|
|
789
|
-
|
|
771
|
+
function canonicalizeHyperliquidTokenCase(value) {
|
|
772
|
+
const trimmed = value.trim();
|
|
773
|
+
if (!trimmed) return "";
|
|
774
|
+
return trimmed === trimmed.toLowerCase() ? trimmed.toUpperCase() : trimmed;
|
|
790
775
|
}
|
|
791
|
-
|
|
792
|
-
|
|
776
|
+
function normalizeHyperliquidBaseSymbol(value) {
|
|
777
|
+
if (!value) return null;
|
|
778
|
+
const trimmed = value.trim();
|
|
779
|
+
if (!trimmed) return null;
|
|
780
|
+
const withoutDex = trimmed.includes(":") ? trimmed.split(":").slice(1).join(":") : trimmed;
|
|
781
|
+
const base = withoutDex.split("-")[0] ?? withoutDex;
|
|
782
|
+
const baseNoPair = base.split("/")[0] ?? base;
|
|
783
|
+
const normalized = canonicalizeHyperliquidTokenCase(baseNoPair);
|
|
784
|
+
if (!normalized || normalized === UNKNOWN_SYMBOL2) return null;
|
|
785
|
+
return normalized;
|
|
793
786
|
}
|
|
794
|
-
|
|
795
|
-
const
|
|
796
|
-
|
|
787
|
+
function normalizeHyperliquidMetaSymbol(symbol) {
|
|
788
|
+
const trimmed = symbol.trim();
|
|
789
|
+
const noDex = trimmed.includes(":") ? trimmed.split(":").slice(1).join(":") : trimmed;
|
|
790
|
+
const noPair = noDex.split("-")[0] ?? noDex;
|
|
791
|
+
return (noPair.split("/")[0] ?? noPair).trim();
|
|
797
792
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
793
|
+
function resolveHyperliquidPair(value) {
|
|
794
|
+
if (!value) return null;
|
|
795
|
+
const trimmed = value.trim();
|
|
796
|
+
if (!trimmed) return null;
|
|
797
|
+
const withoutDex = trimmed.includes(":") ? trimmed.split(":").slice(1).join(":") : trimmed;
|
|
798
|
+
if (withoutDex.includes("/")) {
|
|
799
|
+
const [base, ...rest] = withoutDex.split("/");
|
|
800
|
+
const quote = rest.join("/").trim();
|
|
801
|
+
if (!base || !quote) return null;
|
|
802
|
+
return `${canonicalizeHyperliquidTokenCase(base)}/${canonicalizeHyperliquidTokenCase(quote)}`;
|
|
803
|
+
}
|
|
804
|
+
if (withoutDex.includes("-")) {
|
|
805
|
+
const [base, ...rest] = withoutDex.split("-");
|
|
806
|
+
const quote = rest.join("-").trim();
|
|
807
|
+
if (!base || !quote) return null;
|
|
808
|
+
return `${canonicalizeHyperliquidTokenCase(base)}/${canonicalizeHyperliquidTokenCase(quote)}`;
|
|
809
|
+
}
|
|
810
|
+
return null;
|
|
804
811
|
}
|
|
805
|
-
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
+
function buildHyperliquidMarketDescriptor(input) {
|
|
813
|
+
const rawSymbol = input.symbol?.trim();
|
|
814
|
+
if (!rawSymbol) return null;
|
|
815
|
+
const parsed = parseHyperliquidSymbol(rawSymbol);
|
|
816
|
+
if (!parsed) return null;
|
|
817
|
+
const explicitPair = resolveHyperliquidPair(input.pair);
|
|
818
|
+
const explicitQuote = normalizeHyperliquidQuoteSymbol(input.quote);
|
|
819
|
+
if (parsed.kind === "spot" || parsed.kind === "spotIndex") {
|
|
820
|
+
const canonicalPair2 = explicitPair ?? parsed.pair;
|
|
821
|
+
const pair = canonicalPair2;
|
|
822
|
+
const [pairBase, pairQuote] = (canonicalPair2 ?? "").split("/").map((part) => canonicalizeHyperliquidTokenCase(part).toUpperCase());
|
|
823
|
+
const base2 = pairBase || parsed.base;
|
|
824
|
+
const quote2 = pairQuote || explicitQuote || parsed.quote;
|
|
825
|
+
const normalized2 = pair ?? parsed.normalized;
|
|
826
|
+
const routeTicker = pair && base2 && quote2 ? `${base2}-${quote2}` : parsed.routeTicker;
|
|
827
|
+
const displaySymbol2 = input.displaySymbol?.trim() || (pair && base2 && quote2 ? `${base2}-${quote2}` : parsed.displaySymbol);
|
|
828
|
+
const orderSymbol2 = input.orderSymbol?.trim() || resolveHyperliquidOrderSymbol(normalized2);
|
|
829
|
+
const marketDataCoin2 = input.marketDataCoin?.trim() || (typeof input.spotIndex === "number" ? `@${input.spotIndex}` : resolveHyperliquidMarketDataCoin(normalized2));
|
|
830
|
+
if (!orderSymbol2 || !marketDataCoin2) return null;
|
|
831
|
+
return {
|
|
832
|
+
rawSymbol,
|
|
833
|
+
kind: parsed.kind,
|
|
834
|
+
routeTicker,
|
|
835
|
+
displaySymbol: displaySymbol2,
|
|
836
|
+
normalized: normalized2,
|
|
837
|
+
orderSymbol: orderSymbol2,
|
|
838
|
+
marketDataCoin: marketDataCoin2,
|
|
839
|
+
base: base2 ?? null,
|
|
840
|
+
quote: quote2 ?? null,
|
|
841
|
+
pair,
|
|
842
|
+
canonicalPair: pair,
|
|
843
|
+
dex: null,
|
|
844
|
+
leverageMode: "cross",
|
|
845
|
+
spotIndex: input.spotIndex ?? null,
|
|
846
|
+
assetId: input.assetId ?? null
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
const base = parsed.base;
|
|
850
|
+
const quote = explicitQuote;
|
|
851
|
+
const canonicalPair = base && quote ? `${base}/${quote}` : null;
|
|
852
|
+
const displaySymbol = input.displaySymbol?.trim() || (canonicalPair ? canonicalPair.replace("/", "-") : parsed.dex ? base ?? parsed.normalized : parsed.displaySymbol);
|
|
853
|
+
const normalized = parsed.normalized;
|
|
854
|
+
const orderSymbol = input.orderSymbol?.trim() || resolveHyperliquidOrderSymbol(normalized);
|
|
855
|
+
const marketDataCoin = input.marketDataCoin?.trim() || resolveHyperliquidMarketDataCoin(normalized);
|
|
856
|
+
if (!orderSymbol || !marketDataCoin) return null;
|
|
857
|
+
return {
|
|
858
|
+
rawSymbol,
|
|
859
|
+
kind: parsed.kind,
|
|
860
|
+
routeTicker: parsed.routeTicker,
|
|
861
|
+
displaySymbol,
|
|
862
|
+
normalized,
|
|
863
|
+
orderSymbol,
|
|
864
|
+
marketDataCoin,
|
|
865
|
+
base,
|
|
866
|
+
quote,
|
|
867
|
+
pair: null,
|
|
868
|
+
canonicalPair,
|
|
869
|
+
dex: parsed.dex,
|
|
870
|
+
leverageMode: parsed.leverageMode,
|
|
871
|
+
spotIndex: input.spotIndex ?? null,
|
|
872
|
+
assetId: input.assetId ?? null
|
|
873
|
+
};
|
|
812
874
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
return postInfo(env, {
|
|
816
|
-
type: "historicalOrders",
|
|
817
|
-
user: normalizeAddress(params.user)
|
|
818
|
-
});
|
|
875
|
+
function resolveHyperliquidLeverageMode(symbol) {
|
|
876
|
+
return symbol.includes(":") ? "isolated" : "cross";
|
|
819
877
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
return postInfo(env, {
|
|
823
|
-
type: "userFills",
|
|
824
|
-
user: normalizeAddress(params.user)
|
|
825
|
-
});
|
|
878
|
+
function resolveHyperliquidProfileChain(environment) {
|
|
879
|
+
return environment === "testnet" ? "hyperliquid-testnet" : "hyperliquid";
|
|
826
880
|
}
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
return
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
881
|
+
function buildHyperliquidProfileAssets(params) {
|
|
882
|
+
const chain = resolveHyperliquidProfileChain(params.environment);
|
|
883
|
+
return params.assets.map((asset) => {
|
|
884
|
+
const symbols = asset.assetSymbols.map((symbol) => normalizeHyperliquidBaseSymbol(symbol)).filter((symbol) => Boolean(symbol));
|
|
885
|
+
if (symbols.length === 0) return null;
|
|
886
|
+
const explicitPair = typeof asset.pair === "string" ? resolveHyperliquidPair(asset.pair) : null;
|
|
887
|
+
const derivedPair = symbols.length === 1 ? resolveHyperliquidPair(asset.assetSymbols[0] ?? symbols[0]) : null;
|
|
888
|
+
const pair = explicitPair ?? derivedPair ?? void 0;
|
|
889
|
+
const leverage = typeof asset.leverage === "number" && Number.isFinite(asset.leverage) && asset.leverage > 0 ? asset.leverage : void 0;
|
|
890
|
+
const walletAddress = typeof asset.walletAddress === "string" && asset.walletAddress.trim().length > 0 ? asset.walletAddress.trim() : void 0;
|
|
891
|
+
return {
|
|
892
|
+
venue: "hyperliquid",
|
|
893
|
+
chain,
|
|
894
|
+
assetSymbols: symbols,
|
|
895
|
+
...pair ? { pair } : {},
|
|
896
|
+
...leverage ? { leverage } : {},
|
|
897
|
+
...walletAddress ? { walletAddress } : {}
|
|
898
|
+
};
|
|
899
|
+
}).filter((asset) => asset !== null);
|
|
835
900
|
}
|
|
836
|
-
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
901
|
+
function parseSpotPairSymbol(symbol) {
|
|
902
|
+
const trimmed = symbol.trim();
|
|
903
|
+
if (!trimmed.includes("/")) return null;
|
|
904
|
+
const [rawBase, rawQuote] = trimmed.split("/");
|
|
905
|
+
const base = rawBase?.trim().toUpperCase() ?? "";
|
|
906
|
+
const quote = rawQuote?.trim().toUpperCase() ?? "";
|
|
907
|
+
if (!base || !quote) return null;
|
|
908
|
+
return { base, quote };
|
|
842
909
|
}
|
|
843
|
-
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
});
|
|
910
|
+
function isHyperliquidSpotSymbol(symbol) {
|
|
911
|
+
const trimmed = symbol.trim();
|
|
912
|
+
if (!trimmed) return false;
|
|
913
|
+
if (trimmed.startsWith("@") || trimmed.includes("/")) return true;
|
|
914
|
+
if (trimmed.includes(":")) return false;
|
|
915
|
+
return resolveHyperliquidPair(trimmed) !== null;
|
|
850
916
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
917
|
+
function resolveHyperliquidMarketDataCoin(value) {
|
|
918
|
+
if (!value) return null;
|
|
919
|
+
const trimmed = value.trim();
|
|
920
|
+
if (!trimmed) return null;
|
|
921
|
+
if (trimmed.startsWith("@")) return trimmed;
|
|
922
|
+
const pair = resolveHyperliquidPair(trimmed);
|
|
923
|
+
if (pair && !extractHyperliquidDex(trimmed)) {
|
|
924
|
+
return pair;
|
|
925
|
+
}
|
|
926
|
+
return trimmed;
|
|
857
927
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
if (typeof options.nonce === "number") {
|
|
862
|
-
return options.nonce;
|
|
928
|
+
function supportsHyperliquidBuilderFee(params) {
|
|
929
|
+
if (!isHyperliquidSpotSymbol(params.symbol)) {
|
|
930
|
+
return true;
|
|
863
931
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
932
|
+
return params.side === "sell";
|
|
933
|
+
}
|
|
934
|
+
function resolveSpotMidCandidates(baseSymbol) {
|
|
935
|
+
const base = baseSymbol.trim().toUpperCase();
|
|
936
|
+
if (!base) return [];
|
|
937
|
+
const candidates = [base];
|
|
938
|
+
if (base.startsWith("U") && base.length > 1) {
|
|
939
|
+
candidates.push(base.slice(1));
|
|
867
940
|
}
|
|
868
|
-
return
|
|
941
|
+
return Array.from(new Set(candidates));
|
|
869
942
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
943
|
+
function resolveSpotTokenCandidates(value) {
|
|
944
|
+
const normalized = normalizeSpotTokenName2(value).toUpperCase();
|
|
945
|
+
if (!normalized) return [];
|
|
946
|
+
const candidates = [normalized];
|
|
947
|
+
if (normalized.startsWith("U") && normalized.length > 1) {
|
|
948
|
+
candidates.push(normalized.slice(1));
|
|
949
|
+
}
|
|
950
|
+
return Array.from(new Set(candidates));
|
|
951
|
+
}
|
|
952
|
+
function resolveHyperliquidOrderSymbol(value) {
|
|
953
|
+
if (!value) return null;
|
|
954
|
+
const trimmed = value.trim();
|
|
955
|
+
if (!trimmed) return null;
|
|
956
|
+
if (trimmed.startsWith("@")) return trimmed;
|
|
957
|
+
if (trimmed.includes(":")) {
|
|
958
|
+
const [rawDex, ...restParts] = trimmed.split(":");
|
|
959
|
+
const dex = rawDex.trim().toLowerCase();
|
|
960
|
+
const rest = restParts.join(":");
|
|
961
|
+
const normalizedBase = normalizeHyperliquidBaseSymbol(rest);
|
|
962
|
+
if (!dex || !normalizedBase || normalizedBase === UNKNOWN_SYMBOL2) {
|
|
963
|
+
return null;
|
|
879
964
|
}
|
|
880
|
-
|
|
965
|
+
return `${dex}:${normalizedBase}`;
|
|
881
966
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
967
|
+
const pair = resolveHyperliquidPair(trimmed);
|
|
968
|
+
if (pair) return pair;
|
|
969
|
+
return normalizeHyperliquidBaseSymbol(trimmed);
|
|
970
|
+
}
|
|
971
|
+
function resolveHyperliquidSymbol(asset, override) {
|
|
972
|
+
const raw = override && override.trim().length > 0 ? override.trim() : asset.trim();
|
|
973
|
+
if (!raw) return raw;
|
|
974
|
+
if (raw.startsWith("@")) return raw;
|
|
975
|
+
if (raw.includes(":")) {
|
|
976
|
+
const [dexRaw, ...restParts] = raw.split(":");
|
|
977
|
+
const dex = dexRaw.trim().toLowerCase();
|
|
978
|
+
const rest = restParts.join(":");
|
|
979
|
+
const normalizedBase = normalizeHyperliquidBaseSymbol(rest) ?? canonicalizeHyperliquidTokenCase(rest);
|
|
980
|
+
if (!dex) return normalizedBase;
|
|
981
|
+
return `${dex}:${normalizedBase}`;
|
|
891
982
|
}
|
|
892
|
-
|
|
893
|
-
return
|
|
894
|
-
wallet: this.wallet,
|
|
895
|
-
cancels,
|
|
896
|
-
environment: this.environment,
|
|
897
|
-
vaultAddress: this.vaultAddress,
|
|
898
|
-
expiresAfter: this.expiresAfter,
|
|
899
|
-
nonceSource: this.nonceSource
|
|
900
|
-
});
|
|
983
|
+
if (raw.includes("/")) {
|
|
984
|
+
return resolveHyperliquidPair(raw) ?? raw;
|
|
901
985
|
}
|
|
902
|
-
|
|
903
|
-
return
|
|
904
|
-
wallet: this.wallet,
|
|
905
|
-
environment: this.environment,
|
|
906
|
-
vaultAddress: this.vaultAddress,
|
|
907
|
-
expiresAfter: this.expiresAfter,
|
|
908
|
-
nonceSource: this.nonceSource
|
|
909
|
-
});
|
|
986
|
+
if (raw.includes("-")) {
|
|
987
|
+
return resolveHyperliquidPair(raw) ?? raw;
|
|
910
988
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
989
|
+
return normalizeHyperliquidBaseSymbol(raw) ?? canonicalizeHyperliquidTokenCase(raw);
|
|
990
|
+
}
|
|
991
|
+
function resolveHyperliquidPerpSymbol(asset) {
|
|
992
|
+
const raw = asset.trim();
|
|
993
|
+
if (!raw) return raw;
|
|
994
|
+
const dex = extractHyperliquidDex(raw);
|
|
995
|
+
const base = normalizeHyperliquidBaseSymbol(raw) ?? raw.toUpperCase();
|
|
996
|
+
return dex ? `${dex}:${base}` : base;
|
|
997
|
+
}
|
|
998
|
+
function resolveHyperliquidSpotSymbol(asset, defaultQuote = "USDC") {
|
|
999
|
+
const quote = defaultQuote.trim().toUpperCase() || "USDC";
|
|
1000
|
+
const raw = asset.trim().toUpperCase();
|
|
1001
|
+
if (!raw) {
|
|
1002
|
+
return { symbol: raw, base: raw, quote };
|
|
920
1003
|
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
});
|
|
1004
|
+
const pair = resolveHyperliquidPair(raw);
|
|
1005
|
+
if (pair) {
|
|
1006
|
+
const [base2, pairQuote] = pair.split("/");
|
|
1007
|
+
return {
|
|
1008
|
+
symbol: pair,
|
|
1009
|
+
base: base2?.trim() ?? raw,
|
|
1010
|
+
quote: pairQuote?.trim() ?? quote
|
|
1011
|
+
};
|
|
930
1012
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1013
|
+
const base = normalizeHyperliquidBaseSymbol(raw) ?? raw;
|
|
1014
|
+
return { symbol: `${base}/${quote}`, base, quote };
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// src/adapters/hyperliquid/info.ts
|
|
1018
|
+
var HYPERLIQUID_HIP3_DEXES = [
|
|
1019
|
+
"xyz",
|
|
1020
|
+
"flx",
|
|
1021
|
+
"vntl",
|
|
1022
|
+
"hyna",
|
|
1023
|
+
"km",
|
|
1024
|
+
"cash"
|
|
1025
|
+
];
|
|
1026
|
+
async function postInfo(environment, payload) {
|
|
1027
|
+
const baseUrl = API_BASES[environment];
|
|
1028
|
+
const response = await fetch(`${baseUrl}/info`, {
|
|
1029
|
+
method: "POST",
|
|
1030
|
+
headers: { "content-type": "application/json" },
|
|
1031
|
+
body: JSON.stringify(payload)
|
|
1032
|
+
});
|
|
1033
|
+
const data = await response.json().catch(() => null);
|
|
1034
|
+
if (!response.ok) {
|
|
1035
|
+
throw new HyperliquidApiError(
|
|
1036
|
+
"Hyperliquid info request failed.",
|
|
1037
|
+
data ?? { status: response.status }
|
|
1038
|
+
);
|
|
940
1039
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1040
|
+
return data;
|
|
1041
|
+
}
|
|
1042
|
+
function mergeHyperliquidOpenOrders(batches) {
|
|
1043
|
+
const merged = /* @__PURE__ */ new Map();
|
|
1044
|
+
for (const batch of batches) {
|
|
1045
|
+
for (const order of batch) {
|
|
1046
|
+
const oid = typeof order.oid === "number" || typeof order.oid === "string" ? String(order.oid) : "no-oid";
|
|
1047
|
+
const cloid = typeof order.cloid === "string" && order.cloid.trim().length > 0 ? order.cloid : "no-cloid";
|
|
1048
|
+
merged.set(`${oid}:${cloid}`, order);
|
|
1049
|
+
}
|
|
950
1050
|
}
|
|
951
|
-
|
|
952
|
-
|
|
1051
|
+
return [...merged.values()];
|
|
1052
|
+
}
|
|
1053
|
+
function readNumber(value) {
|
|
1054
|
+
if (typeof value === "number") {
|
|
1055
|
+
return Number.isFinite(value) ? value : null;
|
|
1056
|
+
}
|
|
1057
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1058
|
+
const parsed = Number.parseFloat(value);
|
|
1059
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
1060
|
+
}
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
var HyperliquidInfoClient = class {
|
|
1064
|
+
constructor(environment = "mainnet") {
|
|
1065
|
+
this.environment = environment;
|
|
1066
|
+
}
|
|
1067
|
+
meta() {
|
|
1068
|
+
return fetchHyperliquidMeta(this.environment);
|
|
1069
|
+
}
|
|
1070
|
+
metaAndAssetCtxs() {
|
|
1071
|
+
return fetchHyperliquidMetaAndAssetCtxs(this.environment);
|
|
1072
|
+
}
|
|
1073
|
+
spotMeta() {
|
|
1074
|
+
return fetchHyperliquidSpotMeta(this.environment);
|
|
1075
|
+
}
|
|
1076
|
+
spotMetaAndAssetCtxs() {
|
|
1077
|
+
return fetchHyperliquidSpotMetaAndAssetCtxs(this.environment);
|
|
1078
|
+
}
|
|
1079
|
+
assetCtxs() {
|
|
1080
|
+
return fetchHyperliquidAssetCtxs(this.environment);
|
|
1081
|
+
}
|
|
1082
|
+
spotAssetCtxs() {
|
|
1083
|
+
return fetchHyperliquidSpotAssetCtxs(this.environment);
|
|
1084
|
+
}
|
|
1085
|
+
openOrders(user) {
|
|
1086
|
+
return fetchHyperliquidOpenOrders({ user, environment: this.environment });
|
|
1087
|
+
}
|
|
1088
|
+
frontendOpenOrders(user) {
|
|
1089
|
+
return fetchHyperliquidFrontendOpenOrders({
|
|
1090
|
+
user,
|
|
1091
|
+
environment: this.environment
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
orderStatus(user, oid) {
|
|
1095
|
+
return fetchHyperliquidOrderStatus({
|
|
1096
|
+
user,
|
|
1097
|
+
oid,
|
|
1098
|
+
environment: this.environment
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
historicalOrders(user) {
|
|
1102
|
+
return fetchHyperliquidHistoricalOrders({
|
|
1103
|
+
user,
|
|
1104
|
+
environment: this.environment
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
userFills(user) {
|
|
1108
|
+
return fetchHyperliquidUserFills({ user, environment: this.environment });
|
|
1109
|
+
}
|
|
1110
|
+
userFillsByTime(user, startTime, endTime) {
|
|
1111
|
+
return fetchHyperliquidUserFillsByTime({
|
|
1112
|
+
user,
|
|
1113
|
+
startTime,
|
|
1114
|
+
endTime,
|
|
1115
|
+
environment: this.environment
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
userRateLimit(user) {
|
|
1119
|
+
return fetchHyperliquidUserRateLimit({
|
|
1120
|
+
user,
|
|
1121
|
+
environment: this.environment
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
preTransferCheck(user, source) {
|
|
1125
|
+
return fetchHyperliquidPreTransferCheck({
|
|
1126
|
+
user,
|
|
1127
|
+
source,
|
|
1128
|
+
environment: this.environment
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
spotClearinghouseState(user) {
|
|
1132
|
+
return fetchHyperliquidSpotClearinghouseState({
|
|
1133
|
+
user,
|
|
1134
|
+
environment: this.environment
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
activeAsset(user, symbol) {
|
|
1138
|
+
return fetchHyperliquidActiveAsset({
|
|
1139
|
+
user,
|
|
1140
|
+
symbol,
|
|
1141
|
+
environment: this.environment
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1145
|
+
async function fetchHyperliquidMeta(environment = "mainnet") {
|
|
1146
|
+
return postInfo(environment, { type: "meta" });
|
|
1147
|
+
}
|
|
1148
|
+
async function fetchHyperliquidMetaAndAssetCtxs(environment = "mainnet") {
|
|
1149
|
+
return postInfo(environment, { type: "metaAndAssetCtxs" });
|
|
1150
|
+
}
|
|
1151
|
+
async function fetchHyperliquidDexMetaAndAssetCtxs(environment = "mainnet", dex) {
|
|
1152
|
+
return postInfo(environment, { type: "metaAndAssetCtxs", dex });
|
|
1153
|
+
}
|
|
1154
|
+
async function fetchHyperliquidSpotMeta(environment = "mainnet") {
|
|
1155
|
+
return postInfo(environment, { type: "spotMeta" });
|
|
1156
|
+
}
|
|
1157
|
+
async function fetchHyperliquidSpotMetaAndAssetCtxs(environment = "mainnet") {
|
|
1158
|
+
return postInfo(environment, { type: "spotMetaAndAssetCtxs" });
|
|
1159
|
+
}
|
|
1160
|
+
async function fetchHyperliquidAssetCtxs(environment = "mainnet") {
|
|
1161
|
+
return postInfo(environment, { type: "assetCtxs" });
|
|
1162
|
+
}
|
|
1163
|
+
async function fetchHyperliquidSpotAssetCtxs(environment = "mainnet") {
|
|
1164
|
+
return postInfo(environment, { type: "spotAssetCtxs" });
|
|
1165
|
+
}
|
|
1166
|
+
async function fetchHyperliquidOpenOrders(params) {
|
|
1167
|
+
const env = params.environment ?? "mainnet";
|
|
1168
|
+
return postInfo(env, {
|
|
1169
|
+
type: "openOrders",
|
|
1170
|
+
user: normalizeAddress(params.user),
|
|
1171
|
+
...params.dex ? { dex: params.dex.trim().toLowerCase() } : {}
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
async function fetchHyperliquidFrontendOpenOrders(params) {
|
|
1175
|
+
const env = params.environment ?? "mainnet";
|
|
1176
|
+
return postInfo(env, {
|
|
1177
|
+
type: "frontendOpenOrders",
|
|
1178
|
+
user: normalizeAddress(params.user),
|
|
1179
|
+
...params.dex ? { dex: params.dex.trim().toLowerCase() } : {}
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
async function fetchHyperliquidOrderStatus(params) {
|
|
1183
|
+
const env = params.environment ?? "mainnet";
|
|
1184
|
+
return postInfo(env, {
|
|
1185
|
+
type: "orderStatus",
|
|
1186
|
+
user: normalizeAddress(params.user),
|
|
1187
|
+
oid: params.oid
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
async function fetchHyperliquidHistoricalOrders(params) {
|
|
1191
|
+
const env = params.environment ?? "mainnet";
|
|
1192
|
+
return postInfo(env, {
|
|
1193
|
+
type: "historicalOrders",
|
|
1194
|
+
user: normalizeAddress(params.user),
|
|
1195
|
+
...params.dex ? { dex: params.dex.trim().toLowerCase() } : {}
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
async function fetchHyperliquidUserFills(params) {
|
|
1199
|
+
const env = params.environment ?? "mainnet";
|
|
1200
|
+
return postInfo(env, {
|
|
1201
|
+
type: "userFills",
|
|
1202
|
+
user: normalizeAddress(params.user)
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
async function fetchHyperliquidUserFillsByTime(params) {
|
|
1206
|
+
const env = params.environment ?? "mainnet";
|
|
1207
|
+
return postInfo(env, {
|
|
1208
|
+
type: "userFillsByTime",
|
|
1209
|
+
user: normalizeAddress(params.user),
|
|
1210
|
+
startTime: params.startTime,
|
|
1211
|
+
endTime: params.endTime
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
async function fetchHyperliquidUserRateLimit(params) {
|
|
1215
|
+
const env = params.environment ?? "mainnet";
|
|
1216
|
+
return postInfo(env, {
|
|
1217
|
+
type: "userRateLimit",
|
|
1218
|
+
user: normalizeAddress(params.user)
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
async function fetchHyperliquidPreTransferCheck(params) {
|
|
1222
|
+
const env = params.environment ?? "mainnet";
|
|
1223
|
+
return postInfo(env, {
|
|
1224
|
+
type: "preTransferCheck",
|
|
1225
|
+
user: normalizeAddress(params.user),
|
|
1226
|
+
source: normalizeAddress(params.source)
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
async function fetchHyperliquidSpotClearinghouseState(params) {
|
|
1230
|
+
const env = params.environment ?? "mainnet";
|
|
1231
|
+
return postInfo(env, {
|
|
1232
|
+
type: "spotClearinghouseState",
|
|
1233
|
+
user: normalizeAddress(params.user)
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
function getKnownHyperliquidDexes(environment = "mainnet") {
|
|
1237
|
+
return environment === "mainnet" ? [...HYPERLIQUID_HIP3_DEXES] : [];
|
|
1238
|
+
}
|
|
1239
|
+
async function fetchHyperliquidOpenOrdersAcrossDexes(params) {
|
|
1240
|
+
const environment = params.environment ?? "mainnet";
|
|
1241
|
+
const requests = [
|
|
1242
|
+
...params.includePrimary === false ? [] : [fetchHyperliquidOpenOrders({ environment, user: params.user })],
|
|
1243
|
+
...getKnownHyperliquidDexes(environment).filter((dex) => !(params.dexes && !params.dexes.includes(dex))).map(
|
|
1244
|
+
(dex) => fetchHyperliquidOpenOrders({
|
|
1245
|
+
environment,
|
|
1246
|
+
user: params.user,
|
|
1247
|
+
dex
|
|
1248
|
+
})
|
|
1249
|
+
)
|
|
1250
|
+
];
|
|
1251
|
+
const batches = await Promise.all(requests);
|
|
1252
|
+
return mergeHyperliquidOpenOrders(batches);
|
|
1253
|
+
}
|
|
1254
|
+
async function fetchHyperliquidFrontendOpenOrdersAcrossDexes(params) {
|
|
1255
|
+
const environment = params.environment ?? "mainnet";
|
|
1256
|
+
const requests = [
|
|
1257
|
+
...params.includePrimary === false ? [] : [fetchHyperliquidFrontendOpenOrders({ environment, user: params.user })],
|
|
1258
|
+
...getKnownHyperliquidDexes(environment).filter((dex) => !(params.dexes && !params.dexes.includes(dex))).map(
|
|
1259
|
+
(dex) => fetchHyperliquidFrontendOpenOrders({
|
|
1260
|
+
environment,
|
|
1261
|
+
user: params.user,
|
|
1262
|
+
dex
|
|
1263
|
+
})
|
|
1264
|
+
)
|
|
1265
|
+
];
|
|
1266
|
+
const batches = await Promise.all(requests);
|
|
1267
|
+
return mergeHyperliquidOpenOrders(batches);
|
|
1268
|
+
}
|
|
1269
|
+
async function fetchHyperliquidActiveAsset(params) {
|
|
1270
|
+
const environment = params.environment ?? "mainnet";
|
|
1271
|
+
const coin = resolveHyperliquidOrderSymbol(params.symbol);
|
|
1272
|
+
if (!coin) {
|
|
1273
|
+
throw new Error(`Unable to resolve Hyperliquid active asset symbol: ${params.symbol}`);
|
|
1274
|
+
}
|
|
1275
|
+
const raw = await postInfo(environment, {
|
|
1276
|
+
type: "activeAssetData",
|
|
1277
|
+
user: normalizeAddress(params.user),
|
|
1278
|
+
coin
|
|
1279
|
+
});
|
|
1280
|
+
const record = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
|
|
1281
|
+
const leverageRecord = record?.leverage && typeof record.leverage === "object" && !Array.isArray(record.leverage) ? record.leverage : null;
|
|
1282
|
+
return {
|
|
1283
|
+
coin,
|
|
1284
|
+
leverage: leverageRecord && "value" in leverageRecord ? readNumber(leverageRecord.value) : readNumber(record?.leverage),
|
|
1285
|
+
leverageType: leverageRecord && typeof leverageRecord.type === "string" ? leverageRecord.type : null,
|
|
1286
|
+
raw
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
// src/adapters/hyperliquid/exchange.ts
|
|
1291
|
+
function resolveRequiredExchangeNonce(options) {
|
|
1292
|
+
if (typeof options.nonce === "number") {
|
|
1293
|
+
return options.nonce;
|
|
1294
|
+
}
|
|
1295
|
+
const resolved = options.walletNonceProvider?.() ?? options.wallet.nonceSource?.() ?? options.nonceSource?.();
|
|
1296
|
+
if (resolved === void 0) {
|
|
1297
|
+
throw new Error(`${options.action} requires an explicit nonce or wallet nonce source.`);
|
|
1298
|
+
}
|
|
1299
|
+
return resolved;
|
|
1300
|
+
}
|
|
1301
|
+
var HyperliquidExchangeClient = class {
|
|
1302
|
+
constructor(args) {
|
|
1303
|
+
this.wallet = args.wallet;
|
|
1304
|
+
this.environment = args.environment ?? "mainnet";
|
|
1305
|
+
this.vaultAddress = args.vaultAddress;
|
|
1306
|
+
this.expiresAfter = args.expiresAfter;
|
|
1307
|
+
const resolvedNonceSource = args.walletNonceProvider ?? args.wallet.nonceSource ?? args.nonceSource;
|
|
1308
|
+
if (!resolvedNonceSource) {
|
|
1309
|
+
throw new Error("Wallet nonce source is required for Hyperliquid exchange actions.");
|
|
1310
|
+
}
|
|
1311
|
+
this.nonceSource = resolvedNonceSource;
|
|
1312
|
+
}
|
|
1313
|
+
cancel(cancels) {
|
|
1314
|
+
return cancelHyperliquidOrders({
|
|
953
1315
|
wallet: this.wallet,
|
|
954
|
-
|
|
1316
|
+
cancels,
|
|
955
1317
|
environment: this.environment,
|
|
956
1318
|
vaultAddress: this.vaultAddress,
|
|
957
1319
|
expiresAfter: this.expiresAfter,
|
|
958
1320
|
nonceSource: this.nonceSource
|
|
959
1321
|
});
|
|
960
1322
|
}
|
|
961
|
-
|
|
962
|
-
return
|
|
1323
|
+
cancelByCloid(cancels) {
|
|
1324
|
+
return cancelHyperliquidOrdersByCloid({
|
|
963
1325
|
wallet: this.wallet,
|
|
964
|
-
|
|
1326
|
+
cancels,
|
|
965
1327
|
environment: this.environment,
|
|
966
1328
|
vaultAddress: this.vaultAddress,
|
|
967
1329
|
expiresAfter: this.expiresAfter,
|
|
968
1330
|
nonceSource: this.nonceSource
|
|
969
1331
|
});
|
|
970
1332
|
}
|
|
971
|
-
|
|
972
|
-
return
|
|
1333
|
+
cancelAll() {
|
|
1334
|
+
return cancelAllHyperliquidOrders({
|
|
973
1335
|
wallet: this.wallet,
|
|
974
|
-
input,
|
|
975
1336
|
environment: this.environment,
|
|
976
1337
|
vaultAddress: this.vaultAddress,
|
|
977
1338
|
expiresAfter: this.expiresAfter,
|
|
978
1339
|
nonceSource: this.nonceSource
|
|
979
1340
|
});
|
|
980
1341
|
}
|
|
981
|
-
|
|
982
|
-
return
|
|
1342
|
+
scheduleCancel(time) {
|
|
1343
|
+
return scheduleHyperliquidCancel({
|
|
983
1344
|
wallet: this.wallet,
|
|
984
|
-
|
|
1345
|
+
time,
|
|
985
1346
|
environment: this.environment,
|
|
986
1347
|
vaultAddress: this.vaultAddress,
|
|
987
1348
|
expiresAfter: this.expiresAfter,
|
|
988
1349
|
nonceSource: this.nonceSource
|
|
989
1350
|
});
|
|
990
1351
|
}
|
|
991
|
-
|
|
992
|
-
return
|
|
1352
|
+
modify(modification) {
|
|
1353
|
+
return modifyHyperliquidOrder({
|
|
993
1354
|
wallet: this.wallet,
|
|
1355
|
+
modification,
|
|
994
1356
|
environment: this.environment,
|
|
995
|
-
|
|
996
|
-
|
|
1357
|
+
vaultAddress: this.vaultAddress,
|
|
1358
|
+
expiresAfter: this.expiresAfter,
|
|
1359
|
+
nonceSource: this.nonceSource
|
|
997
1360
|
});
|
|
998
1361
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1362
|
+
batchModify(modifications) {
|
|
1363
|
+
return batchModifyHyperliquidOrders({
|
|
1001
1364
|
wallet: this.wallet,
|
|
1002
|
-
|
|
1365
|
+
modifications,
|
|
1003
1366
|
environment: this.environment,
|
|
1004
1367
|
vaultAddress: this.vaultAddress,
|
|
1005
1368
|
expiresAfter: this.expiresAfter,
|
|
1006
1369
|
nonceSource: this.nonceSource
|
|
1007
|
-
};
|
|
1008
|
-
return setHyperliquidAccountAbstractionMode(
|
|
1009
|
-
params.user ? { ...base, user: params.user } : base
|
|
1010
|
-
);
|
|
1370
|
+
});
|
|
1011
1371
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1372
|
+
twapOrder(twap) {
|
|
1373
|
+
return placeHyperliquidTwapOrder({
|
|
1014
1374
|
wallet: this.wallet,
|
|
1015
|
-
|
|
1375
|
+
twap,
|
|
1016
1376
|
environment: this.environment,
|
|
1017
1377
|
vaultAddress: this.vaultAddress,
|
|
1018
1378
|
expiresAfter: this.expiresAfter,
|
|
1019
1379
|
nonceSource: this.nonceSource
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
twapCancel(cancel) {
|
|
1383
|
+
return cancelHyperliquidTwapOrder({
|
|
1384
|
+
wallet: this.wallet,
|
|
1385
|
+
cancel,
|
|
1386
|
+
environment: this.environment,
|
|
1387
|
+
vaultAddress: this.vaultAddress,
|
|
1388
|
+
expiresAfter: this.expiresAfter,
|
|
1389
|
+
nonceSource: this.nonceSource
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
updateLeverage(input) {
|
|
1393
|
+
return updateHyperliquidLeverage({
|
|
1394
|
+
wallet: this.wallet,
|
|
1395
|
+
input,
|
|
1396
|
+
environment: this.environment,
|
|
1397
|
+
vaultAddress: this.vaultAddress,
|
|
1398
|
+
expiresAfter: this.expiresAfter,
|
|
1399
|
+
nonceSource: this.nonceSource
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
updateIsolatedMargin(input) {
|
|
1403
|
+
return updateHyperliquidIsolatedMargin({
|
|
1404
|
+
wallet: this.wallet,
|
|
1405
|
+
input,
|
|
1406
|
+
environment: this.environment,
|
|
1407
|
+
vaultAddress: this.vaultAddress,
|
|
1408
|
+
expiresAfter: this.expiresAfter,
|
|
1409
|
+
nonceSource: this.nonceSource
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
reserveRequestWeight(weight) {
|
|
1413
|
+
return reserveHyperliquidRequestWeight({
|
|
1414
|
+
wallet: this.wallet,
|
|
1415
|
+
weight,
|
|
1416
|
+
environment: this.environment,
|
|
1417
|
+
vaultAddress: this.vaultAddress,
|
|
1418
|
+
expiresAfter: this.expiresAfter,
|
|
1419
|
+
nonceSource: this.nonceSource
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
spotSend(params) {
|
|
1423
|
+
return sendHyperliquidSpot({
|
|
1424
|
+
wallet: this.wallet,
|
|
1425
|
+
environment: this.environment,
|
|
1426
|
+
nonceSource: this.nonceSource,
|
|
1427
|
+
...params
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
setAccountAbstractionMode(params) {
|
|
1431
|
+
const base = {
|
|
1432
|
+
wallet: this.wallet,
|
|
1433
|
+
mode: params.mode,
|
|
1434
|
+
environment: this.environment,
|
|
1435
|
+
vaultAddress: this.vaultAddress,
|
|
1436
|
+
expiresAfter: this.expiresAfter,
|
|
1437
|
+
nonceSource: this.nonceSource
|
|
1438
|
+
};
|
|
1439
|
+
return setHyperliquidAccountAbstractionMode(
|
|
1440
|
+
params.user ? { ...base, user: params.user } : base
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
setPortfolioMargin(params) {
|
|
1444
|
+
const base = {
|
|
1445
|
+
wallet: this.wallet,
|
|
1446
|
+
enabled: params.enabled,
|
|
1447
|
+
environment: this.environment,
|
|
1448
|
+
vaultAddress: this.vaultAddress,
|
|
1449
|
+
expiresAfter: this.expiresAfter,
|
|
1450
|
+
nonceSource: this.nonceSource
|
|
1451
|
+
};
|
|
1452
|
+
return setHyperliquidPortfolioMargin(params.user ? { ...base, user: params.user } : base);
|
|
1022
1453
|
}
|
|
1023
1454
|
};
|
|
1024
1455
|
async function setHyperliquidPortfolioMargin(options) {
|
|
@@ -1339,425 +1770,159 @@ async function withAssetIndexes(options, entries, mapper) {
|
|
|
1339
1770
|
entries.map(async (entry) => {
|
|
1340
1771
|
const assetIndex = await resolveHyperliquidAssetIndex({
|
|
1341
1772
|
symbol: entry.symbol,
|
|
1342
|
-
baseUrl: API_BASES[env],
|
|
1343
|
-
environment: env,
|
|
1344
|
-
fetcher: (...args) => fetch(...args)
|
|
1345
|
-
});
|
|
1346
|
-
return mapper(assetIndex, entry);
|
|
1347
|
-
})
|
|
1348
|
-
);
|
|
1349
|
-
}
|
|
1350
|
-
async function buildOrder(intent, options) {
|
|
1351
|
-
assertSymbol(intent.symbol);
|
|
1352
|
-
assertPositiveDecimal(intent.price, "price");
|
|
1353
|
-
assertPositiveDecimal(intent.size, "size");
|
|
1354
|
-
const env = options.environment ?? "mainnet";
|
|
1355
|
-
const assetIndex = await resolveHyperliquidAssetIndex({
|
|
1356
|
-
symbol: intent.symbol,
|
|
1357
|
-
baseUrl: API_BASES[env],
|
|
1358
|
-
environment: env,
|
|
1359
|
-
fetcher: (...args) => fetch(...args)
|
|
1360
|
-
});
|
|
1361
|
-
const limitOrTrigger = intent.trigger ? mapTrigger(intent.trigger) : {
|
|
1362
|
-
limit: {
|
|
1363
|
-
tif: intent.tif ?? "Ioc"
|
|
1364
|
-
}
|
|
1365
|
-
};
|
|
1366
|
-
return {
|
|
1367
|
-
a: assetIndex,
|
|
1368
|
-
b: intent.side === "buy",
|
|
1369
|
-
p: toApiDecimal(intent.price),
|
|
1370
|
-
s: toApiDecimal(intent.size),
|
|
1371
|
-
r: intent.reduceOnly ?? false,
|
|
1372
|
-
t: limitOrTrigger,
|
|
1373
|
-
...intent.clientId ? {
|
|
1374
|
-
c: normalizeCloid(intent.clientId)
|
|
1375
|
-
} : {}
|
|
1376
|
-
};
|
|
1377
|
-
}
|
|
1378
|
-
function mapTrigger(trigger) {
|
|
1379
|
-
assertPositiveDecimal(trigger.triggerPx, "triggerPx");
|
|
1380
|
-
return {
|
|
1381
|
-
trigger: {
|
|
1382
|
-
isMarket: Boolean(trigger.isMarket),
|
|
1383
|
-
triggerPx: toApiDecimal(trigger.triggerPx),
|
|
1384
|
-
tpsl: trigger.tpsl
|
|
1385
|
-
}
|
|
1386
|
-
};
|
|
1387
|
-
}
|
|
1388
|
-
function assertSymbol(value) {
|
|
1389
|
-
assertString(value, "symbol");
|
|
1390
|
-
}
|
|
1391
|
-
function normalizeUsdToInt(value) {
|
|
1392
|
-
if (typeof value === "bigint") {
|
|
1393
|
-
if (value < 0n) {
|
|
1394
|
-
throw new Error("usd must be non-negative.");
|
|
1395
|
-
}
|
|
1396
|
-
return Number(value);
|
|
1397
|
-
}
|
|
1398
|
-
const parsed = typeof value === "string" ? Number.parseFloat(value) : Number(value);
|
|
1399
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
1400
|
-
throw new Error("usd must be a non-negative number.");
|
|
1401
|
-
}
|
|
1402
|
-
return Math.round(parsed * 1e6);
|
|
1403
|
-
}
|
|
1404
|
-
function assertString(value, label) {
|
|
1405
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
1406
|
-
throw new Error(`${label} must be a non-empty string.`);
|
|
1407
|
-
}
|
|
1408
|
-
}
|
|
1409
|
-
function assertPositiveDecimal(value, label) {
|
|
1410
|
-
if (typeof value === "number") {
|
|
1411
|
-
assertPositiveNumber(value, label);
|
|
1412
|
-
return;
|
|
1413
|
-
}
|
|
1414
|
-
if (typeof value === "bigint") {
|
|
1415
|
-
if (value <= 0n) {
|
|
1416
|
-
throw new Error(`${label} must be positive.`);
|
|
1417
|
-
}
|
|
1418
|
-
return;
|
|
1419
|
-
}
|
|
1420
|
-
assertString(value, label);
|
|
1421
|
-
if (!/^(?:\d+\.?\d*|\.\d+)$/.test(value.trim())) {
|
|
1422
|
-
throw new Error(`${label} must be a positive decimal string.`);
|
|
1423
|
-
}
|
|
1424
|
-
const numeric = Number(value);
|
|
1425
|
-
if (!Number.isFinite(numeric) || numeric <= 0) {
|
|
1426
|
-
throw new Error(`${label} must be positive.`);
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
function collectExchangeErrorMessages(payload) {
|
|
1430
|
-
if (!payload || typeof payload !== "object") return [];
|
|
1431
|
-
const root = payload;
|
|
1432
|
-
const messages = [];
|
|
1433
|
-
const statuses = root.response?.data?.statuses;
|
|
1434
|
-
if (Array.isArray(statuses)) {
|
|
1435
|
-
statuses.forEach((status, index) => {
|
|
1436
|
-
if (status && typeof status === "object" && "error" in status && typeof status.error === "string") {
|
|
1437
|
-
const errorText = status.error;
|
|
1438
|
-
messages.push(`status[${index}]: ${errorText}`);
|
|
1439
|
-
}
|
|
1440
|
-
});
|
|
1441
|
-
}
|
|
1442
|
-
const singleStatus = root.response?.data?.status;
|
|
1443
|
-
if (singleStatus && typeof singleStatus === "object" && "error" in singleStatus && typeof singleStatus.error === "string") {
|
|
1444
|
-
messages.push(singleStatus.error);
|
|
1445
|
-
}
|
|
1446
|
-
return messages;
|
|
1447
|
-
}
|
|
1448
|
-
async function postExchange(env, body) {
|
|
1449
|
-
const response = await fetch(`${API_BASES[env]}/exchange`, {
|
|
1450
|
-
method: "POST",
|
|
1451
|
-
headers: { "content-type": "application/json" },
|
|
1452
|
-
body: JSON.stringify(body)
|
|
1453
|
-
});
|
|
1454
|
-
const text = await response.text().catch(() => "");
|
|
1455
|
-
const json = (() => {
|
|
1456
|
-
if (!text) return null;
|
|
1457
|
-
try {
|
|
1458
|
-
return JSON.parse(text);
|
|
1459
|
-
} catch {
|
|
1460
|
-
return null;
|
|
1461
|
-
}
|
|
1462
|
-
})();
|
|
1463
|
-
if (!response.ok) {
|
|
1464
|
-
throw new HyperliquidApiError("Hyperliquid exchange action failed.", {
|
|
1465
|
-
status: response.status,
|
|
1466
|
-
statusText: response.statusText,
|
|
1467
|
-
body: json ?? (text ? text : null)
|
|
1468
|
-
});
|
|
1469
|
-
}
|
|
1470
|
-
if (!json) {
|
|
1471
|
-
throw new HyperliquidApiError("Hyperliquid exchange action failed.", {
|
|
1472
|
-
status: response.status,
|
|
1473
|
-
statusText: response.statusText,
|
|
1474
|
-
body: text ? text : null
|
|
1475
|
-
});
|
|
1476
|
-
}
|
|
1477
|
-
if (json.status !== "ok") {
|
|
1478
|
-
throw new HyperliquidApiError("Hyperliquid exchange returned error.", {
|
|
1479
|
-
status: response.status,
|
|
1480
|
-
statusText: response.statusText,
|
|
1481
|
-
body: json
|
|
1482
|
-
});
|
|
1483
|
-
}
|
|
1484
|
-
const nestedErrors = collectExchangeErrorMessages(json);
|
|
1485
|
-
if (nestedErrors.length > 0) {
|
|
1486
|
-
throw new HyperliquidApiError("Hyperliquid exchange returned action errors.", {
|
|
1487
|
-
status: response.status,
|
|
1488
|
-
statusText: response.statusText,
|
|
1489
|
-
body: json,
|
|
1490
|
-
errors: nestedErrors
|
|
1491
|
-
});
|
|
1492
|
-
}
|
|
1493
|
-
return json;
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
// src/adapters/hyperliquid/symbols.ts
|
|
1497
|
-
var UNKNOWN_SYMBOL2 = "UNKNOWN";
|
|
1498
|
-
function extractHyperliquidDex(symbol) {
|
|
1499
|
-
const idx = symbol.indexOf(":");
|
|
1500
|
-
if (idx <= 0) return null;
|
|
1501
|
-
const dex = symbol.slice(0, idx).trim().toLowerCase();
|
|
1502
|
-
return dex || null;
|
|
1503
|
-
}
|
|
1504
|
-
function parseHyperliquidSymbol(value) {
|
|
1505
|
-
if (!value) return null;
|
|
1506
|
-
const trimmed = value.trim();
|
|
1507
|
-
if (!trimmed) return null;
|
|
1508
|
-
if (trimmed.startsWith("@")) {
|
|
1509
|
-
return {
|
|
1510
|
-
raw: trimmed,
|
|
1511
|
-
kind: "spotIndex",
|
|
1512
|
-
normalized: trimmed,
|
|
1513
|
-
routeTicker: trimmed,
|
|
1514
|
-
displaySymbol: trimmed,
|
|
1515
|
-
base: null,
|
|
1516
|
-
quote: null,
|
|
1517
|
-
pair: null,
|
|
1518
|
-
dex: null,
|
|
1519
|
-
leverageMode: "cross"
|
|
1520
|
-
};
|
|
1521
|
-
}
|
|
1522
|
-
const dex = extractHyperliquidDex(trimmed);
|
|
1523
|
-
const pair = resolveHyperliquidPair(trimmed);
|
|
1524
|
-
const base = normalizeHyperliquidBaseSymbol(trimmed);
|
|
1525
|
-
if (dex) {
|
|
1526
|
-
if (!base) return null;
|
|
1527
|
-
return {
|
|
1528
|
-
raw: trimmed,
|
|
1529
|
-
kind: "perp",
|
|
1530
|
-
normalized: `${dex}:${base}`,
|
|
1531
|
-
routeTicker: `${dex}:${base}`,
|
|
1532
|
-
displaySymbol: `${dex.toUpperCase()}:${base}-USDC`,
|
|
1533
|
-
base,
|
|
1534
|
-
quote: null,
|
|
1535
|
-
pair: null,
|
|
1536
|
-
dex,
|
|
1537
|
-
leverageMode: "isolated"
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
if (pair) {
|
|
1541
|
-
const [pairBase, pairQuote] = pair.split("/");
|
|
1542
|
-
return {
|
|
1543
|
-
raw: trimmed,
|
|
1544
|
-
kind: "spot",
|
|
1545
|
-
normalized: pair,
|
|
1546
|
-
routeTicker: pair.replace("/", "-"),
|
|
1547
|
-
displaySymbol: pair.replace("/", "-"),
|
|
1548
|
-
base: pairBase ?? null,
|
|
1549
|
-
quote: pairQuote ?? null,
|
|
1550
|
-
pair,
|
|
1551
|
-
dex: null,
|
|
1552
|
-
leverageMode: "cross"
|
|
1553
|
-
};
|
|
1554
|
-
}
|
|
1555
|
-
if (!base) return null;
|
|
1556
|
-
return {
|
|
1557
|
-
raw: trimmed,
|
|
1558
|
-
kind: "perp",
|
|
1559
|
-
normalized: base,
|
|
1560
|
-
routeTicker: base,
|
|
1561
|
-
displaySymbol: `${base}-USDC`,
|
|
1562
|
-
base,
|
|
1563
|
-
quote: null,
|
|
1564
|
-
pair: null,
|
|
1565
|
-
dex: null,
|
|
1566
|
-
leverageMode: "cross"
|
|
1567
|
-
};
|
|
1568
|
-
}
|
|
1569
|
-
function normalizeSpotTokenName2(value) {
|
|
1570
|
-
const raw = (value ?? "").trim();
|
|
1571
|
-
if (!raw) return "";
|
|
1572
|
-
if (raw.endsWith("0") && raw.length > 1) {
|
|
1573
|
-
return raw.slice(0, -1);
|
|
1574
|
-
}
|
|
1575
|
-
return raw;
|
|
1576
|
-
}
|
|
1577
|
-
function canonicalizeHyperliquidTokenCase(value) {
|
|
1578
|
-
const trimmed = value.trim();
|
|
1579
|
-
if (!trimmed) return "";
|
|
1580
|
-
return trimmed === trimmed.toLowerCase() ? trimmed.toUpperCase() : trimmed;
|
|
1581
|
-
}
|
|
1582
|
-
function normalizeHyperliquidBaseSymbol(value) {
|
|
1583
|
-
if (!value) return null;
|
|
1584
|
-
const trimmed = value.trim();
|
|
1585
|
-
if (!trimmed) return null;
|
|
1586
|
-
const withoutDex = trimmed.includes(":") ? trimmed.split(":").slice(1).join(":") : trimmed;
|
|
1587
|
-
const base = withoutDex.split("-")[0] ?? withoutDex;
|
|
1588
|
-
const baseNoPair = base.split("/")[0] ?? base;
|
|
1589
|
-
const normalized = canonicalizeHyperliquidTokenCase(baseNoPair);
|
|
1590
|
-
if (!normalized || normalized === UNKNOWN_SYMBOL2) return null;
|
|
1591
|
-
return normalized;
|
|
1592
|
-
}
|
|
1593
|
-
function normalizeHyperliquidMetaSymbol(symbol) {
|
|
1594
|
-
const trimmed = symbol.trim();
|
|
1595
|
-
const noDex = trimmed.includes(":") ? trimmed.split(":").slice(1).join(":") : trimmed;
|
|
1596
|
-
const noPair = noDex.split("-")[0] ?? noDex;
|
|
1597
|
-
return (noPair.split("/")[0] ?? noPair).trim();
|
|
1598
|
-
}
|
|
1599
|
-
function resolveHyperliquidPair(value) {
|
|
1600
|
-
if (!value) return null;
|
|
1601
|
-
const trimmed = value.trim();
|
|
1602
|
-
if (!trimmed) return null;
|
|
1603
|
-
const withoutDex = trimmed.includes(":") ? trimmed.split(":").slice(1).join(":") : trimmed;
|
|
1604
|
-
if (withoutDex.includes("/")) {
|
|
1605
|
-
const [base, ...rest] = withoutDex.split("/");
|
|
1606
|
-
const quote = rest.join("/").trim();
|
|
1607
|
-
if (!base || !quote) return null;
|
|
1608
|
-
return `${canonicalizeHyperliquidTokenCase(base)}/${canonicalizeHyperliquidTokenCase(quote)}`;
|
|
1609
|
-
}
|
|
1610
|
-
if (withoutDex.includes("-")) {
|
|
1611
|
-
const [base, ...rest] = withoutDex.split("-");
|
|
1612
|
-
const quote = rest.join("-").trim();
|
|
1613
|
-
if (!base || !quote) return null;
|
|
1614
|
-
return `${canonicalizeHyperliquidTokenCase(base)}/${canonicalizeHyperliquidTokenCase(quote)}`;
|
|
1615
|
-
}
|
|
1616
|
-
return null;
|
|
1617
|
-
}
|
|
1618
|
-
function resolveHyperliquidLeverageMode(symbol) {
|
|
1619
|
-
return symbol.includes(":") ? "isolated" : "cross";
|
|
1620
|
-
}
|
|
1621
|
-
function resolveHyperliquidProfileChain(environment) {
|
|
1622
|
-
return environment === "testnet" ? "hyperliquid-testnet" : "hyperliquid";
|
|
1623
|
-
}
|
|
1624
|
-
function buildHyperliquidProfileAssets(params) {
|
|
1625
|
-
const chain = resolveHyperliquidProfileChain(params.environment);
|
|
1626
|
-
return params.assets.map((asset) => {
|
|
1627
|
-
const symbols = asset.assetSymbols.map((symbol) => normalizeHyperliquidBaseSymbol(symbol)).filter((symbol) => Boolean(symbol));
|
|
1628
|
-
if (symbols.length === 0) return null;
|
|
1629
|
-
const explicitPair = typeof asset.pair === "string" ? resolveHyperliquidPair(asset.pair) : null;
|
|
1630
|
-
const derivedPair = symbols.length === 1 ? resolveHyperliquidPair(asset.assetSymbols[0] ?? symbols[0]) : null;
|
|
1631
|
-
const pair = explicitPair ?? derivedPair ?? void 0;
|
|
1632
|
-
const leverage = typeof asset.leverage === "number" && Number.isFinite(asset.leverage) && asset.leverage > 0 ? asset.leverage : void 0;
|
|
1633
|
-
const walletAddress = typeof asset.walletAddress === "string" && asset.walletAddress.trim().length > 0 ? asset.walletAddress.trim() : void 0;
|
|
1634
|
-
return {
|
|
1635
|
-
venue: "hyperliquid",
|
|
1636
|
-
chain,
|
|
1637
|
-
assetSymbols: symbols,
|
|
1638
|
-
...pair ? { pair } : {},
|
|
1639
|
-
...leverage ? { leverage } : {},
|
|
1640
|
-
...walletAddress ? { walletAddress } : {}
|
|
1641
|
-
};
|
|
1642
|
-
}).filter((asset) => asset !== null);
|
|
1773
|
+
baseUrl: API_BASES[env],
|
|
1774
|
+
environment: env,
|
|
1775
|
+
fetcher: (...args) => fetch(...args)
|
|
1776
|
+
});
|
|
1777
|
+
return mapper(assetIndex, entry);
|
|
1778
|
+
})
|
|
1779
|
+
);
|
|
1643
1780
|
}
|
|
1644
|
-
function
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
const
|
|
1649
|
-
const
|
|
1650
|
-
|
|
1651
|
-
|
|
1781
|
+
async function buildOrder(intent, options) {
|
|
1782
|
+
assertSymbol(intent.symbol);
|
|
1783
|
+
assertPositiveDecimal(intent.price, "price");
|
|
1784
|
+
assertPositiveDecimal(intent.size, "size");
|
|
1785
|
+
const env = options.environment ?? "mainnet";
|
|
1786
|
+
const assetIndex = await resolveHyperliquidAssetIndex({
|
|
1787
|
+
symbol: intent.symbol,
|
|
1788
|
+
baseUrl: API_BASES[env],
|
|
1789
|
+
environment: env,
|
|
1790
|
+
fetcher: (...args) => fetch(...args)
|
|
1791
|
+
});
|
|
1792
|
+
const limitOrTrigger = intent.trigger ? mapTrigger(intent.trigger) : {
|
|
1793
|
+
limit: {
|
|
1794
|
+
tif: intent.tif ?? "Ioc"
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
return {
|
|
1798
|
+
a: assetIndex,
|
|
1799
|
+
b: intent.side === "buy",
|
|
1800
|
+
p: toApiDecimal(intent.price),
|
|
1801
|
+
s: toApiDecimal(intent.size),
|
|
1802
|
+
r: intent.reduceOnly ?? false,
|
|
1803
|
+
t: limitOrTrigger,
|
|
1804
|
+
...intent.clientId ? {
|
|
1805
|
+
c: normalizeCloid(intent.clientId)
|
|
1806
|
+
} : {}
|
|
1807
|
+
};
|
|
1652
1808
|
}
|
|
1653
|
-
function
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1809
|
+
function mapTrigger(trigger) {
|
|
1810
|
+
assertPositiveDecimal(trigger.triggerPx, "triggerPx");
|
|
1811
|
+
return {
|
|
1812
|
+
trigger: {
|
|
1813
|
+
isMarket: Boolean(trigger.isMarket),
|
|
1814
|
+
triggerPx: toApiDecimal(trigger.triggerPx),
|
|
1815
|
+
tpsl: trigger.tpsl
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1659
1818
|
}
|
|
1660
|
-
function
|
|
1661
|
-
|
|
1662
|
-
const trimmed = value.trim();
|
|
1663
|
-
if (!trimmed) return null;
|
|
1664
|
-
if (trimmed.startsWith("@")) return trimmed;
|
|
1665
|
-
const pair = resolveHyperliquidPair(trimmed);
|
|
1666
|
-
if (pair && !extractHyperliquidDex(trimmed)) {
|
|
1667
|
-
return pair;
|
|
1668
|
-
}
|
|
1669
|
-
return trimmed;
|
|
1819
|
+
function assertSymbol(value) {
|
|
1820
|
+
assertString(value, "symbol");
|
|
1670
1821
|
}
|
|
1671
|
-
function
|
|
1672
|
-
if (
|
|
1673
|
-
|
|
1822
|
+
function normalizeUsdToInt(value) {
|
|
1823
|
+
if (typeof value === "bigint") {
|
|
1824
|
+
if (value < 0n) {
|
|
1825
|
+
throw new Error("usd must be non-negative.");
|
|
1826
|
+
}
|
|
1827
|
+
return Number(value);
|
|
1674
1828
|
}
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
const base = baseSymbol.trim().toUpperCase();
|
|
1679
|
-
if (!base) return [];
|
|
1680
|
-
const candidates = [base];
|
|
1681
|
-
if (base.startsWith("U") && base.length > 1) {
|
|
1682
|
-
candidates.push(base.slice(1));
|
|
1829
|
+
const parsed = typeof value === "string" ? Number.parseFloat(value) : Number(value);
|
|
1830
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
1831
|
+
throw new Error("usd must be a non-negative number.");
|
|
1683
1832
|
}
|
|
1684
|
-
return
|
|
1833
|
+
return Math.round(parsed * 1e6);
|
|
1685
1834
|
}
|
|
1686
|
-
function
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
const candidates = [normalized];
|
|
1690
|
-
if (normalized.startsWith("U") && normalized.length > 1) {
|
|
1691
|
-
candidates.push(normalized.slice(1));
|
|
1835
|
+
function assertString(value, label) {
|
|
1836
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
1837
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
1692
1838
|
}
|
|
1693
|
-
return Array.from(new Set(candidates));
|
|
1694
1839
|
}
|
|
1695
|
-
function
|
|
1696
|
-
if (
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
if (trimmed.startsWith("@")) return trimmed;
|
|
1700
|
-
if (trimmed.includes(":")) {
|
|
1701
|
-
const [rawDex, ...restParts] = trimmed.split(":");
|
|
1702
|
-
const dex = rawDex.trim().toLowerCase();
|
|
1703
|
-
const rest = restParts.join(":");
|
|
1704
|
-
const normalizedBase = normalizeHyperliquidBaseSymbol(rest);
|
|
1705
|
-
if (!dex || !normalizedBase || normalizedBase === UNKNOWN_SYMBOL2) {
|
|
1706
|
-
return null;
|
|
1707
|
-
}
|
|
1708
|
-
return `${dex}:${normalizedBase}`;
|
|
1840
|
+
function assertPositiveDecimal(value, label) {
|
|
1841
|
+
if (typeof value === "number") {
|
|
1842
|
+
assertPositiveNumber(value, label);
|
|
1843
|
+
return;
|
|
1709
1844
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
|
-
const raw = override && override.trim().length > 0 ? override.trim() : asset.trim();
|
|
1716
|
-
if (!raw) return raw;
|
|
1717
|
-
if (raw.startsWith("@")) return raw;
|
|
1718
|
-
if (raw.includes(":")) {
|
|
1719
|
-
const [dexRaw, ...restParts] = raw.split(":");
|
|
1720
|
-
const dex = dexRaw.trim().toLowerCase();
|
|
1721
|
-
const rest = restParts.join(":");
|
|
1722
|
-
const normalizedBase = normalizeHyperliquidBaseSymbol(rest) ?? canonicalizeHyperliquidTokenCase(rest);
|
|
1723
|
-
if (!dex) return normalizedBase;
|
|
1724
|
-
return `${dex}:${normalizedBase}`;
|
|
1845
|
+
if (typeof value === "bigint") {
|
|
1846
|
+
if (value <= 0n) {
|
|
1847
|
+
throw new Error(`${label} must be positive.`);
|
|
1848
|
+
}
|
|
1849
|
+
return;
|
|
1725
1850
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1851
|
+
assertString(value, label);
|
|
1852
|
+
if (!/^(?:\d+\.?\d*|\.\d+)$/.test(value.trim())) {
|
|
1853
|
+
throw new Error(`${label} must be a positive decimal string.`);
|
|
1728
1854
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1855
|
+
const numeric = Number(value);
|
|
1856
|
+
if (!Number.isFinite(numeric) || numeric <= 0) {
|
|
1857
|
+
throw new Error(`${label} must be positive.`);
|
|
1731
1858
|
}
|
|
1732
|
-
return normalizeHyperliquidBaseSymbol(raw) ?? canonicalizeHyperliquidTokenCase(raw);
|
|
1733
1859
|
}
|
|
1734
|
-
function
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
const
|
|
1738
|
-
const
|
|
1739
|
-
|
|
1860
|
+
function collectExchangeErrorMessages(payload) {
|
|
1861
|
+
if (!payload || typeof payload !== "object") return [];
|
|
1862
|
+
const root = payload;
|
|
1863
|
+
const messages = [];
|
|
1864
|
+
const statuses = root.response?.data?.statuses;
|
|
1865
|
+
if (Array.isArray(statuses)) {
|
|
1866
|
+
statuses.forEach((status, index) => {
|
|
1867
|
+
if (status && typeof status === "object" && "error" in status && typeof status.error === "string") {
|
|
1868
|
+
const errorText = status.error;
|
|
1869
|
+
messages.push(`status[${index}]: ${errorText}`);
|
|
1870
|
+
}
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
const singleStatus = root.response?.data?.status;
|
|
1874
|
+
if (singleStatus && typeof singleStatus === "object" && "error" in singleStatus && typeof singleStatus.error === "string") {
|
|
1875
|
+
messages.push(singleStatus.error);
|
|
1876
|
+
}
|
|
1877
|
+
return messages;
|
|
1740
1878
|
}
|
|
1741
|
-
function
|
|
1742
|
-
const
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1879
|
+
async function postExchange(env, body) {
|
|
1880
|
+
const response = await fetch(`${API_BASES[env]}/exchange`, {
|
|
1881
|
+
method: "POST",
|
|
1882
|
+
headers: { "content-type": "application/json" },
|
|
1883
|
+
body: JSON.stringify(body)
|
|
1884
|
+
});
|
|
1885
|
+
const text = await response.text().catch(() => "");
|
|
1886
|
+
const json = (() => {
|
|
1887
|
+
if (!text) return null;
|
|
1888
|
+
try {
|
|
1889
|
+
return JSON.parse(text);
|
|
1890
|
+
} catch {
|
|
1891
|
+
return null;
|
|
1892
|
+
}
|
|
1893
|
+
})();
|
|
1894
|
+
if (!response.ok) {
|
|
1895
|
+
throw new HyperliquidApiError("Hyperliquid exchange action failed.", {
|
|
1896
|
+
status: response.status,
|
|
1897
|
+
statusText: response.statusText,
|
|
1898
|
+
body: json ?? (text ? text : null)
|
|
1899
|
+
});
|
|
1746
1900
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
quote: pairQuote?.trim() ?? quote
|
|
1754
|
-
};
|
|
1901
|
+
if (!json) {
|
|
1902
|
+
throw new HyperliquidApiError("Hyperliquid exchange action failed.", {
|
|
1903
|
+
status: response.status,
|
|
1904
|
+
statusText: response.statusText,
|
|
1905
|
+
body: text ? text : null
|
|
1906
|
+
});
|
|
1755
1907
|
}
|
|
1756
|
-
|
|
1757
|
-
|
|
1908
|
+
if (json.status !== "ok") {
|
|
1909
|
+
throw new HyperliquidApiError("Hyperliquid exchange returned error.", {
|
|
1910
|
+
status: response.status,
|
|
1911
|
+
statusText: response.statusText,
|
|
1912
|
+
body: json
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1915
|
+
const nestedErrors = collectExchangeErrorMessages(json);
|
|
1916
|
+
if (nestedErrors.length > 0) {
|
|
1917
|
+
throw new HyperliquidApiError("Hyperliquid exchange returned action errors.", {
|
|
1918
|
+
status: response.status,
|
|
1919
|
+
statusText: response.statusText,
|
|
1920
|
+
body: json,
|
|
1921
|
+
errors: nestedErrors
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
return json;
|
|
1758
1925
|
}
|
|
1759
|
-
|
|
1760
|
-
// src/adapters/hyperliquid/actions.ts
|
|
1761
1926
|
function resolveRequiredNonce(params) {
|
|
1762
1927
|
if (typeof params.nonce === "number") {
|
|
1763
1928
|
return params.nonce;
|
|
@@ -2414,47 +2579,47 @@ async function fetchHyperliquidResolvedMarketDescriptor(params) {
|
|
|
2414
2579
|
quote: parsed.quote ?? "USDC",
|
|
2415
2580
|
...params.mids !== void 0 ? { mids: params.mids } : {}
|
|
2416
2581
|
});
|
|
2417
|
-
const
|
|
2418
|
-
if (!
|
|
2582
|
+
const orderSymbol = resolveHyperliquidOrderSymbol(spotInfo.symbol);
|
|
2583
|
+
if (!orderSymbol) {
|
|
2419
2584
|
throw new Error(`Unable to resolve Hyperliquid spot order symbol: ${params.symbol}`);
|
|
2420
2585
|
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2586
|
+
const descriptor2 = buildHyperliquidMarketDescriptor({
|
|
2587
|
+
symbol: params.symbol,
|
|
2588
|
+
pair: spotInfo.symbol,
|
|
2589
|
+
quote: spotInfo.quote,
|
|
2425
2590
|
displaySymbol: `${spotInfo.base}-${spotInfo.quote}`,
|
|
2426
|
-
|
|
2427
|
-
orderSymbol: orderSymbol2,
|
|
2591
|
+
orderSymbol,
|
|
2428
2592
|
marketDataCoin: `@${spotInfo.marketIndex}`,
|
|
2429
|
-
base: spotInfo.base,
|
|
2430
|
-
quote: spotInfo.quote,
|
|
2431
|
-
pair: spotInfo.symbol,
|
|
2432
|
-
dex: null,
|
|
2433
|
-
leverageMode: "cross",
|
|
2434
2593
|
spotIndex: spotInfo.marketIndex,
|
|
2435
2594
|
assetId: spotInfo.assetId
|
|
2436
|
-
};
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2595
|
+
});
|
|
2596
|
+
if (!descriptor2) {
|
|
2597
|
+
throw new Error(`Unable to build Hyperliquid spot market descriptor: ${params.symbol}`);
|
|
2598
|
+
}
|
|
2599
|
+
return descriptor2;
|
|
2600
|
+
}
|
|
2601
|
+
const quote = parsed.dex ? await (async () => {
|
|
2602
|
+
const dex = parsed.dex;
|
|
2603
|
+
if (!dex) return null;
|
|
2604
|
+
const [dexMetaAndCtxs, spotMetaRaw] = await Promise.all([
|
|
2605
|
+
fetchHyperliquidDexMetaAndAssetCtxs(params.environment, dex),
|
|
2606
|
+
fetchHyperliquidSpotMeta(params.environment)
|
|
2607
|
+
]);
|
|
2608
|
+
const metaHeader = Array.isArray(dexMetaAndCtxs) && dexMetaAndCtxs.length > 0 ? dexMetaAndCtxs[0] : null;
|
|
2609
|
+
const collateralToken = typeof metaHeader?.collateralToken === "number" ? metaHeader.collateralToken : null;
|
|
2610
|
+
if (collateralToken == null) return null;
|
|
2611
|
+
const spotMeta = spotMetaRaw;
|
|
2612
|
+
const token = (spotMeta.tokens ?? []).find((entry) => entry?.index === collateralToken) ?? null;
|
|
2613
|
+
return normalizeSpotTokenName2(token?.name).toUpperCase() || null;
|
|
2614
|
+
})() : "USDC";
|
|
2615
|
+
const descriptor = buildHyperliquidMarketDescriptor({
|
|
2616
|
+
symbol: params.symbol,
|
|
2617
|
+
...quote ? { quote } : {}
|
|
2618
|
+
});
|
|
2619
|
+
if (!descriptor) {
|
|
2620
|
+
throw new Error(`Unable to build Hyperliquid market descriptor: ${params.symbol}`);
|
|
2441
2621
|
}
|
|
2442
|
-
return
|
|
2443
|
-
rawSymbol: params.symbol,
|
|
2444
|
-
kind: parsed.kind,
|
|
2445
|
-
routeTicker: parsed.routeTicker,
|
|
2446
|
-
displaySymbol: parsed.displaySymbol,
|
|
2447
|
-
normalized: parsed.normalized,
|
|
2448
|
-
orderSymbol,
|
|
2449
|
-
marketDataCoin: parsed.normalized,
|
|
2450
|
-
base: parsed.base,
|
|
2451
|
-
quote: parsed.quote,
|
|
2452
|
-
pair: parsed.pair,
|
|
2453
|
-
dex: parsed.dex,
|
|
2454
|
-
leverageMode: parsed.leverageMode,
|
|
2455
|
-
spotIndex: null,
|
|
2456
|
-
assetId: null
|
|
2457
|
-
};
|
|
2622
|
+
return descriptor;
|
|
2458
2623
|
}
|
|
2459
2624
|
async function fetchHyperliquidSizeDecimals(params) {
|
|
2460
2625
|
const { symbol, environment } = params;
|
|
@@ -2908,6 +3073,6 @@ function estimateHyperliquidLiquidationPrice(params) {
|
|
|
2908
3073
|
return liquidationPrice;
|
|
2909
3074
|
}
|
|
2910
3075
|
|
|
2911
|
-
export { DEFAULT_HYPERLIQUID_MARKET_SLIPPAGE_BPS, DEFAULT_HYPERLIQUID_TPSL_MARKET_SLIPPAGE_BPS, HyperliquidApiError, HyperliquidBuilderApprovalError, HyperliquidExchangeClient, HyperliquidGuardError, HyperliquidInfoClient, HyperliquidTermsError, approveHyperliquidBuilderFee, batchModifyHyperliquidOrders, buildHyperliquidMarketIdentity, buildHyperliquidProfileAssets, cancelAllHyperliquidOrders, cancelHyperliquidOrders, cancelHyperliquidOrdersByCloid, cancelHyperliquidTwapOrder, computeHyperliquidMarketIocLimitPrice, createHyperliquidActionHash, createHyperliquidSubAccount, createMonotonicNonceFactory, depositToHyperliquidBridge, estimateHyperliquidLiquidationPrice, extractHyperliquidDex, fetchHyperliquidAssetCtxs, fetchHyperliquidClearinghouseState, fetchHyperliquidFrontendOpenOrders, fetchHyperliquidHistoricalOrders, fetchHyperliquidMeta, fetchHyperliquidMetaAndAssetCtxs, fetchHyperliquidOpenOrders, fetchHyperliquidOrderStatus, fetchHyperliquidPreTransferCheck, fetchHyperliquidResolvedMarketDescriptor, fetchHyperliquidSizeDecimals, fetchHyperliquidSpotAssetCtxs, fetchHyperliquidSpotClearinghouseState, fetchHyperliquidSpotMeta, fetchHyperliquidSpotMetaAndAssetCtxs, fetchHyperliquidTickSize, fetchHyperliquidUserFills, fetchHyperliquidUserFillsByTime, fetchHyperliquidUserRateLimit, formatHyperliquidMarketablePrice, formatHyperliquidPrice, formatHyperliquidSize, getHyperliquidMaxBuilderFee, isHyperliquidSpotSymbol, modifyHyperliquidOrder, normalizeHyperliquidBaseSymbol, normalizeHyperliquidMetaSymbol, normalizeSpotTokenName2 as normalizeSpotTokenName, parseHyperliquidSymbol, parseSpotPairSymbol, placeHyperliquidOrder, placeHyperliquidOrderWithTpSl, placeHyperliquidPositionTpSl, placeHyperliquidTwapOrder, reserveHyperliquidRequestWeight, resolveHyperliquidAbstractionFromMode, resolveHyperliquidLeverageMode, resolveHyperliquidMarketDataCoin, resolveHyperliquidOrderSymbol, resolveHyperliquidPair, resolveHyperliquidPerpSymbol, resolveHyperliquidProfileChain, resolveHyperliquidSpotSymbol, resolveHyperliquidSymbol, resolveSpotMidCandidates, resolveSpotTokenCandidates, scheduleHyperliquidCancel, sendHyperliquidSpot, setHyperliquidAccountAbstractionMode, setHyperliquidPortfolioMargin, supportsHyperliquidBuilderFee, transferHyperliquidSubAccount, updateHyperliquidIsolatedMargin, updateHyperliquidLeverage, withdrawFromHyperliquid };
|
|
3076
|
+
export { DEFAULT_HYPERLIQUID_MARKET_SLIPPAGE_BPS, DEFAULT_HYPERLIQUID_TPSL_MARKET_SLIPPAGE_BPS, HYPERLIQUID_HIP3_DEXES, HyperliquidApiError, HyperliquidBuilderApprovalError, HyperliquidExchangeClient, HyperliquidGuardError, HyperliquidInfoClient, HyperliquidTermsError, approveHyperliquidBuilderFee, batchModifyHyperliquidOrders, buildHyperliquidMarketDescriptor, buildHyperliquidMarketIdentity, buildHyperliquidProfileAssets, cancelAllHyperliquidOrders, cancelHyperliquidOrders, cancelHyperliquidOrdersByCloid, cancelHyperliquidTwapOrder, computeHyperliquidMarketIocLimitPrice, createHyperliquidActionHash, createHyperliquidSubAccount, createMonotonicNonceFactory, depositToHyperliquidBridge, estimateHyperliquidLiquidationPrice, extractHyperliquidDex, fetchHyperliquidActiveAsset, fetchHyperliquidAssetCtxs, fetchHyperliquidClearinghouseState, fetchHyperliquidDexMetaAndAssetCtxs, fetchHyperliquidFrontendOpenOrders, fetchHyperliquidFrontendOpenOrdersAcrossDexes, fetchHyperliquidHistoricalOrders, fetchHyperliquidMeta, fetchHyperliquidMetaAndAssetCtxs, fetchHyperliquidOpenOrders, fetchHyperliquidOpenOrdersAcrossDexes, fetchHyperliquidOrderStatus, fetchHyperliquidPreTransferCheck, fetchHyperliquidResolvedMarketDescriptor, fetchHyperliquidSizeDecimals, fetchHyperliquidSpotAssetCtxs, fetchHyperliquidSpotClearinghouseState, fetchHyperliquidSpotMeta, fetchHyperliquidSpotMetaAndAssetCtxs, fetchHyperliquidTickSize, fetchHyperliquidUserFills, fetchHyperliquidUserFillsByTime, fetchHyperliquidUserRateLimit, formatHyperliquidMarketablePrice, formatHyperliquidPrice, formatHyperliquidSize, getHyperliquidMaxBuilderFee, getKnownHyperliquidDexes, isHyperliquidSpotSymbol, modifyHyperliquidOrder, normalizeHyperliquidBaseSymbol, normalizeHyperliquidMetaSymbol, normalizeSpotTokenName2 as normalizeSpotTokenName, parseHyperliquidSymbol, parseSpotPairSymbol, placeHyperliquidOrder, placeHyperliquidOrderWithTpSl, placeHyperliquidPositionTpSl, placeHyperliquidTwapOrder, reserveHyperliquidRequestWeight, resolveHyperliquidAbstractionFromMode, resolveHyperliquidLeverageMode, resolveHyperliquidMarketDataCoin, resolveHyperliquidOrderSymbol, resolveHyperliquidPair, resolveHyperliquidPerpSymbol, resolveHyperliquidProfileChain, resolveHyperliquidSpotSymbol, resolveHyperliquidSymbol, resolveSpotMidCandidates, resolveSpotTokenCandidates, scheduleHyperliquidCancel, sendHyperliquidSpot, setHyperliquidAccountAbstractionMode, setHyperliquidPortfolioMargin, supportsHyperliquidBuilderFee, transferHyperliquidSubAccount, updateHyperliquidIsolatedMargin, updateHyperliquidLeverage, withdrawFromHyperliquid };
|
|
2912
3077
|
//# sourceMappingURL=browser.js.map
|
|
2913
3078
|
//# sourceMappingURL=browser.js.map
|