@talismn/balances 0.0.0-pr2131-20250807071252 → 0.0.0-pr2134-20250813092023

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.
Files changed (37) hide show
  1. package/dist/declarations/src/BalancesProvider.d.ts +1 -0
  2. package/dist/declarations/src/getMiniMetadatas/getMetadataRpc.d.ts +2 -2
  3. package/dist/declarations/src/getMiniMetadatas/getSpecVersion.d.ts +2 -2
  4. package/dist/declarations/src/getMiniMetadatas/index.d.ts +2 -2
  5. package/dist/declarations/src/modules/index.d.ts +23 -0
  6. package/dist/declarations/src/modules/shared/errors.d.ts +1 -1
  7. package/dist/declarations/src/modules/shared/fetchRuntimeCallResult.d.ts +2 -2
  8. package/dist/declarations/src/modules/shared/rpcQueryPack.d.ts +3 -3
  9. package/dist/declarations/src/modules/sol-native/config.d.ts +3 -0
  10. package/dist/declarations/src/modules/sol-native/fetchBalances.d.ts +3 -0
  11. package/dist/declarations/src/modules/sol-native/fetchTokens.d.ts +3 -0
  12. package/dist/declarations/src/modules/sol-native/getMiniMetadata.d.ts +3 -0
  13. package/dist/declarations/src/modules/sol-native/getTransferCallData.d.ts +3 -0
  14. package/dist/declarations/src/modules/sol-native/index.d.ts +2 -0
  15. package/dist/declarations/src/modules/sol-native/module.d.ts +3 -0
  16. package/dist/declarations/src/modules/sol-native/subscribeBalances.d.ts +3 -0
  17. package/dist/declarations/src/modules/sol-native/types.d.ts +13 -0
  18. package/dist/declarations/src/modules/sol-spl/config.d.ts +3 -0
  19. package/dist/declarations/src/modules/sol-spl/fetchBalances.d.ts +3 -0
  20. package/dist/declarations/src/modules/sol-spl/fetchTokens.d.ts +3 -0
  21. package/dist/declarations/src/modules/sol-spl/getMiniMetadata.d.ts +3 -0
  22. package/dist/declarations/src/modules/sol-spl/getTransferCallData.d.ts +3 -0
  23. package/dist/declarations/src/modules/sol-spl/index.d.ts +2 -0
  24. package/dist/declarations/src/modules/sol-spl/module.d.ts +3 -0
  25. package/dist/declarations/src/modules/sol-spl/subscribeBalances.d.ts +3 -0
  26. package/dist/declarations/src/modules/sol-spl/types.d.ts +14 -0
  27. package/dist/declarations/src/modules/substrate-native/bittensor/getSubtensorStakingBalances.d.ts +2 -2
  28. package/dist/declarations/src/modules/substrate-native/fetchTokens.d.ts +2 -2
  29. package/dist/declarations/src/modules/substrate-psp22/util.d.ts +2 -2
  30. package/dist/declarations/src/types/IBalanceModule.d.ts +26 -19
  31. package/dist/declarations/src/types/balances.d.ts +52 -4
  32. package/dist/declarations/src/types/balancetypes.d.ts +0 -4
  33. package/dist/declarations/src/types/chainConnectors.d.ts +4 -4
  34. package/dist/talismn-balances.cjs.dev.js +750 -245
  35. package/dist/talismn-balances.cjs.prod.js +750 -245
  36. package/dist/talismn-balances.esm.js +740 -239
  37. package/package.json +13 -8
@@ -1,13 +1,18 @@
1
- import { EvmErc20TokenSchema, parseTokenId, parseEvmErc20TokenId, evmErc20TokenId, isTokenOfType, TokenBaseSchema, EvmNativeTokenSchema, evmNativeTokenId, EvmUniswapV2TokenSchema, evmUniswapV2TokenId, SubAssetsTokenSchema, subAssetTokenId, MINIMETADATA_VERSION, SubForeignAssetsTokenSchema, subForeignAssetTokenId, SubHydrationTokenSchema, subHydrationTokenId, SubNativeTokenSchema, subNativeTokenId, SubPsp22TokenSchema, subPsp22TokenId, SubTokensTokenSchema, subTokensTokenId, isNetworkDot } from '@talismn/chaindata-provider';
1
+ import { EvmErc20TokenSchema, parseTokenId, parseEvmErc20TokenId, evmErc20TokenId, isTokenOfType, TokenBaseSchema, EvmNativeTokenSchema, evmNativeTokenId, EvmUniswapV2TokenSchema, evmUniswapV2TokenId, SolNativeTokenSchema, solNativeTokenId, SolSplTokenSchema, solSplTokenId, parseSolSplTokenId, SubAssetsTokenSchema, subAssetTokenId, MINIMETADATA_VERSION, SubForeignAssetsTokenSchema, subForeignAssetTokenId, SubHydrationTokenSchema, subHydrationTokenId, SubNativeTokenSchema, subNativeTokenId, SubPsp22TokenSchema, subPsp22TokenId, SubTokensTokenSchema, subTokensTokenId, isNetworkDot } from '@talismn/chaindata-provider';
2
2
  export { MINIMETADATA_VERSION } from '@talismn/chaindata-provider';
3
- import { isEthereumAddress, isNotNil, BigMath, isArrayOf, isBigInt, planckToTokens, isAbortError, getSharedObservable, keepAlive, isTruthy, normalizeAddress } from '@talismn/util';
3
+ import { isEthereumAddress, isSolanaAddress, normalizeAddress, getAccountPlatformFromAddress } from '@talismn/crypto';
4
4
  import { parseAbi, erc20Abi, getContract, ContractFunctionExecutionError, hexToString, erc20Abi_bytes32, encodeFunctionData, withRetry } from 'viem';
5
5
  import { assign, omit, isEqual, uniq, keyBy, toPairs, keys, fromPairs, values } from 'lodash-es';
6
6
  import z from 'zod/v4';
7
7
  import anylogger from 'anylogger';
8
8
  import { of, Observable, distinctUntilChanged, map, timer, switchMap, from, firstValueFrom, combineLatest, BehaviorSubject, shareReplay, startWith, filter, defer, catchError, EMPTY, tap } from 'rxjs';
9
9
  import BigNumber from 'bignumber.js';
10
+ import { PublicKey, SystemProgram } from '@solana/web3.js';
11
+ import { isNotNil, BigMath, isArrayOf, isBigInt, planckToTokens, isAbortError, getSharedObservable, keepAlive, isTruthy } from '@talismn/util';
10
12
  import { parseMetadataRpc, toHex, unifyMetadata, decAnyMetadata, getDynamicBuilder, getLookupFn, decodeScale, getStorageKeyPrefix, Twox128, compactMetadata, encodeMetadata, papiParse, papiStringify } from '@talismn/scale';
13
+ import { deserializeMetadata } from '@metaplex-foundation/mpl-token-metadata';
14
+ import { sol, publicKey } from '@metaplex-foundation/umi';
15
+ import { MintLayout, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, createTransferInstruction, TOKEN_PROGRAM_ID, getAccount } from '@solana/spl-token';
11
16
  import { newTokenRates } from '@talismn/token-rates';
12
17
  import { mergeUint8 } from '@polkadot-api/utils';
13
18
  import { Binary, Enum, AccountId } from 'polkadot-api';
@@ -19,8 +24,8 @@ import { u8aToHex, u8aConcatStrict, u8aToString, hexToNumber } from '@polkadot/u
19
24
  import PQueue from 'p-queue';
20
25
  import { fetchBestMetadata } from '@talismn/sapi';
21
26
 
22
- const MODULE_TYPE$8 = EvmErc20TokenSchema.shape.type.value;
23
- const PLATFORM$8 = EvmErc20TokenSchema.shape.platform.value;
27
+ const MODULE_TYPE$a = EvmErc20TokenSchema.shape.type.value;
28
+ const PLATFORM$a = EvmErc20TokenSchema.shape.platform.value;
24
29
 
25
30
  const abiMulticall = parseAbi(["struct Call { address target; bytes callData; }", "struct Call3 { address target; bool allowFailure; bytes callData; }", "struct Call3Value { address target; bool allowFailure; uint256 value; bytes callData; }", "struct Result { bool success; bytes returnData; }", "function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData)", "function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData)", "function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData)", "function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData)", "function getBasefee() view returns (uint256 basefee)", "function getBlockHash(uint256 blockNumber) view returns (bytes32 blockHash)", "function getBlockNumber() view returns (uint256 blockNumber)", "function getChainId() view returns (uint256 chainid)", "function getCurrentBlockCoinbase() view returns (address coinbase)", "function getCurrentBlockDifficulty() view returns (uint256 difficulty)", "function getCurrentBlockGasLimit() view returns (uint256 gaslimit)", "function getCurrentBlockTimestamp() view returns (uint256 timestamp)", "function getEthBalance(address addr) view returns (uint256 balance)", "function getLastBlockHash() view returns (bytes32 blockHash)", "function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData)", "function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData)"]);
26
31
 
@@ -616,7 +621,7 @@ const getBalanceDefs = addressesByToken => {
616
621
  // if there is at least one storage entry, the results will be an array with a single object
617
622
  // if the storage has no entries in it (ex: Assets on ewx or moonbeam), the response will be an empty array
618
623
 
619
- const fetchBalances$8 = async ({
624
+ const fetchBalances$a = async ({
620
625
  networkId,
621
626
  tokensWithAddresses,
622
627
  connector
@@ -628,7 +633,7 @@ const fetchBalances$8 = async ({
628
633
  const client = await connector.getPublicClientForEvmNetwork(networkId);
629
634
  if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
630
635
  for (const [token, addresses] of tokensWithAddresses) {
631
- if (token.type !== MODULE_TYPE$8 || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for EVM ERC20 balance module: ${token.type} on ${token.networkId}`);
636
+ if (token.type !== MODULE_TYPE$a || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for EVM ERC20 balance module: ${token.type} on ${token.networkId}`);
632
637
  for (const address of addresses) if (!isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
633
638
  }
634
639
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
@@ -658,7 +663,7 @@ const fetchWithoutAggregator = async (client, balanceDefs) => {
658
663
  address,
659
664
  tokenId: token.id,
660
665
  value: result.toString(),
661
- source: MODULE_TYPE$8,
666
+ source: MODULE_TYPE$a,
662
667
  networkId: parseEvmErc20TokenId(token.id).networkId,
663
668
  status: "live"
664
669
  };
@@ -701,7 +706,7 @@ const fetchWithAggregator = async (client, balanceDefs, erc20BalancesAggregatorA
701
706
  address: balanceDef.address,
702
707
  tokenId: balanceDef.token.id,
703
708
  value: erc20Balances[index].toString(),
704
- source: MODULE_TYPE$8,
709
+ source: MODULE_TYPE$a,
705
710
  networkId: parseTokenId(balanceDef.token.id).networkId,
706
711
  status: "live"
707
712
  }));
@@ -758,7 +763,7 @@ const getTypedContract$1 = (client, abi, contractAddress) => getContract({
758
763
  }
759
764
  });
760
765
 
761
- const TokenCacheSchema$1 = z.discriminatedUnion("isValid", [z.strictObject({
766
+ const TokenCacheSchema$2 = z.discriminatedUnion("isValid", [z.strictObject({
762
767
  id: EvmErc20TokenSchema.shape.id,
763
768
  isValid: z.literal(true),
764
769
  ...EvmErc20TokenSchema.pick({
@@ -770,7 +775,7 @@ const TokenCacheSchema$1 = z.discriminatedUnion("isValid", [z.strictObject({
770
775
  id: EvmErc20TokenSchema.shape.id,
771
776
  isValid: z.literal(false)
772
777
  })]);
773
- const fetchTokens$8 = async ({
778
+ const fetchTokens$a = async ({
774
779
  networkId,
775
780
  tokens,
776
781
  connector,
@@ -779,7 +784,7 @@ const fetchTokens$8 = async ({
779
784
  const result = [];
780
785
  for (const tokenConfig of tokens) {
781
786
  const tokenId = evmErc20TokenId(networkId, tokenConfig.contractAddress);
782
- const cached = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
787
+ const cached = cache[tokenId] && TokenCacheSchema$2.safeParse(cache[tokenId]).data;
783
788
  if (!cached) {
784
789
  const client = await connector.getPublicClientForEvmNetwork(networkId);
785
790
  if (!client) {
@@ -792,7 +797,7 @@ const fetchTokens$8 = async ({
792
797
  decimals,
793
798
  symbol
794
799
  } = await getErc20ContractData$1(client, tokenConfig.contractAddress);
795
- cache[tokenId] = TokenCacheSchema$1.parse({
800
+ cache[tokenId] = TokenCacheSchema$2.parse({
796
801
  id: tokenId,
797
802
  symbol,
798
803
  decimals,
@@ -810,11 +815,11 @@ const fetchTokens$8 = async ({
810
815
  }
811
816
  const base = {
812
817
  id: tokenId,
813
- type: MODULE_TYPE$8,
814
- platform: PLATFORM$8,
818
+ type: MODULE_TYPE$a,
819
+ platform: PLATFORM$a,
815
820
  networkId
816
821
  };
817
- const cached2 = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
822
+ const cached2 = cache[tokenId] && TokenCacheSchema$2.safeParse(cache[tokenId]).data;
818
823
  if (cached2?.isValid === false) continue;
819
824
  const token = assign(base, cached2?.isValid ? omit(cached2, ["isValid"]) : {}, tokenConfig);
820
825
  const parsed = EvmErc20TokenSchema.safeParse(token);
@@ -829,17 +834,17 @@ const fetchTokens$8 = async ({
829
834
  return result;
830
835
  };
831
836
 
832
- const getMiniMetadata$8 = () => {
837
+ const getMiniMetadata$a = () => {
833
838
  throw new Error("MiniMetadata is not supported for ethereum tokens");
834
839
  };
835
840
 
836
- const getTransferCallData$8 = ({
841
+ const getTransferCallData$a = ({
837
842
  from,
838
843
  to,
839
844
  value,
840
845
  token
841
846
  }) => {
842
- if (!isTokenOfType(token, MODULE_TYPE$8)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$8}.`);
847
+ if (!isTokenOfType(token, MODULE_TYPE$a)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$a}.`);
843
848
  if (!isEthereumAddress(from)) throw new Error("Invalid from address");
844
849
  if (!isEthereumAddress(to)) throw new Error("Invalid to address");
845
850
  const data = encodeFunctionData({
@@ -854,8 +859,8 @@ const getTransferCallData$8 = ({
854
859
  };
855
860
  };
856
861
 
857
- const SUBSCRIPTION_INTERVAL$4 = 6_000;
858
- const subscribeBalances$8 = ({
862
+ const SUBSCRIPTION_INTERVAL$6 = 6_000;
863
+ const subscribeBalances$a = ({
859
864
  networkId,
860
865
  tokensWithAddresses,
861
866
  connector
@@ -869,17 +874,17 @@ const subscribeBalances$8 = ({
869
874
  const poll = async () => {
870
875
  try {
871
876
  if (abortController.signal.aborted) return;
872
- const balances = await fetchBalances$8({
877
+ const balances = await fetchBalances$a({
873
878
  networkId,
874
879
  tokensWithAddresses: tokensWithAddresses,
875
880
  connector
876
881
  });
877
882
  if (abortController.signal.aborted) return;
878
883
  subscriber.next(balances);
879
- setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
884
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
880
885
  } catch (error) {
881
886
  log.error("Error", {
882
- module: MODULE_TYPE$8,
887
+ module: MODULE_TYPE$a,
883
888
  networkId,
884
889
  addressesByToken: tokensWithAddresses,
885
890
  error
@@ -895,13 +900,13 @@ const subscribeBalances$8 = ({
895
900
  };
896
901
 
897
902
  const EvmErc20BalanceModule = {
898
- type: MODULE_TYPE$8,
899
- platform: PLATFORM$8,
900
- getMiniMetadata: getMiniMetadata$8,
901
- fetchTokens: fetchTokens$8,
902
- fetchBalances: fetchBalances$8,
903
- subscribeBalances: subscribeBalances$8,
904
- getTransferCallData: getTransferCallData$8
903
+ type: MODULE_TYPE$a,
904
+ platform: PLATFORM$a,
905
+ getMiniMetadata: getMiniMetadata$a,
906
+ fetchTokens: fetchTokens$a,
907
+ fetchBalances: fetchBalances$a,
908
+ subscribeBalances: subscribeBalances$a,
909
+ getTransferCallData: getTransferCallData$a
905
910
  };
906
911
 
907
912
  const TokenConfigBaseSchema = TokenBaseSchema.partial().omit({
@@ -914,10 +919,10 @@ const EvmErc20TokenConfigSchema = z.strictObject({
914
919
  ...TokenConfigBaseSchema.shape
915
920
  });
916
921
 
917
- const MODULE_TYPE$7 = EvmNativeTokenSchema.shape.type.value;
918
- const PLATFORM$7 = EvmNativeTokenSchema.shape.platform.value;
922
+ const MODULE_TYPE$9 = EvmNativeTokenSchema.shape.type.value;
923
+ const PLATFORM$9 = EvmNativeTokenSchema.shape.platform.value;
919
924
 
920
- const fetchBalances$7 = async ({
925
+ const fetchBalances$9 = async ({
921
926
  networkId,
922
927
  tokensWithAddresses,
923
928
  connector
@@ -929,7 +934,7 @@ const fetchBalances$7 = async ({
929
934
  const client = await connector.getPublicClientForEvmNetwork(networkId);
930
935
  if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
931
936
  for (const [token, addresses] of tokensWithAddresses) {
932
- if (token.type !== MODULE_TYPE$7 || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for EVM ERC20 balance module: ${token.type} on ${token.networkId}`);
937
+ if (token.type !== MODULE_TYPE$9 || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for EVM ERC20 balance module: ${token.type} on ${token.networkId}`);
933
938
  for (const address of addresses) if (!isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
934
939
  }
935
940
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
@@ -956,7 +961,7 @@ const fetchWithoutMulticall = async (client, balanceDefs) => {
956
961
  address,
957
962
  tokenId: token.id,
958
963
  value: result.toString(),
959
- source: MODULE_TYPE$7,
964
+ source: MODULE_TYPE$9,
960
965
  networkId: parseTokenId(token.id).networkId,
961
966
  status: "live"
962
967
  };
@@ -1002,7 +1007,7 @@ const fetchWithMulticall = async (client, balanceDefs, multicall3Address) => {
1002
1007
  address: balanceDefs[index].address,
1003
1008
  tokenId: balanceDefs[index].token.id,
1004
1009
  value: result.result.toString(),
1005
- source: MODULE_TYPE$7,
1010
+ source: MODULE_TYPE$9,
1006
1011
  networkId: parseTokenId(balanceDefs[index].token.id).networkId,
1007
1012
  status: "live"
1008
1013
  });
@@ -1032,7 +1037,7 @@ const fetchWithMulticall = async (client, balanceDefs, multicall3Address) => {
1032
1037
  }
1033
1038
  };
1034
1039
 
1035
- const fetchTokens$7 = async ({
1040
+ const fetchTokens$9 = async ({
1036
1041
  networkId,
1037
1042
  tokens
1038
1043
  }) => {
@@ -1040,8 +1045,8 @@ const fetchTokens$7 = async ({
1040
1045
  if (tokens.length !== 1) throw new Error("EVM Native module expects the nativeCurrency to be passed as a single token in the array");
1041
1046
  const token = assign({
1042
1047
  id: evmNativeTokenId(networkId),
1043
- type: MODULE_TYPE$7,
1044
- platform: PLATFORM$7,
1048
+ type: MODULE_TYPE$9,
1049
+ platform: PLATFORM$9,
1045
1050
  networkId,
1046
1051
  isDefault: true
1047
1052
  }, tokens[0]);
@@ -1053,17 +1058,17 @@ const fetchTokens$7 = async ({
1053
1058
  return [parsed.data];
1054
1059
  };
1055
1060
 
1056
- const getMiniMetadata$7 = () => {
1061
+ const getMiniMetadata$9 = () => {
1057
1062
  throw new Error("MiniMetadata is not supported for ethereum tokens");
1058
1063
  };
1059
1064
 
1060
- const getTransferCallData$7 = ({
1065
+ const getTransferCallData$9 = ({
1061
1066
  from,
1062
1067
  to,
1063
1068
  value,
1064
1069
  token
1065
1070
  }) => {
1066
- if (!isTokenOfType(token, MODULE_TYPE$7)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$7}.`);
1071
+ if (!isTokenOfType(token, MODULE_TYPE$9)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$9}.`);
1067
1072
  if (!isEthereumAddress(from)) throw new Error("Invalid from address");
1068
1073
  if (!isEthereumAddress(to)) throw new Error("Invalid to address");
1069
1074
  return {
@@ -1074,8 +1079,8 @@ const getTransferCallData$7 = ({
1074
1079
  };
1075
1080
  };
1076
1081
 
1077
- const SUBSCRIPTION_INTERVAL$3 = 6_000;
1078
- const subscribeBalances$7 = ({
1082
+ const SUBSCRIPTION_INTERVAL$5 = 6_000;
1083
+ const subscribeBalances$9 = ({
1079
1084
  networkId,
1080
1085
  tokensWithAddresses,
1081
1086
  connector
@@ -1089,17 +1094,17 @@ const subscribeBalances$7 = ({
1089
1094
  const poll = async () => {
1090
1095
  try {
1091
1096
  if (abortController.signal.aborted) return;
1092
- const balances = await fetchBalances$7({
1097
+ const balances = await fetchBalances$9({
1093
1098
  networkId,
1094
1099
  tokensWithAddresses: tokensWithAddresses,
1095
1100
  connector
1096
1101
  });
1097
1102
  if (abortController.signal.aborted) return;
1098
1103
  subscriber.next(balances);
1099
- setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
1104
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
1100
1105
  } catch (error) {
1101
1106
  log.error("Error", {
1102
- module: MODULE_TYPE$7,
1107
+ module: MODULE_TYPE$9,
1103
1108
  networkId,
1104
1109
  addressesByToken: tokensWithAddresses,
1105
1110
  error
@@ -1115,13 +1120,13 @@ const subscribeBalances$7 = ({
1115
1120
  };
1116
1121
 
1117
1122
  const EvmNativeBalanceModule = {
1118
- type: MODULE_TYPE$7,
1119
- platform: PLATFORM$7,
1120
- getMiniMetadata: getMiniMetadata$7,
1121
- fetchTokens: fetchTokens$7,
1122
- fetchBalances: fetchBalances$7,
1123
- subscribeBalances: subscribeBalances$7,
1124
- getTransferCallData: getTransferCallData$7
1123
+ type: MODULE_TYPE$9,
1124
+ platform: PLATFORM$9,
1125
+ getMiniMetadata: getMiniMetadata$9,
1126
+ fetchTokens: fetchTokens$9,
1127
+ fetchBalances: fetchBalances$9,
1128
+ subscribeBalances: subscribeBalances$9,
1129
+ getTransferCallData: getTransferCallData$9
1125
1130
  };
1126
1131
 
1127
1132
  // to be used by chaindata too
@@ -1129,10 +1134,10 @@ const EvmNativeTokenConfigSchema = z.strictObject({
1129
1134
  ...TokenConfigBaseSchema.shape
1130
1135
  });
1131
1136
 
1132
- const MODULE_TYPE$6 = EvmUniswapV2TokenSchema.shape.type.value;
1133
- const PLATFORM$6 = EvmUniswapV2TokenSchema.shape.platform.value;
1137
+ const MODULE_TYPE$8 = EvmUniswapV2TokenSchema.shape.type.value;
1138
+ const PLATFORM$8 = EvmUniswapV2TokenSchema.shape.platform.value;
1134
1139
 
1135
- const fetchBalances$6 = async ({
1140
+ const fetchBalances$8 = async ({
1136
1141
  networkId,
1137
1142
  tokensWithAddresses,
1138
1143
  connector
@@ -1144,7 +1149,7 @@ const fetchBalances$6 = async ({
1144
1149
  const client = await connector.getPublicClientForEvmNetwork(networkId);
1145
1150
  if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
1146
1151
  for (const [token, addresses] of tokensWithAddresses) {
1147
- if (token.type !== MODULE_TYPE$6 || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for EVM ERC20 balance module: ${token.type} on ${token.networkId}`);
1152
+ if (token.type !== MODULE_TYPE$8 || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for EVM ERC20 balance module: ${token.type} on ${token.networkId}`);
1148
1153
  for (const address of addresses) if (!isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
1149
1154
  }
1150
1155
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
@@ -1231,7 +1236,7 @@ const fetchPoolBalances = async (client, balanceDefs) => {
1231
1236
  acc.success.push({
1232
1237
  address,
1233
1238
  tokenId: token.id,
1234
- source: MODULE_TYPE$6,
1239
+ source: MODULE_TYPE$8,
1235
1240
  networkId: parseTokenId(token.id).networkId,
1236
1241
  status: "live",
1237
1242
  values: [{
@@ -1291,7 +1296,7 @@ const getUniswapV2PairContractData = async (client, contractAddress) => {
1291
1296
  };
1292
1297
  };
1293
1298
 
1294
- const TokenCacheSchema = z.discriminatedUnion("isValid", [z.strictObject({
1299
+ const TokenCacheSchema$1 = z.discriminatedUnion("isValid", [z.strictObject({
1295
1300
  id: EvmUniswapV2TokenSchema.shape.id,
1296
1301
  isValid: z.literal(true),
1297
1302
  ...EvmUniswapV2TokenSchema.pick({
@@ -1309,7 +1314,7 @@ const TokenCacheSchema = z.discriminatedUnion("isValid", [z.strictObject({
1309
1314
  id: EvmUniswapV2TokenSchema.shape.id,
1310
1315
  isValid: z.literal(false)
1311
1316
  })]);
1312
- const fetchTokens$6 = async ({
1317
+ const fetchTokens$8 = async ({
1313
1318
  networkId,
1314
1319
  tokens,
1315
1320
  connector,
@@ -1318,7 +1323,7 @@ const fetchTokens$6 = async ({
1318
1323
  const result = [];
1319
1324
  for (const tokenConfig of tokens) {
1320
1325
  const tokenId = evmUniswapV2TokenId(networkId, tokenConfig.contractAddress);
1321
- const cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1326
+ const cached = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
1322
1327
  if (!cached) {
1323
1328
  const client = await connector.getPublicClientForEvmNetwork(networkId);
1324
1329
  if (!client) {
@@ -1340,7 +1345,7 @@ const fetchTokens$6 = async ({
1340
1345
  symbol: symbol1,
1341
1346
  decimals: decimals1
1342
1347
  } = await getErc20ContractData(client, token1);
1343
- cache[tokenId] = TokenCacheSchema.parse({
1348
+ cache[tokenId] = TokenCacheSchema$1.parse({
1344
1349
  id: tokenId,
1345
1350
  symbol: `${symbol0}/${symbol1}`,
1346
1351
  decimals,
@@ -1366,48 +1371,601 @@ const fetchTokens$6 = async ({
1366
1371
  continue;
1367
1372
  }
1368
1373
  }
1374
+ const base = {
1375
+ id: tokenId,
1376
+ type: MODULE_TYPE$8,
1377
+ platform: PLATFORM$8,
1378
+ networkId
1379
+ };
1380
+ const cached2 = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
1381
+ if (cached2?.isValid === false) continue;
1382
+ const token = assign(base, cached2?.isValid ? omit(cached2, ["isValid"]) : {}, tokenConfig);
1383
+ const parsed = EvmUniswapV2TokenSchema.safeParse(token);
1384
+ if (!parsed.success) {
1385
+ log.warn("Ignoring token with invalid schema", token);
1386
+ continue;
1387
+ }
1388
+ result.push(parsed.data);
1389
+ }
1390
+ return result;
1391
+ };
1392
+
1393
+ const getMiniMetadata$8 = () => {
1394
+ throw new Error("MiniMetadata is not supported for ethereum tokens");
1395
+ };
1396
+
1397
+ const getTransferCallData$8 = ({
1398
+ from,
1399
+ to,
1400
+ value,
1401
+ token
1402
+ }) => {
1403
+ if (!isTokenOfType(token, MODULE_TYPE$8)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$8}.`);
1404
+ if (!isEthereumAddress(from)) throw new Error("Invalid from address");
1405
+ if (!isEthereumAddress(to)) throw new Error("Invalid to address");
1406
+ const data = encodeFunctionData({
1407
+ abi: erc20Abi,
1408
+ functionName: "transfer",
1409
+ args: [to, BigInt(value)]
1410
+ });
1411
+ return {
1412
+ from,
1413
+ to: token.contractAddress,
1414
+ data
1415
+ };
1416
+ };
1417
+
1418
+ const SUBSCRIPTION_INTERVAL$4 = 6_000;
1419
+ const subscribeBalances$8 = ({
1420
+ networkId,
1421
+ tokensWithAddresses,
1422
+ connector
1423
+ }) => {
1424
+ if (!tokensWithAddresses.length) return of({
1425
+ success: [],
1426
+ errors: []
1427
+ });
1428
+ return new Observable(subscriber => {
1429
+ const abortController = new AbortController();
1430
+ const poll = async () => {
1431
+ try {
1432
+ if (abortController.signal.aborted) return;
1433
+ const balances = await fetchBalances$8({
1434
+ networkId,
1435
+ tokensWithAddresses: tokensWithAddresses,
1436
+ connector
1437
+ });
1438
+ if (abortController.signal.aborted) return;
1439
+ subscriber.next(balances);
1440
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
1441
+ } catch (error) {
1442
+ log.error("Error", {
1443
+ module: MODULE_TYPE$8,
1444
+ networkId,
1445
+ addressesByToken: tokensWithAddresses,
1446
+ error
1447
+ });
1448
+ subscriber.error(error);
1449
+ }
1450
+ };
1451
+ poll();
1452
+ return () => {
1453
+ abortController.abort();
1454
+ };
1455
+ }).pipe(distinctUntilChanged(isEqual));
1456
+ };
1457
+
1458
+ const EvmUniswapV2BalanceModule = {
1459
+ type: MODULE_TYPE$8,
1460
+ platform: PLATFORM$8,
1461
+ getMiniMetadata: getMiniMetadata$8,
1462
+ fetchTokens: fetchTokens$8,
1463
+ fetchBalances: fetchBalances$8,
1464
+ subscribeBalances: subscribeBalances$8,
1465
+ getTransferCallData: getTransferCallData$8
1466
+ };
1467
+
1468
+ // to be used by chaindata too
1469
+ const EvmUniswapV2TokenConfigSchema = z.strictObject({
1470
+ contractAddress: EvmUniswapV2TokenSchema.shape.contractAddress,
1471
+ ...TokenConfigBaseSchema.shape
1472
+ });
1473
+
1474
+ const MODULE_TYPE$7 = SolNativeTokenSchema.shape.type.value;
1475
+ const PLATFORM$7 = SolNativeTokenSchema.shape.platform.value;
1476
+
1477
+ const fetchBalances$7 = async ({
1478
+ networkId,
1479
+ tokensWithAddresses,
1480
+ connector
1481
+ }) => {
1482
+ if (!tokensWithAddresses.length) return {
1483
+ success: [],
1484
+ errors: []
1485
+ };
1486
+ const connection = await connector.getConnection(networkId);
1487
+ if (!connection) throw new Error(`Could not get rpc provider for sol network ${networkId}`);
1488
+ for (const [token, addresses] of tokensWithAddresses) {
1489
+ if (token.type !== MODULE_TYPE$7 || token.networkId !== networkId) throw new Error(`Invalid token type or networkId for balance module: ${token.type} on ${token.networkId}`);
1490
+ for (const address of addresses) if (!isSolanaAddress(address)) throw new Error(`Invalid solana address for balance module: ${address} for token ${token.id}`);
1491
+ }
1492
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
1493
+ const results = await Promise.allSettled(balanceDefs.map(async ({
1494
+ token,
1495
+ address
1496
+ }) => {
1497
+ try {
1498
+ const publicKey = new PublicKey(address);
1499
+ const lamports = await connection.getBalance(publicKey);
1500
+ return {
1501
+ address: address,
1502
+ tokenId: token.id,
1503
+ value: lamports.toString(),
1504
+ source: MODULE_TYPE$7,
1505
+ networkId: token.networkId,
1506
+ status: "live"
1507
+ };
1508
+ } catch (err) {
1509
+ throw new BalanceFetchError(`Failed to get balance for token ${token.id} and address ${address} on chain ${networkId}`, token.id, address, err);
1510
+ }
1511
+ }));
1512
+ return results.reduce((acc, result) => {
1513
+ if (result.status === "fulfilled") acc.success.push(result.value);else {
1514
+ const error = result.reason;
1515
+ acc.errors.push({
1516
+ tokenId: error.tokenId,
1517
+ address: error.address,
1518
+ error
1519
+ });
1520
+ }
1521
+ return acc;
1522
+ }, {
1523
+ success: [],
1524
+ errors: []
1525
+ });
1526
+ };
1527
+
1528
+ const fetchTokens$7 = async ({
1529
+ networkId,
1530
+ tokens
1531
+ }) => {
1532
+ // assume there is one and only one token in the array
1533
+ if (tokens.length !== 1) throw new Error("EVM Native module expects the nativeCurrency to be passed as a single token in the array");
1534
+ const token = assign({
1535
+ id: solNativeTokenId(networkId),
1536
+ type: MODULE_TYPE$7,
1537
+ platform: PLATFORM$7,
1538
+ networkId,
1539
+ isDefault: true
1540
+ }, tokens[0]);
1541
+ const parsed = SolNativeTokenSchema.safeParse(token);
1542
+ if (!parsed.success) {
1543
+ log.warn("Ignoring token with invalid schema", token);
1544
+ return [];
1545
+ }
1546
+ return [parsed.data];
1547
+ };
1548
+
1549
+ const getMiniMetadata$7 = () => {
1550
+ throw new Error("MiniMetadata is not supported for sol-native tokens");
1551
+ };
1552
+
1553
+ const getTransferCallData$7 = ({
1554
+ from,
1555
+ to,
1556
+ value,
1557
+ token
1558
+ }) => {
1559
+ if (!isTokenOfType(token, MODULE_TYPE$7)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$7}.`);
1560
+ const fromPubkey = new PublicKey(from);
1561
+ const transferIx = SystemProgram.transfer({
1562
+ fromPubkey,
1563
+ toPubkey: new PublicKey(to),
1564
+ lamports: Number(value)
1565
+ });
1566
+ return [transferIx];
1567
+ };
1568
+
1569
+ const SUBSCRIPTION_INTERVAL$3 = 6_000;
1570
+ const subscribeBalances$7 = ({
1571
+ networkId,
1572
+ tokensWithAddresses,
1573
+ connector
1574
+ }) => {
1575
+ if (!tokensWithAddresses.length) return of({
1576
+ success: [],
1577
+ errors: []
1578
+ });
1579
+ return new Observable(subscriber => {
1580
+ const abortController = new AbortController();
1581
+ const poll = async () => {
1582
+ try {
1583
+ if (abortController.signal.aborted) return;
1584
+ const balances = await fetchBalances$7({
1585
+ networkId,
1586
+ tokensWithAddresses,
1587
+ connector
1588
+ });
1589
+ if (abortController.signal.aborted) return;
1590
+ subscriber.next(balances);
1591
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
1592
+ } catch (error) {
1593
+ log.error("Error", {
1594
+ module: MODULE_TYPE$7,
1595
+ networkId,
1596
+ tokensWithAddresses,
1597
+ error
1598
+ });
1599
+ subscriber.error(error);
1600
+ }
1601
+ };
1602
+ poll();
1603
+ return () => {
1604
+ abortController.abort();
1605
+ };
1606
+ }).pipe(distinctUntilChanged(isEqual));
1607
+ };
1608
+
1609
+ const SolNativeBalanceModule = {
1610
+ type: MODULE_TYPE$7,
1611
+ platform: PLATFORM$7,
1612
+ getMiniMetadata: getMiniMetadata$7,
1613
+ fetchTokens: fetchTokens$7,
1614
+ fetchBalances: fetchBalances$7,
1615
+ subscribeBalances: subscribeBalances$7,
1616
+ getTransferCallData: getTransferCallData$7
1617
+ };
1618
+
1619
+ // to be used by chaindata too
1620
+ const SolNativeTokenConfigSchema = z.strictObject({
1621
+ ...TokenConfigBaseSchema.shape
1622
+ });
1623
+
1624
+ const MODULE_TYPE$6 = SolSplTokenSchema.shape.type.value;
1625
+ const PLATFORM$6 = SolSplTokenSchema.shape.platform.value;
1626
+
1627
+ const fetchRuntimeCallResult = async (connector, networkId, metadataRpc, apiName, method, args) => {
1628
+ const {
1629
+ builder
1630
+ } = parseMetadataRpc(metadataRpc);
1631
+ const call = builder.buildRuntimeCall(apiName, method);
1632
+ const hex = await connector.send(networkId, "state_call", [`${apiName}_${method}`, toHex(call.args.enc(args))]);
1633
+ return call.value.dec(hex);
1634
+ };
1635
+
1636
+ const hasStorageItem = (metadata, palletName, itemName) => {
1637
+ const pallet = metadata.pallets.find(p => p.name === palletName);
1638
+ if (!pallet || !pallet.storage) return false;
1639
+ return pallet.storage.items.some(item => item.name === itemName);
1640
+ };
1641
+ const hasStorageItems = (metadata, palletName, itemNames) => {
1642
+ const pallet = metadata.pallets.find(p => p.name === palletName);
1643
+ if (!pallet || !pallet.storage) return false;
1644
+ return itemNames.every(itemName => pallet.storage?.items.some(item => item.name === itemName));
1645
+ };
1646
+ const hasRuntimeApi = (metadata, apiName, method) => {
1647
+ const api = metadata.apis.find(api => api.name === apiName);
1648
+ if (!api || !api.methods) return false;
1649
+ return api.methods.some(m => m.name === method);
1650
+ };
1651
+ const getConstantValue = (metadataRpc, pallet, constant) => {
1652
+ const {
1653
+ unifiedMetadata,
1654
+ builder
1655
+ } = parseMetadataRpc(metadataRpc);
1656
+ const codec = builder.buildConstant(pallet, constant);
1657
+ const encodedValue = unifiedMetadata.pallets.find(({
1658
+ name
1659
+ }) => name === pallet)?.constants.find(({
1660
+ name
1661
+ }) => name === constant)?.value;
1662
+ if (!encodedValue) throw new Error(`Constant ${pallet}.${constant} not found`);
1663
+ return codec.dec(encodedValue);
1664
+ };
1665
+ const tryGetConstantValue = (metadataRpc, pallet, constant) => {
1666
+ const {
1667
+ unifiedMetadata,
1668
+ builder
1669
+ } = parseMetadataRpc(metadataRpc);
1670
+ const encodedValue = unifiedMetadata.pallets.find(({
1671
+ name
1672
+ }) => name === pallet)?.constants.find(({
1673
+ name
1674
+ }) => name === constant)?.value;
1675
+ if (!encodedValue) return null;
1676
+ const codec = builder.buildConstant(pallet, constant);
1677
+ return codec.dec(encodedValue);
1678
+ };
1679
+
1680
+ const fetchRpcQueryPack = async (connector, networkId, queries) => {
1681
+ const allStateKeys = queries.flatMap(({
1682
+ stateKeys
1683
+ }) => stateKeys).filter(isNotNil);
1684
+
1685
+ // doing a query without keys would throw an error => return early
1686
+ if (!allStateKeys.length) return queries.map(({
1687
+ stateKeys,
1688
+ decodeResult
1689
+ }) => decodeResult(stateKeys.map(() => null)));
1690
+ const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
1691
+ return decodeRpcQueryPack(queries, result);
1692
+ };
1693
+ const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
1694
+ const allStateKeys = queries.flatMap(({
1695
+ stateKeys
1696
+ }) => stateKeys).filter(isNotNil);
1697
+
1698
+ // doing a query without keys would throw an error => return early
1699
+ if (!allStateKeys.length) return of(queries.map(({
1700
+ stateKeys,
1701
+ decodeResult
1702
+ }) => decodeResult(stateKeys.map(() => null))));
1703
+ return new Observable(subscriber => {
1704
+ // first subscription callback includes results for all state keys, but further callbacks will only include the ones that changed
1705
+ // => we need to keep all results in memory and update them after each callback, so we can emit the full result set each time
1706
+ const changesCache = {};
1707
+ const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
1708
+ if (error) subscriber.error(error);else if (result) {
1709
+ // update the cache
1710
+ for (const [stateKey, encodedResult] of result.changes) changesCache[stateKey] = encodedResult;
1711
+
1712
+ // regenerate the full changes array
1713
+ const changes = toPairs(changesCache);
1714
+
1715
+ // decode and emit results for all queries
1716
+ subscriber.next(decodeRpcQueryPack(queries, {
1717
+ block: result.block,
1718
+ changes
1719
+ }));
1720
+ }
1721
+ }, timeout);
1722
+ return () => {
1723
+ promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
1724
+ };
1725
+ });
1726
+ };
1727
+ const decodeRpcQueryPack = (queries, result) => {
1728
+ return queries.reduce((acc, {
1729
+ stateKeys,
1730
+ decodeResult
1731
+ }) => {
1732
+ const changes = stateKeys.map(stateKey => {
1733
+ if (!stateKey || !result) return null;
1734
+ const change = result.changes.find(([key]) => key === stateKey);
1735
+ if (!change) return null;
1736
+ return change[1];
1737
+ });
1738
+ acc.push(decodeResult(changes));
1739
+ return acc;
1740
+ }, []);
1741
+ };
1742
+
1743
+ const buildNetworkStorageCoders = (chainId, miniMetadata, coders) => {
1744
+ if (!miniMetadata.data) return null;
1745
+ const metadata = unifyMetadata(decAnyMetadata(miniMetadata.data));
1746
+ try {
1747
+ const scaleBuilder = getDynamicBuilder(getLookupFn(metadata));
1748
+ const builtCoders = Object.fromEntries(Object.entries(coders).flatMap(([key, moduleMethodOrFn]) => {
1749
+ const [module, method] = typeof moduleMethodOrFn === "function" ? moduleMethodOrFn({
1750
+ chainId
1751
+ }) : moduleMethodOrFn;
1752
+ try {
1753
+ return [[key, scaleBuilder.buildStorage(module, method)]];
1754
+ } catch (cause) {
1755
+ log.trace(`Failed to build SCALE coder for chain ${chainId} (${module}::${method})`, cause);
1756
+ return [];
1757
+ }
1758
+ }));
1759
+ return builtCoders;
1760
+ } catch (cause) {
1761
+ log.error(`Failed to build SCALE coders for chain ${chainId} (${JSON.stringify(coders)})`, cause);
1762
+ }
1763
+ return null;
1764
+ };
1765
+
1766
+ const SPL_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
1767
+ const fetchBalances$6 = async ({
1768
+ networkId,
1769
+ tokensWithAddresses,
1770
+ connector
1771
+ }) => {
1772
+ if (!tokensWithAddresses.length) return {
1773
+ success: [],
1774
+ errors: []
1775
+ };
1776
+ const connection = await connector.getConnection(networkId);
1777
+ if (!connection) throw new Error(`Could not get connection for Solana network ${networkId}`);
1778
+ const accountAddresses = uniq(tokensWithAddresses.flatMap(([, addresses]) => addresses));
1779
+ const balancesPerAddress = await Promise.all(accountAddresses.map(async address => {
1780
+ const tokenAccounts = await connection.getParsedTokenAccountsByOwner(new PublicKey(address), {
1781
+ programId: new PublicKey(SPL_PROGRAM_ID) // SPL Token Program ID
1782
+ });
1783
+ const balances = tokenAccounts.value.map(d => {
1784
+ try {
1785
+ const mintAddress = d.account.data.parsed.info.mint;
1786
+ const value = d.account.data.parsed.info.tokenAmount.amount ?? "0";
1787
+ return {
1788
+ tokenId: solSplTokenId(networkId, mintAddress),
1789
+ networkId,
1790
+ address,
1791
+ source: MODULE_TYPE$6,
1792
+ status: "live",
1793
+ value
1794
+ };
1795
+ } catch (err) {
1796
+ log.warn("Failed to parse token amount", {
1797
+ address,
1798
+ d
1799
+ });
1800
+ return null;
1801
+ }
1802
+ }).filter(isNotNil);
1803
+ return [address, balances];
1804
+ }));
1805
+ const allBalancesByKey = keyBy(balancesPerAddress.flatMap(([, addressBalances]) => addressBalances), b => getBalanceKey(b.tokenId, b.address));
1806
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
1807
+
1808
+ // return a balance entry for all token/address pairs that were requested
1809
+ const success = balanceDefs.map(bd => {
1810
+ const found = allBalancesByKey[getBalanceKey(bd.token.id, bd.address)];
1811
+ return found ?? {
1812
+ tokenId: bd.token.id,
1813
+ networkId: bd.token.networkId,
1814
+ address: bd.address,
1815
+ source: MODULE_TYPE$6,
1816
+ status: "live",
1817
+ value: "0"
1818
+ };
1819
+ });
1820
+
1821
+ // return only the balances that match the tokens we are interested in
1822
+ return {
1823
+ success,
1824
+ errors: []
1825
+ }; // TODO output errors if any
1826
+ };
1827
+ const getBalanceKey = (tokenId, address) => `${tokenId}:${address}`;
1828
+
1829
+ const TokenCacheSchema = z.discriminatedUnion("isValid", [z.strictObject({
1830
+ id: SolSplTokenSchema.shape.id,
1831
+ isValid: z.literal(true),
1832
+ ...SolSplTokenSchema.pick({
1833
+ symbol: true,
1834
+ decimals: true,
1835
+ name: true,
1836
+ logo: true
1837
+ }).shape
1838
+ }), z.strictObject({
1839
+ id: SolSplTokenSchema.shape.id,
1840
+ isValid: z.literal(false)
1841
+ })]);
1842
+ const METAPLEX_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
1843
+ const fetchTokens$6 = async ({
1844
+ networkId,
1845
+ tokens,
1846
+ connector,
1847
+ cache
1848
+ }) => {
1849
+ const result = [];
1850
+ for (const tokenConfig of tokens) {
1851
+ const tokenId = solSplTokenId(networkId, tokenConfig.mintAddress);
1852
+ let cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1853
+ if (!cached) {
1854
+ const tokenInfo = await fetchOnChainTokenData(connector, tokenId);
1855
+ if (tokenInfo) cache[tokenId] = tokenInfo;
1856
+ }
1857
+ cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1858
+ if (cached?.isValid === false) continue;
1369
1859
  const base = {
1370
1860
  id: tokenId,
1371
1861
  type: MODULE_TYPE$6,
1372
1862
  platform: PLATFORM$6,
1373
1863
  networkId
1374
1864
  };
1375
- const cached2 = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1376
- if (cached2?.isValid === false) continue;
1377
- const token = assign(base, cached2?.isValid ? omit(cached2, ["isValid"]) : {}, tokenConfig);
1378
- const parsed = EvmUniswapV2TokenSchema.safeParse(token);
1865
+ const token = assign(base, cached?.isValid ? omit(cached, ["isValid"]) : {}, tokenConfig);
1866
+ const parsed = SolSplTokenSchema.safeParse(token);
1379
1867
  if (!parsed.success) {
1380
- log.warn("Ignoring token with invalid schema", token);
1868
+ log.warn("Ignoring token with invalid SolSplTokenSchema", {
1869
+ token
1870
+ });
1381
1871
  continue;
1382
1872
  }
1383
1873
  result.push(parsed.data);
1384
1874
  }
1385
1875
  return result;
1386
1876
  };
1877
+ const ERROR_NO_MINT = "No mint info available";
1878
+ const ERROR_NO_METADATA = "No metadata account found";
1879
+ const ERROR_INVALID_DATA = "Invalid on-chain data";
1880
+ const fetchOnChainTokenData = async (connector, tokenId) => {
1881
+ try {
1882
+ const {
1883
+ networkId,
1884
+ mintAddress
1885
+ } = parseSolSplTokenId(tokenId);
1886
+ const connection = await connector.getConnection(networkId);
1887
+ if (!connection) {
1888
+ log.warn(`No connection found for network ${networkId}`);
1889
+ return null;
1890
+ }
1891
+ const mintPubKey = new PublicKey(mintAddress);
1892
+ const mintInfo = await connection.getAccountInfo(mintPubKey);
1893
+ if (!mintInfo?.data) throw new Error(ERROR_NO_MINT);
1894
+ const mint = MintLayout.decode(mintInfo.data);
1895
+ const [metadataPDA] = PublicKey.findProgramAddressSync([Buffer.from("metadata"), METAPLEX_PROGRAM_ID.toBuffer(), mintPubKey.toBuffer()], METAPLEX_PROGRAM_ID);
1896
+
1897
+ // 3. Fetch metadata account directly (traditional way)
1898
+ const metadataAccount = await connection.getAccountInfo(new PublicKey(metadataPDA));
1899
+ if (!metadataAccount) throw new Error(ERROR_NO_METADATA);
1900
+ const metadata = deserializeMetadata({
1901
+ publicKey: publicKey(metadataPDA),
1902
+ executable: metadataAccount.executable,
1903
+ owner: publicKey(metadataAccount.owner),
1904
+ lamports: sol(metadataAccount.lamports),
1905
+ data: metadataAccount.data
1906
+ });
1907
+ const parsed = TokenCacheSchema.safeParse({
1908
+ id: tokenId,
1909
+ symbol: metadata.symbol.trim(),
1910
+ name: metadata.name.trim(),
1911
+ decimals: mint.decimals,
1912
+ isValid: true
1913
+ });
1914
+ if (!parsed.success) throw new Error(ERROR_INVALID_DATA);
1915
+ return parsed.data;
1916
+ } catch (err) {
1917
+ const msg = err.message;
1918
+ if ([ERROR_NO_MINT, ERROR_NO_METADATA, ERROR_INVALID_DATA].includes(msg)) return TokenCacheSchema.parse({
1919
+ id: tokenId,
1920
+ isValid: false
1921
+ });
1922
+ log.warn("Failed to fetch sol-spl token data for %s", tokenId, {
1923
+ err
1924
+ });
1925
+ }
1926
+ return null;
1927
+ };
1387
1928
 
1388
1929
  const getMiniMetadata$6 = () => {
1389
- throw new Error("MiniMetadata is not supported for ethereum tokens");
1930
+ throw new Error("MiniMetadata is not supported for solana tokens");
1390
1931
  };
1391
1932
 
1392
- const getTransferCallData$6 = ({
1933
+ const getTransferCallData$6 = async ({
1393
1934
  from,
1394
1935
  to,
1395
1936
  value,
1396
- token
1937
+ token,
1938
+ connector
1397
1939
  }) => {
1398
1940
  if (!isTokenOfType(token, MODULE_TYPE$6)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$6}.`);
1399
- if (!isEthereumAddress(from)) throw new Error("Invalid from address");
1400
- if (!isEthereumAddress(to)) throw new Error("Invalid to address");
1401
- const data = encodeFunctionData({
1402
- abi: erc20Abi,
1403
- functionName: "transfer",
1404
- args: [to, BigInt(value)]
1405
- });
1406
- return {
1407
- from,
1408
- to: token.contractAddress,
1409
- data
1410
- };
1941
+ const connection = await connector.getConnection(token.networkId);
1942
+ const instructions = [];
1943
+ const mint = new PublicKey(token.mintAddress);
1944
+ const fromWallet = new PublicKey(from);
1945
+ const toWallet = new PublicKey(to);
1946
+
1947
+ // Get associated token accounts
1948
+ const fromTokenAccount = await getAssociatedTokenAddress(mint, fromWallet);
1949
+ const toTokenAccount = await getAssociatedTokenAddress(mint, toWallet);
1950
+
1951
+ // Create the target token account if it doesn't exist
1952
+ if (!(await tokenAccountExists(connection, toTokenAccount))) {
1953
+ instructions.push(createAssociatedTokenAccountInstruction(fromWallet,
1954
+ // funder
1955
+ toTokenAccount, toWallet, mint));
1956
+ }
1957
+
1958
+ // Transfer the tokens
1959
+ instructions.push(createTransferInstruction(fromTokenAccount, toTokenAccount, fromWallet, BigInt(value), [], TOKEN_PROGRAM_ID));
1960
+ return instructions;
1961
+ };
1962
+ const tokenAccountExists = async (connection, address) => {
1963
+ try {
1964
+ await getAccount(connection, address);
1965
+ return true;
1966
+ } catch {
1967
+ return false;
1968
+ }
1411
1969
  };
1412
1970
 
1413
1971
  const SUBSCRIPTION_INTERVAL$2 = 6_000;
@@ -1450,7 +2008,7 @@ const subscribeBalances$6 = ({
1450
2008
  }).pipe(distinctUntilChanged(isEqual));
1451
2009
  };
1452
2010
 
1453
- const EvmUniswapV2BalanceModule = {
2011
+ const SolSplBalanceModule = {
1454
2012
  type: MODULE_TYPE$6,
1455
2013
  platform: PLATFORM$6,
1456
2014
  getMiniMetadata: getMiniMetadata$6,
@@ -1461,153 +2019,14 @@ const EvmUniswapV2BalanceModule = {
1461
2019
  };
1462
2020
 
1463
2021
  // to be used by chaindata too
1464
- const EvmUniswapV2TokenConfigSchema = z.strictObject({
1465
- contractAddress: EvmUniswapV2TokenSchema.shape.contractAddress,
2022
+ const SolSplTokenConfigSchema = z.strictObject({
2023
+ mintAddress: SolSplTokenSchema.shape.mintAddress,
1466
2024
  ...TokenConfigBaseSchema.shape
1467
2025
  });
1468
2026
 
1469
2027
  const MODULE_TYPE$5 = SubAssetsTokenSchema.shape.type.value;
1470
2028
  const PLATFORM$5 = SubAssetsTokenSchema.shape.platform.value;
1471
2029
 
1472
- const fetchRpcQueryPack = async (connector, networkId, queries) => {
1473
- const allStateKeys = queries.flatMap(({
1474
- stateKeys
1475
- }) => stateKeys).filter(isNotNil);
1476
-
1477
- // doing a query without keys would throw an error => return early
1478
- if (!allStateKeys.length) return queries.map(({
1479
- stateKeys,
1480
- decodeResult
1481
- }) => decodeResult(stateKeys.map(() => null)));
1482
- const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
1483
- return decodeRpcQueryPack(queries, result);
1484
- };
1485
- const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
1486
- const allStateKeys = queries.flatMap(({
1487
- stateKeys
1488
- }) => stateKeys).filter(isNotNil);
1489
-
1490
- // doing a query without keys would throw an error => return early
1491
- if (!allStateKeys.length) return of(queries.map(({
1492
- stateKeys,
1493
- decodeResult
1494
- }) => decodeResult(stateKeys.map(() => null))));
1495
- return new Observable(subscriber => {
1496
- // first subscription callback includes results for all state keys, but further callbacks will only include the ones that changed
1497
- // => we need to keep all results in memory and update them after each callback, so we can emit the full result set each time
1498
- const changesCache = {};
1499
- const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
1500
- if (error) subscriber.error(error);else if (result) {
1501
- // update the cache
1502
- for (const [stateKey, encodedResult] of result.changes) changesCache[stateKey] = encodedResult;
1503
-
1504
- // regenerate the full changes array
1505
- const changes = toPairs(changesCache);
1506
-
1507
- // decode and emit results for all queries
1508
- subscriber.next(decodeRpcQueryPack(queries, {
1509
- block: result.block,
1510
- changes
1511
- }));
1512
- }
1513
- }, timeout);
1514
- return () => {
1515
- promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
1516
- };
1517
- });
1518
- };
1519
- const decodeRpcQueryPack = (queries, result) => {
1520
- return queries.reduce((acc, {
1521
- stateKeys,
1522
- decodeResult
1523
- }) => {
1524
- const changes = stateKeys.map(stateKey => {
1525
- if (!stateKey || !result) return null;
1526
- const change = result.changes.find(([key]) => key === stateKey);
1527
- if (!change) return null;
1528
- return change[1];
1529
- });
1530
- acc.push(decodeResult(changes));
1531
- return acc;
1532
- }, []);
1533
- };
1534
-
1535
- const fetchRuntimeCallResult = async (connector, networkId, metadataRpc, apiName, method, args) => {
1536
- const {
1537
- builder
1538
- } = parseMetadataRpc(metadataRpc);
1539
- const call = builder.buildRuntimeCall(apiName, method);
1540
- const hex = await connector.send(networkId, "state_call", [`${apiName}_${method}`, toHex(call.args.enc(args))]);
1541
- return call.value.dec(hex);
1542
- };
1543
-
1544
- const hasStorageItem = (metadata, palletName, itemName) => {
1545
- const pallet = metadata.pallets.find(p => p.name === palletName);
1546
- if (!pallet || !pallet.storage) return false;
1547
- return pallet.storage.items.some(item => item.name === itemName);
1548
- };
1549
- const hasStorageItems = (metadata, palletName, itemNames) => {
1550
- const pallet = metadata.pallets.find(p => p.name === palletName);
1551
- if (!pallet || !pallet.storage) return false;
1552
- return itemNames.every(itemName => pallet.storage?.items.some(item => item.name === itemName));
1553
- };
1554
- const hasRuntimeApi = (metadata, apiName, method) => {
1555
- const api = metadata.apis.find(api => api.name === apiName);
1556
- if (!api || !api.methods) return false;
1557
- return api.methods.some(m => m.name === method);
1558
- };
1559
- const getConstantValue = (metadataRpc, pallet, constant) => {
1560
- const {
1561
- unifiedMetadata,
1562
- builder
1563
- } = parseMetadataRpc(metadataRpc);
1564
- const codec = builder.buildConstant(pallet, constant);
1565
- const encodedValue = unifiedMetadata.pallets.find(({
1566
- name
1567
- }) => name === pallet)?.constants.find(({
1568
- name
1569
- }) => name === constant)?.value;
1570
- if (!encodedValue) throw new Error(`Constant ${pallet}.${constant} not found`);
1571
- return codec.dec(encodedValue);
1572
- };
1573
- const tryGetConstantValue = (metadataRpc, pallet, constant) => {
1574
- const {
1575
- unifiedMetadata,
1576
- builder
1577
- } = parseMetadataRpc(metadataRpc);
1578
- const encodedValue = unifiedMetadata.pallets.find(({
1579
- name
1580
- }) => name === pallet)?.constants.find(({
1581
- name
1582
- }) => name === constant)?.value;
1583
- if (!encodedValue) return null;
1584
- const codec = builder.buildConstant(pallet, constant);
1585
- return codec.dec(encodedValue);
1586
- };
1587
-
1588
- const buildNetworkStorageCoders = (chainId, miniMetadata, coders) => {
1589
- if (!miniMetadata.data) return null;
1590
- const metadata = unifyMetadata(decAnyMetadata(miniMetadata.data));
1591
- try {
1592
- const scaleBuilder = getDynamicBuilder(getLookupFn(metadata));
1593
- const builtCoders = Object.fromEntries(Object.entries(coders).flatMap(([key, moduleMethodOrFn]) => {
1594
- const [module, method] = typeof moduleMethodOrFn === "function" ? moduleMethodOrFn({
1595
- chainId
1596
- }) : moduleMethodOrFn;
1597
- try {
1598
- return [[key, scaleBuilder.buildStorage(module, method)]];
1599
- } catch (cause) {
1600
- log.trace(`Failed to build SCALE coder for chain ${chainId} (${module}::${method})`, cause);
1601
- return [];
1602
- }
1603
- }));
1604
- return builtCoders;
1605
- } catch (cause) {
1606
- log.error(`Failed to build SCALE coders for chain ${chainId} (${JSON.stringify(coders)})`, cause);
1607
- }
1608
- return null;
1609
- };
1610
-
1611
2030
  const buildQueries$2 = (networkId, balanceDefs, miniMetadata) => {
1612
2031
  const networkStorageCoders = buildNetworkStorageCoders(networkId, miniMetadata, {
1613
2032
  storage: ["Assets", "Account"]
@@ -1843,11 +2262,6 @@ function includeInTotalExtraAmount(extra) {
1843
2262
  return extra.filter(extra => extra.includeInTotal).map(extra => extra.amount.planck).reduce((a, b) => a + b, 0n);
1844
2263
  }
1845
2264
 
1846
- /**
1847
- * Have the importing library define its Token and BalanceJson enums (as a sum type of all plugins) and pass them into some
1848
- * internal global typescript context, which is then picked up on by this module.
1849
- */
1850
-
1851
2265
  /** A utility type used to extract the underlying `BalanceType` of a specific source from a generalised `BalanceJson` */
1852
2266
 
1853
2267
  /** TODO: Remove this in favour of a frontend-friendly `ChaindataProvider` */
@@ -2584,8 +2998,6 @@ const getValueId = amount => {
2584
2998
 
2585
2999
  /** A labelled extra amount of a balance */
2586
3000
 
2587
- /** Used by plugins to help define their custom `BalanceType` */
2588
-
2589
3001
  /** For fast db access, you can calculate the primary key for a miniMetadata using this method */
2590
3002
  const deriveMiniMetadataId = ({
2591
3003
  source,
@@ -6142,7 +6554,7 @@ const SubTokensMiniMetadataExtraSchema = z.strictObject({
6142
6554
  palletId: z.string()
6143
6555
  });
6144
6556
 
6145
- const BALANCE_MODULES = [SubNativeBalanceModule, SubAssetsBalanceModule, SubHydrationBalanceModule, SubForeignAssetsBalanceModule, SubPsp22BalanceModule, SubTokensBalanceModule, EvmErc20BalanceModule, EvmUniswapV2BalanceModule, EvmNativeBalanceModule];
6557
+ const BALANCE_MODULES = [SubNativeBalanceModule, SubAssetsBalanceModule, SubHydrationBalanceModule, SubForeignAssetsBalanceModule, SubPsp22BalanceModule, SubTokensBalanceModule, EvmErc20BalanceModule, EvmUniswapV2BalanceModule, EvmNativeBalanceModule, SolNativeBalanceModule, SolSplBalanceModule];
6146
6558
 
6147
6559
  // share requests as all modules will call this at once
6148
6560
  const CACHE$1 = new Map();
@@ -6320,10 +6732,25 @@ class BalancesProvider {
6320
6732
  {
6321
6733
  return this.getEthereumNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
6322
6734
  }
6735
+ case "solana":
6736
+ {
6737
+ return this.getSolanaNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
6738
+ }
6323
6739
  case "polkadot":
6324
6740
  {
6325
6741
  return this.getPolkadotNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
6326
6742
  }
6743
+ default:
6744
+ {
6745
+ log.warn("[balances] Unsupported network platform for module", {
6746
+ networkId,
6747
+ mod
6748
+ });
6749
+ return of({
6750
+ status: "live",
6751
+ balances: []
6752
+ });
6753
+ }
6327
6754
  }
6328
6755
  }));
6329
6756
  }), map(results => {
@@ -6353,7 +6780,7 @@ class BalancesProvider {
6353
6780
  address
6354
6781
  })));
6355
6782
  if (!this.#chainConnectors.substrate) {
6356
- log.debug("[balances] no substrate connector or miniMetadata for module", mod.type);
6783
+ log.warn("[balances] no substrate connector or miniMetadata for module", mod.type);
6357
6784
  return defer(() => of({
6358
6785
  status: "initialising",
6359
6786
  balances: this.getStoredBalances(moduleAddressesByTokenId)
@@ -6404,7 +6831,7 @@ class BalancesProvider {
6404
6831
  address
6405
6832
  })));
6406
6833
  if (!this.#chainConnectors.evm) {
6407
- log.debug("[balances] no ethereum connector for module", mod.type);
6834
+ log.warn("[balances] no ethereum connector for module", mod.type);
6408
6835
  return defer(() => of({
6409
6836
  status: "initialising",
6410
6837
  balances: this.getStoredBalances(moduleAddressesByTokenId)
@@ -6436,6 +6863,56 @@ class BalancesProvider {
6436
6863
  })));
6437
6864
  });
6438
6865
  }
6866
+ getSolanaNetworkModuleBalances$(networkId, tokensWithAddresses, mod) {
6867
+ return getSharedObservable(`BalancesProvider.getSolanaNetworkModuleBalances$`, {
6868
+ networkId,
6869
+ mod,
6870
+ tokensWithAddresses
6871
+ }, () => {
6872
+ if (!tokensWithAddresses.length) return of({
6873
+ status: "live",
6874
+ balances: []
6875
+ });
6876
+ const moduleAddressesByTokenId = fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
6877
+
6878
+ // all balance ids expected in result set
6879
+ const balanceIds = toPairs(moduleAddressesByTokenId).flatMap(([tokenId, addresses]) => addresses.map(address => getBalanceId({
6880
+ tokenId,
6881
+ address
6882
+ })));
6883
+ if (!this.#chainConnectors.solana) {
6884
+ log.warn("[balances] no solana connector for module", mod.type);
6885
+ return defer(() => of({
6886
+ status: "initialising",
6887
+ balances: this.getStoredBalances(moduleAddressesByTokenId)
6888
+ }));
6889
+ }
6890
+ const moduleBalances$ = mod.subscribeBalances({
6891
+ networkId,
6892
+ tokensWithAddresses,
6893
+ connector: this.#chainConnectors.solana
6894
+ }).pipe(catchError(() => EMPTY),
6895
+ // don't emit, let provider mark balances stale
6896
+ map(results => ({
6897
+ status: "live",
6898
+ // exclude zero balances
6899
+ balances: results.success.filter(b => new Balance(b).total.planck > 0n)
6900
+ })), tap(results => {
6901
+ this.updateStorage$(balanceIds, results);
6902
+ }),
6903
+ // shareReplay + keepAlive(0) keep the subscription alive while root observable is being unsubscribed+resubscribed, in case any input change
6904
+ shareReplay({
6905
+ refCount: true,
6906
+ bufferSize: 1
6907
+ }), keepAlive(0));
6908
+
6909
+ // defer the startWith call to start with up to date balances each time the observable is re-subscribed to
6910
+ return defer(() => moduleBalances$.pipe(startWith({
6911
+ status: "initialising",
6912
+ balances: this.getStoredBalances(moduleAddressesByTokenId)
6913
+ })));
6914
+ });
6915
+ }
6439
6916
  updateStorage$(balanceIds, balancesResult) {
6440
6917
  if (balancesResult.status !== "live") return;
6441
6918
  const storage = this.#storage.getValue();
@@ -6546,18 +7023,42 @@ class BalancesProvider {
6546
7023
  }));
6547
7024
  }
6548
7025
  }
6549
- const isAddressCompatibleWithNetwork = (network, address) => {
7026
+ const isAccountPlatformCompatibleWithNetwork = (network, platform) => {
6550
7027
  switch (network.platform) {
6551
7028
  case "ethereum":
6552
- return isEthereumAddress(address);
7029
+ return platform === "ethereum";
7030
+ case "solana":
7031
+ return platform === "solana";
6553
7032
  case "polkadot":
6554
- return isEthereumAddress(address) ? network.account === "secp256k1" : network.account !== "secp256k1";
7033
+ {
7034
+ switch (network.account) {
7035
+ case "secp256k1":
7036
+ return platform === "ethereum";
7037
+ case "*25519":
7038
+ return platform === "polkadot";
7039
+ default:
7040
+ throw new Error(`Unsupported polkadot network account type ${network.account}`);
7041
+ }
7042
+ }
6555
7043
  default:
6556
7044
  log.warn("Unsupported network platform", network);
6557
7045
  throw new Error("Unsupported network platform");
6558
7046
  }
6559
7047
  };
7048
+
7049
+ /**
7050
+ * If this is the address of an account, use isAccountCompatibleWithChain instead.
7051
+ * Otherwise it could lead to a loss of funds
7052
+ * @param chain
7053
+ * @param address
7054
+ * @returns
7055
+ */
7056
+ const isAddressCompatibleWithNetwork = (network, address) => {
7057
+ // TODO try with return true to check if wallet filters correctly upfront
7058
+ const accountPlatform = getAccountPlatformFromAddress(address);
7059
+ return isAccountPlatformCompatibleWithNetwork(network, accountPlatform);
7060
+ };
6560
7061
  const sortByBalanceId = (a, b) => getBalanceId(a).localeCompare(getBalanceId(b));
6561
7062
  const sortByMiniMetadataId = (a, b) => a.id.localeCompare(b.id);
6562
7063
 
6563
- export { BALANCE_MODULES, Balance, BalanceFormatter, BalanceValueGetter, Balances, BalancesProvider, Change24hCurrencyFormatter, EvmErc20BalanceModule, EvmErc20TokenConfigSchema, EvmNativeBalanceModule, EvmNativeTokenConfigSchema, EvmUniswapV2BalanceModule, EvmUniswapV2TokenConfigSchema, FiatSumBalancesFormatter, ONE_ALPHA_TOKEN, PlanckSumBalancesFormatter, SCALE_FACTOR, SUBTENSOR_MIN_STAKE_AMOUNT_PLANK, SUBTENSOR_ROOT_NETUID, SubAssetsBalanceModule, SubAssetsTokenConfigSchema, SubForeignAssetsBalanceModule, SubForeignAssetsTokenConfigSchema, SubHydrationBalanceModule, SubHydrationTokenConfigSchema, SubNativeBalanceModule, SubNativeMiniMetadataExtraSchema, SubNativeModuleConfigSchema, SubNativeTokenConfigSchema, SubPsp22BalanceModule, SubPsp22TokenConfigSchema, SubTokensBalanceModule, SubTokensMiniMetadataExtraSchema, SubTokensModuleConfigSchema, SubTokensTokenConfigSchema, SumBalancesFormatter, abiMulticall, calculateAlphaPrice, calculateTaoAmountFromAlpha, calculateTaoFromDynamicInfo, deriveMiniMetadataId, erc20BalancesAggregatorAbi, excludeFromFeePayableLocks, excludeFromTransferableAmount, filterBaseLocks, filterMirrorTokens, getBalanceId, getLockTitle, getLockedType, getValueId, includeInTotalExtraAmount, uniswapV2PairAbi };
7064
+ export { BALANCE_MODULES, Balance, BalanceFormatter, BalanceValueGetter, Balances, BalancesProvider, Change24hCurrencyFormatter, EvmErc20BalanceModule, EvmErc20TokenConfigSchema, EvmNativeBalanceModule, EvmNativeTokenConfigSchema, EvmUniswapV2BalanceModule, EvmUniswapV2TokenConfigSchema, FiatSumBalancesFormatter, ONE_ALPHA_TOKEN, PlanckSumBalancesFormatter, SCALE_FACTOR, SUBTENSOR_MIN_STAKE_AMOUNT_PLANK, SUBTENSOR_ROOT_NETUID, SolNativeBalanceModule, SolNativeTokenConfigSchema, SolSplBalanceModule, SolSplTokenConfigSchema, SubAssetsBalanceModule, SubAssetsTokenConfigSchema, SubForeignAssetsBalanceModule, SubForeignAssetsTokenConfigSchema, SubHydrationBalanceModule, SubHydrationTokenConfigSchema, SubNativeBalanceModule, SubNativeMiniMetadataExtraSchema, SubNativeModuleConfigSchema, SubNativeTokenConfigSchema, SubPsp22BalanceModule, SubPsp22TokenConfigSchema, SubTokensBalanceModule, SubTokensMiniMetadataExtraSchema, SubTokensModuleConfigSchema, SubTokensTokenConfigSchema, SumBalancesFormatter, abiMulticall, calculateAlphaPrice, calculateTaoAmountFromAlpha, calculateTaoFromDynamicInfo, deriveMiniMetadataId, erc20BalancesAggregatorAbi, excludeFromFeePayableLocks, excludeFromTransferableAmount, filterBaseLocks, filterMirrorTokens, getBalanceId, getLockTitle, getLockedType, getValueId, includeInTotalExtraAmount, uniswapV2PairAbi };