@talismn/balances 0.0.0-pr2136-20250814032256 → 0.0.0-pr2136-20250815050739
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/declarations/src/BalancesProvider.d.ts +0 -1
- package/dist/declarations/src/getMiniMetadatas/getMetadataRpc.d.ts +2 -2
- package/dist/declarations/src/getMiniMetadatas/getSpecVersion.d.ts +2 -2
- package/dist/declarations/src/getMiniMetadatas/index.d.ts +2 -2
- package/dist/declarations/src/modules/index.d.ts +0 -23
- package/dist/declarations/src/modules/shared/errors.d.ts +1 -1
- package/dist/declarations/src/modules/shared/fetchRuntimeCallResult.d.ts +2 -2
- package/dist/declarations/src/modules/shared/rpcQueryPack.d.ts +3 -3
- package/dist/declarations/src/modules/substrate-native/bittensor/getSubtensorStakingBalances.d.ts +2 -2
- package/dist/declarations/src/modules/substrate-native/fetchTokens.d.ts +2 -2
- package/dist/declarations/src/modules/substrate-psp22/util.d.ts +2 -2
- package/dist/declarations/src/types/IBalanceModule.d.ts +19 -26
- package/dist/declarations/src/types/balances.d.ts +4 -52
- package/dist/declarations/src/types/balancetypes.d.ts +4 -0
- package/dist/declarations/src/types/chainConnectors.d.ts +4 -4
- package/dist/talismn-balances.cjs.dev.js +254 -759
- package/dist/talismn-balances.cjs.prod.js +254 -759
- package/dist/talismn-balances.esm.js +246 -747
- package/package.json +8 -13
- package/dist/declarations/src/modules/sol-native/config.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/fetchBalances.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/fetchTokens.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/getMiniMetadata.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/getTransferCallData.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/index.d.ts +0 -2
- package/dist/declarations/src/modules/sol-native/module.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/subscribeBalances.d.ts +0 -3
- package/dist/declarations/src/modules/sol-native/types.d.ts +0 -13
- package/dist/declarations/src/modules/sol-spl/config.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/fetchBalances.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/fetchTokens.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/getMiniMetadata.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/getTransferCallData.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/index.d.ts +0 -2
- package/dist/declarations/src/modules/sol-spl/module.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/subscribeBalances.d.ts +0 -3
- package/dist/declarations/src/modules/sol-spl/types.d.ts +0 -14
@@ -1,19 +1,14 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
3
|
var chaindataProvider = require('@talismn/chaindata-provider');
|
4
|
-
var
|
4
|
+
var util = require('@talismn/util');
|
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');
|
13
11
|
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');
|
17
12
|
var tokenRates = require('@talismn/token-rates');
|
18
13
|
var utils = require('@polkadot-api/utils');
|
19
14
|
var polkadotApi = require('polkadot-api');
|
@@ -33,8 +28,8 @@ var BigNumber__default = /*#__PURE__*/_interopDefault(BigNumber);
|
|
33
28
|
var upperFirst__default = /*#__PURE__*/_interopDefault(upperFirst);
|
34
29
|
var PQueue__default = /*#__PURE__*/_interopDefault(PQueue);
|
35
30
|
|
36
|
-
const MODULE_TYPE$
|
37
|
-
const PLATFORM$
|
31
|
+
const MODULE_TYPE$8 = chaindataProvider.EvmErc20TokenSchema.shape.type.value;
|
32
|
+
const PLATFORM$8 = chaindataProvider.EvmErc20TokenSchema.shape.platform.value;
|
38
33
|
|
39
34
|
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)"]);
|
40
35
|
|
@@ -630,7 +625,7 @@ const getBalanceDefs = addressesByToken => {
|
|
630
625
|
// if there is at least one storage entry, the results will be an array with a single object
|
631
626
|
// if the storage has no entries in it (ex: Assets on ewx or moonbeam), the response will be an empty array
|
632
627
|
|
633
|
-
const fetchBalances$
|
628
|
+
const fetchBalances$8 = async ({
|
634
629
|
networkId,
|
635
630
|
tokensWithAddresses,
|
636
631
|
connector
|
@@ -642,8 +637,8 @@ const fetchBalances$a = async ({
|
|
642
637
|
const client = await connector.getPublicClientForEvmNetwork(networkId);
|
643
638
|
if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
|
644
639
|
for (const [token, addresses] of tokensWithAddresses) {
|
645
|
-
if (token.type !== MODULE_TYPE$
|
646
|
-
for (const address of addresses) if (!
|
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}`);
|
647
642
|
}
|
648
643
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
649
644
|
if (client.chain?.contracts?.erc20Aggregator && balanceDefs.length > 1) {
|
@@ -672,7 +667,7 @@ const fetchWithoutAggregator = async (client, balanceDefs) => {
|
|
672
667
|
address,
|
673
668
|
tokenId: token.id,
|
674
669
|
value: result.toString(),
|
675
|
-
source: MODULE_TYPE$
|
670
|
+
source: MODULE_TYPE$8,
|
676
671
|
networkId: chaindataProvider.parseEvmErc20TokenId(token.id).networkId,
|
677
672
|
status: "live"
|
678
673
|
};
|
@@ -715,7 +710,7 @@ const fetchWithAggregator = async (client, balanceDefs, erc20BalancesAggregatorA
|
|
715
710
|
address: balanceDef.address,
|
716
711
|
tokenId: balanceDef.token.id,
|
717
712
|
value: erc20Balances[index].toString(),
|
718
|
-
source: MODULE_TYPE$
|
713
|
+
source: MODULE_TYPE$8,
|
719
714
|
networkId: chaindataProvider.parseTokenId(balanceDef.token.id).networkId,
|
720
715
|
status: "live"
|
721
716
|
}));
|
@@ -772,7 +767,7 @@ const getTypedContract$1 = (client, abi, contractAddress) => viem.getContract({
|
|
772
767
|
}
|
773
768
|
});
|
774
769
|
|
775
|
-
const TokenCacheSchema$
|
770
|
+
const TokenCacheSchema$1 = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
|
776
771
|
id: chaindataProvider.EvmErc20TokenSchema.shape.id,
|
777
772
|
isValid: z__default.default.literal(true),
|
778
773
|
...chaindataProvider.EvmErc20TokenSchema.pick({
|
@@ -784,7 +779,7 @@ const TokenCacheSchema$2 = z__default.default.discriminatedUnion("isValid", [z__
|
|
784
779
|
id: chaindataProvider.EvmErc20TokenSchema.shape.id,
|
785
780
|
isValid: z__default.default.literal(false)
|
786
781
|
})]);
|
787
|
-
const fetchTokens$
|
782
|
+
const fetchTokens$8 = async ({
|
788
783
|
networkId,
|
789
784
|
tokens,
|
790
785
|
connector,
|
@@ -793,7 +788,7 @@ const fetchTokens$a = async ({
|
|
793
788
|
const result = [];
|
794
789
|
for (const tokenConfig of tokens) {
|
795
790
|
const tokenId = chaindataProvider.evmErc20TokenId(networkId, tokenConfig.contractAddress);
|
796
|
-
const cached = cache[tokenId] && TokenCacheSchema$
|
791
|
+
const cached = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
|
797
792
|
if (!cached) {
|
798
793
|
const client = await connector.getPublicClientForEvmNetwork(networkId);
|
799
794
|
if (!client) {
|
@@ -806,7 +801,7 @@ const fetchTokens$a = async ({
|
|
806
801
|
decimals,
|
807
802
|
symbol
|
808
803
|
} = await getErc20ContractData$1(client, tokenConfig.contractAddress);
|
809
|
-
cache[tokenId] = TokenCacheSchema$
|
804
|
+
cache[tokenId] = TokenCacheSchema$1.parse({
|
810
805
|
id: tokenId,
|
811
806
|
symbol,
|
812
807
|
decimals,
|
@@ -824,11 +819,11 @@ const fetchTokens$a = async ({
|
|
824
819
|
}
|
825
820
|
const base = {
|
826
821
|
id: tokenId,
|
827
|
-
type: MODULE_TYPE$
|
828
|
-
platform: PLATFORM$
|
822
|
+
type: MODULE_TYPE$8,
|
823
|
+
platform: PLATFORM$8,
|
829
824
|
networkId
|
830
825
|
};
|
831
|
-
const cached2 = cache[tokenId] && TokenCacheSchema$
|
826
|
+
const cached2 = cache[tokenId] && TokenCacheSchema$1.safeParse(cache[tokenId]).data;
|
832
827
|
if (cached2?.isValid === false) continue;
|
833
828
|
const token = lodashEs.assign(base, cached2?.isValid ? lodashEs.omit(cached2, ["isValid"]) : {}, tokenConfig);
|
834
829
|
const parsed = chaindataProvider.EvmErc20TokenSchema.safeParse(token);
|
@@ -843,19 +838,19 @@ const fetchTokens$a = async ({
|
|
843
838
|
return result;
|
844
839
|
};
|
845
840
|
|
846
|
-
const getMiniMetadata$
|
841
|
+
const getMiniMetadata$8 = () => {
|
847
842
|
throw new Error("MiniMetadata is not supported for ethereum tokens");
|
848
843
|
};
|
849
844
|
|
850
|
-
const getTransferCallData$
|
845
|
+
const getTransferCallData$8 = ({
|
851
846
|
from,
|
852
847
|
to,
|
853
848
|
value,
|
854
849
|
token
|
855
850
|
}) => {
|
856
|
-
if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$
|
857
|
-
if (!
|
858
|
-
if (!
|
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");
|
859
854
|
const data = viem.encodeFunctionData({
|
860
855
|
abi: viem.erc20Abi,
|
861
856
|
functionName: "transfer",
|
@@ -868,8 +863,8 @@ const getTransferCallData$a = ({
|
|
868
863
|
};
|
869
864
|
};
|
870
865
|
|
871
|
-
const SUBSCRIPTION_INTERVAL$
|
872
|
-
const subscribeBalances$
|
866
|
+
const SUBSCRIPTION_INTERVAL$4 = 6_000;
|
867
|
+
const subscribeBalances$8 = ({
|
873
868
|
networkId,
|
874
869
|
tokensWithAddresses,
|
875
870
|
connector
|
@@ -883,17 +878,17 @@ const subscribeBalances$a = ({
|
|
883
878
|
const poll = async () => {
|
884
879
|
try {
|
885
880
|
if (abortController.signal.aborted) return;
|
886
|
-
const balances = await fetchBalances$
|
881
|
+
const balances = await fetchBalances$8({
|
887
882
|
networkId,
|
888
883
|
tokensWithAddresses: tokensWithAddresses,
|
889
884
|
connector
|
890
885
|
});
|
891
886
|
if (abortController.signal.aborted) return;
|
892
887
|
subscriber.next(balances);
|
893
|
-
setTimeout(poll, SUBSCRIPTION_INTERVAL$
|
888
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$4);
|
894
889
|
} catch (error) {
|
895
890
|
log.error("Error", {
|
896
|
-
module: MODULE_TYPE$
|
891
|
+
module: MODULE_TYPE$8,
|
897
892
|
networkId,
|
898
893
|
addressesByToken: tokensWithAddresses,
|
899
894
|
error
|
@@ -909,13 +904,13 @@ const subscribeBalances$a = ({
|
|
909
904
|
};
|
910
905
|
|
911
906
|
const EvmErc20BalanceModule = {
|
912
|
-
type: MODULE_TYPE$
|
913
|
-
platform: PLATFORM$
|
914
|
-
getMiniMetadata: getMiniMetadata$
|
915
|
-
fetchTokens: fetchTokens$
|
916
|
-
fetchBalances: fetchBalances$
|
917
|
-
subscribeBalances: subscribeBalances$
|
918
|
-
getTransferCallData: getTransferCallData$
|
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
|
919
914
|
};
|
920
915
|
|
921
916
|
const TokenConfigBaseSchema = chaindataProvider.TokenBaseSchema.partial().omit({
|
@@ -928,10 +923,10 @@ const EvmErc20TokenConfigSchema = z__default.default.strictObject({
|
|
928
923
|
...TokenConfigBaseSchema.shape
|
929
924
|
});
|
930
925
|
|
931
|
-
const MODULE_TYPE$
|
932
|
-
const PLATFORM$
|
926
|
+
const MODULE_TYPE$7 = chaindataProvider.EvmNativeTokenSchema.shape.type.value;
|
927
|
+
const PLATFORM$7 = chaindataProvider.EvmNativeTokenSchema.shape.platform.value;
|
933
928
|
|
934
|
-
const fetchBalances$
|
929
|
+
const fetchBalances$7 = async ({
|
935
930
|
networkId,
|
936
931
|
tokensWithAddresses,
|
937
932
|
connector
|
@@ -943,8 +938,8 @@ const fetchBalances$9 = async ({
|
|
943
938
|
const client = await connector.getPublicClientForEvmNetwork(networkId);
|
944
939
|
if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
|
945
940
|
for (const [token, addresses] of tokensWithAddresses) {
|
946
|
-
if (token.type !== MODULE_TYPE$
|
947
|
-
for (const address of addresses) if (!
|
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}`);
|
948
943
|
}
|
949
944
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
950
945
|
if (client.chain?.contracts?.multicall3 && balanceDefs.length > 1) {
|
@@ -970,7 +965,7 @@ const fetchWithoutMulticall = async (client, balanceDefs) => {
|
|
970
965
|
address,
|
971
966
|
tokenId: token.id,
|
972
967
|
value: result.toString(),
|
973
|
-
source: MODULE_TYPE$
|
968
|
+
source: MODULE_TYPE$7,
|
974
969
|
networkId: chaindataProvider.parseTokenId(token.id).networkId,
|
975
970
|
status: "live"
|
976
971
|
};
|
@@ -1016,7 +1011,7 @@ const fetchWithMulticall = async (client, balanceDefs, multicall3Address) => {
|
|
1016
1011
|
address: balanceDefs[index].address,
|
1017
1012
|
tokenId: balanceDefs[index].token.id,
|
1018
1013
|
value: result.result.toString(),
|
1019
|
-
source: MODULE_TYPE$
|
1014
|
+
source: MODULE_TYPE$7,
|
1020
1015
|
networkId: chaindataProvider.parseTokenId(balanceDefs[index].token.id).networkId,
|
1021
1016
|
status: "live"
|
1022
1017
|
});
|
@@ -1046,7 +1041,7 @@ const fetchWithMulticall = async (client, balanceDefs, multicall3Address) => {
|
|
1046
1041
|
}
|
1047
1042
|
};
|
1048
1043
|
|
1049
|
-
const fetchTokens$
|
1044
|
+
const fetchTokens$7 = async ({
|
1050
1045
|
networkId,
|
1051
1046
|
tokens
|
1052
1047
|
}) => {
|
@@ -1054,8 +1049,8 @@ const fetchTokens$9 = async ({
|
|
1054
1049
|
if (tokens.length !== 1) throw new Error("EVM Native module expects the nativeCurrency to be passed as a single token in the array");
|
1055
1050
|
const token = lodashEs.assign({
|
1056
1051
|
id: chaindataProvider.evmNativeTokenId(networkId),
|
1057
|
-
type: MODULE_TYPE$
|
1058
|
-
platform: PLATFORM$
|
1052
|
+
type: MODULE_TYPE$7,
|
1053
|
+
platform: PLATFORM$7,
|
1059
1054
|
networkId,
|
1060
1055
|
isDefault: true
|
1061
1056
|
}, tokens[0]);
|
@@ -1067,19 +1062,19 @@ const fetchTokens$9 = async ({
|
|
1067
1062
|
return [parsed.data];
|
1068
1063
|
};
|
1069
1064
|
|
1070
|
-
const getMiniMetadata$
|
1065
|
+
const getMiniMetadata$7 = () => {
|
1071
1066
|
throw new Error("MiniMetadata is not supported for ethereum tokens");
|
1072
1067
|
};
|
1073
1068
|
|
1074
|
-
const getTransferCallData$
|
1069
|
+
const getTransferCallData$7 = ({
|
1075
1070
|
from,
|
1076
1071
|
to,
|
1077
1072
|
value,
|
1078
1073
|
token
|
1079
1074
|
}) => {
|
1080
|
-
if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$
|
1081
|
-
if (!
|
1082
|
-
if (!
|
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");
|
1083
1078
|
return {
|
1084
1079
|
from,
|
1085
1080
|
to,
|
@@ -1088,8 +1083,8 @@ const getTransferCallData$9 = ({
|
|
1088
1083
|
};
|
1089
1084
|
};
|
1090
1085
|
|
1091
|
-
const SUBSCRIPTION_INTERVAL$
|
1092
|
-
const subscribeBalances$
|
1086
|
+
const SUBSCRIPTION_INTERVAL$3 = 6_000;
|
1087
|
+
const subscribeBalances$7 = ({
|
1093
1088
|
networkId,
|
1094
1089
|
tokensWithAddresses,
|
1095
1090
|
connector
|
@@ -1103,17 +1098,17 @@ const subscribeBalances$9 = ({
|
|
1103
1098
|
const poll = async () => {
|
1104
1099
|
try {
|
1105
1100
|
if (abortController.signal.aborted) return;
|
1106
|
-
const balances = await fetchBalances$
|
1101
|
+
const balances = await fetchBalances$7({
|
1107
1102
|
networkId,
|
1108
1103
|
tokensWithAddresses: tokensWithAddresses,
|
1109
1104
|
connector
|
1110
1105
|
});
|
1111
1106
|
if (abortController.signal.aborted) return;
|
1112
1107
|
subscriber.next(balances);
|
1113
|
-
setTimeout(poll, SUBSCRIPTION_INTERVAL$
|
1108
|
+
setTimeout(poll, SUBSCRIPTION_INTERVAL$3);
|
1114
1109
|
} catch (error) {
|
1115
1110
|
log.error("Error", {
|
1116
|
-
module: MODULE_TYPE$
|
1111
|
+
module: MODULE_TYPE$7,
|
1117
1112
|
networkId,
|
1118
1113
|
addressesByToken: tokensWithAddresses,
|
1119
1114
|
error
|
@@ -1129,13 +1124,13 @@ const subscribeBalances$9 = ({
|
|
1129
1124
|
};
|
1130
1125
|
|
1131
1126
|
const EvmNativeBalanceModule = {
|
1132
|
-
type: MODULE_TYPE$
|
1133
|
-
platform: PLATFORM$
|
1134
|
-
getMiniMetadata: getMiniMetadata$
|
1135
|
-
fetchTokens: fetchTokens$
|
1136
|
-
fetchBalances: fetchBalances$
|
1137
|
-
subscribeBalances: subscribeBalances$
|
1138
|
-
getTransferCallData: getTransferCallData$
|
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
|
1139
1134
|
};
|
1140
1135
|
|
1141
1136
|
// to be used by chaindata too
|
@@ -1143,10 +1138,10 @@ const EvmNativeTokenConfigSchema = z__default.default.strictObject({
|
|
1143
1138
|
...TokenConfigBaseSchema.shape
|
1144
1139
|
});
|
1145
1140
|
|
1146
|
-
const MODULE_TYPE$
|
1147
|
-
const PLATFORM$
|
1141
|
+
const MODULE_TYPE$6 = chaindataProvider.EvmUniswapV2TokenSchema.shape.type.value;
|
1142
|
+
const PLATFORM$6 = chaindataProvider.EvmUniswapV2TokenSchema.shape.platform.value;
|
1148
1143
|
|
1149
|
-
const fetchBalances$
|
1144
|
+
const fetchBalances$6 = async ({
|
1150
1145
|
networkId,
|
1151
1146
|
tokensWithAddresses,
|
1152
1147
|
connector
|
@@ -1158,8 +1153,8 @@ const fetchBalances$8 = async ({
|
|
1158
1153
|
const client = await connector.getPublicClientForEvmNetwork(networkId);
|
1159
1154
|
if (!client) throw new Error(`Could not get rpc provider for evm network ${networkId}`);
|
1160
1155
|
for (const [token, addresses] of tokensWithAddresses) {
|
1161
|
-
if (token.type !== MODULE_TYPE$
|
1162
|
-
for (const address of addresses) if (!
|
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}`);
|
1163
1158
|
}
|
1164
1159
|
const balanceDefs = getBalanceDefs(tokensWithAddresses);
|
1165
1160
|
return fetchPoolBalances(client, balanceDefs);
|
@@ -1245,7 +1240,7 @@ const fetchPoolBalances = async (client, balanceDefs) => {
|
|
1245
1240
|
acc.success.push({
|
1246
1241
|
address,
|
1247
1242
|
tokenId: token.id,
|
1248
|
-
source: MODULE_TYPE$
|
1243
|
+
source: MODULE_TYPE$6,
|
1249
1244
|
networkId: chaindataProvider.parseTokenId(token.id).networkId,
|
1250
1245
|
status: "live",
|
1251
1246
|
values: [{
|
@@ -1305,7 +1300,7 @@ const getUniswapV2PairContractData = async (client, contractAddress) => {
|
|
1305
1300
|
};
|
1306
1301
|
};
|
1307
1302
|
|
1308
|
-
const TokenCacheSchema
|
1303
|
+
const TokenCacheSchema = z__default.default.discriminatedUnion("isValid", [z__default.default.strictObject({
|
1309
1304
|
id: chaindataProvider.EvmUniswapV2TokenSchema.shape.id,
|
1310
1305
|
isValid: z__default.default.literal(true),
|
1311
1306
|
...chaindataProvider.EvmUniswapV2TokenSchema.pick({
|
@@ -1323,7 +1318,7 @@ const TokenCacheSchema$1 = z__default.default.discriminatedUnion("isValid", [z__
|
|
1323
1318
|
id: chaindataProvider.EvmUniswapV2TokenSchema.shape.id,
|
1324
1319
|
isValid: z__default.default.literal(false)
|
1325
1320
|
})]);
|
1326
|
-
const fetchTokens$
|
1321
|
+
const fetchTokens$6 = async ({
|
1327
1322
|
networkId,
|
1328
1323
|
tokens,
|
1329
1324
|
connector,
|
@@ -1332,7 +1327,7 @@ const fetchTokens$8 = async ({
|
|
1332
1327
|
const result = [];
|
1333
1328
|
for (const tokenConfig of tokens) {
|
1334
1329
|
const tokenId = chaindataProvider.evmUniswapV2TokenId(networkId, tokenConfig.contractAddress);
|
1335
|
-
const cached = cache[tokenId] && TokenCacheSchema
|
1330
|
+
const cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
|
1336
1331
|
if (!cached) {
|
1337
1332
|
const client = await connector.getPublicClientForEvmNetwork(networkId);
|
1338
1333
|
if (!client) {
|
@@ -1354,7 +1349,7 @@ const fetchTokens$8 = async ({
|
|
1354
1349
|
symbol: symbol1,
|
1355
1350
|
decimals: decimals1
|
1356
1351
|
} = await getErc20ContractData(client, token1);
|
1357
|
-
cache[tokenId] = TokenCacheSchema
|
1352
|
+
cache[tokenId] = TokenCacheSchema.parse({
|
1358
1353
|
id: tokenId,
|
1359
1354
|
symbol: `${symbol0}/${symbol1}`,
|
1360
1355
|
decimals,
|
@@ -1370,611 +1365,58 @@ const fetchTokens$8 = async ({
|
|
1370
1365
|
} catch (err) {
|
1371
1366
|
const msg = err.shortMessage;
|
1372
1367
|
if (msg.includes("returned no data") || msg.includes("is out of bounds") || msg.includes("reverted")) {
|
1373
|
-
cache[tokenId] = {
|
1374
|
-
id: tokenId,
|
1375
|
-
isValid: false
|
1376
|
-
};
|
1377
|
-
} else {
|
1378
|
-
log.warn(`Failed to fetch UniswapV2 token data for ${tokenConfig.contractAddress}`, err.shortMessage);
|
1379
|
-
}
|
1380
|
-
continue;
|
1381
|
-
}
|
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;
|
1368
|
+
cache[tokenId] = {
|
1369
|
+
id: tokenId,
|
1370
|
+
isValid: false
|
1371
|
+
};
|
1372
|
+
} else {
|
1373
|
+
log.warn(`Failed to fetch UniswapV2 token data for ${tokenConfig.contractAddress}`, err.shortMessage);
|
1374
|
+
}
|
1375
|
+
continue;
|
1376
|
+
}
|
1865
1377
|
}
|
1866
|
-
cached = cache[tokenId] && TokenCacheSchema.safeParse(cache[tokenId]).data;
|
1867
|
-
if (cached?.isValid === false) continue;
|
1868
1378
|
const base = {
|
1869
1379
|
id: tokenId,
|
1870
1380
|
type: MODULE_TYPE$6,
|
1871
1381
|
platform: PLATFORM$6,
|
1872
1382
|
networkId
|
1873
1383
|
};
|
1874
|
-
const
|
1875
|
-
|
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);
|
1876
1388
|
if (!parsed.success) {
|
1877
|
-
log.warn("Ignoring token with invalid
|
1878
|
-
token
|
1879
|
-
});
|
1389
|
+
log.warn("Ignoring token with invalid schema", token);
|
1880
1390
|
continue;
|
1881
1391
|
}
|
1882
1392
|
result.push(parsed.data);
|
1883
1393
|
}
|
1884
1394
|
return result;
|
1885
1395
|
};
|
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
|
-
};
|
1937
1396
|
|
1938
1397
|
const getMiniMetadata$6 = () => {
|
1939
|
-
throw new Error("MiniMetadata is not supported for
|
1398
|
+
throw new Error("MiniMetadata is not supported for ethereum tokens");
|
1940
1399
|
};
|
1941
1400
|
|
1942
|
-
const getTransferCallData$6 =
|
1401
|
+
const getTransferCallData$6 = ({
|
1943
1402
|
from,
|
1944
1403
|
to,
|
1945
1404
|
value,
|
1946
|
-
token
|
1947
|
-
connector
|
1405
|
+
token
|
1948
1406
|
}) => {
|
1949
1407
|
if (!chaindataProvider.isTokenOfType(token, MODULE_TYPE$6)) throw new Error(`Token type ${token.type} is not ${MODULE_TYPE$6}.`);
|
1950
|
-
|
1951
|
-
|
1952
|
-
const
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
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
|
-
}
|
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
|
+
};
|
1978
1420
|
};
|
1979
1421
|
|
1980
1422
|
const SUBSCRIPTION_INTERVAL$2 = 6_000;
|
@@ -2017,7 +1459,7 @@ const subscribeBalances$6 = ({
|
|
2017
1459
|
}).pipe(rxjs.distinctUntilChanged(lodashEs.isEqual));
|
2018
1460
|
};
|
2019
1461
|
|
2020
|
-
const
|
1462
|
+
const EvmUniswapV2BalanceModule = {
|
2021
1463
|
type: MODULE_TYPE$6,
|
2022
1464
|
platform: PLATFORM$6,
|
2023
1465
|
getMiniMetadata: getMiniMetadata$6,
|
@@ -2028,14 +1470,153 @@ const SolSplBalanceModule = {
|
|
2028
1470
|
};
|
2029
1471
|
|
2030
1472
|
// to be used by chaindata too
|
2031
|
-
const
|
2032
|
-
|
1473
|
+
const EvmUniswapV2TokenConfigSchema = z__default.default.strictObject({
|
1474
|
+
contractAddress: chaindataProvider.EvmUniswapV2TokenSchema.shape.contractAddress,
|
2033
1475
|
...TokenConfigBaseSchema.shape
|
2034
1476
|
});
|
2035
1477
|
|
2036
1478
|
const MODULE_TYPE$5 = chaindataProvider.SubAssetsTokenSchema.shape.type.value;
|
2037
1479
|
const PLATFORM$5 = chaindataProvider.SubAssetsTokenSchema.shape.platform.value;
|
2038
1480
|
|
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
|
+
|
2039
1620
|
const buildQueries$2 = (networkId, balanceDefs, miniMetadata) => {
|
2040
1621
|
const networkStorageCoders = buildNetworkStorageCoders(networkId, miniMetadata, {
|
2041
1622
|
storage: ["Assets", "Account"]
|
@@ -2271,6 +1852,11 @@ function includeInTotalExtraAmount(extra) {
|
|
2271
1852
|
return extra.filter(extra => extra.includeInTotal).map(extra => extra.amount.planck).reduce((a, b) => a + b, 0n);
|
2272
1853
|
}
|
2273
1854
|
|
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
|
+
|
2274
1860
|
/** A utility type used to extract the underlying `BalanceType` of a specific source from a generalised `BalanceJson` */
|
2275
1861
|
|
2276
1862
|
/** TODO: Remove this in favour of a frontend-friendly `ChaindataProvider` */
|
@@ -3007,6 +2593,8 @@ const getValueId = amount => {
|
|
3007
2593
|
|
3008
2594
|
/** A labelled extra amount of a balance */
|
3009
2595
|
|
2596
|
+
/** Used by plugins to help define their custom `BalanceType` */
|
2597
|
+
|
3010
2598
|
/** For fast db access, you can calculate the primary key for a miniMetadata using this method */
|
3011
2599
|
const deriveMiniMetadataId = ({
|
3012
2600
|
source,
|
@@ -6563,7 +6151,7 @@ const SubTokensMiniMetadataExtraSchema = z__default.default.strictObject({
|
|
6563
6151
|
palletId: z__default.default.string()
|
6564
6152
|
});
|
6565
6153
|
|
6566
|
-
const BALANCE_MODULES = [SubNativeBalanceModule, SubAssetsBalanceModule, SubHydrationBalanceModule, SubForeignAssetsBalanceModule, SubPsp22BalanceModule, SubTokensBalanceModule, EvmErc20BalanceModule, EvmUniswapV2BalanceModule, EvmNativeBalanceModule
|
6154
|
+
const BALANCE_MODULES = [SubNativeBalanceModule, SubAssetsBalanceModule, SubHydrationBalanceModule, SubForeignAssetsBalanceModule, SubPsp22BalanceModule, SubTokensBalanceModule, EvmErc20BalanceModule, EvmUniswapV2BalanceModule, EvmNativeBalanceModule];
|
6567
6155
|
|
6568
6156
|
// share requests as all modules will call this at once
|
6569
6157
|
const CACHE$1 = new Map();
|
@@ -6741,25 +6329,10 @@ class BalancesProvider {
|
|
6741
6329
|
{
|
6742
6330
|
return this.getEthereumNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
|
6743
6331
|
}
|
6744
|
-
case "solana":
|
6745
|
-
{
|
6746
|
-
return this.getSolanaNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
|
6747
|
-
}
|
6748
6332
|
case "polkadot":
|
6749
6333
|
{
|
6750
6334
|
return this.getPolkadotNetworkModuleBalances$(networkId, tokensWithAddresses, mod);
|
6751
6335
|
}
|
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
|
-
}
|
6763
6336
|
}
|
6764
6337
|
}));
|
6765
6338
|
}), rxjs.map(results => {
|
@@ -6789,7 +6362,7 @@ class BalancesProvider {
|
|
6789
6362
|
address
|
6790
6363
|
})));
|
6791
6364
|
if (!this.#chainConnectors.substrate) {
|
6792
|
-
log.
|
6365
|
+
log.debug("[balances] no substrate connector or miniMetadata for module", mod.type);
|
6793
6366
|
return rxjs.defer(() => rxjs.of({
|
6794
6367
|
status: "initialising",
|
6795
6368
|
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
@@ -6840,7 +6413,7 @@ class BalancesProvider {
|
|
6840
6413
|
address
|
6841
6414
|
})));
|
6842
6415
|
if (!this.#chainConnectors.evm) {
|
6843
|
-
log.
|
6416
|
+
log.debug("[balances] no ethereum connector for module", mod.type);
|
6844
6417
|
return rxjs.defer(() => rxjs.of({
|
6845
6418
|
status: "initialising",
|
6846
6419
|
balances: this.getStoredBalances(moduleAddressesByTokenId)
|
@@ -6872,56 +6445,6 @@ class BalancesProvider {
|
|
6872
6445
|
})));
|
6873
6446
|
});
|
6874
6447
|
}
|
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
|
-
}
|
6925
6448
|
updateStorage$(balanceIds, balancesResult) {
|
6926
6449
|
if (balancesResult.status !== "live") return;
|
6927
6450
|
const storage = this.#storage.getValue();
|
@@ -7027,46 +6550,22 @@ class BalancesProvider {
|
|
7027
6550
|
return lodashEs.fromPairs(lodashEs.toPairs(addressesByTokenId).map(([tokenId, addresses]) => {
|
7028
6551
|
const networkId = chaindataProvider.parseTokenId(tokenId).networkId;
|
7029
6552
|
const network = networksById[networkId];
|
7030
|
-
return [tokenId, lodashEs.uniq(addresses.map(
|
6553
|
+
return [tokenId, lodashEs.uniq(addresses.map(util.normalizeAddress)).filter(address => network && isAddressCompatibleWithNetwork(network, address))];
|
7031
6554
|
}).filter(([, addresses]) => addresses.length > 0));
|
7032
6555
|
}));
|
7033
6556
|
}
|
7034
6557
|
}
|
7035
|
-
const
|
6558
|
+
const isAddressCompatibleWithNetwork = (network, address) => {
|
7036
6559
|
switch (network.platform) {
|
7037
6560
|
case "ethereum":
|
7038
|
-
return
|
7039
|
-
case "solana":
|
7040
|
-
return platform === "solana";
|
6561
|
+
return util.isEthereumAddress(address);
|
7041
6562
|
case "polkadot":
|
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
|
-
}
|
6563
|
+
return util.isEthereumAddress(address) ? network.account === "secp256k1" : network.account !== "secp256k1";
|
7052
6564
|
default:
|
7053
6565
|
log.warn("Unsupported network platform", network);
|
7054
6566
|
throw new Error("Unsupported network platform");
|
7055
6567
|
}
|
7056
6568
|
};
|
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
|
-
};
|
7070
6569
|
const sortByBalanceId = (a, b) => getBalanceId(a).localeCompare(getBalanceId(b));
|
7071
6570
|
const sortByMiniMetadataId = (a, b) => a.id.localeCompare(b.id);
|
7072
6571
|
|
@@ -7093,10 +6592,6 @@ exports.PlanckSumBalancesFormatter = PlanckSumBalancesFormatter;
|
|
7093
6592
|
exports.SCALE_FACTOR = SCALE_FACTOR;
|
7094
6593
|
exports.SUBTENSOR_MIN_STAKE_AMOUNT_PLANK = SUBTENSOR_MIN_STAKE_AMOUNT_PLANK;
|
7095
6594
|
exports.SUBTENSOR_ROOT_NETUID = SUBTENSOR_ROOT_NETUID;
|
7096
|
-
exports.SolNativeBalanceModule = SolNativeBalanceModule;
|
7097
|
-
exports.SolNativeTokenConfigSchema = SolNativeTokenConfigSchema;
|
7098
|
-
exports.SolSplBalanceModule = SolSplBalanceModule;
|
7099
|
-
exports.SolSplTokenConfigSchema = SolSplTokenConfigSchema;
|
7100
6595
|
exports.SubAssetsBalanceModule = SubAssetsBalanceModule;
|
7101
6596
|
exports.SubAssetsTokenConfigSchema = SubAssetsTokenConfigSchema;
|
7102
6597
|
exports.SubForeignAssetsBalanceModule = SubForeignAssetsBalanceModule;
|