@1delta/data-sdk 0.0.46 → 0.0.47
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.d.ts +1 -0
- package/dist/index.js +153 -14
- package/dist/index.mjs +146 -15
- package/dist/remoteCache.d.ts +68 -0
- package/dist/tokens.d.ts +12 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -862,12 +862,143 @@ var parseFraxlendPairKey = (lender) => {
|
|
|
862
862
|
return { chainId: m[1], pair: m[2].toLowerCase() };
|
|
863
863
|
};
|
|
864
864
|
|
|
865
|
+
// src/remoteCache.ts
|
|
866
|
+
var FRESH_TTL_MS = 5 * 60 * 1e3;
|
|
867
|
+
var REMOTE_CACHE_STORE_TTL_S = 7 * 24 * 60 * 60;
|
|
868
|
+
var STATE_KEY = "__1delta_remote_cache__";
|
|
869
|
+
function getState() {
|
|
870
|
+
const g = globalThis;
|
|
871
|
+
if (!g[STATE_KEY]) g[STATE_KEY] = { memo: /* @__PURE__ */ new Map(), inflight: /* @__PURE__ */ new Map() };
|
|
872
|
+
return g[STATE_KEY];
|
|
873
|
+
}
|
|
874
|
+
function setRemoteCacheStore(next) {
|
|
875
|
+
getState().store = next;
|
|
876
|
+
}
|
|
877
|
+
function setRemoteCacheGithubToken(token) {
|
|
878
|
+
getState().githubToken = token;
|
|
879
|
+
}
|
|
880
|
+
function clearRemoteCache() {
|
|
881
|
+
const state = getState();
|
|
882
|
+
state.memo.clear();
|
|
883
|
+
state.inflight.clear();
|
|
884
|
+
}
|
|
885
|
+
var RAW_HOST = "https://raw.githubusercontent.com/";
|
|
886
|
+
function githubApiMirror(url) {
|
|
887
|
+
if (!url.startsWith(RAW_HOST)) return void 0;
|
|
888
|
+
const [owner, repo, ref, ...path] = url.slice(RAW_HOST.length).split("/");
|
|
889
|
+
if (!owner || !repo || !ref || path.length === 0) return void 0;
|
|
890
|
+
return `https://api.github.com/repos/${owner}/${repo}/contents/${path.join("/")}?ref=${ref}`;
|
|
891
|
+
}
|
|
892
|
+
var RemoteFetchError = class extends Error {
|
|
893
|
+
constructor(message, status) {
|
|
894
|
+
super(message);
|
|
895
|
+
this.status = status;
|
|
896
|
+
this.name = "RemoteFetchError";
|
|
897
|
+
}
|
|
898
|
+
/** 404/410 — re-fetching cannot change the answer. */
|
|
899
|
+
get isMissing() {
|
|
900
|
+
return this.status === 404 || this.status === 410;
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
async function fetchRemoteJson(url, label) {
|
|
904
|
+
const res = await fetch(url);
|
|
905
|
+
if (res.ok) return await res.json();
|
|
906
|
+
const mirror = githubApiMirror(url);
|
|
907
|
+
const worthRetrying = res.status === 429 || res.status >= 500;
|
|
908
|
+
if (!mirror || !worthRetrying) {
|
|
909
|
+
throw new RemoteFetchError(`${label} fetch failed: HTTP ${res.status} from ${new URL(url).host}`, res.status);
|
|
910
|
+
}
|
|
911
|
+
const headers = {
|
|
912
|
+
Accept: "application/vnd.github.raw",
|
|
913
|
+
// The GitHub API rejects a request that sends no User-Agent.
|
|
914
|
+
"User-Agent": "1delta-data-sdk"
|
|
915
|
+
};
|
|
916
|
+
const token = getState().githubToken;
|
|
917
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
918
|
+
const viaApi = await fetch(mirror, { headers });
|
|
919
|
+
if (!viaApi.ok) {
|
|
920
|
+
throw new RemoteFetchError(
|
|
921
|
+
`${label} fetch failed: HTTP ${res.status} from raw.githubusercontent.com, HTTP ${viaApi.status} from api.github.com`,
|
|
922
|
+
res.status
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
return await viaApi.json();
|
|
926
|
+
}
|
|
927
|
+
var storeKey = (key) => `remote-cache:v1:${key}`;
|
|
928
|
+
async function readStore(key, isValid) {
|
|
929
|
+
const { store } = getState();
|
|
930
|
+
if (!store) return void 0;
|
|
931
|
+
try {
|
|
932
|
+
const raw = await store.get(storeKey(key));
|
|
933
|
+
if (!raw) return void 0;
|
|
934
|
+
const parsed = JSON.parse(raw);
|
|
935
|
+
if (typeof parsed?.at !== "number" || !isValid(parsed.value)) return void 0;
|
|
936
|
+
return parsed;
|
|
937
|
+
} catch {
|
|
938
|
+
return void 0;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
async function writeStore(key, entry) {
|
|
942
|
+
const { store } = getState();
|
|
943
|
+
if (!store) return;
|
|
944
|
+
try {
|
|
945
|
+
await store.put(storeKey(key), JSON.stringify(entry), REMOTE_CACHE_STORE_TTL_S);
|
|
946
|
+
} catch {
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
async function loadCached(key, load, isValid) {
|
|
950
|
+
const { memo, inflight } = getState();
|
|
951
|
+
const cached = memo.get(key);
|
|
952
|
+
if (cached && Date.now() - cached.at < FRESH_TTL_MS) return cached.value;
|
|
953
|
+
const pending = inflight.get(key);
|
|
954
|
+
if (pending) return pending;
|
|
955
|
+
const task = (async () => {
|
|
956
|
+
const stored = await readStore(key, isValid);
|
|
957
|
+
if (stored && Date.now() - stored.at < FRESH_TTL_MS) {
|
|
958
|
+
memo.set(key, stored);
|
|
959
|
+
return stored.value;
|
|
960
|
+
}
|
|
961
|
+
try {
|
|
962
|
+
const value = await load();
|
|
963
|
+
const entry = { at: Date.now(), value };
|
|
964
|
+
memo.set(key, entry);
|
|
965
|
+
await writeStore(key, entry);
|
|
966
|
+
return value;
|
|
967
|
+
} catch (error) {
|
|
968
|
+
const stale = memo.get(key) ?? stored;
|
|
969
|
+
if (!stale) throw error;
|
|
970
|
+
memo.set(key, stale);
|
|
971
|
+
return stale.value;
|
|
972
|
+
}
|
|
973
|
+
})().finally(() => {
|
|
974
|
+
inflight.delete(key);
|
|
975
|
+
});
|
|
976
|
+
inflight.set(key, task);
|
|
977
|
+
return task;
|
|
978
|
+
}
|
|
979
|
+
async function loadCachedJson(key, url, isValid, label = key) {
|
|
980
|
+
return loadCached(key, () => fetchRemoteJson(url, label), isValid);
|
|
981
|
+
}
|
|
982
|
+
|
|
865
983
|
// src/tokens.ts
|
|
866
984
|
var getListUrl = (chainId) => `https://raw.githubusercontent.com/1delta-DAO/token-lists/main/${chainId}.json`;
|
|
985
|
+
var MAIN_TOKENS_URL = "https://raw.githubusercontent.com/1delta-DAO/token-lists/main/main-tokens.json";
|
|
986
|
+
var isTokenListFile = (value) => !!value?.list && typeof value.list === "object";
|
|
987
|
+
async function loadTokenListFile(chainId) {
|
|
988
|
+
return loadCached(
|
|
989
|
+
`token-list:${chainId}`,
|
|
990
|
+
async () => {
|
|
991
|
+
const json = await fetchRemoteJson(getListUrl(chainId), `Token list for chain ${chainId}`);
|
|
992
|
+
return {
|
|
993
|
+
list: json.list,
|
|
994
|
+
mainTokens: json.mainTokens ?? []
|
|
995
|
+
};
|
|
996
|
+
},
|
|
997
|
+
isTokenListFile
|
|
998
|
+
);
|
|
999
|
+
}
|
|
867
1000
|
async function fetchTokenList(chainId) {
|
|
868
|
-
|
|
869
|
-
if (!data.ok) throw new Error(`HTTP error! status: ${data.status}`);
|
|
870
|
-
return (await data.json()).list;
|
|
1001
|
+
return (await loadTokenListFile(chainId)).list;
|
|
871
1002
|
}
|
|
872
1003
|
async function fetchTokenLists(chainIds) {
|
|
873
1004
|
const promises = chainIds.map(async (chainId) => {
|
|
@@ -878,25 +1009,27 @@ async function fetchTokenLists(chainIds) {
|
|
|
878
1009
|
return Object.fromEntries(results);
|
|
879
1010
|
}
|
|
880
1011
|
async function fetchTokenListFile(chainId) {
|
|
881
|
-
const
|
|
882
|
-
|
|
883
|
-
const json = await data.json();
|
|
884
|
-
return {
|
|
885
|
-
list: json.list,
|
|
886
|
-
mainTokens: json.mainTokens ?? []
|
|
887
|
-
};
|
|
1012
|
+
const file = await loadTokenListFile(chainId);
|
|
1013
|
+
return { list: file.list, mainTokens: file.mainTokens };
|
|
888
1014
|
}
|
|
889
|
-
var MAIN_TOKENS_URL = "https://raw.githubusercontent.com/1delta-DAO/token-lists/main/main-tokens.json";
|
|
890
1015
|
async function fetchMainTokensMap() {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1016
|
+
try {
|
|
1017
|
+
return await loadCached(
|
|
1018
|
+
"main-tokens",
|
|
1019
|
+
() => fetchRemoteJson(MAIN_TOKENS_URL, "main-tokens"),
|
|
1020
|
+
(value) => !!value && typeof value === "object"
|
|
1021
|
+
);
|
|
1022
|
+
} catch {
|
|
1023
|
+
return void 0;
|
|
1024
|
+
}
|
|
894
1025
|
}
|
|
895
1026
|
|
|
896
1027
|
exports.CURVANCE_MONAD_CONFIG = CURVANCE_MONAD_CONFIG;
|
|
897
1028
|
exports.FRAXLEND_ETHEREUM_CONFIG = FRAXLEND_ETHEREUM_CONFIG;
|
|
898
1029
|
exports.GEARBOX_ACCOUNT_COMPRESSOR_V310 = GEARBOX_ACCOUNT_COMPRESSOR_V310;
|
|
1030
|
+
exports.REMOTE_CACHE_STORE_TTL_S = REMOTE_CACHE_STORE_TTL_S;
|
|
899
1031
|
exports.RESUPPLY_ETHEREUM_CONFIG = RESUPPLY_ETHEREUM_CONFIG;
|
|
1032
|
+
exports.RemoteFetchError = RemoteFetchError;
|
|
900
1033
|
exports.aaveOracles = aaveOracles;
|
|
901
1034
|
exports.aaveOraclesConfig = aaveOraclesConfig;
|
|
902
1035
|
exports.aavePools = aavePools;
|
|
@@ -909,6 +1042,7 @@ exports.aaveV4Spokes = aaveV4Spokes;
|
|
|
909
1042
|
exports.aaveWethGateway = aaveWethGateway;
|
|
910
1043
|
exports.chainLogoURI = chainLogoURI;
|
|
911
1044
|
exports.chains = chains;
|
|
1045
|
+
exports.clearRemoteCache = clearRemoteCache;
|
|
912
1046
|
exports.compoundV2Oracles = compoundV2Oracles;
|
|
913
1047
|
exports.compoundV2OraclesConfig = compoundV2OraclesConfig;
|
|
914
1048
|
exports.compoundV2Pools = compoundV2Pools;
|
|
@@ -942,6 +1076,7 @@ exports.exactlyMarketByAsset = exactlyMarketByAsset;
|
|
|
942
1076
|
exports.exactlyMarkets = exactlyMarkets;
|
|
943
1077
|
exports.exactlyMarketsByChain = exactlyMarketsByChain;
|
|
944
1078
|
exports.fetchMainTokensMap = fetchMainTokensMap;
|
|
1079
|
+
exports.fetchRemoteJson = fetchRemoteJson;
|
|
945
1080
|
exports.fetchTokenList = fetchTokenList;
|
|
946
1081
|
exports.fetchTokenListFile = fetchTokenListFile;
|
|
947
1082
|
exports.fetchTokenLists = fetchTokenLists;
|
|
@@ -1011,6 +1146,8 @@ exports.llamaLendMarketByVault = llamaLendMarketByVault;
|
|
|
1011
1146
|
exports.llamaLendMarkets = llamaLendMarkets;
|
|
1012
1147
|
exports.llamaLendSupportsDelegation = llamaLendSupportsDelegation;
|
|
1013
1148
|
exports.llamaLendSupportsLeverage = llamaLendSupportsLeverage;
|
|
1149
|
+
exports.loadCached = loadCached;
|
|
1150
|
+
exports.loadCachedJson = loadCachedJson;
|
|
1014
1151
|
exports.midnightApiBaseOverride = midnightApiBaseOverride;
|
|
1015
1152
|
exports.midnightConfig = midnightConfig;
|
|
1016
1153
|
exports.midnightMarketById = midnightMarketById;
|
|
@@ -1041,6 +1178,8 @@ exports.riverLendersByChain = riverLendersByChain;
|
|
|
1041
1178
|
exports.riverMarketByIndex = riverMarketByIndex;
|
|
1042
1179
|
exports.riverMarkets = riverMarkets;
|
|
1043
1180
|
exports.setMidnightApiBase = setMidnightApiBase;
|
|
1181
|
+
exports.setRemoteCacheGithubToken = setRemoteCacheGithubToken;
|
|
1182
|
+
exports.setRemoteCacheStore = setRemoteCacheStore;
|
|
1044
1183
|
exports.setTermApiBase = setTermApiBase;
|
|
1045
1184
|
exports.siloMarkets = siloMarkets;
|
|
1046
1185
|
exports.siloMarketsV3 = siloMarketsV3;
|
package/dist/index.mjs
CHANGED
|
@@ -860,12 +860,143 @@ var parseFraxlendPairKey = (lender) => {
|
|
|
860
860
|
return { chainId: m[1], pair: m[2].toLowerCase() };
|
|
861
861
|
};
|
|
862
862
|
|
|
863
|
+
// src/remoteCache.ts
|
|
864
|
+
var FRESH_TTL_MS = 5 * 60 * 1e3;
|
|
865
|
+
var REMOTE_CACHE_STORE_TTL_S = 7 * 24 * 60 * 60;
|
|
866
|
+
var STATE_KEY = "__1delta_remote_cache__";
|
|
867
|
+
function getState() {
|
|
868
|
+
const g = globalThis;
|
|
869
|
+
if (!g[STATE_KEY]) g[STATE_KEY] = { memo: /* @__PURE__ */ new Map(), inflight: /* @__PURE__ */ new Map() };
|
|
870
|
+
return g[STATE_KEY];
|
|
871
|
+
}
|
|
872
|
+
function setRemoteCacheStore(next) {
|
|
873
|
+
getState().store = next;
|
|
874
|
+
}
|
|
875
|
+
function setRemoteCacheGithubToken(token) {
|
|
876
|
+
getState().githubToken = token;
|
|
877
|
+
}
|
|
878
|
+
function clearRemoteCache() {
|
|
879
|
+
const state = getState();
|
|
880
|
+
state.memo.clear();
|
|
881
|
+
state.inflight.clear();
|
|
882
|
+
}
|
|
883
|
+
var RAW_HOST = "https://raw.githubusercontent.com/";
|
|
884
|
+
function githubApiMirror(url) {
|
|
885
|
+
if (!url.startsWith(RAW_HOST)) return void 0;
|
|
886
|
+
const [owner, repo, ref, ...path] = url.slice(RAW_HOST.length).split("/");
|
|
887
|
+
if (!owner || !repo || !ref || path.length === 0) return void 0;
|
|
888
|
+
return `https://api.github.com/repos/${owner}/${repo}/contents/${path.join("/")}?ref=${ref}`;
|
|
889
|
+
}
|
|
890
|
+
var RemoteFetchError = class extends Error {
|
|
891
|
+
constructor(message, status) {
|
|
892
|
+
super(message);
|
|
893
|
+
this.status = status;
|
|
894
|
+
this.name = "RemoteFetchError";
|
|
895
|
+
}
|
|
896
|
+
/** 404/410 — re-fetching cannot change the answer. */
|
|
897
|
+
get isMissing() {
|
|
898
|
+
return this.status === 404 || this.status === 410;
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
async function fetchRemoteJson(url, label) {
|
|
902
|
+
const res = await fetch(url);
|
|
903
|
+
if (res.ok) return await res.json();
|
|
904
|
+
const mirror = githubApiMirror(url);
|
|
905
|
+
const worthRetrying = res.status === 429 || res.status >= 500;
|
|
906
|
+
if (!mirror || !worthRetrying) {
|
|
907
|
+
throw new RemoteFetchError(`${label} fetch failed: HTTP ${res.status} from ${new URL(url).host}`, res.status);
|
|
908
|
+
}
|
|
909
|
+
const headers = {
|
|
910
|
+
Accept: "application/vnd.github.raw",
|
|
911
|
+
// The GitHub API rejects a request that sends no User-Agent.
|
|
912
|
+
"User-Agent": "1delta-data-sdk"
|
|
913
|
+
};
|
|
914
|
+
const token = getState().githubToken;
|
|
915
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
916
|
+
const viaApi = await fetch(mirror, { headers });
|
|
917
|
+
if (!viaApi.ok) {
|
|
918
|
+
throw new RemoteFetchError(
|
|
919
|
+
`${label} fetch failed: HTTP ${res.status} from raw.githubusercontent.com, HTTP ${viaApi.status} from api.github.com`,
|
|
920
|
+
res.status
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
return await viaApi.json();
|
|
924
|
+
}
|
|
925
|
+
var storeKey = (key) => `remote-cache:v1:${key}`;
|
|
926
|
+
async function readStore(key, isValid) {
|
|
927
|
+
const { store } = getState();
|
|
928
|
+
if (!store) return void 0;
|
|
929
|
+
try {
|
|
930
|
+
const raw = await store.get(storeKey(key));
|
|
931
|
+
if (!raw) return void 0;
|
|
932
|
+
const parsed = JSON.parse(raw);
|
|
933
|
+
if (typeof parsed?.at !== "number" || !isValid(parsed.value)) return void 0;
|
|
934
|
+
return parsed;
|
|
935
|
+
} catch {
|
|
936
|
+
return void 0;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
async function writeStore(key, entry) {
|
|
940
|
+
const { store } = getState();
|
|
941
|
+
if (!store) return;
|
|
942
|
+
try {
|
|
943
|
+
await store.put(storeKey(key), JSON.stringify(entry), REMOTE_CACHE_STORE_TTL_S);
|
|
944
|
+
} catch {
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
async function loadCached(key, load, isValid) {
|
|
948
|
+
const { memo, inflight } = getState();
|
|
949
|
+
const cached = memo.get(key);
|
|
950
|
+
if (cached && Date.now() - cached.at < FRESH_TTL_MS) return cached.value;
|
|
951
|
+
const pending = inflight.get(key);
|
|
952
|
+
if (pending) return pending;
|
|
953
|
+
const task = (async () => {
|
|
954
|
+
const stored = await readStore(key, isValid);
|
|
955
|
+
if (stored && Date.now() - stored.at < FRESH_TTL_MS) {
|
|
956
|
+
memo.set(key, stored);
|
|
957
|
+
return stored.value;
|
|
958
|
+
}
|
|
959
|
+
try {
|
|
960
|
+
const value = await load();
|
|
961
|
+
const entry = { at: Date.now(), value };
|
|
962
|
+
memo.set(key, entry);
|
|
963
|
+
await writeStore(key, entry);
|
|
964
|
+
return value;
|
|
965
|
+
} catch (error) {
|
|
966
|
+
const stale = memo.get(key) ?? stored;
|
|
967
|
+
if (!stale) throw error;
|
|
968
|
+
memo.set(key, stale);
|
|
969
|
+
return stale.value;
|
|
970
|
+
}
|
|
971
|
+
})().finally(() => {
|
|
972
|
+
inflight.delete(key);
|
|
973
|
+
});
|
|
974
|
+
inflight.set(key, task);
|
|
975
|
+
return task;
|
|
976
|
+
}
|
|
977
|
+
async function loadCachedJson(key, url, isValid, label = key) {
|
|
978
|
+
return loadCached(key, () => fetchRemoteJson(url, label), isValid);
|
|
979
|
+
}
|
|
980
|
+
|
|
863
981
|
// src/tokens.ts
|
|
864
982
|
var getListUrl = (chainId) => `https://raw.githubusercontent.com/1delta-DAO/token-lists/main/${chainId}.json`;
|
|
983
|
+
var MAIN_TOKENS_URL = "https://raw.githubusercontent.com/1delta-DAO/token-lists/main/main-tokens.json";
|
|
984
|
+
var isTokenListFile = (value) => !!value?.list && typeof value.list === "object";
|
|
985
|
+
async function loadTokenListFile(chainId) {
|
|
986
|
+
return loadCached(
|
|
987
|
+
`token-list:${chainId}`,
|
|
988
|
+
async () => {
|
|
989
|
+
const json = await fetchRemoteJson(getListUrl(chainId), `Token list for chain ${chainId}`);
|
|
990
|
+
return {
|
|
991
|
+
list: json.list,
|
|
992
|
+
mainTokens: json.mainTokens ?? []
|
|
993
|
+
};
|
|
994
|
+
},
|
|
995
|
+
isTokenListFile
|
|
996
|
+
);
|
|
997
|
+
}
|
|
865
998
|
async function fetchTokenList(chainId) {
|
|
866
|
-
|
|
867
|
-
if (!data.ok) throw new Error(`HTTP error! status: ${data.status}`);
|
|
868
|
-
return (await data.json()).list;
|
|
999
|
+
return (await loadTokenListFile(chainId)).list;
|
|
869
1000
|
}
|
|
870
1001
|
async function fetchTokenLists(chainIds) {
|
|
871
1002
|
const promises = chainIds.map(async (chainId) => {
|
|
@@ -876,19 +1007,19 @@ async function fetchTokenLists(chainIds) {
|
|
|
876
1007
|
return Object.fromEntries(results);
|
|
877
1008
|
}
|
|
878
1009
|
async function fetchTokenListFile(chainId) {
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
const json = await data.json();
|
|
882
|
-
return {
|
|
883
|
-
list: json.list,
|
|
884
|
-
mainTokens: json.mainTokens ?? []
|
|
885
|
-
};
|
|
1010
|
+
const file = await loadTokenListFile(chainId);
|
|
1011
|
+
return { list: file.list, mainTokens: file.mainTokens };
|
|
886
1012
|
}
|
|
887
|
-
var MAIN_TOKENS_URL = "https://raw.githubusercontent.com/1delta-DAO/token-lists/main/main-tokens.json";
|
|
888
1013
|
async function fetchMainTokensMap() {
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1014
|
+
try {
|
|
1015
|
+
return await loadCached(
|
|
1016
|
+
"main-tokens",
|
|
1017
|
+
() => fetchRemoteJson(MAIN_TOKENS_URL, "main-tokens"),
|
|
1018
|
+
(value) => !!value && typeof value === "object"
|
|
1019
|
+
);
|
|
1020
|
+
} catch {
|
|
1021
|
+
return void 0;
|
|
1022
|
+
}
|
|
892
1023
|
}
|
|
893
1024
|
|
|
894
|
-
export { CURVANCE_MONAD_CONFIG, FRAXLEND_ETHEREUM_CONFIG, GEARBOX_ACCOUNT_COMPRESSOR_V310, RESUPPLY_ETHEREUM_CONFIG, aaveOracles, aaveOraclesConfig, aavePools, aaveReserves, aaveTokens, aaveV4Oracles, aaveV4Peripherals, aaveV4SpokeLenderKey, aaveV4Spokes, aaveWethGateway, chainLogoURI, chains, compoundV2Oracles, compoundV2OraclesConfig, compoundV2Pools, compoundV2Reserves, compoundV2TokenArray, compoundV2Tokens, compoundV3BaseData, compoundV3Bulker, compoundV3OraclesData, compoundV3Pools, compoundV3Reserves, curvanceConfig, curvanceConfigFor, curvanceLendersByChain, curvancePositionManager, curvancePositionManagersFor, dolomiteChains, dolomiteConfigs, dolomiteEmode, dolomiteMarketIdByToken, dssChainData, dssConfigFor, dssDebtJoin, dssDebtToken, dssMarketByIlk, eulerConfigs, eulerVaults, exactlyConfig, exactlyMarketByAddress, exactlyMarketByAsset, exactlyMarkets, exactlyMarketsByChain, fetchMainTokensMap, fetchTokenList, fetchTokenListFile, fetchTokenLists, findAaveV4PositionManager, fluidChains, fluidResolvers, fluidVaultEntries, fluidVaults, frankencoinChainData, frankencoinConfig, frankencoinConfigFor, frankencoinLendersByChain, frankencoinMarketByPosition, frankencoinMarkets, fraxlendConfig, fraxlendConfigFor, fraxlendLendersByChain, fraxlendPairKey, fraxlendPairsFor, gearboxAccountCompressor, gearboxAddressProviderV310, gearboxBotListV3, gearboxChains, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxResolvers, gearboxV3LenderKey, getAaveV4GatewayAddresses, getAaveV4PositionManagers, getAaveV4SpokeAccess, getAaveV4SpokeEntry, getAaveV4SpokePeripherals, getChainEntries, getSiloV2MarketEntry, getSiloV3MarketEntry, initConfig, initializeChainData, initializeLenderData, inverseChainData, inverseConfig, inverseConfigFor, inverseLendersByChain, inverseMarketByAddress, inverseMarkets, isAaveV4OperationRestricted, isListaSmartLpAsset, liquityBranchByIndex, liquityBranchByTroveManager, liquityBranchesByChain, liquityConfig, liquityConfigFor, liquityLendersByChain, liquityMarkets, listaCollateralProvider, listaCollateralProviders, listaNativeProvider, listaSmartLpByCollateral, llamaLendApiBaseUrl, llamaLendChainData, llamaLendConfig, llamaLendConfigFor, llamaLendLenderKey, llamaLendLendersByChain, llamaLendLeverageZap, llamaLendMarketByController, llamaLendMarketByVault, llamaLendMarkets, llamaLendSupportsDelegation, llamaLendSupportsLeverage, midnightApiBaseOverride, midnightConfig, midnightMarketById, midnightMarkets, midnightMarketsByChain, morphoBundler3, morphoOracles, morphoPools, morphoTypeMarkets, morphoTypeOracles, morphoTypeVaults, parseAaveV4SpokeLenderKey, parseFraxlendPairKey, parseGearboxV3LenderKey, parseLlamaLendLenderKey, parseSiloV2LenderKey, parseSiloV3LenderKey, parseTermMaxLenderKey, resolveMidnightApiBase, resolveTermApiBase, resupplyConfig, resupplyConfigFor, resupplyLendersByChain, riverChainData, riverConfig, riverConfigFor, riverLendersByChain, riverMarketByIndex, riverMarkets, setMidnightApiBase, setTermApiBase, siloMarkets, siloMarketsV3, siloPeripherals, siloPeripheralsV3, siloV2LenderKey, siloV3LenderKey, skyChainData, skyConfig, skyConfigFor, skyLendersByChain, skyMarkets, tellerConfig, tellerConfigByChain, tellerPoolByAddress, tellerPools, tellerPoolsByChain, termApiBaseOverride, termConfig, termMarketById, termMarkets, termMarketsByChain, termMaxApiBaseUrl, termMaxChainIds, termMaxConfig, termMaxConfigByChain, termMaxLenderKey, usddChainData, usddConfig, usddConfigFor, usddLendersByChain, usddMarketByIlk, usddMarkets };
|
|
1025
|
+
export { CURVANCE_MONAD_CONFIG, FRAXLEND_ETHEREUM_CONFIG, GEARBOX_ACCOUNT_COMPRESSOR_V310, REMOTE_CACHE_STORE_TTL_S, RESUPPLY_ETHEREUM_CONFIG, RemoteFetchError, aaveOracles, aaveOraclesConfig, aavePools, aaveReserves, aaveTokens, aaveV4Oracles, aaveV4Peripherals, aaveV4SpokeLenderKey, aaveV4Spokes, aaveWethGateway, chainLogoURI, chains, clearRemoteCache, compoundV2Oracles, compoundV2OraclesConfig, compoundV2Pools, compoundV2Reserves, compoundV2TokenArray, compoundV2Tokens, compoundV3BaseData, compoundV3Bulker, compoundV3OraclesData, compoundV3Pools, compoundV3Reserves, curvanceConfig, curvanceConfigFor, curvanceLendersByChain, curvancePositionManager, curvancePositionManagersFor, dolomiteChains, dolomiteConfigs, dolomiteEmode, dolomiteMarketIdByToken, dssChainData, dssConfigFor, dssDebtJoin, dssDebtToken, dssMarketByIlk, eulerConfigs, eulerVaults, exactlyConfig, exactlyMarketByAddress, exactlyMarketByAsset, exactlyMarkets, exactlyMarketsByChain, fetchMainTokensMap, fetchRemoteJson, fetchTokenList, fetchTokenListFile, fetchTokenLists, findAaveV4PositionManager, fluidChains, fluidResolvers, fluidVaultEntries, fluidVaults, frankencoinChainData, frankencoinConfig, frankencoinConfigFor, frankencoinLendersByChain, frankencoinMarketByPosition, frankencoinMarkets, fraxlendConfig, fraxlendConfigFor, fraxlendLendersByChain, fraxlendPairKey, fraxlendPairsFor, gearboxAccountCompressor, gearboxAddressProviderV310, gearboxBotListV3, gearboxChains, gearboxMarketCompressor, gearboxMarketConfigurators, gearboxResolvers, gearboxV3LenderKey, getAaveV4GatewayAddresses, getAaveV4PositionManagers, getAaveV4SpokeAccess, getAaveV4SpokeEntry, getAaveV4SpokePeripherals, getChainEntries, getSiloV2MarketEntry, getSiloV3MarketEntry, initConfig, initializeChainData, initializeLenderData, inverseChainData, inverseConfig, inverseConfigFor, inverseLendersByChain, inverseMarketByAddress, inverseMarkets, isAaveV4OperationRestricted, isListaSmartLpAsset, liquityBranchByIndex, liquityBranchByTroveManager, liquityBranchesByChain, liquityConfig, liquityConfigFor, liquityLendersByChain, liquityMarkets, listaCollateralProvider, listaCollateralProviders, listaNativeProvider, listaSmartLpByCollateral, llamaLendApiBaseUrl, llamaLendChainData, llamaLendConfig, llamaLendConfigFor, llamaLendLenderKey, llamaLendLendersByChain, llamaLendLeverageZap, llamaLendMarketByController, llamaLendMarketByVault, llamaLendMarkets, llamaLendSupportsDelegation, llamaLendSupportsLeverage, loadCached, loadCachedJson, midnightApiBaseOverride, midnightConfig, midnightMarketById, midnightMarkets, midnightMarketsByChain, morphoBundler3, morphoOracles, morphoPools, morphoTypeMarkets, morphoTypeOracles, morphoTypeVaults, parseAaveV4SpokeLenderKey, parseFraxlendPairKey, parseGearboxV3LenderKey, parseLlamaLendLenderKey, parseSiloV2LenderKey, parseSiloV3LenderKey, parseTermMaxLenderKey, resolveMidnightApiBase, resolveTermApiBase, resupplyConfig, resupplyConfigFor, resupplyLendersByChain, riverChainData, riverConfig, riverConfigFor, riverLendersByChain, riverMarketByIndex, riverMarkets, setMidnightApiBase, setRemoteCacheGithubToken, setRemoteCacheStore, setTermApiBase, siloMarkets, siloMarketsV3, siloPeripherals, siloPeripheralsV3, siloV2LenderKey, siloV3LenderKey, skyChainData, skyConfig, skyConfigFor, skyLendersByChain, skyMarkets, tellerConfig, tellerConfigByChain, tellerPoolByAddress, tellerPools, tellerPoolsByChain, termApiBaseOverride, termConfig, termMarketById, termMarkets, termMarketsByChain, termMaxApiBaseUrl, termMaxChainIds, termMaxConfig, termMaxConfigByChain, termMaxLenderKey, usddChainData, usddConfig, usddConfigFor, usddLendersByChain, usddMarketByIlk, usddMarkets };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache for the static JSON this SDK reads from GitHub (token lists, the chain
|
|
3
|
+
* registry).
|
|
4
|
+
*
|
|
5
|
+
* raw.githubusercontent.com rate-limits per EGRESS IP, and Cloudflare Workers
|
|
6
|
+
* share theirs — so an uncached fetch per request 429s in bursts. Before this
|
|
7
|
+
* existed that surfaced as a hard `INTERNAL_ERROR` 500 on every route needing a
|
|
8
|
+
* token list, and as a silently EMPTY chain registry (every chain rendered as
|
|
9
|
+
* "Chain 8453") that a 10-minute init cache then pinned in place.
|
|
10
|
+
*
|
|
11
|
+
* These files change on the order of days, so serving a stale copy is strictly
|
|
12
|
+
* better than failing — hence the stale-on-error fallback, which is the part
|
|
13
|
+
* that actually survives an outage.
|
|
14
|
+
*/
|
|
15
|
+
/** How long a persisted copy is kept around purely as the stale fallback. */
|
|
16
|
+
export declare const REMOTE_CACHE_STORE_TTL_S: number;
|
|
17
|
+
/**
|
|
18
|
+
* Durable backing store — a Cloudflare KV namespace in the workers, absent
|
|
19
|
+
* everywhere else. Without one the cache is per-process, which still collapses
|
|
20
|
+
* N requests into one upstream fetch but cannot help a cold start; with one, a
|
|
21
|
+
* fresh isolate never touches GitHub at all.
|
|
22
|
+
*/
|
|
23
|
+
export interface RemoteCacheStore {
|
|
24
|
+
get(key: string): Promise<string | null>;
|
|
25
|
+
put(key: string, value: string, ttlSeconds: number): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/** Installs (or with `undefined`, removes) the durable store. */
|
|
28
|
+
export declare function setRemoteCacheStore(next: RemoteCacheStore | undefined): void;
|
|
29
|
+
/**
|
|
30
|
+
* Optional GitHub token for the API mirror below. Unauthenticated it allows 60
|
|
31
|
+
* requests/hour per IP, which is thin for a shared Worker egress; a token
|
|
32
|
+
* raises that to 5,000. Only ever used on the fallback path.
|
|
33
|
+
*/
|
|
34
|
+
export declare function setRemoteCacheGithubToken(token: string | undefined): void;
|
|
35
|
+
/** Drops every cached value. Intended for tests. */
|
|
36
|
+
export declare function clearRemoteCache(): void;
|
|
37
|
+
/**
|
|
38
|
+
* A non-2xx from the remote. Carries the ORIGIN status so a caller can tell a
|
|
39
|
+
* settled answer (404/410 — the file is not published) from a transient one
|
|
40
|
+
* (429/5xx — the same URL may work a second later). Callers that collapse the
|
|
41
|
+
* two re-fetch known-missing files forever, or treat a rate limit as proof that
|
|
42
|
+
* a lender has no config.
|
|
43
|
+
*/
|
|
44
|
+
export declare class RemoteFetchError extends Error {
|
|
45
|
+
/** Status from the ORIGIN host, not from the mirror. */
|
|
46
|
+
readonly status: number;
|
|
47
|
+
constructor(message: string,
|
|
48
|
+
/** Status from the ORIGIN host, not from the mirror. */
|
|
49
|
+
status: number);
|
|
50
|
+
/** 404/410 — re-fetching cannot change the answer. */
|
|
51
|
+
get isMissing(): boolean;
|
|
52
|
+
}
|
|
53
|
+
/** Fetches JSON from `url`, retrying via the GitHub API when raw rate-limits. */
|
|
54
|
+
export declare function fetchRemoteJson<T>(url: string, label: string): Promise<T>;
|
|
55
|
+
/**
|
|
56
|
+
* Serves `key` from memory, then the durable store, then `load()` — and on a
|
|
57
|
+
* failed `load()` falls back to whatever stale copy either layer holds, only
|
|
58
|
+
* rethrowing when there is nothing to fall back to.
|
|
59
|
+
*
|
|
60
|
+
* Concurrent callers for the same key share one in-flight load.
|
|
61
|
+
*
|
|
62
|
+
* `isValid` guards the durable layer: a truncated or shape-changed entry is
|
|
63
|
+
* treated as absent rather than served, since a bad token list silently
|
|
64
|
+
* mis-decimals every balance built from it.
|
|
65
|
+
*/
|
|
66
|
+
export declare function loadCached<T>(key: string, load: () => Promise<T>, isValid: (value: any) => boolean): Promise<T>;
|
|
67
|
+
/** `loadCached` over a JSON URL, failing on any non-2xx so stale can take over. */
|
|
68
|
+
export declare function loadCachedJson<T>(key: string, url: string, isValid: (value: any) => boolean, label?: string): Promise<T>;
|
package/dist/tokens.d.ts
CHANGED
|
@@ -13,10 +13,6 @@ export interface TokenListEntry {
|
|
|
13
13
|
type TokenList = {
|
|
14
14
|
[addr: string]: TokenListEntry;
|
|
15
15
|
};
|
|
16
|
-
export declare function fetchTokenList(chainId: string): Promise<TokenList>;
|
|
17
|
-
export declare function fetchTokenLists(chainIds: string[]): Promise<{
|
|
18
|
-
[chainId: string]: TokenList;
|
|
19
|
-
}>;
|
|
20
16
|
export interface TokenListFileData {
|
|
21
17
|
list: TokenList;
|
|
22
18
|
/**
|
|
@@ -26,7 +22,18 @@ export interface TokenListFileData {
|
|
|
26
22
|
*/
|
|
27
23
|
mainTokens: string[];
|
|
28
24
|
}
|
|
29
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* NOTE: cached — the returned `list` is a SHARED object. Treat it as read-only;
|
|
27
|
+
* mutating it corrupts the copy every other caller sees.
|
|
28
|
+
*/
|
|
29
|
+
export declare function fetchTokenList(chainId: string): Promise<TokenList>;
|
|
30
|
+
export declare function fetchTokenLists(chainIds: string[]): Promise<{
|
|
31
|
+
[chainId: string]: TokenList;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Like {@link fetchTokenList} but keeps the `mainTokens` curation. Same
|
|
35
|
+
* read-only caveat on `list`.
|
|
36
|
+
*/
|
|
30
37
|
export declare function fetchTokenListFile(chainId: string): Promise<TokenListFileData>;
|
|
31
38
|
/**
|
|
32
39
|
* Aggregated chainId → mainTokens map (one small file for all chains, so
|