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

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,14 +1,19 @@
1
1
  'use strict';
2
2
 
3
3
  var chaindataProvider = require('@talismn/chaindata-provider');
4
- var util = require('@talismn/util');
4
+ var crypto = require('@talismn/crypto');
5
5
  var viem = require('viem');
6
6
  var lodashEs = require('lodash-es');
7
7
  var z = require('zod/v4');
8
8
  var anylogger = require('anylogger');
9
9
  var rxjs = require('rxjs');
10
10
  var BigNumber = require('bignumber.js');
11
+ var web3_js = require('@solana/web3.js');
12
+ var util = require('@talismn/util');
11
13
  var scale = require('@talismn/scale');
14
+ var mplTokenMetadata = require('@metaplex-foundation/mpl-token-metadata');
15
+ var umi = require('@metaplex-foundation/umi');
16
+ var splToken = require('@solana/spl-token');
12
17
  var tokenRates = require('@talismn/token-rates');
13
18
  var utils = require('@polkadot-api/utils');
14
19
  var polkadotApi = require('polkadot-api');
@@ -28,8 +33,8 @@ var BigNumber__default = /*#__PURE__*/_interopDefault(BigNumber);
28
33
  var upperFirst__default = /*#__PURE__*/_interopDefault(upperFirst);
29
34
  var PQueue__default = /*#__PURE__*/_interopDefault(PQueue);
30
35
 
31
- const MODULE_TYPE$8 = chaindataProvider.EvmErc20TokenSchema.shape.type.value;
32
- const PLATFORM$8 = chaindataProvider.EvmErc20TokenSchema.shape.platform.value;
36
+ const MODULE_TYPE$a = chaindataProvider.EvmErc20TokenSchema.shape.type.value;
37
+ const PLATFORM$a = chaindataProvider.EvmErc20TokenSchema.shape.platform.value;
33
38
 
34
39
  const abiMulticall = viem.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)"]);
35
40
 
@@ -625,7 +630,7 @@ const getBalanceDefs = addressesByToken => {
625
630
  // if there is at least one storage entry, the results will be an array with a single object
626
631
  // if the storage has no entries in it (ex: Assets on ewx or moonbeam), the response will be an empty array
627
632
 
628
- const fetchBalances$8 = async ({
633
+ const fetchBalances$a = async ({
629
634
  networkId,
630
635
  tokensWithAddresses,
631
636
  connector
@@ -637,8 +642,8 @@ const fetchBalances$8 = async ({
637
642
  const client = await connector.getPublicClientForEvmNetwork(networkId);
638
643
  if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
639
644
  for (const [token, addresses] of tokensWithAddresses) {
640
- 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}`);
641
- for (const address of addresses) if (!util.isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
645
+ 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}`);
646
+ for (const address of addresses) if (!crypto.isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
642
647
  }
643
648
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
644
649
  if (client.chain?.contracts?.erc20Aggregator && balanceDefs.length > 1) {
@@ -667,7 +672,7 @@ const fetchWithoutAggregator = async (client, balanceDefs) => {
667
672
  address,
668
673
  tokenId: token.id,
669
674
  value: result.toString(),
670
- source: MODULE_TYPE$8,
675
+ source: MODULE_TYPE$a,
671
676
  networkId: chaindataProvider.parseEvmErc20TokenId(token.id).networkId,
672
677
  status: "live"
673
678
  };
@@ -710,7 +715,7 @@ const fetchWithAggregator = async (client, balanceDefs, erc20BalancesAggregatorA
710
715
  address: balanceDef.address,
711
716
  tokenId: balanceDef.token.id,
712
717
  value: erc20Balances[index].toString(),
713
- source: MODULE_TYPE$8,
718
+ source: MODULE_TYPE$a,
714
719
  networkId: chaindataProvider.parseTokenId(balanceDef.token.id).networkId,
715
720
  status: "live"
716
721
  }));
@@ -767,7 +772,7 @@ const getTypedContract$1 = (client, abi, contractAddress) => viem.getContract({
767
772
  }
768
773
  });
769
774
 
770
- const TokenCacheSchema$1 = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
775
+ const TokenCacheSchema$2 = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
771
776
  id: chaindataProvider.EvmErc20TokenSchema.shape.id,
772
777
  isValid: z__default.default.literal(true),
773
778
  ...chaindataProvider.EvmErc20TokenSchema.pick({
@@ -779,7 +784,7 @@ const TokenCacheSchema$1 = z__default.default.discriminatedUnion("isValid", [z__
779
784
  id: chaindataProvider.EvmErc20TokenSchema.shape.id,
780
785
  isValid: z__default.default.literal(false)
781
786
  })]);
782
- const fetchTokens$8 = async ({
787
+ const fetchTokens$a = async ({
783
788
  networkId,
784
789
  tokens,
785
790
  connector,
@@ -788,7 +793,7 @@ const fetchTokens$8 = async ({
788
793
  const result = [];
789
794
  for (const tokenConfig of tokens) {
790
795
  const tokenId = chaindataProvider.evmErc20TokenId(networkId, tokenConfig.contractAddress);
791
- const cached = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
796
+ const cached = cache[tokenId] && TokenCacheSchema$2.safeParse(cache[tokenId]).data;
792
797
  if (!cached) {
793
798
  const client = await connector.getPublicClientForEvmNetwork(networkId);
794
799
  if (!client) {
@@ -801,7 +806,7 @@ const fetchTokens$8 = async ({
801
806
  decimals,
802
807
  symbol
803
808
  } = await getErc20ContractData$1(client, tokenConfig.contractAddress);
804
- cache[tokenId] = TokenCacheSchema$1.parse({
809
+ cache[tokenId] = TokenCacheSchema$2.parse({
805
810
  id: tokenId,
806
811
  symbol,
807
812
  decimals,
@@ -819,11 +824,11 @@ const fetchTokens$8 = async ({
819
824
  }
820
825
  const base = {
821
826
  id: tokenId,
822
- type: MODULE_TYPE$8,
823
- platform: PLATFORM$8,
827
+ type: MODULE_TYPE$a,
828
+ platform: PLATFORM$a,
824
829
  networkId
825
830
  };
826
- const cached2 = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
831
+ const cached2 = cache[tokenId] && TokenCacheSchema$2.safeParse(cache[tokenId]).data;
827
832
  if (cached2?.isValid === false) continue;
828
833
  const token = lodashEs.assign(base, cached2?.isValid ? lodashEs.omit(cached2, ["isValid"]) : {}, tokenConfig);
829
834
  const parsed = chaindataProvider.EvmErc20TokenSchema.safeParse(token);
@@ -838,19 +843,19 @@ const fetchTokens$8 = async ({
838
843
  return result;
839
844
  };
840
845
 
841
- const getMiniMetadata$8 = () => {
846
+ const getMiniMetadata$a = () => {
842
847
  throw new Error("MiniMetadata is not supported for ethereum tokens");
843
848
  };
844
849
 
845
- const getTransferCallData$8 = ({
850
+ const getTransferCallData$a = ({
846
851
  from,
847
852
  to,
848
853
  value,
849
854
  token
850
855
  }) => {
851
- if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$8)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$8}.`);
852
- if (!util.isEthereumAddress(from)) throw new Error("Invalid from address");
853
- if (!util.isEthereumAddress(to)) throw new Error("Invalid to address");
856
+ if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$a)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$a}.`);
857
+ if (!crypto.isEthereumAddress(from)) throw new Error("Invalid from address");
858
+ if (!crypto.isEthereumAddress(to)) throw new Error("Invalid to address");
854
859
  const data = viem.encodeFunctionData({
855
860
  abi: viem.erc20Abi,
856
861
  functionName: "transfer",
@@ -863,8 +868,8 @@ const getTransferCallData$8 = ({
863
868
  };
864
869
  };
865
870
 
866
- const SUBSCRIPTION_INTERVAL$4 = 6_000;
867
- const subscribeBalances$8 = ({
871
+ const SUBSCRIPTION_INTERVAL$6 = 6_000;
872
+ const subscribeBalances$a = ({
868
873
  networkId,
869
874
  tokensWithAddresses,
870
875
  connector
@@ -878,17 +883,17 @@ const subscribeBalances$8 = ({
878
883
  const poll = async () => {
879
884
  try {
880
885
  if (abortController.signal.aborted) return;
881
- const balances = await fetchBalances$8({
886
+ const balances = await fetchBalances$a({
882
887
  networkId,
883
888
  tokensWithAddresses: tokensWithAddresses,
884
889
  connector
885
890
  });
886
891
  if (abortController.signal.aborted) return;
887
892
  subscriber.next(balances);
888
- setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
893
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$6);
889
894
  } catch (error) {
890
895
  log.error("Error", {
891
- module: MODULE_TYPE$8,
896
+ module: MODULE_TYPE$a,
892
897
  networkId,
893
898
  addressesByToken: tokensWithAddresses,
894
899
  error
@@ -904,13 +909,13 @@ const subscribeBalances$8 = ({
904
909
  };
905
910
 
906
911
  const EvmErc20BalanceModule = {
907
- type: MODULE_TYPE$8,
908
- platform: PLATFORM$8,
909
- getMiniMetadata: getMiniMetadata$8,
910
- fetchTokens: fetchTokens$8,
911
- fetchBalances: fetchBalances$8,
912
- subscribeBalances: subscribeBalances$8,
913
- getTransferCallData: getTransferCallData$8
912
+ type: MODULE_TYPE$a,
913
+ platform: PLATFORM$a,
914
+ getMiniMetadata: getMiniMetadata$a,
915
+ fetchTokens: fetchTokens$a,
916
+ fetchBalances: fetchBalances$a,
917
+ subscribeBalances: subscribeBalances$a,
918
+ getTransferCallData: getTransferCallData$a
914
919
  };
915
920
 
916
921
  const TokenConfigBaseSchema = chaindataProvider.TokenBaseSchema.partial().omit({
@@ -923,10 +928,10 @@ const EvmErc20TokenConfigSchema = z__default.default.strictObject({
923
928
  ...TokenConfigBaseSchema.shape
924
929
  });
925
930
 
926
- const MODULE_TYPE$7 = chaindataProvider.EvmNativeTokenSchema.shape.type.value;
927
- const PLATFORM$7 = chaindataProvider.EvmNativeTokenSchema.shape.platform.value;
931
+ const MODULE_TYPE$9 = chaindataProvider.EvmNativeTokenSchema.shape.type.value;
932
+ const PLATFORM$9 = chaindataProvider.EvmNativeTokenSchema.shape.platform.value;
928
933
 
929
- const fetchBalances$7 = async ({
934
+ const fetchBalances$9 = async ({
930
935
  networkId,
931
936
  tokensWithAddresses,
932
937
  connector
@@ -938,8 +943,8 @@ const fetchBalances$7 = async ({
938
943
  const client = await connector.getPublicClientForEvmNetwork(networkId);
939
944
  if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
940
945
  for (const [token, addresses] of tokensWithAddresses) {
941
- 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}`);
942
- for (const address of addresses) if (!util.isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
946
+ 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}`);
947
+ for (const address of addresses) if (!crypto.isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
943
948
  }
944
949
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
945
950
  if (client.chain?.contracts?.multicall3 && balanceDefs.length > 1) {
@@ -965,7 +970,7 @@ const fetchWithoutMulticall = async (client, balanceDefs) => {
965
970
  address,
966
971
  tokenId: token.id,
967
972
  value: result.toString(),
968
- source: MODULE_TYPE$7,
973
+ source: MODULE_TYPE$9,
969
974
  networkId: chaindataProvider.parseTokenId(token.id).networkId,
970
975
  status: "live"
971
976
  };
@@ -1011,7 +1016,7 @@ const fetchWithMulticall = async (client, balanceDefs, multicall3Address) => {
1011
1016
  address: balanceDefs[index].address,
1012
1017
  tokenId: balanceDefs[index].token.id,
1013
1018
  value: result.result.toString(),
1014
- source: MODULE_TYPE$7,
1019
+ source: MODULE_TYPE$9,
1015
1020
  networkId: chaindataProvider.parseTokenId(balanceDefs[index].token.id).networkId,
1016
1021
  status: "live"
1017
1022
  });
@@ -1041,7 +1046,7 @@ const fetchWithMulticall = async (client, balanceDefs, multicall3Address) => {
1041
1046
  }
1042
1047
  };
1043
1048
 
1044
- const fetchTokens$7 = async ({
1049
+ const fetchTokens$9 = async ({
1045
1050
  networkId,
1046
1051
  tokens
1047
1052
  }) => {
@@ -1049,8 +1054,8 @@ const fetchTokens$7 = async ({
1049
1054
  if (tokens.length !== 1) throw new Error("EVM Native module expects the nativeCurrency to be passed as a single token in the array");
1050
1055
  const token = lodashEs.assign({
1051
1056
  id: chaindataProvider.evmNativeTokenId(networkId),
1052
- type: MODULE_TYPE$7,
1053
- platform: PLATFORM$7,
1057
+ type: MODULE_TYPE$9,
1058
+ platform: PLATFORM$9,
1054
1059
  networkId,
1055
1060
  isDefault: true
1056
1061
  }, tokens[0]);
@@ -1062,19 +1067,19 @@ const fetchTokens$7 = async ({
1062
1067
  return [parsed.data];
1063
1068
  };
1064
1069
 
1065
- const getMiniMetadata$7 = () => {
1070
+ const getMiniMetadata$9 = () => {
1066
1071
  throw new Error("MiniMetadata is not supported for ethereum tokens");
1067
1072
  };
1068
1073
 
1069
- const getTransferCallData$7 = ({
1074
+ const getTransferCallData$9 = ({
1070
1075
  from,
1071
1076
  to,
1072
1077
  value,
1073
1078
  token
1074
1079
  }) => {
1075
- if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$7)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$7}.`);
1076
- if (!util.isEthereumAddress(from)) throw new Error("Invalid from address");
1077
- if (!util.isEthereumAddress(to)) throw new Error("Invalid to address");
1080
+ if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$9)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$9}.`);
1081
+ if (!crypto.isEthereumAddress(from)) throw new Error("Invalid from address");
1082
+ if (!crypto.isEthereumAddress(to)) throw new Error("Invalid to address");
1078
1083
  return {
1079
1084
  from,
1080
1085
  to,
@@ -1083,8 +1088,8 @@ const getTransferCallData$7 = ({
1083
1088
  };
1084
1089
  };
1085
1090
 
1086
- const SUBSCRIPTION_INTERVAL$3 = 6_000;
1087
- const subscribeBalances$7 = ({
1091
+ const SUBSCRIPTION_INTERVAL$5 = 6_000;
1092
+ const subscribeBalances$9 = ({
1088
1093
  networkId,
1089
1094
  tokensWithAddresses,
1090
1095
  connector
@@ -1098,17 +1103,17 @@ const subscribeBalances$7 = ({
1098
1103
  const poll = async () => {
1099
1104
  try {
1100
1105
  if (abortController.signal.aborted) return;
1101
- const balances = await fetchBalances$7({
1106
+ const balances = await fetchBalances$9({
1102
1107
  networkId,
1103
1108
  tokensWithAddresses: tokensWithAddresses,
1104
1109
  connector
1105
1110
  });
1106
1111
  if (abortController.signal.aborted) return;
1107
1112
  subscriber.next(balances);
1108
- setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
1113
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$5);
1109
1114
  } catch (error) {
1110
1115
  log.error("Error", {
1111
- module: MODULE_TYPE$7,
1116
+ module: MODULE_TYPE$9,
1112
1117
  networkId,
1113
1118
  addressesByToken: tokensWithAddresses,
1114
1119
  error
@@ -1124,13 +1129,13 @@ const subscribeBalances$7 = ({
1124
1129
  };
1125
1130
 
1126
1131
  const EvmNativeBalanceModule = {
1127
- type: MODULE_TYPE$7,
1128
- platform: PLATFORM$7,
1129
- getMiniMetadata: getMiniMetadata$7,
1130
- fetchTokens: fetchTokens$7,
1131
- fetchBalances: fetchBalances$7,
1132
- subscribeBalances: subscribeBalances$7,
1133
- getTransferCallData: getTransferCallData$7
1132
+ type: MODULE_TYPE$9,
1133
+ platform: PLATFORM$9,
1134
+ getMiniMetadata: getMiniMetadata$9,
1135
+ fetchTokens: fetchTokens$9,
1136
+ fetchBalances: fetchBalances$9,
1137
+ subscribeBalances: subscribeBalances$9,
1138
+ getTransferCallData: getTransferCallData$9
1134
1139
  };
1135
1140
 
1136
1141
  // to be used by chaindata too
@@ -1138,10 +1143,10 @@ const EvmNativeTokenConfigSchema = z__default.default.strictObject({
1138
1143
  ...TokenConfigBaseSchema.shape
1139
1144
  });
1140
1145
 
1141
- const MODULE_TYPE$6 = chaindataProvider.EvmUniswapV2TokenSchema.shape.type.value;
1142
- const PLATFORM$6 = chaindataProvider.EvmUniswapV2TokenSchema.shape.platform.value;
1146
+ const MODULE_TYPE$8 = chaindataProvider.EvmUniswapV2TokenSchema.shape.type.value;
1147
+ const PLATFORM$8 = chaindataProvider.EvmUniswapV2TokenSchema.shape.platform.value;
1143
1148
 
1144
- const fetchBalances$6 = async ({
1149
+ const fetchBalances$8 = async ({
1145
1150
  networkId,
1146
1151
  tokensWithAddresses,
1147
1152
  connector
@@ -1153,8 +1158,8 @@ const fetchBalances$6 = async ({
1153
1158
  const client = await connector.getPublicClientForEvmNetwork(networkId);
1154
1159
  if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
1155
1160
  for (const [token, addresses] of tokensWithAddresses) {
1156
- 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}`);
1157
- for (const address of addresses) if (!util.isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
1161
+ 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}`);
1162
+ for (const address of addresses) if (!crypto.isEthereumAddress(address)) throw new Error(`Invalid ethereum address for EVM ERC20 balance module: ${address} for token ${token.id}`);
1158
1163
  }
1159
1164
  const balanceDefs = getBalanceDefs(tokensWithAddresses);
1160
1165
  return fetchPoolBalances(client, balanceDefs);
@@ -1240,7 +1245,7 @@ const fetchPoolBalances = async (client, balanceDefs) => {
1240
1245
  acc.success.push({
1241
1246
  address,
1242
1247
  tokenId: token.id,
1243
- source: MODULE_TYPE$6,
1248
+ source: MODULE_TYPE$8,
1244
1249
  networkId: chaindataProvider.parseTokenId(token.id).networkId,
1245
1250
  status: "live",
1246
1251
  values: [{
@@ -1300,7 +1305,7 @@ const getUniswapV2PairContractData = async (client, contractAddress) => {
1300
1305
  };
1301
1306
  };
1302
1307
 
1303
- const TokenCacheSchema = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
1308
+ const TokenCacheSchema$1 = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
1304
1309
  id: chaindataProvider.EvmUniswapV2TokenSchema.shape.id,
1305
1310
  isValid: z__default.default.literal(true),
1306
1311
  ...chaindataProvider.EvmUniswapV2TokenSchema.pick({
@@ -1318,7 +1323,7 @@ const TokenCacheSchema = z__default.default.discriminatedUnion("isValid", [z__de
1318
1323
  id: chaindataProvider.EvmUniswapV2TokenSchema.shape.id,
1319
1324
  isValid: z__default.default.literal(false)
1320
1325
  })]);
1321
- const fetchTokens$6 = async ({
1326
+ const fetchTokens$8 = async ({
1322
1327
  networkId,
1323
1328
  tokens,
1324
1329
  connector,
@@ -1327,7 +1332,7 @@ const fetchTokens$6 = async ({
1327
1332
  const result = [];
1328
1333
  for (const tokenConfig of tokens) {
1329
1334
  const tokenId = chaindataProvider.evmUniswapV2TokenId(networkId, tokenConfig.contractAddress);
1330
- const cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1335
+ const cached = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
1331
1336
  if (!cached) {
1332
1337
  const client = await connector.getPublicClientForEvmNetwork(networkId);
1333
1338
  if (!client) {
@@ -1349,7 +1354,7 @@ const fetchTokens$6 = async ({
1349
1354
  symbol: symbol1,
1350
1355
  decimals: decimals1
1351
1356
  } = await getErc20ContractData(client, token1);
1352
- cache[tokenId] = TokenCacheSchema.parse({
1357
+ cache[tokenId] = TokenCacheSchema$1.parse({
1353
1358
  id: tokenId,
1354
1359
  symbol: `${symbol0}/${symbol1}`,
1355
1360
  decimals,
@@ -1375,48 +1380,601 @@ const fetchTokens$6 = async ({
1375
1380
  continue;
1376
1381
  }
1377
1382
  }
1383
+ const base = {
1384
+ id: tokenId,
1385
+ type: MODULE_TYPE$8,
1386
+ platform: PLATFORM$8,
1387
+ networkId
1388
+ };
1389
+ const cached2 = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
1390
+ if (cached2?.isValid === false) continue;
1391
+ const token = lodashEs.assign(base, cached2?.isValid ? lodashEs.omit(cached2, ["isValid"]) : {}, tokenConfig);
1392
+ const parsed = chaindataProvider.EvmUniswapV2TokenSchema.safeParse(token);
1393
+ if (!parsed.success) {
1394
+ log.warn("Ignoring token with invalid schema", token);
1395
+ continue;
1396
+ }
1397
+ result.push(parsed.data);
1398
+ }
1399
+ return result;
1400
+ };
1401
+
1402
+ const getMiniMetadata$8 = () => {
1403
+ throw new Error("MiniMetadata is not supported for ethereum tokens");
1404
+ };
1405
+
1406
+ const getTransferCallData$8 = ({
1407
+ from,
1408
+ to,
1409
+ value,
1410
+ token
1411
+ }) => {
1412
+ if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$8)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$8}.`);
1413
+ if (!crypto.isEthereumAddress(from)) throw new Error("Invalid from address");
1414
+ if (!crypto.isEthereumAddress(to)) throw new Error("Invalid to address");
1415
+ const data = viem.encodeFunctionData({
1416
+ abi: viem.erc20Abi,
1417
+ functionName: "transfer",
1418
+ args: [to, BigInt(value)]
1419
+ });
1420
+ return {
1421
+ from,
1422
+ to: token.contractAddress,
1423
+ data
1424
+ };
1425
+ };
1426
+
1427
+ const SUBSCRIPTION_INTERVAL$4 = 6_000;
1428
+ const subscribeBalances$8 = ({
1429
+ networkId,
1430
+ tokensWithAddresses,
1431
+ connector
1432
+ }) => {
1433
+ if (!tokensWithAddresses.length) return rxjs.of({
1434
+ success: [],
1435
+ errors: []
1436
+ });
1437
+ return new rxjs.Observable(subscriber => {
1438
+ const abortController = new AbortController();
1439
+ const poll = async () => {
1440
+ try {
1441
+ if (abortController.signal.aborted) return;
1442
+ const balances = await fetchBalances$8({
1443
+ networkId,
1444
+ tokensWithAddresses: tokensWithAddresses,
1445
+ connector
1446
+ });
1447
+ if (abortController.signal.aborted) return;
1448
+ subscriber.next(balances);
1449
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
1450
+ } catch (error) {
1451
+ log.error("Error", {
1452
+ module: MODULE_TYPE$8,
1453
+ networkId,
1454
+ addressesByToken: tokensWithAddresses,
1455
+ error
1456
+ });
1457
+ subscriber.error(error);
1458
+ }
1459
+ };
1460
+ poll();
1461
+ return () => {
1462
+ abortController.abort();
1463
+ };
1464
+ }).pipe(rxjs.distinctUntilChanged(lodashEs.isEqual));
1465
+ };
1466
+
1467
+ const EvmUniswapV2BalanceModule = {
1468
+ type: MODULE_TYPE$8,
1469
+ platform: PLATFORM$8,
1470
+ getMiniMetadata: getMiniMetadata$8,
1471
+ fetchTokens: fetchTokens$8,
1472
+ fetchBalances: fetchBalances$8,
1473
+ subscribeBalances: subscribeBalances$8,
1474
+ getTransferCallData: getTransferCallData$8
1475
+ };
1476
+
1477
+ // to be used by chaindata too
1478
+ const EvmUniswapV2TokenConfigSchema = z__default.default.strictObject({
1479
+ contractAddress: chaindataProvider.EvmUniswapV2TokenSchema.shape.contractAddress,
1480
+ ...TokenConfigBaseSchema.shape
1481
+ });
1482
+
1483
+ const MODULE_TYPE$7 = chaindataProvider.SolNativeTokenSchema.shape.type.value;
1484
+ const PLATFORM$7 = chaindataProvider.SolNativeTokenSchema.shape.platform.value;
1485
+
1486
+ const fetchBalances$7 = async ({
1487
+ networkId,
1488
+ tokensWithAddresses,
1489
+ connector
1490
+ }) => {
1491
+ if (!tokensWithAddresses.length) return {
1492
+ success: [],
1493
+ errors: []
1494
+ };
1495
+ const connection = await connector.getConnection(networkId);
1496
+ if (!connection) throw new Error(`Could not get rpc provider for sol network ${networkId}`);
1497
+ for (const [token, addresses] of tokensWithAddresses) {
1498
+ 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}`);
1499
+ for (const address of addresses) if (!crypto.isSolanaAddress(address)) throw new Error(`Invalid solana address for balance module: ${address} for token ${token.id}`);
1500
+ }
1501
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
1502
+ const results = await Promise.allSettled(balanceDefs.map(async ({
1503
+ token,
1504
+ address
1505
+ }) => {
1506
+ try {
1507
+ const publicKey = new web3_js.PublicKey(address);
1508
+ const lamports = await connection.getBalance(publicKey);
1509
+ return {
1510
+ address: address,
1511
+ tokenId: token.id,
1512
+ value: lamports.toString(),
1513
+ source: MODULE_TYPE$7,
1514
+ networkId: token.networkId,
1515
+ status: "live"
1516
+ };
1517
+ } catch (err) {
1518
+ throw new BalanceFetchError(`Failed to get balance for token ${token.id} and address ${address} on chain ${networkId}`, token.id, address, err);
1519
+ }
1520
+ }));
1521
+ return results.reduce((acc, result) => {
1522
+ if (result.status === "fulfilled") acc.success.push(result.value);else {
1523
+ const error = result.reason;
1524
+ acc.errors.push({
1525
+ tokenId: error.tokenId,
1526
+ address: error.address,
1527
+ error
1528
+ });
1529
+ }
1530
+ return acc;
1531
+ }, {
1532
+ success: [],
1533
+ errors: []
1534
+ });
1535
+ };
1536
+
1537
+ const fetchTokens$7 = async ({
1538
+ networkId,
1539
+ tokens
1540
+ }) => {
1541
+ // assume there is one and only one token in the array
1542
+ if (tokens.length !== 1) throw new Error("EVM Native module expects the nativeCurrency to be passed as a single token in the array");
1543
+ const token = lodashEs.assign({
1544
+ id: chaindataProvider.solNativeTokenId(networkId),
1545
+ type: MODULE_TYPE$7,
1546
+ platform: PLATFORM$7,
1547
+ networkId,
1548
+ isDefault: true
1549
+ }, tokens[0]);
1550
+ const parsed = chaindataProvider.SolNativeTokenSchema.safeParse(token);
1551
+ if (!parsed.success) {
1552
+ log.warn("Ignoring token with invalid schema", token);
1553
+ return [];
1554
+ }
1555
+ return [parsed.data];
1556
+ };
1557
+
1558
+ const getMiniMetadata$7 = () => {
1559
+ throw new Error("MiniMetadata is not supported for sol-native tokens");
1560
+ };
1561
+
1562
+ const getTransferCallData$7 = ({
1563
+ from,
1564
+ to,
1565
+ value,
1566
+ token
1567
+ }) => {
1568
+ if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$7)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$7}.`);
1569
+ const fromPubkey = new web3_js.PublicKey(from);
1570
+ const transferIx = web3_js.SystemProgram.transfer({
1571
+ fromPubkey,
1572
+ toPubkey: new web3_js.PublicKey(to),
1573
+ lamports: Number(value)
1574
+ });
1575
+ return [transferIx];
1576
+ };
1577
+
1578
+ const SUBSCRIPTION_INTERVAL$3 = 6_000;
1579
+ const subscribeBalances$7 = ({
1580
+ networkId,
1581
+ tokensWithAddresses,
1582
+ connector
1583
+ }) => {
1584
+ if (!tokensWithAddresses.length) return rxjs.of({
1585
+ success: [],
1586
+ errors: []
1587
+ });
1588
+ return new rxjs.Observable(subscriber => {
1589
+ const abortController = new AbortController();
1590
+ const poll = async () => {
1591
+ try {
1592
+ if (abortController.signal.aborted) return;
1593
+ const balances = await fetchBalances$7({
1594
+ networkId,
1595
+ tokensWithAddresses,
1596
+ connector
1597
+ });
1598
+ if (abortController.signal.aborted) return;
1599
+ subscriber.next(balances);
1600
+ setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
1601
+ } catch (error) {
1602
+ log.error("Error", {
1603
+ module: MODULE_TYPE$7,
1604
+ networkId,
1605
+ tokensWithAddresses,
1606
+ error
1607
+ });
1608
+ subscriber.error(error);
1609
+ }
1610
+ };
1611
+ poll();
1612
+ return () => {
1613
+ abortController.abort();
1614
+ };
1615
+ }).pipe(rxjs.distinctUntilChanged(lodashEs.isEqual));
1616
+ };
1617
+
1618
+ const SolNativeBalanceModule = {
1619
+ type: MODULE_TYPE$7,
1620
+ platform: PLATFORM$7,
1621
+ getMiniMetadata: getMiniMetadata$7,
1622
+ fetchTokens: fetchTokens$7,
1623
+ fetchBalances: fetchBalances$7,
1624
+ subscribeBalances: subscribeBalances$7,
1625
+ getTransferCallData: getTransferCallData$7
1626
+ };
1627
+
1628
+ // to be used by chaindata too
1629
+ const SolNativeTokenConfigSchema = z__default.default.strictObject({
1630
+ ...TokenConfigBaseSchema.shape
1631
+ });
1632
+
1633
+ const MODULE_TYPE$6 = chaindataProvider.SolSplTokenSchema.shape.type.value;
1634
+ const PLATFORM$6 = chaindataProvider.SolSplTokenSchema.shape.platform.value;
1635
+
1636
+ const fetchRuntimeCallResult = async (connector, networkId, metadataRpc, apiName, method, args) => {
1637
+ const {
1638
+ builder
1639
+ } = scale.parseMetadataRpc(metadataRpc);
1640
+ const call = builder.buildRuntimeCall(apiName, method);
1641
+ const hex = await connector.send(networkId, "state_call", [`${apiName}_${method}`, scale.toHex(call.args.enc(args))]);
1642
+ return call.value.dec(hex);
1643
+ };
1644
+
1645
+ const hasStorageItem = (metadata, palletName, itemName) => {
1646
+ const pallet = metadata.pallets.find(p => p.name === palletName);
1647
+ if (!pallet || !pallet.storage) return false;
1648
+ return pallet.storage.items.some(item => item.name === itemName);
1649
+ };
1650
+ const hasStorageItems = (metadata, palletName, itemNames) => {
1651
+ const pallet = metadata.pallets.find(p => p.name === palletName);
1652
+ if (!pallet || !pallet.storage) return false;
1653
+ return itemNames.every(itemName => pallet.storage?.items.some(item => item.name === itemName));
1654
+ };
1655
+ const hasRuntimeApi = (metadata, apiName, method) => {
1656
+ const api = metadata.apis.find(api => api.name === apiName);
1657
+ if (!api || !api.methods) return false;
1658
+ return api.methods.some(m => m.name === method);
1659
+ };
1660
+ const getConstantValue = (metadataRpc, pallet, constant) => {
1661
+ const {
1662
+ unifiedMetadata,
1663
+ builder
1664
+ } = scale.parseMetadataRpc(metadataRpc);
1665
+ const codec = builder.buildConstant(pallet, constant);
1666
+ const encodedValue = unifiedMetadata.pallets.find(({
1667
+ name
1668
+ }) => name === pallet)?.constants.find(({
1669
+ name
1670
+ }) => name === constant)?.value;
1671
+ if (!encodedValue) throw new Error(`Constant ${pallet}.${constant} not found`);
1672
+ return codec.dec(encodedValue);
1673
+ };
1674
+ const tryGetConstantValue = (metadataRpc, pallet, constant) => {
1675
+ const {
1676
+ unifiedMetadata,
1677
+ builder
1678
+ } = scale.parseMetadataRpc(metadataRpc);
1679
+ const encodedValue = unifiedMetadata.pallets.find(({
1680
+ name
1681
+ }) => name === pallet)?.constants.find(({
1682
+ name
1683
+ }) => name === constant)?.value;
1684
+ if (!encodedValue) return null;
1685
+ const codec = builder.buildConstant(pallet, constant);
1686
+ return codec.dec(encodedValue);
1687
+ };
1688
+
1689
+ const fetchRpcQueryPack = async (connector, networkId, queries) => {
1690
+ const allStateKeys = queries.flatMap(({
1691
+ stateKeys
1692
+ }) => stateKeys).filter(util.isNotNil);
1693
+
1694
+ // doing a query without keys would throw an error => return early
1695
+ if (!allStateKeys.length) return queries.map(({
1696
+ stateKeys,
1697
+ decodeResult
1698
+ }) => decodeResult(stateKeys.map(() => null)));
1699
+ const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
1700
+ return decodeRpcQueryPack(queries, result);
1701
+ };
1702
+ const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
1703
+ const allStateKeys = queries.flatMap(({
1704
+ stateKeys
1705
+ }) => stateKeys).filter(util.isNotNil);
1706
+
1707
+ // doing a query without keys would throw an error => return early
1708
+ if (!allStateKeys.length) return rxjs.of(queries.map(({
1709
+ stateKeys,
1710
+ decodeResult
1711
+ }) => decodeResult(stateKeys.map(() => null))));
1712
+ return new rxjs.Observable(subscriber => {
1713
+ // first subscription callback includes results for all state keys, but further callbacks will only include the ones that changed
1714
+ // => we need to keep all results in memory and update them after each callback, so we can emit the full result set each time
1715
+ const changesCache = {};
1716
+ const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
1717
+ if (error) subscriber.error(error);else if (result) {
1718
+ // update the cache
1719
+ for (const [stateKey, encodedResult] of result.changes) changesCache[stateKey] = encodedResult;
1720
+
1721
+ // regenerate the full changes array
1722
+ const changes = lodashEs.toPairs(changesCache);
1723
+
1724
+ // decode and emit results for all queries
1725
+ subscriber.next(decodeRpcQueryPack(queries, {
1726
+ block: result.block,
1727
+ changes
1728
+ }));
1729
+ }
1730
+ }, timeout);
1731
+ return () => {
1732
+ promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
1733
+ };
1734
+ });
1735
+ };
1736
+ const decodeRpcQueryPack = (queries, result) => {
1737
+ return queries.reduce((acc, {
1738
+ stateKeys,
1739
+ decodeResult
1740
+ }) => {
1741
+ const changes = stateKeys.map(stateKey => {
1742
+ if (!stateKey || !result) return null;
1743
+ const change = result.changes.find(([key]) => key === stateKey);
1744
+ if (!change) return null;
1745
+ return change[1];
1746
+ });
1747
+ acc.push(decodeResult(changes));
1748
+ return acc;
1749
+ }, []);
1750
+ };
1751
+
1752
+ const buildNetworkStorageCoders = (chainId, miniMetadata, coders) => {
1753
+ if (!miniMetadata.data) return null;
1754
+ const metadata = scale.unifyMetadata(scale.decAnyMetadata(miniMetadata.data));
1755
+ try {
1756
+ const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(metadata));
1757
+ const builtCoders = Object.fromEntries(Object.entries(coders).flatMap(([key, moduleMethodOrFn]) => {
1758
+ const [module, method] = typeof moduleMethodOrFn === "function" ? moduleMethodOrFn({
1759
+ chainId
1760
+ }) : moduleMethodOrFn;
1761
+ try {
1762
+ return [[key, scaleBuilder.buildStorage(module, method)]];
1763
+ } catch (cause) {
1764
+ log.trace(`Failed to build SCALE coder for chain ${chainId} (${module}::${method})`, cause);
1765
+ return [];
1766
+ }
1767
+ }));
1768
+ return builtCoders;
1769
+ } catch (cause) {
1770
+ log.error(`Failed to build SCALE coders for chain ${chainId} (${JSON.stringify(coders)})`, cause);
1771
+ }
1772
+ return null;
1773
+ };
1774
+
1775
+ const SPL_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
1776
+ const fetchBalances$6 = async ({
1777
+ networkId,
1778
+ tokensWithAddresses,
1779
+ connector
1780
+ }) => {
1781
+ if (!tokensWithAddresses.length) return {
1782
+ success: [],
1783
+ errors: []
1784
+ };
1785
+ const connection = await connector.getConnection(networkId);
1786
+ if (!connection) throw new Error(`Could not get connection for Solana network ${networkId}`);
1787
+ const accountAddresses = lodashEs.uniq(tokensWithAddresses.flatMap(([, addresses]) => addresses));
1788
+ const balancesPerAddress = await Promise.all(accountAddresses.map(async address => {
1789
+ const tokenAccounts = await connection.getParsedTokenAccountsByOwner(new web3_js.PublicKey(address), {
1790
+ programId: new web3_js.PublicKey(SPL_PROGRAM_ID) // SPL Token Program ID
1791
+ });
1792
+ const balances = tokenAccounts.value.map(d => {
1793
+ try {
1794
+ const mintAddress = d.account.data.parsed.info.mint;
1795
+ const value = d.account.data.parsed.info.tokenAmount.amount ?? "0";
1796
+ return {
1797
+ tokenId: chaindataProvider.solSplTokenId(networkId, mintAddress),
1798
+ networkId,
1799
+ address,
1800
+ source: MODULE_TYPE$6,
1801
+ status: "live",
1802
+ value
1803
+ };
1804
+ } catch (err) {
1805
+ log.warn("Failed to parse token amount", {
1806
+ address,
1807
+ d
1808
+ });
1809
+ return null;
1810
+ }
1811
+ }).filter(util.isNotNil);
1812
+ return [address, balances];
1813
+ }));
1814
+ const allBalancesByKey = lodashEs.keyBy(balancesPerAddress.flatMap(([, addressBalances]) => addressBalances), b => getBalanceKey(b.tokenId, b.address));
1815
+ const balanceDefs = getBalanceDefs(tokensWithAddresses);
1816
+
1817
+ // return a balance entry for all token/address pairs that were requested
1818
+ const success = balanceDefs.map(bd => {
1819
+ const found = allBalancesByKey[getBalanceKey(bd.token.id, bd.address)];
1820
+ return found ?? {
1821
+ tokenId: bd.token.id,
1822
+ networkId: bd.token.networkId,
1823
+ address: bd.address,
1824
+ source: MODULE_TYPE$6,
1825
+ status: "live",
1826
+ value: "0"
1827
+ };
1828
+ });
1829
+
1830
+ // return only the balances that match the tokens we are interested in
1831
+ return {
1832
+ success,
1833
+ errors: []
1834
+ }; // TODO output errors if any
1835
+ };
1836
+ const getBalanceKey = (tokenId, address) => `${tokenId}:${address}`;
1837
+
1838
+ const TokenCacheSchema = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
1839
+ id: chaindataProvider.SolSplTokenSchema.shape.id,
1840
+ isValid: z__default.default.literal(true),
1841
+ ...chaindataProvider.SolSplTokenSchema.pick({
1842
+ symbol: true,
1843
+ decimals: true,
1844
+ name: true,
1845
+ logo: true
1846
+ }).shape
1847
+ }), z__default.default.strictObject({
1848
+ id: chaindataProvider.SolSplTokenSchema.shape.id,
1849
+ isValid: z__default.default.literal(false)
1850
+ })]);
1851
+ const METAPLEX_PROGRAM_ID = new web3_js.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
1852
+ const fetchTokens$6 = async ({
1853
+ networkId,
1854
+ tokens,
1855
+ connector,
1856
+ cache
1857
+ }) => {
1858
+ const result = [];
1859
+ for (const tokenConfig of tokens) {
1860
+ const tokenId = chaindataProvider.solSplTokenId(networkId, tokenConfig.mintAddress);
1861
+ let cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1862
+ if (!cached) {
1863
+ const tokenInfo = await fetchOnChainTokenData(connector, tokenId);
1864
+ if (tokenInfo) cache[tokenId] = tokenInfo;
1865
+ }
1866
+ cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1867
+ if (cached?.isValid === false) continue;
1378
1868
  const base = {
1379
1869
  id: tokenId,
1380
1870
  type: MODULE_TYPE$6,
1381
1871
  platform: PLATFORM$6,
1382
1872
  networkId
1383
1873
  };
1384
- const cached2 = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
1385
- if (cached2?.isValid === false) continue;
1386
- const token = lodashEs.assign(base, cached2?.isValid ? lodashEs.omit(cached2, ["isValid"]) : {}, tokenConfig);
1387
- const parsed = chaindataProvider.EvmUniswapV2TokenSchema.safeParse(token);
1874
+ const token = lodashEs.assign(base, cached?.isValid ? lodashEs.omit(cached, ["isValid"]) : {}, tokenConfig);
1875
+ const parsed = chaindataProvider.SolSplTokenSchema.safeParse(token);
1388
1876
  if (!parsed.success) {
1389
- log.warn("Ignoring token with invalid schema", token);
1877
+ log.warn("Ignoring token with invalid SolSplTokenSchema", {
1878
+ token
1879
+ });
1390
1880
  continue;
1391
1881
  }
1392
1882
  result.push(parsed.data);
1393
1883
  }
1394
1884
  return result;
1395
1885
  };
1886
+ const ERROR_NO_MINT = "No mint info available";
1887
+ const ERROR_NO_METADATA = "No metadata account found";
1888
+ const ERROR_INVALID_DATA = "Invalid on-chain data";
1889
+ const fetchOnChainTokenData = async (connector, tokenId) => {
1890
+ try {
1891
+ const {
1892
+ networkId,
1893
+ mintAddress
1894
+ } = chaindataProvider.parseSolSplTokenId(tokenId);
1895
+ const connection = await connector.getConnection(networkId);
1896
+ if (!connection) {
1897
+ log.warn(`No connection found for network ${networkId}`);
1898
+ return null;
1899
+ }
1900
+ const mintPubKey = new web3_js.PublicKey(mintAddress);
1901
+ const mintInfo = await connection.getAccountInfo(mintPubKey);
1902
+ if (!mintInfo?.data) throw new Error(ERROR_NO_MINT);
1903
+ const mint = splToken.MintLayout.decode(mintInfo.data);
1904
+ const [metadataPDA] = web3_js.PublicKey.findProgramAddressSync([Buffer.from("metadata"), METAPLEX_PROGRAM_ID.toBuffer(), mintPubKey.toBuffer()], METAPLEX_PROGRAM_ID);
1905
+
1906
+ // 3. Fetch metadata account directly (traditional way)
1907
+ const metadataAccount = await connection.getAccountInfo(new web3_js.PublicKey(metadataPDA));
1908
+ if (!metadataAccount) throw new Error(ERROR_NO_METADATA);
1909
+ const metadata = mplTokenMetadata.deserializeMetadata({
1910
+ publicKey: umi.publicKey(metadataPDA),
1911
+ executable: metadataAccount.executable,
1912
+ owner: umi.publicKey(metadataAccount.owner),
1913
+ lamports: umi.sol(metadataAccount.lamports),
1914
+ data: metadataAccount.data
1915
+ });
1916
+ const parsed = TokenCacheSchema.safeParse({
1917
+ id: tokenId,
1918
+ symbol: metadata.symbol.trim(),
1919
+ name: metadata.name.trim(),
1920
+ decimals: mint.decimals,
1921
+ isValid: true
1922
+ });
1923
+ if (!parsed.success) throw new Error(ERROR_INVALID_DATA);
1924
+ return parsed.data;
1925
+ } catch (err) {
1926
+ const msg = err.message;
1927
+ if ([ERROR_NO_MINT, ERROR_NO_METADATA, ERROR_INVALID_DATA].includes(msg)) return TokenCacheSchema.parse({
1928
+ id: tokenId,
1929
+ isValid: false
1930
+ });
1931
+ log.warn("Failed to fetch sol-spl token data for %s", tokenId, {
1932
+ err
1933
+ });
1934
+ }
1935
+ return null;
1936
+ };
1396
1937
 
1397
1938
  const getMiniMetadata$6 = () => {
1398
- throw new Error("MiniMetadata is not supported for ethereum tokens");
1939
+ throw new Error("MiniMetadata is not supported for solana tokens");
1399
1940
  };
1400
1941
 
1401
- const getTransferCallData$6 = ({
1942
+ const getTransferCallData$6 = async ({
1402
1943
  from,
1403
1944
  to,
1404
1945
  value,
1405
- token
1946
+ token,
1947
+ connector
1406
1948
  }) => {
1407
1949
  if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$6)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$6}.`);
1408
- if (!util.isEthereumAddress(from)) throw new Error("Invalid from address");
1409
- if (!util.isEthereumAddress(to)) throw new Error("Invalid to address");
1410
- const data = viem.encodeFunctionData({
1411
- abi: viem.erc20Abi,
1412
- functionName: "transfer",
1413
- args: [to, BigInt(value)]
1414
- });
1415
- return {
1416
- from,
1417
- to: token.contractAddress,
1418
- data
1419
- };
1950
+ const connection = await connector.getConnection(token.networkId);
1951
+ const instructions = [];
1952
+ const mint = new web3_js.PublicKey(token.mintAddress);
1953
+ const fromWallet = new web3_js.PublicKey(from);
1954
+ const toWallet = new web3_js.PublicKey(to);
1955
+
1956
+ // Get associated token accounts
1957
+ const fromTokenAccount = await splToken.getAssociatedTokenAddress(mint, fromWallet);
1958
+ const toTokenAccount = await splToken.getAssociatedTokenAddress(mint, toWallet);
1959
+
1960
+ // Create the target token account if it doesn't exist
1961
+ if (!(await tokenAccountExists(connection, toTokenAccount))) {
1962
+ instructions.push(splToken.createAssociatedTokenAccountInstruction(fromWallet,
1963
+ // funder
1964
+ toTokenAccount, toWallet, mint));
1965
+ }
1966
+
1967
+ // Transfer the tokens
1968
+ instructions.push(splToken.createTransferInstruction(fromTokenAccount, toTokenAccount, fromWallet, BigInt(value), [], splToken.TOKEN_PROGRAM_ID));
1969
+ return instructions;
1970
+ };
1971
+ const tokenAccountExists = async (connection, address) => {
1972
+ try {
1973
+ await splToken.getAccount(connection, address);
1974
+ return true;
1975
+ } catch {
1976
+ return false;
1977
+ }
1420
1978
  };
1421
1979
 
1422
1980
  const SUBSCRIPTION_INTERVAL$2 = 6_000;
@@ -1459,7 +2017,7 @@ const subscribeBalances$6 = ({
1459
2017
  }).pipe(rxjs.distinctUntilChanged(lodashEs.isEqual));
1460
2018
  };
1461
2019
 
1462
- const EvmUniswapV2BalanceModule = {
2020
+ const SolSplBalanceModule = {
1463
2021
  type: MODULE_TYPE$6,
1464
2022
  platform: PLATFORM$6,
1465
2023
  getMiniMetadata: getMiniMetadata$6,
@@ -1470,153 +2028,14 @@ const EvmUniswapV2BalanceModule = {
1470
2028
  };
1471
2029
 
1472
2030
  // to be used by chaindata too
1473
- const EvmUniswapV2TokenConfigSchema = z__default.default.strictObject({
1474
- contractAddress: chaindataProvider.EvmUniswapV2TokenSchema.shape.contractAddress,
2031
+ const SolSplTokenConfigSchema = z__default.default.strictObject({
2032
+ mintAddress: chaindataProvider.SolSplTokenSchema.shape.mintAddress,
1475
2033
  ...TokenConfigBaseSchema.shape
1476
2034
  });
1477
2035
 
1478
2036
  const MODULE_TYPE$5 = chaindataProvider.SubAssetsTokenSchema.shape.type.value;
1479
2037
  const PLATFORM$5 = chaindataProvider.SubAssetsTokenSchema.shape.platform.value;
1480
2038
 
1481
- const fetchRpcQueryPack = async (connector, networkId, queries) => {
1482
- const allStateKeys = queries.flatMap(({
1483
- stateKeys
1484
- }) => stateKeys).filter(util.isNotNil);
1485
-
1486
- // doing a query without keys would throw an error => return early
1487
- if (!allStateKeys.length) return queries.map(({
1488
- stateKeys,
1489
- decodeResult
1490
- }) => decodeResult(stateKeys.map(() => null)));
1491
- const [result] = await connector.send(networkId, "state_queryStorageAt", [allStateKeys]);
1492
- return decodeRpcQueryPack(queries, result);
1493
- };
1494
- const getRpcQueryPack$ = (connector, networkId, queries, timeout = false) => {
1495
- const allStateKeys = queries.flatMap(({
1496
- stateKeys
1497
- }) => stateKeys).filter(util.isNotNil);
1498
-
1499
- // doing a query without keys would throw an error => return early
1500
- if (!allStateKeys.length) return rxjs.of(queries.map(({
1501
- stateKeys,
1502
- decodeResult
1503
- }) => decodeResult(stateKeys.map(() => null))));
1504
- return new rxjs.Observable(subscriber => {
1505
- // first subscription callback includes results for all state keys, but further callbacks will only include the ones that changed
1506
- // => we need to keep all results in memory and update them after each callback, so we can emit the full result set each time
1507
- const changesCache = {};
1508
- const promUnsub = connector.subscribe(networkId, "state_subscribeStorage", "state_storage", [allStateKeys], (error, result) => {
1509
- if (error) subscriber.error(error);else if (result) {
1510
- // update the cache
1511
- for (const [stateKey, encodedResult] of result.changes) changesCache[stateKey] = encodedResult;
1512
-
1513
- // regenerate the full changes array
1514
- const changes = lodashEs.toPairs(changesCache);
1515
-
1516
- // decode and emit results for all queries
1517
- subscriber.next(decodeRpcQueryPack(queries, {
1518
- block: result.block,
1519
- changes
1520
- }));
1521
- }
1522
- }, timeout);
1523
- return () => {
1524
- promUnsub.then(unsub => unsub("state_unsubscribeStorage"));
1525
- };
1526
- });
1527
- };
1528
- const decodeRpcQueryPack = (queries, result) => {
1529
- return queries.reduce((acc, {
1530
- stateKeys,
1531
- decodeResult
1532
- }) => {
1533
- const changes = stateKeys.map(stateKey => {
1534
- if (!stateKey || !result) return null;
1535
- const change = result.changes.find(([key]) => key === stateKey);
1536
- if (!change) return null;
1537
- return change[1];
1538
- });
1539
- acc.push(decodeResult(changes));
1540
- return acc;
1541
- }, []);
1542
- };
1543
-
1544
- const fetchRuntimeCallResult = async (connector, networkId, metadataRpc, apiName, method, args) => {
1545
- const {
1546
- builder
1547
- } = scale.parseMetadataRpc(metadataRpc);
1548
- const call = builder.buildRuntimeCall(apiName, method);
1549
- const hex = await connector.send(networkId, "state_call", [`${apiName}_${method}`, scale.toHex(call.args.enc(args))]);
1550
- return call.value.dec(hex);
1551
- };
1552
-
1553
- const hasStorageItem = (metadata, palletName, itemName) => {
1554
- const pallet = metadata.pallets.find(p => p.name === palletName);
1555
- if (!pallet || !pallet.storage) return false;
1556
- return pallet.storage.items.some(item => item.name === itemName);
1557
- };
1558
- const hasStorageItems = (metadata, palletName, itemNames) => {
1559
- const pallet = metadata.pallets.find(p => p.name === palletName);
1560
- if (!pallet || !pallet.storage) return false;
1561
- return itemNames.every(itemName => pallet.storage?.items.some(item => item.name === itemName));
1562
- };
1563
- const hasRuntimeApi = (metadata, apiName, method) => {
1564
- const api = metadata.apis.find(api => api.name === apiName);
1565
- if (!api || !api.methods) return false;
1566
- return api.methods.some(m => m.name === method);
1567
- };
1568
- const getConstantValue = (metadataRpc, pallet, constant) => {
1569
- const {
1570
- unifiedMetadata,
1571
- builder
1572
- } = scale.parseMetadataRpc(metadataRpc);
1573
- const codec = builder.buildConstant(pallet, constant);
1574
- const encodedValue = unifiedMetadata.pallets.find(({
1575
- name
1576
- }) => name === pallet)?.constants.find(({
1577
- name
1578
- }) => name === constant)?.value;
1579
- if (!encodedValue) throw new Error(`Constant ${pallet}.${constant} not found`);
1580
- return codec.dec(encodedValue);
1581
- };
1582
- const tryGetConstantValue = (metadataRpc, pallet, constant) => {
1583
- const {
1584
- unifiedMetadata,
1585
- builder
1586
- } = scale.parseMetadataRpc(metadataRpc);
1587
- const encodedValue = unifiedMetadata.pallets.find(({
1588
- name
1589
- }) => name === pallet)?.constants.find(({
1590
- name
1591
- }) => name === constant)?.value;
1592
- if (!encodedValue) return null;
1593
- const codec = builder.buildConstant(pallet, constant);
1594
- return codec.dec(encodedValue);
1595
- };
1596
-
1597
- const buildNetworkStorageCoders = (chainId, miniMetadata, coders) => {
1598
- if (!miniMetadata.data) return null;
1599
- const metadata = scale.unifyMetadata(scale.decAnyMetadata(miniMetadata.data));
1600
- try {
1601
- const scaleBuilder = scale.getDynamicBuilder(scale.getLookupFn(metadata));
1602
- const builtCoders = Object.fromEntries(Object.entries(coders).flatMap(([key, moduleMethodOrFn]) => {
1603
- const [module, method] = typeof moduleMethodOrFn === "function" ? moduleMethodOrFn({
1604
- chainId
1605
- }) : moduleMethodOrFn;
1606
- try {
1607
- return [[key, scaleBuilder.buildStorage(module, method)]];
1608
- } catch (cause) {
1609
- log.trace(`Failed to build SCALE coder for chain ${chainId} (${module}::${method})`, cause);
1610
- return [];
1611
- }
1612
- }));
1613
- return builtCoders;
1614
- } catch (cause) {
1615
- log.error(`Failed to build SCALE coders for chain ${chainId} (${JSON.stringify(coders)})`, cause);
1616
- }
1617
- return null;
1618
- };
1619
-
1620
2039
  const buildQueries$2 = (networkId, balanceDefs, miniMetadata) => {
1621
2040
  const networkStorageCoders = buildNetworkStorageCoders(networkId, miniMetadata, {
1622
2041
  storage: ["Assets", "Account"]
@@ -1852,11 +2271,6 @@ function includeInTotalExtraAmount(extra) {
1852
2271
  return extra.filter(extra => extra.includeInTotal).map(extra => extra.amount.planck).reduce((a, b) => a + b, 0n);
1853
2272
  }
1854
2273
 
1855
- /**
1856
- * Have the importing library define its Token and BalanceJson enums (as a sum type of all plugins) and pass them into some
1857
- * internal global typescript context, which is then picked up on by this module.
1858
- */
1859
-
1860
2274
  /** A utility type used to extract the underlying `BalanceType` of a specific source from a generalised `BalanceJson` */
1861
2275
 
1862
2276
  /** TODO: Remove this in favour of a frontend-friendly `ChaindataProvider` */
@@ -2593,8 +3007,6 @@ const getValueId = amount => {
2593
3007
 
2594
3008
  /** A labelled extra amount of a balance */
2595
3009
 
2596
- /** Used by plugins to help define their custom `BalanceType` */
2597
-
2598
3010
  /** For fast db access, you can calculate the primary key for a miniMetadata using this method */
2599
3011
  const deriveMiniMetadataId = ({
2600
3012
  source,
@@ -6151,7 +6563,7 @@ const SubTokensMiniMetadataExtraSchema = z__default.default.strictObject({
6151
6563
  palletId: z__default.default.string()
6152
6564
  });
6153
6565
 
6154
- const BALANCE_MODULES = [SubNativeBalanceModule, SubAssetsBalanceModule, SubHydrationBalanceModule, SubForeignAssetsBalanceModule, SubPsp22BalanceModule, SubTokensBalanceModule, EvmErc20BalanceModule, EvmUniswapV2BalanceModule, EvmNativeBalanceModule];
6566
+ const BALANCE_MODULES = [SubNativeBalanceModule, SubAssetsBalanceModule, SubHydrationBalanceModule, SubForeignAssetsBalanceModule, SubPsp22BalanceModule, SubTokensBalanceModule, EvmErc20BalanceModule, EvmUniswapV2BalanceModule, EvmNativeBalanceModule, SolNativeBalanceModule, SolSplBalanceModule];
6155
6567
 
6156
6568
  // share requests as all modules will call this at once
6157
6569
  const CACHE$1 = new Map();
@@ -6329,10 +6741,25 @@ class BalancesProvider {
6329
6741
  {
6330
6742
  return this.getEthereumNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
6331
6743
  }
6744
+ case "solana":
6745
+ {
6746
+ return this.getSolanaNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
6747
+ }
6332
6748
  case "polkadot":
6333
6749
  {
6334
6750
  return this.getPolkadotNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
6335
6751
  }
6752
+ default:
6753
+ {
6754
+ log.warn("[balances] Unsupported network platform for module", {
6755
+ networkId,
6756
+ mod
6757
+ });
6758
+ return rxjs.of({
6759
+ status: "live",
6760
+ balances: []
6761
+ });
6762
+ }
6336
6763
  }
6337
6764
  }));
6338
6765
  }), rxjs.map(results => {
@@ -6362,7 +6789,7 @@ class BalancesProvider {
6362
6789
  address
6363
6790
  })));
6364
6791
  if (!this.#chainConnectors.substrate) {
6365
- log.debug("[balances] no substrate connector or miniMetadata for module", mod.type);
6792
+ log.warn("[balances] no substrate connector or miniMetadata for module", mod.type);
6366
6793
  return rxjs.defer(() => rxjs.of({
6367
6794
  status: "initialising",
6368
6795
  balances: this.getStoredBalances(moduleAddressesByTokenId)
@@ -6413,7 +6840,7 @@ class BalancesProvider {
6413
6840
  address
6414
6841
  })));
6415
6842
  if (!this.#chainConnectors.evm) {
6416
- log.debug("[balances] no ethereum connector for module", mod.type);
6843
+ log.warn("[balances] no ethereum connector for module", mod.type);
6417
6844
  return rxjs.defer(() => rxjs.of({
6418
6845
  status: "initialising",
6419
6846
  balances: this.getStoredBalances(moduleAddressesByTokenId)
@@ -6445,6 +6872,56 @@ class BalancesProvider {
6445
6872
  })));
6446
6873
  });
6447
6874
  }
6875
+ getSolanaNetworkModuleBalances$(networkId, tokensWithAddresses, mod) {
6876
+ return util.getSharedObservable(`BalancesProvider.getSolanaNetworkModuleBalances$`, {
6877
+ networkId,
6878
+ mod,
6879
+ tokensWithAddresses
6880
+ }, () => {
6881
+ if (!tokensWithAddresses.length) return rxjs.of({
6882
+ status: "live",
6883
+ balances: []
6884
+ });
6885
+ const moduleAddressesByTokenId = lodashEs.fromPairs(tokensWithAddresses.map(([token, addresses]) => [token.id, addresses]));
6886
+
6887
+ // all balance ids expected in result set
6888
+ const balanceIds = lodashEs.toPairs(moduleAddressesByTokenId).flatMap(([tokenId, addresses]) => addresses.map(address => getBalanceId({
6889
+ tokenId,
6890
+ address
6891
+ })));
6892
+ if (!this.#chainConnectors.solana) {
6893
+ log.warn("[balances] no solana connector for module", mod.type);
6894
+ return rxjs.defer(() => rxjs.of({
6895
+ status: "initialising",
6896
+ balances: this.getStoredBalances(moduleAddressesByTokenId)
6897
+ }));
6898
+ }
6899
+ const moduleBalances$ = mod.subscribeBalances({
6900
+ networkId,
6901
+ tokensWithAddresses,
6902
+ connector: this.#chainConnectors.solana
6903
+ }).pipe(rxjs.catchError(() => rxjs.EMPTY),
6904
+ // don't emit, let provider mark balances stale
6905
+ rxjs.map(results => ({
6906
+ status: "live",
6907
+ // exclude zero balances
6908
+ balances: results.success.filter(b => new Balance(b).total.planck > 0n)
6909
+ })), rxjs.tap(results => {
6910
+ this.updateStorage$(balanceIds, results);
6911
+ }),
6912
+ // shareReplay + keepAlive(0) keep the subscription alive while root observable is being unsubscribed+resubscribed, in case any input change
6913
+ rxjs.shareReplay({
6914
+ refCount: true,
6915
+ bufferSize: 1
6916
+ }), util.keepAlive(0));
6917
+
6918
+ // defer the startWith call to start with up to date balances each time the observable is re-subscribed to
6919
+ return rxjs.defer(() => moduleBalances$.pipe(rxjs.startWith({
6920
+ status: "initialising",
6921
+ balances: this.getStoredBalances(moduleAddressesByTokenId)
6922
+ })));
6923
+ });
6924
+ }
6448
6925
  updateStorage$(balanceIds, balancesResult) {
6449
6926
  if (balancesResult.status !== "live") return;
6450
6927
  const storage = this.#storage.getValue();
@@ -6550,22 +7027,46 @@ class BalancesProvider {
6550
7027
  return lodashEs.fromPairs(lodashEs.toPairs(addressesByTokenId).map(([tokenId, addresses]) => {
6551
7028
  const networkId = chaindataProvider.parseTokenId(tokenId).networkId;
6552
7029
  const network = networksById[networkId];
6553
- return [tokenId, lodashEs.uniq(addresses.map(util.normalizeAddress)).filter(address => network && isAddressCompatibleWithNetwork(network, address))];
7030
+ return [tokenId, lodashEs.uniq(addresses.map(crypto.normalizeAddress)).filter(address => network && isAddressCompatibleWithNetwork(network, address))];
6554
7031
  }).filter(([, addresses]) => addresses.length > 0));
6555
7032
  }));
6556
7033
  }
6557
7034
  }
6558
- const isAddressCompatibleWithNetwork = (network, address) => {
7035
+ const isAccountPlatformCompatibleWithNetwork = (network, platform) => {
6559
7036
  switch (network.platform) {
6560
7037
  case "ethereum":
6561
- return util.isEthereumAddress(address);
7038
+ return platform === "ethereum";
7039
+ case "solana":
7040
+ return platform === "solana";
6562
7041
  case "polkadot":
6563
- return util.isEthereumAddress(address) ? network.account === "secp256k1" : network.account !== "secp256k1";
7042
+ {
7043
+ switch (network.account) {
7044
+ case "secp256k1":
7045
+ return platform === "ethereum";
7046
+ case "*25519":
7047
+ return platform === "polkadot";
7048
+ default:
7049
+ throw new Error(`Unsupported polkadot network account type ${network.account}`);
7050
+ }
7051
+ }
6564
7052
  default:
6565
7053
  log.warn("Unsupported network platform", network);
6566
7054
  throw new Error("Unsupported network platform");
6567
7055
  }
6568
7056
  };
7057
+
7058
+ /**
7059
+ * If this is the address of an account, use isAccountCompatibleWithChain instead.
7060
+ * Otherwise it could lead to a loss of funds
7061
+ * @param chain
7062
+ * @param address
7063
+ * @returns
7064
+ */
7065
+ const isAddressCompatibleWithNetwork = (network, address) => {
7066
+ // TODO try with return true to check if wallet filters correctly upfront
7067
+ const accountPlatform = crypto.getAccountPlatformFromAddress(address);
7068
+ return isAccountPlatformCompatibleWithNetwork(network, accountPlatform);
7069
+ };
6569
7070
  const sortByBalanceId = (a, b) => getBalanceId(a).localeCompare(getBalanceId(b));
6570
7071
  const sortByMiniMetadataId = (a, b) => a.id.localeCompare(b.id);
6571
7072
 
@@ -6592,6 +7093,10 @@ exports.PlanckSumBalancesFormatter = PlanckSumBalancesFormatter;
6592
7093
  exports.SCALE_FACTOR = SCALE_FACTOR;
6593
7094
  exports.SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = SUBTENSOR_MIN_STAKE_AMOUNT_PLANK;
6594
7095
  exports.SUBTENSOR_ROOT_NETUID = SUBTENSOR_ROOT_NETUID;
7096
+ exports.SolNativeBalanceModule = SolNativeBalanceModule;
7097
+ exports.SolNativeTokenConfigSchema = SolNativeTokenConfigSchema;
7098
+ exports.SolSplBalanceModule = SolSplBalanceModule;
7099
+ exports.SolSplTokenConfigSchema = SolSplTokenConfigSchema;
6595
7100
  exports.SubAssetsBalanceModule = SubAssetsBalanceModule;
6596
7101
  exports.SubAssetsTokenConfigSchema = SubAssetsTokenConfigSchema;
6597
7102
  exports.SubForeignAssetsBalanceModule = SubForeignAssetsBalanceModule;