@pear-protocol/hyperliquid-sdk 0.0.73-beta.5 → 0.0.73-beta.7
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/clients/auth.d.ts +1 -1
- package/dist/index.js +112 -34
- package/dist/utils/http.d.ts +2 -2
- package/package.json +1 -1
package/dist/clients/auth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApiResponse, GetEIP712MessageResponse, AuthenticateRequest, AuthenticateResponse, RefreshTokenResponse, LogoutResponse } from
|
|
1
|
+
import type { ApiResponse, GetEIP712MessageResponse, AuthenticateRequest, AuthenticateResponse, RefreshTokenResponse, LogoutResponse } from "../types";
|
|
2
2
|
export declare function getEIP712Message(baseUrl: string, address: string, clientId: string): Promise<ApiResponse<GetEIP712MessageResponse>>;
|
|
3
3
|
export declare function authenticate(baseUrl: string, body: AuthenticateRequest): Promise<ApiResponse<AuthenticateResponse>>;
|
|
4
4
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1509,6 +1509,20 @@ const useWebData = () => {
|
|
|
1509
1509
|
};
|
|
1510
1510
|
};
|
|
1511
1511
|
|
|
1512
|
+
/**
|
|
1513
|
+
* Check if two symbols match, handling kPEPE/KPEPE variations
|
|
1514
|
+
* Returns true if symbols match (case-insensitive for k-prefix tokens)
|
|
1515
|
+
*/
|
|
1516
|
+
function symbolsMatch(assetName, searchSymbol) {
|
|
1517
|
+
// Exact match
|
|
1518
|
+
if (assetName === searchSymbol)
|
|
1519
|
+
return true;
|
|
1520
|
+
// Try case-insensitive match for k-prefix tokens (kPEPE vs KPEPE)
|
|
1521
|
+
if (assetName.toUpperCase() === searchSymbol.toUpperCase()) {
|
|
1522
|
+
return true;
|
|
1523
|
+
}
|
|
1524
|
+
return false;
|
|
1525
|
+
}
|
|
1512
1526
|
/**
|
|
1513
1527
|
* Extracts token metadata from aggregated WebData3 contexts and AllMids data
|
|
1514
1528
|
*/
|
|
@@ -1529,8 +1543,9 @@ class TokenMetadataExtractor {
|
|
|
1529
1543
|
}
|
|
1530
1544
|
// Find token index in aggregated universe
|
|
1531
1545
|
// For HIP3 assets, match both name AND marketPrefix
|
|
1546
|
+
// Uses symbolsMatch to handle kPEPE/KPEPE case variations
|
|
1532
1547
|
const universeIndex = perpMetaAssets.findIndex((asset) => {
|
|
1533
|
-
if (asset.name
|
|
1548
|
+
if (!symbolsMatch(asset.name, symbol))
|
|
1534
1549
|
return false;
|
|
1535
1550
|
// If marketPrefix is specified, match it; otherwise match assets without prefix
|
|
1536
1551
|
if (marketPrefix) {
|
|
@@ -1549,15 +1564,20 @@ class TokenMetadataExtractor {
|
|
|
1549
1564
|
}
|
|
1550
1565
|
// Get current price - prefer assetCtx.midPx as it's already index-matched,
|
|
1551
1566
|
// fall back to allMids lookup if midPx is null
|
|
1552
|
-
const
|
|
1567
|
+
const actualSymbol = universeAsset.name; // Use actual symbol from universe (handles kPEPE vs KPEPE)
|
|
1568
|
+
const prefixedKeyColon = marketPrefix
|
|
1569
|
+
? `${marketPrefix}:${actualSymbol}`
|
|
1570
|
+
: null;
|
|
1553
1571
|
let currentPrice = 0;
|
|
1554
1572
|
// Primary source: assetCtx.midPx (already properly indexed)
|
|
1555
1573
|
if (assetCtx.midPx) {
|
|
1556
1574
|
currentPrice = parseFloat(assetCtx.midPx);
|
|
1557
1575
|
}
|
|
1558
1576
|
// Fallback: allMids lookup with multiple key formats for HIP3 markets
|
|
1577
|
+
// Try actual symbol from universe first, then input symbol
|
|
1559
1578
|
if (!currentPrice || isNaN(currentPrice)) {
|
|
1560
1579
|
const currentPriceStr = (prefixedKeyColon && allMids.mids[prefixedKeyColon]) ||
|
|
1580
|
+
allMids.mids[actualSymbol] ||
|
|
1561
1581
|
allMids.mids[symbol];
|
|
1562
1582
|
currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
|
|
1563
1583
|
}
|
|
@@ -1571,10 +1591,12 @@ class TokenMetadataExtractor {
|
|
|
1571
1591
|
const markPrice = parseFloat(assetCtx.markPx);
|
|
1572
1592
|
const oraclePrice = parseFloat(assetCtx.oraclePx);
|
|
1573
1593
|
// Extract leverage info from activeAssetData if available
|
|
1574
|
-
// Try prefixed key first (e.g., "xyz:TSLA"), then
|
|
1594
|
+
// Try prefixed key first (e.g., "xyz:TSLA"), then actual symbol, then input symbol
|
|
1575
1595
|
const activeDataKey = prefixedKeyColon && (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[prefixedKeyColon])
|
|
1576
1596
|
? prefixedKeyColon
|
|
1577
|
-
:
|
|
1597
|
+
: (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[actualSymbol])
|
|
1598
|
+
? actualSymbol
|
|
1599
|
+
: symbol;
|
|
1578
1600
|
const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[activeDataKey];
|
|
1579
1601
|
const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
|
|
1580
1602
|
const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
|
|
@@ -1626,7 +1648,7 @@ class TokenMetadataExtractor {
|
|
|
1626
1648
|
static isTokenAvailable(symbol, perpMetaAssets) {
|
|
1627
1649
|
if (!perpMetaAssets)
|
|
1628
1650
|
return false;
|
|
1629
|
-
return perpMetaAssets.some((asset) => asset.name
|
|
1651
|
+
return perpMetaAssets.some((asset) => symbolsMatch(asset.name, symbol));
|
|
1630
1652
|
}
|
|
1631
1653
|
}
|
|
1632
1654
|
|
|
@@ -5910,10 +5932,10 @@ function toApiError(error) {
|
|
|
5910
5932
|
var _a;
|
|
5911
5933
|
const axiosError = error;
|
|
5912
5934
|
const payload = (axiosError && axiosError.response ? axiosError.response.data : undefined);
|
|
5913
|
-
const message = typeof payload ===
|
|
5935
|
+
const message = typeof payload === "object" && payload && "message" in payload
|
|
5914
5936
|
? String(payload.message)
|
|
5915
|
-
: (axiosError === null || axiosError === void 0 ? void 0 : axiosError.message) ||
|
|
5916
|
-
const errField = typeof payload ===
|
|
5937
|
+
: (axiosError === null || axiosError === void 0 ? void 0 : axiosError.message) || "Request failed";
|
|
5938
|
+
const errField = typeof payload === "object" && payload && "error" in payload
|
|
5917
5939
|
? String(payload.error)
|
|
5918
5940
|
: undefined;
|
|
5919
5941
|
return {
|
|
@@ -5923,8 +5945,8 @@ function toApiError(error) {
|
|
|
5923
5945
|
};
|
|
5924
5946
|
}
|
|
5925
5947
|
function joinUrl(baseUrl, path) {
|
|
5926
|
-
const cleanBase = baseUrl.replace(/\/$/,
|
|
5927
|
-
const cleanPath = path.startsWith(
|
|
5948
|
+
const cleanBase = baseUrl.replace(/\/$/, "");
|
|
5949
|
+
const cleanPath = path.startsWith("/") ? path : `/${path}`;
|
|
5928
5950
|
return `${cleanBase}${cleanPath}`;
|
|
5929
5951
|
}
|
|
5930
5952
|
/**
|
|
@@ -5953,7 +5975,7 @@ function addAuthInterceptors(params) {
|
|
|
5953
5975
|
pendingRequests = [];
|
|
5954
5976
|
}
|
|
5955
5977
|
const isOurApiUrl = (url) => Boolean(url && url.startsWith(apiBaseUrl));
|
|
5956
|
-
const isRefreshUrl = (url) => Boolean(url && url.startsWith(joinUrl(apiBaseUrl,
|
|
5978
|
+
const isRefreshUrl = (url) => Boolean(url && url.startsWith(joinUrl(apiBaseUrl, "/auth/refresh")));
|
|
5957
5979
|
const reqId = apiClient.interceptors.request.use((config) => {
|
|
5958
5980
|
var _a;
|
|
5959
5981
|
try {
|
|
@@ -5961,11 +5983,12 @@ function addAuthInterceptors(params) {
|
|
|
5961
5983
|
const token = getAccessToken();
|
|
5962
5984
|
if (token) {
|
|
5963
5985
|
config.headers = (_a = config.headers) !== null && _a !== void 0 ? _a : {};
|
|
5964
|
-
|
|
5986
|
+
config.headers["Authorization"] = `Bearer ${token}`;
|
|
5965
5987
|
}
|
|
5966
5988
|
}
|
|
5967
5989
|
}
|
|
5968
|
-
catch (
|
|
5990
|
+
catch (err) {
|
|
5991
|
+
console.error("[Auth Interceptor] Request interceptor error:", err);
|
|
5969
5992
|
}
|
|
5970
5993
|
return config;
|
|
5971
5994
|
});
|
|
@@ -5976,22 +5999,36 @@ function addAuthInterceptors(params) {
|
|
|
5976
5999
|
const url = originalRequest === null || originalRequest === void 0 ? void 0 : originalRequest.url;
|
|
5977
6000
|
// If not our API or not 401, just reject
|
|
5978
6001
|
if (!status || status !== 401 || !isOurApiUrl(url)) {
|
|
6002
|
+
if (status === 401) {
|
|
6003
|
+
console.warn("[Auth Interceptor] 401 received but URL check failed:", {
|
|
6004
|
+
url,
|
|
6005
|
+
apiBaseUrl,
|
|
6006
|
+
isOurApiUrl: isOurApiUrl(url),
|
|
6007
|
+
});
|
|
6008
|
+
}
|
|
5979
6009
|
return Promise.reject(error);
|
|
5980
6010
|
}
|
|
6011
|
+
console.log("[Auth Interceptor] 401 detected, attempting token refresh for URL:", url);
|
|
5981
6012
|
// If the 401 is from refresh endpoint itself -> force logout
|
|
5982
6013
|
if (isRefreshUrl(url)) {
|
|
6014
|
+
console.warn("[Auth Interceptor] Refresh endpoint returned 401, logging out");
|
|
5983
6015
|
try {
|
|
5984
6016
|
await logout();
|
|
5985
6017
|
}
|
|
5986
|
-
catch (
|
|
6018
|
+
catch (err) {
|
|
6019
|
+
console.error("[Auth Interceptor] Logout failed:", err);
|
|
6020
|
+
}
|
|
5987
6021
|
return Promise.reject(error);
|
|
5988
6022
|
}
|
|
5989
6023
|
// Prevent infinite loop
|
|
5990
6024
|
if (originalRequest && originalRequest._retry) {
|
|
6025
|
+
console.warn("[Auth Interceptor] Request already retried, logging out");
|
|
5991
6026
|
try {
|
|
5992
6027
|
await logout();
|
|
5993
6028
|
}
|
|
5994
|
-
catch (
|
|
6029
|
+
catch (err) {
|
|
6030
|
+
console.error("[Auth Interceptor] Logout failed:", err);
|
|
6031
|
+
}
|
|
5995
6032
|
return Promise.reject(error);
|
|
5996
6033
|
}
|
|
5997
6034
|
// Mark so we don't retry twice
|
|
@@ -6005,31 +6042,45 @@ function addAuthInterceptors(params) {
|
|
|
6005
6042
|
if (!newToken || !originalRequest)
|
|
6006
6043
|
return reject(error);
|
|
6007
6044
|
originalRequest.headers = (_a = originalRequest.headers) !== null && _a !== void 0 ? _a : {};
|
|
6008
|
-
originalRequest.headers[
|
|
6045
|
+
originalRequest.headers["Authorization"] =
|
|
6046
|
+
`Bearer ${newToken}`;
|
|
6009
6047
|
resolve(apiClient.request(originalRequest));
|
|
6010
6048
|
});
|
|
6011
6049
|
});
|
|
6012
6050
|
}
|
|
6013
6051
|
isRefreshing = true;
|
|
6014
6052
|
try {
|
|
6053
|
+
console.log("[Auth Interceptor] Refreshing tokens...");
|
|
6015
6054
|
const refreshed = await refreshTokens();
|
|
6016
|
-
const newAccessToken = (_b = (refreshed &&
|
|
6055
|
+
const newAccessToken = (_b = (refreshed &&
|
|
6056
|
+
(refreshed.accessToken || ((_a = refreshed.data) === null || _a === void 0 ? void 0 : _a.accessToken)))) !== null && _b !== void 0 ? _b : null;
|
|
6057
|
+
if (!newAccessToken) {
|
|
6058
|
+
console.error("[Auth Interceptor] Token refresh succeeded but no access token in response:", refreshed);
|
|
6059
|
+
}
|
|
6060
|
+
else {
|
|
6061
|
+
console.log("[Auth Interceptor] Token refresh successful");
|
|
6062
|
+
}
|
|
6017
6063
|
resolvePendingRequests(newAccessToken);
|
|
6018
6064
|
if (originalRequest) {
|
|
6019
6065
|
originalRequest.headers = (_c = originalRequest.headers) !== null && _c !== void 0 ? _c : {};
|
|
6020
6066
|
if (newAccessToken)
|
|
6021
|
-
|
|
6067
|
+
originalRequest.headers["Authorization"] =
|
|
6068
|
+
`Bearer ${newAccessToken}`;
|
|
6069
|
+
console.log("[Auth Interceptor] Retrying original request with new token");
|
|
6022
6070
|
const resp = await apiClient.request(originalRequest);
|
|
6023
6071
|
return resp;
|
|
6024
6072
|
}
|
|
6025
6073
|
return Promise.reject(error);
|
|
6026
6074
|
}
|
|
6027
6075
|
catch (refreshErr) {
|
|
6076
|
+
console.error("[Auth Interceptor] Token refresh failed:", refreshErr);
|
|
6028
6077
|
resolvePendingRequests(null);
|
|
6029
6078
|
try {
|
|
6030
6079
|
await logout();
|
|
6031
6080
|
}
|
|
6032
|
-
catch (
|
|
6081
|
+
catch (err) {
|
|
6082
|
+
console.error("[Auth Interceptor] Logout failed:", err);
|
|
6083
|
+
}
|
|
6033
6084
|
return Promise.reject(refreshErr);
|
|
6034
6085
|
}
|
|
6035
6086
|
finally {
|
|
@@ -6040,11 +6091,15 @@ function addAuthInterceptors(params) {
|
|
|
6040
6091
|
try {
|
|
6041
6092
|
apiClient.interceptors.request.eject(reqId);
|
|
6042
6093
|
}
|
|
6043
|
-
catch (
|
|
6094
|
+
catch (err) {
|
|
6095
|
+
console.error("[Auth Interceptor] Failed to eject request interceptor:", err);
|
|
6096
|
+
}
|
|
6044
6097
|
try {
|
|
6045
6098
|
apiClient.interceptors.response.eject(resId);
|
|
6046
6099
|
}
|
|
6047
|
-
catch (
|
|
6100
|
+
catch (err) {
|
|
6101
|
+
console.error("[Auth Interceptor] Failed to eject response interceptor:", err);
|
|
6102
|
+
}
|
|
6048
6103
|
};
|
|
6049
6104
|
}
|
|
6050
6105
|
|
|
@@ -8046,20 +8101,34 @@ function usePortfolio() {
|
|
|
8046
8101
|
}
|
|
8047
8102
|
|
|
8048
8103
|
async function getEIP712Message(baseUrl, address, clientId) {
|
|
8049
|
-
const url = joinUrl(baseUrl,
|
|
8104
|
+
const url = joinUrl(baseUrl, "/auth/eip712-message");
|
|
8050
8105
|
try {
|
|
8051
|
-
const resp = await
|
|
8052
|
-
|
|
8106
|
+
const resp = await apiClient.get(url, {
|
|
8107
|
+
params: { address, clientId },
|
|
8108
|
+
timeout: 30000,
|
|
8109
|
+
});
|
|
8110
|
+
return {
|
|
8111
|
+
data: resp.data,
|
|
8112
|
+
status: resp.status,
|
|
8113
|
+
headers: resp.headers,
|
|
8114
|
+
};
|
|
8053
8115
|
}
|
|
8054
8116
|
catch (error) {
|
|
8055
8117
|
throw toApiError(error);
|
|
8056
8118
|
}
|
|
8057
8119
|
}
|
|
8058
8120
|
async function authenticate(baseUrl, body) {
|
|
8059
|
-
const url = joinUrl(baseUrl,
|
|
8121
|
+
const url = joinUrl(baseUrl, "/auth/login");
|
|
8060
8122
|
try {
|
|
8061
|
-
const resp = await
|
|
8062
|
-
|
|
8123
|
+
const resp = await apiClient.post(url, body, {
|
|
8124
|
+
headers: { "Content-Type": "application/json" },
|
|
8125
|
+
timeout: 30000,
|
|
8126
|
+
});
|
|
8127
|
+
return {
|
|
8128
|
+
data: resp.data,
|
|
8129
|
+
status: resp.status,
|
|
8130
|
+
headers: resp.headers,
|
|
8131
|
+
};
|
|
8063
8132
|
}
|
|
8064
8133
|
catch (error) {
|
|
8065
8134
|
throw toApiError(error);
|
|
@@ -8070,7 +8139,7 @@ async function authenticate(baseUrl, body) {
|
|
|
8070
8139
|
*/
|
|
8071
8140
|
async function authenticateWithPrivy(baseUrl, params) {
|
|
8072
8141
|
const body = {
|
|
8073
|
-
method:
|
|
8142
|
+
method: "privy_access_token",
|
|
8074
8143
|
address: params.address,
|
|
8075
8144
|
clientId: params.clientId,
|
|
8076
8145
|
details: { appId: params.appId, accessToken: params.accessToken },
|
|
@@ -8078,20 +8147,28 @@ async function authenticateWithPrivy(baseUrl, params) {
|
|
|
8078
8147
|
return authenticate(baseUrl, body);
|
|
8079
8148
|
}
|
|
8080
8149
|
async function refreshToken(baseUrl, refreshTokenVal) {
|
|
8081
|
-
const url = joinUrl(baseUrl,
|
|
8150
|
+
const url = joinUrl(baseUrl, "/auth/refresh");
|
|
8082
8151
|
try {
|
|
8083
|
-
const resp = await
|
|
8084
|
-
return {
|
|
8152
|
+
const resp = await apiClient.post(url, { refreshToken: refreshTokenVal }, { headers: { "Content-Type": "application/json" }, timeout: 30000 });
|
|
8153
|
+
return {
|
|
8154
|
+
data: resp.data,
|
|
8155
|
+
status: resp.status,
|
|
8156
|
+
headers: resp.headers,
|
|
8157
|
+
};
|
|
8085
8158
|
}
|
|
8086
8159
|
catch (error) {
|
|
8087
8160
|
throw toApiError(error);
|
|
8088
8161
|
}
|
|
8089
8162
|
}
|
|
8090
8163
|
async function logout(baseUrl, refreshTokenVal) {
|
|
8091
|
-
const url = joinUrl(baseUrl,
|
|
8164
|
+
const url = joinUrl(baseUrl, "/auth/logout");
|
|
8092
8165
|
try {
|
|
8093
|
-
const resp = await
|
|
8094
|
-
return {
|
|
8166
|
+
const resp = await apiClient.post(url, { refreshToken: refreshTokenVal }, { headers: { "Content-Type": "application/json" }, timeout: 30000 });
|
|
8167
|
+
return {
|
|
8168
|
+
data: resp.data,
|
|
8169
|
+
status: resp.status,
|
|
8170
|
+
headers: resp.headers,
|
|
8171
|
+
};
|
|
8095
8172
|
}
|
|
8096
8173
|
catch (error) {
|
|
8097
8174
|
throw toApiError(error);
|
|
@@ -8119,6 +8196,7 @@ function useAuth() {
|
|
|
8119
8196
|
return;
|
|
8120
8197
|
}
|
|
8121
8198
|
if (address) {
|
|
8199
|
+
refreshTokens();
|
|
8122
8200
|
// If we already have an address in state, use it to load the session
|
|
8123
8201
|
const accessTokenKey = `${address}_accessToken`;
|
|
8124
8202
|
const refreshTokenKey = `${address}_refreshToken`;
|
package/dist/utils/http.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AxiosInstance } from
|
|
2
|
-
import { ApiErrorResponse } from
|
|
1
|
+
import type { AxiosInstance } from "axios";
|
|
2
|
+
import { ApiErrorResponse } from "../types";
|
|
3
3
|
export declare function toApiError(error: unknown): ApiErrorResponse;
|
|
4
4
|
export declare function joinUrl(baseUrl: string, path: string): string;
|
|
5
5
|
/**
|