@t2000/engine 0.50.0 → 0.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1963,7 +1963,7 @@ declare const balanceCheckTool: Tool<{
1963
1963
  pendingRewards: number;
1964
1964
  gasReserve: number;
1965
1965
  defi: number;
1966
- defiByProtocol: Partial<Record<"cetus" | "suilend" | "scallop" | "bluefin" | "aftermath" | "haedal", number>>;
1966
+ defiByProtocol: Partial<Record<"aftermath" | "alphafi" | "alphalend" | "bluefin" | "bluemove" | "bucket" | "bucket2" | "cetus" | "deepbook" | "ember" | "ferra" | "flowx" | "haedal" | "kai" | "kriya" | "magma" | "momentum" | "r25" | "scallop" | "steamm" | "suilend" | "suins-staking" | "suistake" | "turbos" | "typus" | "unihouse" | "walrus", number>>;
1967
1967
  defiSource: "blockvision" | "partial" | "degraded";
1968
1968
  total: number;
1969
1969
  stables: number;
package/dist/index.js CHANGED
@@ -714,13 +714,39 @@ function parseNumberOrNull(input) {
714
714
  var DEFI_PORTFOLIO_TIMEOUT_MS = 4e3;
715
715
  var DEFI_CACHE_TTL_MS = 6e4;
716
716
  var DEFI_PROTOCOLS = [
717
+ "aftermath",
718
+ "alphafi",
719
+ "alphalend",
720
+ "bluefin",
721
+ "bluemove",
722
+ "bucket",
723
+ "bucket2",
717
724
  "cetus",
718
- "suilend",
725
+ "deepbook",
726
+ "ember",
727
+ "ferra",
728
+ "flowx",
729
+ "haedal",
730
+ "kai",
731
+ "kriya",
732
+ "magma",
733
+ "momentum",
734
+ "r25",
719
735
  "scallop",
720
- "bluefin",
721
- "aftermath",
722
- "haedal"
736
+ "steamm",
737
+ "suilend",
738
+ "suins-staking",
739
+ "suistake",
740
+ "turbos",
741
+ "typus",
742
+ "unihouse",
743
+ "walrus"
723
744
  ];
745
+ var SUI_TYPE_FULL = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI";
746
+ var USDC_TYPE_FULL = "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC";
747
+ var BLUE_TYPE_FULL = "0xe1b45a0e641b9955a20aa0ad1c1f4ad86aad8afb07296d4085e349a50e90bdca::blue::BLUE";
748
+ var WAL_TYPE_FULL = "0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL";
749
+ var NS_TYPE_FULL = "0x5145494a5f5100e645e4b0aa950fa6b68f614e8c59e17bc5ded3495123a79178::ns::NS";
724
750
  var defiCache = /* @__PURE__ */ new Map();
725
751
  var defiInflight = /* @__PURE__ */ new Map();
726
752
  async function fetchAddressDefiPortfolio(address, apiKey, priceHints = {}) {
@@ -775,7 +801,7 @@ async function fetchAddressDefiPortfolio(address, apiKey, priceHints = {}) {
775
801
  continue;
776
802
  }
777
803
  try {
778
- const usd = NORMALIZERS[proto](s.value, prices);
804
+ const usd = normalizeProtocol(proto, s.value, prices);
779
805
  if (Number.isFinite(usd) && usd !== 0) {
780
806
  perProtocol[proto] = usd;
781
807
  totalUsd += usd;
@@ -827,6 +853,166 @@ async function fetchOneDefiProtocol(address, protocol, apiKey) {
827
853
  if (json.code !== 200 || !json.result) return null;
828
854
  return json.result;
829
855
  }
856
+ var PAIR_A_COIN_KEYS = ["coinTypeA", "coinTypeX", "tokenXType"];
857
+ var PAIR_B_COIN_KEYS = ["coinTypeB", "coinTypeY", "tokenYType"];
858
+ var PAIR_A_AMOUNT_KEYS = [
859
+ "balanceA",
860
+ "amountA",
861
+ "coinAmountA",
862
+ "coinAAmount",
863
+ "coinTypeAAmount",
864
+ "tokenXBalance",
865
+ "tokenXAmount",
866
+ "amountX",
867
+ "valueA"
868
+ ];
869
+ var PAIR_B_AMOUNT_KEYS = [
870
+ "balanceB",
871
+ "amountB",
872
+ "coinAmountB",
873
+ "coinBAmount",
874
+ "coinTypeBAmount",
875
+ "tokenYBalance",
876
+ "tokenYAmount",
877
+ "amountY",
878
+ "valueB"
879
+ ];
880
+ var PAIR_A_DECIMALS_KEYS = ["coinTypeADecimals", "tokenXDecimals", "decimalsA"];
881
+ var PAIR_B_DECIMALS_KEYS = ["coinTypeBDecimals", "tokenYDecimals", "decimalsB"];
882
+ var SINGLE_COIN_KEYS = ["coinType", "depositToken", "token"];
883
+ var SINGLE_AMOUNT_KEYS = ["amount", "balance", "value", "equity"];
884
+ var SINGLE_DECIMALS_KEYS = ["decimals", "decimal", "coinDecimals"];
885
+ var DEBT_KEYS = /* @__PURE__ */ new Set([
886
+ "borrow",
887
+ "borrows",
888
+ "debt",
889
+ "debts",
890
+ "borrowings",
891
+ "borrowedpools"
892
+ ]);
893
+ var SKIP_KEYS = /* @__PURE__ */ new Set([
894
+ "rewards",
895
+ "reward",
896
+ "fees",
897
+ "fee",
898
+ "pendingrewards",
899
+ "incentiveinfos",
900
+ "feereward",
901
+ "incentivereward"
902
+ ]);
903
+ function isCoinTypeString(v) {
904
+ if (typeof v !== "string" || !v.includes("::")) return false;
905
+ return v.startsWith("0x") || /^[0-9a-fA-F]/.test(v);
906
+ }
907
+ function ensure0xPrefix(coinType) {
908
+ return coinType.startsWith("0x") ? coinType : "0x" + coinType;
909
+ }
910
+ function isAmountValue(v) {
911
+ return typeof v === "string" && v.trim().length > 0 || typeof v === "number" && Number.isFinite(v);
912
+ }
913
+ function isFiniteNumber(v) {
914
+ return typeof v === "number" && Number.isFinite(v);
915
+ }
916
+ function pickField(obj, keys, predicate) {
917
+ for (const k of keys) {
918
+ const v = obj[k];
919
+ if (predicate(v)) return v;
920
+ }
921
+ return void 0;
922
+ }
923
+ function nestedDecimals(node) {
924
+ if (!node || typeof node !== "object") return void 0;
925
+ const obj = node;
926
+ if (typeof obj.decimals === "number") return obj.decimals;
927
+ return void 0;
928
+ }
929
+ function toHumanQuantity(raw, decimalsHint) {
930
+ if (typeof raw === "number") {
931
+ if (!Number.isFinite(raw)) return 0;
932
+ if (!Number.isInteger(raw)) return raw;
933
+ if (decimalsHint != null) return raw / 10 ** decimalsHint;
934
+ return raw;
935
+ }
936
+ const trimmed = raw.trim();
937
+ if (trimmed.length === 0) return 0;
938
+ if (trimmed.includes(".") || trimmed.includes("e") || trimmed.includes("E")) {
939
+ const n2 = Number(trimmed);
940
+ return Number.isFinite(n2) ? n2 : 0;
941
+ }
942
+ const n = Number(trimmed);
943
+ if (!Number.isFinite(n)) return 0;
944
+ const dec = decimalsHint ?? 9;
945
+ return n / 10 ** dec;
946
+ }
947
+ function priceFor(coinType, prices) {
948
+ const prefixed = ensure0xPrefix(coinType);
949
+ const norm = normalizeCoinType(prefixed);
950
+ return prices[norm] ?? prices[prefixed] ?? prices[coinType] ?? STABLE_USD_PRICES[norm] ?? 0;
951
+ }
952
+ function toUsd(coinType, raw, decimalsHint, prices) {
953
+ if (raw == null || typeof raw !== "string" && typeof raw !== "number") return 0;
954
+ if (typeof raw === "string" && raw.trim().length === 0) return 0;
955
+ const prefixed = ensure0xPrefix(coinType);
956
+ const decimals = typeof decimalsHint === "number" ? decimalsHint : getDecimalsForCoinType(prefixed);
957
+ const human = toHumanQuantity(raw, decimals);
958
+ if (!Number.isFinite(human)) return 0;
959
+ return human * priceFor(prefixed, prices);
960
+ }
961
+ function extractPair(obj) {
962
+ const coinTypeA = pickField(obj, PAIR_A_COIN_KEYS, isCoinTypeString);
963
+ const coinTypeB = pickField(obj, PAIR_B_COIN_KEYS, isCoinTypeString);
964
+ if (!coinTypeA || !coinTypeB) return null;
965
+ const amountA = pickField(obj, PAIR_A_AMOUNT_KEYS, isAmountValue);
966
+ const amountB = pickField(obj, PAIR_B_AMOUNT_KEYS, isAmountValue);
967
+ if (amountA == null || amountB == null) return null;
968
+ const decimalsA = pickField(obj, PAIR_A_DECIMALS_KEYS, isFiniteNumber) ?? nestedDecimals(obj.coinA);
969
+ const decimalsB = pickField(obj, PAIR_B_DECIMALS_KEYS, isFiniteNumber) ?? nestedDecimals(obj.coinB);
970
+ return { coinTypeA, amountA, decimalsA, coinTypeB, amountB, decimalsB };
971
+ }
972
+ function extractSingle(obj) {
973
+ const coinType = pickField(obj, SINGLE_COIN_KEYS, isCoinTypeString);
974
+ if (!coinType) return null;
975
+ const amount = pickField(obj, SINGLE_AMOUNT_KEYS, isAmountValue);
976
+ if (amount == null) return null;
977
+ const decimals = pickField(obj, SINGLE_DECIMALS_KEYS, isFiniteNumber);
978
+ const isBorrow = obj.type === "Borrow";
979
+ return { coinType, amount, decimals, isBorrow };
980
+ }
981
+ function walkProtocolResponse(result, prices) {
982
+ let total = 0;
983
+ walk(result, false);
984
+ return total;
985
+ function walk(node, debtSide) {
986
+ if (!node || typeof node !== "object") return;
987
+ if (Array.isArray(node)) {
988
+ for (const item of node) walk(item, debtSide);
989
+ return;
990
+ }
991
+ const obj = node;
992
+ if (typeof obj.totalSupplyValue === "number") total += obj.totalSupplyValue;
993
+ if (typeof obj.totalCollateralValue === "number") total += obj.totalCollateralValue;
994
+ if (typeof obj.totalLockedScaValue === "number") total += obj.totalLockedScaValue;
995
+ if (typeof obj.totalDebtValue === "number") total -= obj.totalDebtValue;
996
+ const pair = extractPair(obj);
997
+ if (pair) {
998
+ const a = toUsd(pair.coinTypeA, pair.amountA, pair.decimalsA, prices);
999
+ const b = toUsd(pair.coinTypeB, pair.amountB, pair.decimalsB, prices);
1000
+ total += debtSide ? -(a + b) : a + b;
1001
+ } else {
1002
+ const single = extractSingle(obj);
1003
+ if (single) {
1004
+ const usd = toUsd(single.coinType, single.amount, single.decimals, prices);
1005
+ total += debtSide || single.isBorrow ? -usd : usd;
1006
+ }
1007
+ }
1008
+ for (const [k, v] of Object.entries(obj)) {
1009
+ const lk = k.toLowerCase();
1010
+ if (SKIP_KEYS.has(lk)) continue;
1011
+ const childDebt = debtSide || DEBT_KEYS.has(lk);
1012
+ walk(v, childDebt);
1013
+ }
1014
+ }
1015
+ }
830
1016
  function collectCoinTypes(obj, out) {
831
1017
  if (!obj || typeof obj !== "object") return;
832
1018
  if (Array.isArray(obj)) {
@@ -834,139 +1020,108 @@ function collectCoinTypes(obj, out) {
834
1020
  return;
835
1021
  }
836
1022
  for (const [k, v] of Object.entries(obj)) {
837
- if (typeof v === "string" && v.startsWith("0x") && v.includes("::")) {
1023
+ if (typeof v === "string" && isCoinTypeString(v)) {
838
1024
  const lk = k.toLowerCase();
839
- if (lk.includes("cointype") || lk === "cointypea" || lk === "cointypeb" || lk === "tokenxtype" || lk === "tokenytype" || lk === "coinaddress" || lk === "phantomtype" || lk === "typename") {
840
- out.add(v);
1025
+ if (lk.includes("cointype") || lk === "tokenxtype" || lk === "tokenytype" || lk === "deposittoken" || lk === "rewardstoken" || lk === "token" || lk === "coinaddress" || lk === "phantomtype" || lk === "typename") {
1026
+ out.add(ensure0xPrefix(v));
841
1027
  }
842
1028
  } else if (typeof v === "object" && v !== null) {
843
1029
  collectCoinTypes(v, out);
844
1030
  }
845
1031
  }
846
1032
  }
847
- function priceFor(coinType, prices) {
848
- const norm = normalizeCoinType(coinType);
849
- return prices[norm] ?? prices[coinType] ?? STABLE_USD_PRICES[norm] ?? 0;
850
- }
851
- function rawToUsd(coinType, raw, decimalsHint, prices) {
852
- if (raw == null) return 0;
853
- const decimals = typeof decimalsHint === "number" ? decimalsHint : getDecimalsForCoinType(coinType);
854
- const amount = Number(raw) / 10 ** decimals;
855
- if (!Number.isFinite(amount)) return 0;
856
- return amount * priceFor(coinType, prices);
857
- }
858
- var NORMALIZERS = {
859
- cetus: normalizeCetus,
860
- suilend: normalizeSuilend,
861
- scallop: normalizeScallop,
862
- bluefin: normalizeBluefin,
863
- aftermath: normalizeAftermath,
864
- haedal: normalizeHaedal
865
- };
866
- function normalizeCetus(result, prices) {
867
- const data = result.cetus ?? {};
868
- let total = 0;
869
- const sumPair = (item, aField, bField) => {
870
- if (item.coinTypeA && item[aField] != null) {
871
- const dec = item.coinTypeADecimals ?? item.coinA?.decimals;
872
- total += rawToUsd(item.coinTypeA, item[aField], dec, prices);
873
- }
874
- if (item.coinTypeB && item[bField] != null) {
875
- const dec = item.coinTypeBDecimals ?? item.coinB?.decimals;
876
- total += rawToUsd(item.coinTypeB, item[bField], dec, prices);
877
- }
878
- };
879
- for (const lp of data.lps ?? []) sumPair(lp, "balanceA", "balanceB");
880
- for (const farm of data.farms ?? []) sumPair(farm, "balanceA", "balanceB");
881
- for (const vault of data.vaults ?? []) sumPair(vault, "coinAAmount", "coinBAmount");
882
- return total;
883
- }
884
- function normalizeSuilend(result, prices) {
885
- const data = result.suilend ?? {};
886
- let total = 0;
887
- for (const d of data.deposits ?? []) {
888
- if (d.coinType && d.amount != null) total += rawToUsd(d.coinType, d.amount, d.decimals, prices);
889
- }
890
- for (const b of data.borrows ?? []) {
891
- if (b.coinType && b.amount != null) total -= rawToUsd(b.coinType, b.amount, b.decimals, prices);
892
- }
893
- for (const s of data.strategies ?? []) {
894
- if (s.coinType && s.amount != null) total += rawToUsd(s.coinType, s.amount, s.decimals, prices);
895
- }
896
- return total;
897
- }
898
- function normalizeScallop(result, _prices) {
899
- const s = result.scallop;
900
- if (!s) return 0;
901
- const supply = Number(s.totalSupplyValue ?? 0);
902
- const collateral = Number(s.totalCollateralValue ?? 0);
903
- const locked = Number(s.totalLockedScaValue ?? 0);
904
- const debt = Number(s.totalDebtValue ?? 0);
905
- const net = (Number.isFinite(supply) ? supply : 0) + (Number.isFinite(collateral) ? collateral : 0) + (Number.isFinite(locked) ? locked : 0) - (Number.isFinite(debt) ? debt : 0);
906
- return net;
907
- }
908
1033
  function normalizeBluefin(result, prices) {
909
1034
  const data = result.bluefin ?? {};
910
1035
  let total = 0;
911
1036
  for (const lp of data.lps ?? []) {
912
1037
  if (lp.coinTypeA && lp.coinAmountA != null) {
913
- total += rawToUsd(lp.coinTypeA, lp.coinAmountA, void 0, prices);
1038
+ total += toUsd(lp.coinTypeA, lp.coinAmountA, void 0, prices);
914
1039
  }
915
1040
  if (lp.coinTypeB && lp.coinAmountB != null) {
916
- total += rawToUsd(lp.coinTypeB, lp.coinAmountB, void 0, prices);
1041
+ total += toUsd(lp.coinTypeB, lp.coinAmountB, void 0, prices);
917
1042
  }
918
1043
  }
919
1044
  if (data.usdcVault?.amount != null) {
920
- total += rawToUsd(
921
- "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
922
- data.usdcVault.amount,
923
- 6,
924
- prices
925
- );
1045
+ total += toUsd(USDC_TYPE_FULL, data.usdcVault.amount, 6, prices);
926
1046
  }
927
1047
  if (data.blueVault?.amount != null) {
928
- total += rawToUsd(
929
- "0xe1b45a0e641b9955a20aa0ad1c1f4ad86aad8afb07296d4085e349a50e90bdca::blue::BLUE",
930
- data.blueVault.amount,
931
- 9,
932
- prices
933
- );
934
- }
935
- return total;
936
- }
937
- function normalizeAftermath(result, prices) {
938
- const data = result.aftermath ?? {};
939
- let total = 0;
940
- const positions = [...data.lpPositions ?? [], ...data.farmPositions ?? []];
941
- for (const pos of positions) {
942
- for (const c of pos.coins ?? []) {
943
- if (c.coinType && c.amount != null) {
944
- total += rawToUsd(c.coinType, c.amount, void 0, prices);
945
- }
946
- }
1048
+ total += toUsd(BLUE_TYPE_FULL, data.blueVault.amount, 9, prices);
947
1049
  }
948
1050
  return total;
949
1051
  }
950
1052
  function normalizeHaedal(result, prices) {
951
- const SUI_TYPE_FULL = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI";
952
1053
  const data = result.haedal ?? {};
953
1054
  let total = 0;
954
1055
  for (const lp of data.lps ?? []) {
955
- const item = lp;
956
- if (item.coinTypeA && item.balanceA != null) {
957
- total += rawToUsd(item.coinTypeA, item.balanceA, void 0, prices);
1056
+ if (lp.coinTypeA && lp.balanceA != null) {
1057
+ total += toUsd(lp.coinTypeA, lp.balanceA, void 0, prices);
958
1058
  }
959
- if (item.coinTypeB && item.balanceB != null) {
960
- total += rawToUsd(item.coinTypeB, item.balanceB, void 0, prices);
1059
+ if (lp.coinTypeB && lp.balanceB != null) {
1060
+ total += toUsd(lp.coinTypeB, lp.balanceB, void 0, prices);
961
1061
  }
962
1062
  }
963
1063
  for (const stake of data.stakings ?? []) {
964
1064
  if (stake.sui_amount != null) {
965
- total += rawToUsd(SUI_TYPE_FULL, stake.sui_amount, 9, prices);
1065
+ total += toUsd(SUI_TYPE_FULL, stake.sui_amount, 9, prices);
1066
+ }
1067
+ }
1068
+ return total;
1069
+ }
1070
+ function normalizeKai(result, prices) {
1071
+ const data = result.kai ?? {};
1072
+ let total = 0;
1073
+ for (const v of data.vaults ?? []) {
1074
+ const coinType = v.coin?.p?.phantomType ?? v.coin?.p?.typeName;
1075
+ if (coinType && v.equity != null) {
1076
+ total += toUsd(coinType, v.equity, v.coin?.decimals, prices);
1077
+ }
1078
+ }
1079
+ for (const lp of data.lpVaults ?? []) {
1080
+ const coinTypeA = lp.coinA?.p?.phantomType ?? lp.coinA?.p?.typeName;
1081
+ const coinTypeB = lp.coinB?.p?.phantomType ?? lp.coinB?.p?.typeName;
1082
+ if (coinTypeA && lp.balanceA != null) {
1083
+ total += toUsd(coinTypeA, lp.balanceA, lp.coinA?.decimals, prices);
1084
+ }
1085
+ if (coinTypeB && lp.balanceB != null) {
1086
+ total += toUsd(coinTypeB, lp.balanceB, lp.coinB?.decimals, prices);
966
1087
  }
967
1088
  }
968
1089
  return total;
969
1090
  }
1091
+ function sumBareStakings(data, impliedCoinType, decimals, prices) {
1092
+ if (!data) return 0;
1093
+ let total = 0;
1094
+ for (const s of data.stakings ?? []) {
1095
+ const amt = s.sui_amount ?? s.amount;
1096
+ if (amt != null) total += toUsd(impliedCoinType, amt, decimals, prices);
1097
+ }
1098
+ return total;
1099
+ }
1100
+ function normalizeSuistake(result, prices) {
1101
+ const data = result.suistake;
1102
+ return sumBareStakings(data, SUI_TYPE_FULL, 9, prices);
1103
+ }
1104
+ function normalizeWalrus(result, prices) {
1105
+ const data = result.walrus;
1106
+ return sumBareStakings(data, WAL_TYPE_FULL, 9, prices);
1107
+ }
1108
+ function normalizeSuinsStaking(result, prices) {
1109
+ const data = result["suins-staking"] ?? result.suinsStaking ?? result.suins_staking;
1110
+ return sumBareStakings(data, NS_TYPE_FULL, 6, prices);
1111
+ }
1112
+ var BESPOKE_NORMALIZERS = {
1113
+ bluefin: normalizeBluefin,
1114
+ haedal: normalizeHaedal,
1115
+ kai: normalizeKai,
1116
+ suistake: normalizeSuistake,
1117
+ walrus: normalizeWalrus,
1118
+ "suins-staking": normalizeSuinsStaking
1119
+ };
1120
+ function normalizeProtocol(protocol, result, prices) {
1121
+ const bespoke = BESPOKE_NORMALIZERS[protocol];
1122
+ if (bespoke) return bespoke(result, prices);
1123
+ return walkProtocolResponse(result, prices);
1124
+ }
970
1125
  function clearPortfolioCache() {
971
1126
  portfolioCache.clear();
972
1127
  portfolioInflight.clear();