@subwallet/extension-base 1.3.3-0 → 1.3.4-0

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 (114) hide show
  1. package/background/KoniTypes.d.ts +13 -0
  2. package/background/KoniTypes.js +1 -0
  3. package/cjs/background/KoniTypes.js +1 -0
  4. package/cjs/constants/blocked-actions-list.js +1 -2
  5. package/cjs/constants/index.js +16 -1
  6. package/cjs/constants/remind-notification-time.js +14 -0
  7. package/cjs/core/logic-validation/transfer.js +12 -6
  8. package/cjs/core/substrate/xcm-parser.js +13 -1
  9. package/cjs/koni/api/contract-handler/utils/index.js +20 -1
  10. package/cjs/koni/background/handlers/Extension.js +110 -23
  11. package/cjs/koni/background/handlers/State.js +5 -2
  12. package/cjs/packageInfo.js +1 -1
  13. package/cjs/services/balance-service/helpers/process.js +2 -1
  14. package/cjs/services/balance-service/transfer/xcm/availBridge.js +198 -0
  15. package/cjs/services/balance-service/transfer/xcm/index.js +50 -5
  16. package/cjs/services/chain-service/handler/EvmApi.js +12 -21
  17. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +29 -0
  18. package/cjs/services/chain-service/index.js +44 -13
  19. package/cjs/services/chain-service/utils/index.js +20 -0
  20. package/cjs/services/earning-service/handlers/base.js +12 -3
  21. package/cjs/services/earning-service/handlers/native-staking/amplitude.js +10 -2
  22. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +2 -0
  23. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +2 -0
  24. package/cjs/services/earning-service/handlers/native-staking/tao.js +10 -2
  25. package/cjs/services/earning-service/handlers/nomination-pool/index.js +9 -4
  26. package/cjs/services/earning-service/service.js +5 -0
  27. package/cjs/services/inapp-notification-service/consts.js +31 -0
  28. package/cjs/services/inapp-notification-service/index.js +260 -0
  29. package/cjs/services/inapp-notification-service/interfaces.js +32 -0
  30. package/cjs/services/inapp-notification-service/utils.js +197 -0
  31. package/cjs/services/keyring-service/context/account-context.js +9 -0
  32. package/cjs/services/keyring-service/context/state.js +4 -0
  33. package/cjs/services/setting-service/SettingService.js +9 -1
  34. package/cjs/services/setting-service/constants.js +16 -1
  35. package/cjs/services/storage-service/DatabaseService.js +42 -3
  36. package/cjs/services/storage-service/databases/index.js +3 -0
  37. package/cjs/services/storage-service/db-stores/InappNotification.js +81 -0
  38. package/cjs/services/transaction-service/index.js +13 -0
  39. package/cjs/types/avail-bridge/index.js +1 -0
  40. package/cjs/types/notification/index.js +1 -0
  41. package/cjs/utils/account/transform.js +9 -5
  42. package/cjs/utils/staticData/index.js +7 -2
  43. package/constants/blocked-actions-list.js +1 -2
  44. package/constants/index.d.ts +2 -0
  45. package/constants/index.js +3 -1
  46. package/constants/remind-notification-time.d.ts +2 -0
  47. package/constants/remind-notification-time.js +7 -0
  48. package/core/logic-validation/transfer.js +12 -6
  49. package/core/substrate/xcm-parser.d.ts +1 -0
  50. package/core/substrate/xcm-parser.js +12 -1
  51. package/koni/api/contract-handler/utils/avail_bridge_abi.json +1659 -0
  52. package/koni/api/contract-handler/utils/avail_test_bridge_abi.json +1692 -0
  53. package/koni/api/contract-handler/utils/index.d.ts +4 -0
  54. package/koni/api/contract-handler/utils/index.js +15 -0
  55. package/koni/background/handlers/Extension.d.ts +7 -0
  56. package/koni/background/handlers/Extension.js +112 -25
  57. package/koni/background/handlers/State.d.ts +2 -0
  58. package/koni/background/handlers/State.js +5 -2
  59. package/package.json +54 -6
  60. package/packageInfo.js +1 -1
  61. package/services/balance-service/helpers/process.js +2 -1
  62. package/services/balance-service/transfer/xcm/availBridge.d.ts +45 -0
  63. package/services/balance-service/transfer/xcm/availBridge.js +186 -0
  64. package/services/balance-service/transfer/xcm/index.d.ts +8 -8
  65. package/services/balance-service/transfer/xcm/index.js +46 -5
  66. package/services/chain-service/handler/EvmApi.js +12 -21
  67. package/services/chain-service/handler/SubstrateChainHandler.d.ts +2 -0
  68. package/services/chain-service/handler/SubstrateChainHandler.js +29 -0
  69. package/services/chain-service/index.d.ts +2 -0
  70. package/services/chain-service/index.js +45 -14
  71. package/services/chain-service/types.d.ts +2 -1
  72. package/services/chain-service/utils/index.d.ts +3 -0
  73. package/services/chain-service/utils/index.js +14 -0
  74. package/services/earning-service/handlers/base.d.ts +2 -0
  75. package/services/earning-service/handlers/base.js +9 -0
  76. package/services/earning-service/handlers/native-staking/amplitude.js +10 -2
  77. package/services/earning-service/handlers/native-staking/para-chain.js +2 -0
  78. package/services/earning-service/handlers/native-staking/relay-chain.js +2 -0
  79. package/services/earning-service/handlers/native-staking/tao.d.ts +4 -0
  80. package/services/earning-service/handlers/native-staking/tao.js +5 -1
  81. package/services/earning-service/handlers/nomination-pool/index.d.ts +1 -1
  82. package/services/earning-service/handlers/nomination-pool/index.js +9 -4
  83. package/services/earning-service/service.d.ts +2 -0
  84. package/services/earning-service/service.js +5 -0
  85. package/services/inapp-notification-service/consts.d.ts +18 -0
  86. package/services/inapp-notification-service/consts.js +22 -0
  87. package/services/inapp-notification-service/index.d.ts +37 -0
  88. package/services/inapp-notification-service/index.js +252 -0
  89. package/services/inapp-notification-service/interfaces.d.ts +77 -0
  90. package/services/inapp-notification-service/interfaces.js +24 -0
  91. package/services/inapp-notification-service/utils.d.ts +55 -0
  92. package/services/inapp-notification-service/utils.js +173 -0
  93. package/services/keyring-service/context/account-context.d.ts +3 -0
  94. package/services/keyring-service/context/account-context.js +9 -0
  95. package/services/keyring-service/context/state.d.ts +1 -0
  96. package/services/keyring-service/context/state.js +4 -0
  97. package/services/setting-service/SettingService.js +9 -1
  98. package/services/setting-service/constants.d.ts +2 -0
  99. package/services/setting-service/constants.js +15 -0
  100. package/services/storage-service/DatabaseService.d.ts +15 -0
  101. package/services/storage-service/DatabaseService.js +42 -3
  102. package/services/storage-service/databases/index.d.ts +2 -0
  103. package/services/storage-service/databases/index.js +3 -0
  104. package/services/storage-service/db-stores/InappNotification.d.ts +14 -0
  105. package/services/storage-service/db-stores/InappNotification.js +73 -0
  106. package/services/transaction-service/index.js +13 -0
  107. package/types/avail-bridge/index.d.ts +6 -0
  108. package/types/avail-bridge/index.js +1 -0
  109. package/types/notification/index.d.ts +9 -0
  110. package/types/notification/index.js +1 -0
  111. package/utils/account/transform.js +9 -5
  112. package/utils/staticData/index.d.ts +5 -1
  113. package/utils/staticData/index.js +5 -2
  114. package/utils/staticData/remindNotificationTime.json +1 -0
@@ -0,0 +1,186 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { COMMON_CHAIN_SLUGS } from '@subwallet/chain-list';
5
+ import { getWeb3Contract } from '@subwallet/extension-base/koni/api/contract-handler/evm/web3';
6
+ import { _AVAIL_BRIDGE_GATEWAY_ABI, _AVAIL_TEST_BRIDGE_GATEWAY_ABI, getAvailBridgeGatewayContract } from '@subwallet/extension-base/koni/api/contract-handler/utils';
7
+ import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils';
8
+ import { AVAIL_BRIDGE_API } from '@subwallet/extension-base/services/inapp-notification-service/utils';
9
+ import { decodeAddress } from '@subwallet/keyring';
10
+ import { u8aToHex } from '@polkadot/util';
11
+ export const AvailBridgeConfig = {
12
+ ASSET_ID: '0x0000000000000000000000000000000000000000000000000000000000000000',
13
+ ETHEREUM_DOMAIN: 2,
14
+ // todo: check if these config can change later
15
+ AVAIL_DOMAIN: 1
16
+ };
17
+ export async function getAvailBridgeTxFromEth(originChainInfo, sender, recipient, value, evmApi) {
18
+ var _priority$maxFeePerGa, _priority$maxPriority;
19
+ const availBridgeContractAddress = getAvailBridgeGatewayContract(originChainInfo.slug);
20
+ const ABI = getAvailBridgeAbi(originChainInfo.slug);
21
+ const availBridgeContract = getWeb3Contract(availBridgeContractAddress, evmApi, ABI);
22
+ const _address = u8aToHex(decodeAddress(recipient));
23
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
24
+ const sendAvail = availBridgeContract.methods.sendAVAIL(_address, value);
25
+ const transferData = sendAvail.encodeABI();
26
+ const priority = await calculateGasFeeParams(evmApi, evmApi.chainSlug);
27
+ const gasLimit = await sendAvail.estimateGas({
28
+ from: sender
29
+ });
30
+ return {
31
+ from: sender,
32
+ to: availBridgeContractAddress,
33
+ value: '0',
34
+ data: transferData,
35
+ gasPrice: priority.gasPrice,
36
+ maxFeePerGas: (_priority$maxFeePerGa = priority.maxFeePerGas) === null || _priority$maxFeePerGa === void 0 ? void 0 : _priority$maxFeePerGa.toString(),
37
+ maxPriorityFeePerGas: (_priority$maxPriority = priority.maxPriorityFeePerGas) === null || _priority$maxPriority === void 0 ? void 0 : _priority$maxPriority.toString(),
38
+ gas: gasLimit
39
+ };
40
+ }
41
+ export async function getAvailBridgeExtrinsicFromAvail(recipient, sendingValue, substrateApi) {
42
+ const data = {
43
+ message: {
44
+ FungibleToken: {
45
+ assetId: AvailBridgeConfig.ASSET_ID,
46
+ amount: BigInt(sendingValue)
47
+ }
48
+ },
49
+ to: `${recipient.padEnd(66, '0')}`,
50
+ domain: AvailBridgeConfig.ETHEREUM_DOMAIN
51
+ };
52
+ const chainApi = await substrateApi.isReady;
53
+ return chainApi.api.tx.vector.sendMessage(data.message, data.to, data.domain);
54
+ }
55
+ export async function getClaimTxOnAvail(notification, substrateApi) {
56
+ const chainApi = await substrateApi.isReady;
57
+ const chainSlug = chainApi.chainSlug;
58
+ const metadata = notification.metadata;
59
+ const lastestEthHeadSlot = await getLastestEthHeadSlot(chainSlug);
60
+ const lastestBlockHash = await getLastestBlockHash(chainSlug, lastestEthHeadSlot);
61
+ const proof = await getClaimProofOnAvail(chainSlug, lastestBlockHash, metadata.messageId);
62
+ return chainApi.api.tx.vector.execute(lastestEthHeadSlot, getAddressMessage(notification), proof.accountProof, proof.storageProof);
63
+ }
64
+ async function getLastestEthHeadSlot(chainSlug) {
65
+ try {
66
+ const api = getAvailBridgeApi(chainSlug);
67
+ const rawResponse = await fetch(`${api}/eth/head`);
68
+ const response = await rawResponse.json();
69
+ return response.slot;
70
+ } catch (e) {
71
+ console.error(e);
72
+ throw e;
73
+ }
74
+ }
75
+ async function getLastestBlockHash(chainSlug, slot) {
76
+ try {
77
+ const api = getAvailBridgeApi(chainSlug);
78
+ const rawResponse = await fetch(`${api}/beacon/slot/${slot}`);
79
+ const response = await rawResponse.json();
80
+ return response.blockHash;
81
+ } catch (e) {
82
+ console.error(e);
83
+ throw e;
84
+ }
85
+ }
86
+ async function getClaimProofOnAvail(chainSlug, blockHash, messageId) {
87
+ try {
88
+ const api = getAvailBridgeApi(chainSlug);
89
+ const rawResponse = await fetch(`${api}/avl/proof/${blockHash}/${messageId}`);
90
+ return await rawResponse.json();
91
+ } catch (e) {
92
+ console.error(e);
93
+ throw e;
94
+ }
95
+ }
96
+ async function getClaimProofOnEthereum(chainSlug, blockHash, transactionIndex) {
97
+ try {
98
+ const api = getAvailBridgeApi(chainSlug);
99
+ const rawResponse = await fetch(`${api}/eth/proof/${blockHash}?index=${transactionIndex}`);
100
+ return await rawResponse.json();
101
+ } catch (e) {
102
+ console.error(e);
103
+ throw e;
104
+ }
105
+ }
106
+ function getAvailBridgeApi(chainSlug) {
107
+ if (chainSlug === 'avail_mainnet' || chainSlug === COMMON_CHAIN_SLUGS.ETHEREUM) {
108
+ // todo: add COMMON_CHAIN_SLUGS for AVAIL, AVAIL TURING
109
+ return AVAIL_BRIDGE_API.AVAIL_MAINNET;
110
+ }
111
+ return AVAIL_BRIDGE_API.AVAIL_TESTNET;
112
+ }
113
+ export async function getClaimTxOnEthereum(chainSlug, notification, evmApi) {
114
+ var _priority$maxFeePerGa2, _priority$maxPriority2;
115
+ const availBridgeContractAddress = getAvailBridgeGatewayContract(chainSlug);
116
+ const ABI = getAvailBridgeAbi(chainSlug);
117
+ const availBridgeContract = getWeb3Contract(availBridgeContractAddress, evmApi, ABI);
118
+ const metadata = notification.metadata;
119
+ const merkleProof = await getClaimProofOnEthereum(chainSlug, metadata.sourceBlockHash, metadata.sourceTransactionIndex);
120
+
121
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
122
+ const transfer = availBridgeContract.methods.receiveAVAIL({
123
+ messageType: '0x02',
124
+ from: merkleProof.message.from,
125
+ to: merkleProof.message.to,
126
+ originDomain: merkleProof.message.originDomain,
127
+ destinationDomain: merkleProof.message.destinationDomain,
128
+ data: evmApi.api.eth.abi.encodeParameters([{
129
+ name: 'assetId',
130
+ type: 'bytes32'
131
+ }, {
132
+ name: 'amount',
133
+ type: 'uint256'
134
+ }], [merkleProof.message.message.fungibleToken.asset_id, BigInt(merkleProof.message.message.fungibleToken.amount)]),
135
+ messageId: merkleProof.message.id
136
+ }, {
137
+ dataRootProof: merkleProof.dataRootProof,
138
+ leafProof: merkleProof.leafProof,
139
+ rangeHash: merkleProof.rangeHash,
140
+ dataRootIndex: merkleProof.dataRootIndex,
141
+ blobRoot: merkleProof.blobRoot,
142
+ bridgeRoot: merkleProof.bridgeRoot,
143
+ leaf: merkleProof.leaf,
144
+ leafIndex: merkleProof.leafIndex
145
+ });
146
+ const transferData = transfer.encodeABI();
147
+ const gasLimit = await transfer.estimateGas({
148
+ from: metadata.receiverAddress
149
+ });
150
+ const priority = await calculateGasFeeParams(evmApi, evmApi.chainSlug);
151
+ return {
152
+ from: metadata.receiverAddress,
153
+ to: availBridgeContractAddress,
154
+ value: '0',
155
+ data: transferData,
156
+ gasPrice: priority.gasPrice,
157
+ maxFeePerGas: (_priority$maxFeePerGa2 = priority.maxFeePerGas) === null || _priority$maxFeePerGa2 === void 0 ? void 0 : _priority$maxFeePerGa2.toString(),
158
+ maxPriorityFeePerGas: (_priority$maxPriority2 = priority.maxPriorityFeePerGas) === null || _priority$maxPriority2 === void 0 ? void 0 : _priority$maxPriority2.toString(),
159
+ gas: gasLimit
160
+ };
161
+ }
162
+ function getAddressMessage(notification) {
163
+ const metadata = notification.metadata;
164
+ return {
165
+ message: {
166
+ FungibleToken: {
167
+ assetId: AvailBridgeConfig.ASSET_ID,
168
+ amount: metadata.amount
169
+ }
170
+ },
171
+ from: `${metadata.depositorAddress.padEnd(66, '0')}`,
172
+ to: u8aToHex(decodeAddress(metadata.receiverAddress)),
173
+ originDomain: AvailBridgeConfig.ETHEREUM_DOMAIN,
174
+ destinationDomain: AvailBridgeConfig.AVAIL_DOMAIN,
175
+ id: metadata.messageId
176
+ };
177
+ }
178
+ function getAvailBridgeAbi(chainSlug) {
179
+ if (chainSlug === COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA) {
180
+ return _AVAIL_TEST_BRIDGE_GATEWAY_ABI;
181
+ }
182
+ return _AVAIL_BRIDGE_GATEWAY_ABI;
183
+ }
184
+ export function isAvailChainBridge(chainSlug) {
185
+ return ['avail_mainnet', 'availTuringTest'].includes(chainSlug);
186
+ }
@@ -3,19 +3,19 @@ import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain
3
3
  import BigN from 'bignumber.js';
4
4
  import { TransactionConfig } from 'web3-core';
5
5
  import { SubmittableExtrinsic } from '@polkadot/api/types';
6
- declare type CreateXcmExtrinsicProps = {
6
+ export declare type CreateXcmExtrinsicProps = {
7
7
  originTokenInfo: _ChainAsset;
8
8
  destinationTokenInfo: _ChainAsset;
9
9
  recipient: string;
10
10
  sendingValue: string;
11
- substrateApi: _SubstrateApi;
11
+ evmApi?: _EvmApi;
12
+ substrateApi?: _SubstrateApi;
12
13
  chainInfoMap: Record<string, _ChainInfo>;
14
+ sender?: string;
13
15
  };
14
- declare type CreateSnowBridgeExtrinsicProps = Omit<CreateXcmExtrinsicProps, 'substrateApi'> & {
15
- evmApi: _EvmApi;
16
- sender: string;
17
- };
18
- export declare const createSnowBridgeExtrinsic: ({ chainInfoMap, destinationTokenInfo, evmApi, originTokenInfo, recipient, sender, sendingValue }: CreateSnowBridgeExtrinsicProps) => Promise<TransactionConfig>;
16
+ export declare type FunctionCreateXcmExtrinsic = (props: CreateXcmExtrinsicProps) => Promise<SubmittableExtrinsic<'promise'> | TransactionConfig>;
17
+ export declare const createSnowBridgeExtrinsic: ({ chainInfoMap, destinationTokenInfo, evmApi, originTokenInfo, recipient, sender, sendingValue }: CreateXcmExtrinsicProps) => Promise<TransactionConfig>;
19
18
  export declare const createXcmExtrinsic: ({ chainInfoMap, destinationTokenInfo, originTokenInfo, recipient, sendingValue, substrateApi }: CreateXcmExtrinsicProps) => Promise<SubmittableExtrinsic<'promise'>>;
19
+ export declare const createAvailBridgeTxFromEth: ({ chainInfoMap, evmApi, originTokenInfo, recipient, sender, sendingValue }: CreateXcmExtrinsicProps) => Promise<TransactionConfig>;
20
+ export declare const createAvailBridgeExtrinsicFromAvail: ({ recipient, sendingValue, substrateApi }: CreateXcmExtrinsicProps) => Promise<SubmittableExtrinsic<'promise'>>;
20
21
  export declare const getXcmMockTxFee: (substrateApi: _SubstrateApi, chainInfoMap: Record<string, _ChainInfo>, originTokenInfo: _ChainAsset, destinationTokenInfo: _ChainAsset) => Promise<BigN>;
21
- export {};
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
5
+ import { getAvailBridgeExtrinsicFromAvail, getAvailBridgeTxFromEth } from '@subwallet/extension-base/services/balance-service/transfer/xcm/availBridge';
5
6
  import { getExtrinsicByPolkadotXcmPallet } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polkadotXcm';
6
7
  import { getSnowBridgeEvmTransfer } from '@subwallet/extension-base/services/balance-service/transfer/xcm/snowBridge';
7
8
  import { getExtrinsicByXcmPalletPallet } from '@subwallet/extension-base/services/balance-service/transfer/xcm/xcmPallet';
@@ -10,7 +11,7 @@ import { _XCM_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-servi
10
11
  import { _isChainEvmCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
11
12
  import BigN from 'bignumber.js';
12
13
  import { u8aToHex } from '@polkadot/util';
13
- import { addressToEvm, isEthereumAddress } from '@polkadot/util-crypto';
14
+ import { addressToEvm } from '@polkadot/util-crypto';
14
15
  export const createSnowBridgeExtrinsic = async ({
15
16
  chainInfoMap,
16
17
  destinationTokenInfo,
@@ -25,6 +26,12 @@ export const createSnowBridgeExtrinsic = async ({
25
26
  if (!_isSnowBridgeXcm(originChainInfo, destinationChainInfo)) {
26
27
  throw new Error('This is not a valid SnowBridge transfer');
27
28
  }
29
+ if (!evmApi) {
30
+ throw Error('Evm API is not available');
31
+ }
32
+ if (!sender) {
33
+ throw Error('Sender is required');
34
+ }
28
35
  return getSnowBridgeEvmTransfer(originTokenInfo, originChainInfo, destinationChainInfo, sender, recipient, sendingValue, evmApi);
29
36
  };
30
37
  export const createXcmExtrinsic = async ({
@@ -37,6 +44,9 @@ export const createXcmExtrinsic = async ({
37
44
  }) => {
38
45
  const originChainInfo = chainInfoMap[originTokenInfo.originChain];
39
46
  const destinationChainInfo = chainInfoMap[destinationTokenInfo.originChain];
47
+ if (!substrateApi) {
48
+ throw Error('Substrate API is not available');
49
+ }
40
50
  const chainApi = await substrateApi.isReady;
41
51
  const api = chainApi.api;
42
52
  const polkadotXcmSpecialCases = _XCM_CHAIN_GROUP.polkadotXcmSpecialCases.includes(originChainInfo.slug) && _isNativeToken(originTokenInfo);
@@ -48,24 +58,55 @@ export const createXcmExtrinsic = async ({
48
58
  }
49
59
  return getExtrinsicByXtokensPallet(originTokenInfo, originChainInfo, destinationChainInfo, recipient, sendingValue, api);
50
60
  };
61
+ export const createAvailBridgeTxFromEth = ({
62
+ chainInfoMap,
63
+ evmApi,
64
+ originTokenInfo,
65
+ recipient,
66
+ sender,
67
+ sendingValue
68
+ }) => {
69
+ const originChainInfo = chainInfoMap[originTokenInfo.originChain];
70
+ if (!evmApi) {
71
+ throw Error('Evm API is not available');
72
+ }
73
+ if (!sender) {
74
+ throw Error('Sender is required');
75
+ }
76
+ return getAvailBridgeTxFromEth(originChainInfo, sender, recipient, sendingValue, evmApi);
77
+ };
78
+ export const createAvailBridgeExtrinsicFromAvail = async ({
79
+ recipient,
80
+ sendingValue,
81
+ substrateApi
82
+ }) => {
83
+ if (!substrateApi) {
84
+ throw Error('Substrate API is not available');
85
+ }
86
+ return await getAvailBridgeExtrinsicFromAvail(recipient, sendingValue, substrateApi);
87
+ };
51
88
  export const getXcmMockTxFee = async (substrateApi, chainInfoMap, originTokenInfo, destinationTokenInfo) => {
52
89
  try {
53
90
  var _paymentInfo$partialF;
54
91
  const destChainInfo = chainInfoMap[destinationTokenInfo.originChain];
55
92
  const originChainInfo = chainInfoMap[originTokenInfo.originChain];
56
- const address = '5DRewsYzhJqZXU3SRaWy1FSt5iDr875ao91aw5fjrJmDG4Ap'; // todo: move this
93
+ const fakeAddress = '5DRewsYzhJqZXU3SRaWy1FSt5iDr875ao91aw5fjrJmDG4Ap'; // todo: move this
94
+ const substrateAddress = fakeAddress; // todo: move this
95
+ const evmAddress = u8aToHex(addressToEvm(fakeAddress)); // todo: move this
57
96
 
58
97
  // mock receiving account from sender
59
- const recipient = !isEthereumAddress(address) && _isChainEvmCompatible(destChainInfo) && !_isChainEvmCompatible(originChainInfo) ? u8aToHex(addressToEvm(address)) : address;
98
+ const sender = _isChainEvmCompatible(originChainInfo) ? evmAddress : substrateAddress;
99
+ const recipient = _isChainEvmCompatible(destChainInfo) ? evmAddress : substrateAddress;
60
100
  const mockTx = await createXcmExtrinsic({
61
101
  chainInfoMap,
62
102
  destinationTokenInfo,
63
103
  originTokenInfo,
64
- recipient: recipient,
104
+ sender,
105
+ recipient,
65
106
  sendingValue: '1000000000000000000',
66
107
  substrateApi
67
108
  });
68
- const paymentInfo = await mockTx.paymentInfo(address);
109
+ const paymentInfo = await mockTx.paymentInfo(fakeAddress);
69
110
  return new BigN((paymentInfo === null || paymentInfo === void 0 ? void 0 : (_paymentInfo$partialF = paymentInfo.partialFee) === null || _paymentInfo$partialF === void 0 ? void 0 : _paymentInfo$partialF.toString()) || '0');
70
111
  } catch (e) {
71
112
  console.error('error mocking xcm tx fee', e);
@@ -72,15 +72,11 @@ export class EvmApi {
72
72
  createIntervalCheckApi() {
73
73
  this.clearIntervalCheckApi();
74
74
  return setInterval(() => {
75
- if (!this.ignoreNetListen) {
76
- this.api.eth.net.isListening().then(() => {
77
- this.onConnect();
78
- }).catch(() => {
79
- this.onDisconnect();
80
- });
81
- } else {
75
+ this.api.eth.getChainId().then(() => {
82
76
  this.onConnect();
83
- }
77
+ }).catch(() => {
78
+ this.onDisconnect();
79
+ });
84
80
  }, 10000);
85
81
  }
86
82
  clearIntervalCheckApi() {
@@ -93,21 +89,16 @@ export class EvmApi {
93
89
  this.updateConnectionStatus(_ChainConnectionStatus.CONNECTING);
94
90
 
95
91
  // Check if api is ready
96
- if (!this.ignoreNetListen) {
97
- this.api.eth.net.isListening().then(() => {
98
- this.isApiReadyOnce = true;
99
- this.onConnect();
100
- }).catch(error => {
101
- this.isApiReadyOnce = false;
102
- this.isApiReady = false;
103
- this.isReadyHandler.reject(error);
104
- this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
105
- console.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`);
106
- });
107
- } else {
92
+ this.api.eth.getChainId().then(() => {
108
93
  this.isApiReadyOnce = true;
109
94
  this.onConnect();
110
- }
95
+ }).catch(error => {
96
+ this.isApiReadyOnce = false;
97
+ this.isApiReady = false;
98
+ this.isReadyHandler.reject(error);
99
+ this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
100
+ console.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`);
101
+ });
111
102
 
112
103
  // Interval to check connecting status
113
104
  this.intervalCheckApi = this.createIntervalCheckApi();
@@ -19,7 +19,9 @@ export declare class SubstrateChainHandler extends AbstractChainHandler {
19
19
  private getPsp34TokenInfo;
20
20
  private getGrc20TokenInfo;
21
21
  private getVftTokenInfo;
22
+ private getLocalTokenInfo;
22
23
  getSubstrateContractTokenInfo(contractAddress: string, tokenType: _AssetType, originChain: string, contractCaller?: string): Promise<_SmartContractTokenInfo>;
24
+ getSubstrateAssetIdTokenInfo(assetId: string, originChain: string): Promise<_SmartContractTokenInfo>;
23
25
  setSubstrateApi(chainSlug: string, substrateApi: _SubstrateApi): void;
24
26
  destroySubstrateApi(chainSlug: string): void;
25
27
  initApi(chainSlug: string, apiUrl: string, { externalApiPromise, onUpdateStatus, providerName }?: Omit<_ApiOptions, 'metadata'>): Promise<_SubstrateApi>;
@@ -179,6 +179,15 @@ export class SubstrateChainHandler extends AbstractChainHandler {
179
179
  }
180
180
  return [nameRes, decimals, symbolRes, contractError];
181
181
  }
182
+ async getLocalTokenInfo(apiPromise, assetId) {
183
+ const _metadata = await apiPromise.query.assets.metadata(assetId);
184
+ const metadata = _metadata.toPrimitive();
185
+ let idError = false;
186
+ if (!metadata.name || !metadata.symbol) {
187
+ idError = true;
188
+ }
189
+ return [metadata.name, metadata.decimals, metadata.symbol, idError];
190
+ }
182
191
  async getSubstrateContractTokenInfo(contractAddress, tokenType, originChain, contractCaller) {
183
192
  // todo: improve this funtion later
184
193
 
@@ -218,6 +227,26 @@ export class SubstrateChainHandler extends AbstractChainHandler {
218
227
  };
219
228
  }
220
229
  }
230
+ async getSubstrateAssetIdTokenInfo(assetId, originChain) {
231
+ const apiPromise = this.getSubstrateApiByChain(originChain).api;
232
+ try {
233
+ const [name, decimals, symbol, contractError] = await this.getLocalTokenInfo(apiPromise, assetId);
234
+ return {
235
+ name,
236
+ decimals,
237
+ symbol,
238
+ contractError
239
+ };
240
+ } catch (e) {
241
+ this.logger.error(e);
242
+ return {
243
+ name: '',
244
+ decimals: -1,
245
+ symbol: '',
246
+ contractError: true
247
+ };
248
+ }
249
+ }
221
250
  setSubstrateApi(chainSlug, substrateApi) {
222
251
  this.substrateApiMap[chainSlug] = substrateApi;
223
252
  }
@@ -63,6 +63,7 @@ export declare class ChainService {
63
63
  getAssetRegistry(): Record<string, _ChainAsset>;
64
64
  getMultiChainAssetMap(): Record<string, _MultiChainAsset>;
65
65
  getSmartContractTokens(): Record<string, _ChainAsset>;
66
+ getAssetHubToken(): Record<string, _ChainAsset>;
66
67
  getChainInfoMap(): Record<string, _ChainInfo>;
67
68
  getEvmChainInfoMap(): Record<string, _ChainInfo>;
68
69
  getSubstrateChainInfoMap(): Record<string, _ChainInfo>;
@@ -131,6 +132,7 @@ export declare class ChainService {
131
132
  private getChainSpecByProvider;
132
133
  private validateProvider;
133
134
  private getSmartContractTokenInfo;
135
+ private getAssetIdTokenInfo;
134
136
  validateCustomToken(data: _ValidateCustomAssetRequest): Promise<_ValidateCustomAssetResponse>;
135
137
  private generateSlugForSmartContractAsset;
136
138
  private generateSlugForNativeToken;
@@ -10,7 +10,7 @@ import { SubstrateChainHandler } from '@subwallet/extension-base/services/chain-
10
10
  import { TonChainHandler } from '@subwallet/extension-base/services/chain-service/handler/TonChainHandler';
11
11
  import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types';
12
12
  import { _ChainConnectionStatus, _CUSTOM_PREFIX, _NFT_CONTRACT_STANDARDS, _SMART_CONTRACT_STANDARDS } from '@subwallet/extension-base/services/chain-service/types';
13
- import { _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, fetchPatchData, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
13
+ import { _isAssetAutoEnable, _isAssetCanPayTxFee, _isAssetFungibleToken, _isChainEnabled, _isCustomAsset, _isCustomChain, _isCustomProvider, _isEqualContractAddress, _isEqualSmartContractAsset, _isLocalToken, _isMantaZkAsset, _isPureEvmChain, _isPureSubstrateChain, _parseAssetRefKey, fetchPatchData, randomizeProvider, updateLatestChainInfo } from '@subwallet/extension-base/services/chain-service/utils';
14
14
  import AssetSettingStore from '@subwallet/extension-base/stores/AssetSetting';
15
15
  import { addLazy, calculateMetadataHash, fetchStaticData, filterAssetsByChainAndType, getShortMetadata, MODULE_SUPPORT } from '@subwallet/extension-base/utils';
16
16
  import { BehaviorSubject, Subject } from 'rxjs';
@@ -186,6 +186,15 @@ export class ChainService {
186
186
  });
187
187
  return filteredAssetRegistry;
188
188
  }
189
+ getAssetHubToken() {
190
+ const assetHubToken = {};
191
+ Object.values(this.getAssetRegistry()).forEach(asset => {
192
+ if (['statemint', 'statemine'].includes(asset.originChain)) {
193
+ assetHubToken[asset.slug] = asset;
194
+ }
195
+ });
196
+ return assetHubToken;
197
+ }
189
198
  getChainInfoMap() {
190
199
  return this.dataMap.chainInfoMap;
191
200
  }
@@ -435,7 +444,7 @@ export class ChainService {
435
444
  upsertCustomToken(token) {
436
445
  if (token.slug.length === 0) {
437
446
  // new token
438
- if (token.assetType === _AssetType.NATIVE) {
447
+ if (token.assetType === _AssetType.NATIVE || token.assetType === _AssetType.LOCAL) {
439
448
  const defaultSlug = this.generateSlugForNativeToken(token.originChain, token.assetType, token.symbol);
440
449
  token.slug = `${_CUSTOM_PREFIX}${defaultSlug}`;
441
450
  } else {
@@ -444,7 +453,7 @@ export class ChainService {
444
453
  token.slug = `${_CUSTOM_PREFIX}${defaultSlug}`;
445
454
  }
446
455
  }
447
- if (token.originChain && _isAssetFungibleToken(token)) {
456
+ if (token.originChain && (_isAssetFungibleToken(token) || _isLocalToken(token))) {
448
457
  var _this$getChainInfoByK;
449
458
  token.hasValue = !((_this$getChainInfoByK = this.getChainInfoByKey(token.originChain)) !== null && _this$getChainInfoByK !== void 0 && _this$getChainInfoByK.isTestnet);
450
459
  }
@@ -1510,13 +1519,35 @@ export class ChainService {
1510
1519
  contractError: false
1511
1520
  };
1512
1521
  }
1522
+ async getAssetIdTokenInfo(assetId, tokenType, chain) {
1523
+ if ([_AssetType.LOCAL].includes(tokenType) && assetId) {
1524
+ return await this.substrateChainHandler.getSubstrateAssetIdTokenInfo(assetId, chain);
1525
+ }
1526
+ return {
1527
+ decimals: -1,
1528
+ name: '',
1529
+ symbol: '',
1530
+ contractError: false
1531
+ };
1532
+ }
1513
1533
  async validateCustomToken(data) {
1514
1534
  const assetRegistry = this.getSmartContractTokens();
1535
+ const asset = this.getAssetHubToken();
1515
1536
  let existedToken;
1516
1537
  for (const token of Object.values(assetRegistry)) {
1517
1538
  var _token$metadata2;
1518
1539
  const contractAddress = token === null || token === void 0 ? void 0 : (_token$metadata2 = token.metadata) === null || _token$metadata2 === void 0 ? void 0 : _token$metadata2.contractAddress;
1519
- if (_isEqualContractAddress(contractAddress, data.contractAddress) && token.assetType === data.type && token.originChain === data.originChain) {
1540
+ if (data.contractAddress) {
1541
+ if (_isEqualContractAddress(contractAddress, data.contractAddress) && token.assetType === data.type && token.originChain === data.originChain) {
1542
+ existedToken = token;
1543
+ break;
1544
+ }
1545
+ }
1546
+ }
1547
+ for (const token of Object.values(asset)) {
1548
+ var _token$metadata3;
1549
+ const assetId = token === null || token === void 0 ? void 0 : (_token$metadata3 = token.metadata) === null || _token$metadata3 === void 0 ? void 0 : _token$metadata3.assetId;
1550
+ if (assetId === data.assetId && token.assetType === data.type && token.originChain === data.originChain) {
1520
1551
  existedToken = token;
1521
1552
  break;
1522
1553
  }
@@ -1532,18 +1563,18 @@ export class ChainService {
1532
1563
  contractError: false
1533
1564
  };
1534
1565
  }
1535
- const {
1536
- contractError,
1537
- decimals,
1538
- name,
1539
- symbol
1540
- } = await this.getSmartContractTokenInfo(data.contractAddress, data.type, data.originChain, data.contractCaller);
1566
+ let info;
1567
+ if (data.contractAddress) {
1568
+ info = await this.getSmartContractTokenInfo(data.contractAddress, data.type, data.originChain, data.contractCaller);
1569
+ } else {
1570
+ info = await this.getAssetIdTokenInfo(data.assetId, data.type, data.originChain);
1571
+ }
1541
1572
  return {
1542
- name,
1543
- decimals,
1544
- symbol,
1573
+ name: info.name,
1574
+ decimals: info.decimals,
1575
+ symbol: info.symbol,
1545
1576
  isExist: !!existedToken,
1546
- contractError
1577
+ contractError: info.contractError
1547
1578
  };
1548
1579
  }
1549
1580
  generateSlugForSmartContractAsset(originChain, assetType, symbol, contractAddress) {
@@ -160,10 +160,11 @@ export interface EnableMultiChainParams {
160
160
  enableTokens?: boolean;
161
161
  }
162
162
  export interface _ValidateCustomAssetRequest {
163
- contractAddress: string;
163
+ contractAddress?: string;
164
164
  originChain: string;
165
165
  type: _AssetType;
166
166
  contractCaller?: string;
167
+ assetId?: string;
167
168
  }
168
169
  export interface _SmartContractTokenInfo {
169
170
  name: string;
@@ -53,6 +53,8 @@ export declare function _isChainSupportEvmNft(chainInfo: _ChainInfo): boolean;
53
53
  export declare function _isChainSupportWasmNft(chainInfo: _ChainInfo): boolean;
54
54
  export declare function _isChainSupportEvmERC20(chainInfo: _ChainInfo): boolean;
55
55
  export declare function _isChainSupportWasmPSP22(chainInfo: _ChainInfo): boolean;
56
+ export declare function _isAssetHubChain(chainInfo: _ChainInfo): boolean;
57
+ export declare function _isAssetHubToken(token: _ChainAsset): boolean;
56
58
  export declare function _isChainSupportGRC20(chainInfo: _ChainInfo): boolean;
57
59
  export declare function _isChainSupportVFT(chainInfo: _ChainInfo): boolean;
58
60
  export declare const _isSupportOrdinal: (chain: string) => boolean;
@@ -88,6 +90,7 @@ export declare function _getChainName(chainInfo?: _ChainInfo): string;
88
90
  export declare function _getAssetDecimals(assetInfo?: _ChainAsset): number;
89
91
  export declare function _getBlockExplorerFromChain(chainInfo: _ChainInfo): string | undefined;
90
92
  export declare function _parseMetadataForSmartContractAsset(contractAddress: string): Record<string, string>;
93
+ export declare function _parseMetadataForAssetId(assetId: string): Record<string, string>;
91
94
  export declare function _isChainTestNet(chainInfo: _ChainInfo): boolean;
92
95
  export declare function _isAssetFungibleToken(chainAsset: _ChainAsset): boolean;
93
96
  export declare const _isAssetAutoEnable: (chainAsset: _ChainAsset) => boolean;
@@ -194,6 +194,12 @@ export function _isChainSupportWasmPSP22(chainInfo) {
194
194
  var _chainInfo$substrateI10, _chainInfo$substrateI11;
195
195
  return ((_chainInfo$substrateI10 = chainInfo.substrateInfo) === null || _chainInfo$substrateI10 === void 0 ? void 0 : (_chainInfo$substrateI11 = _chainInfo$substrateI10.supportSmartContract) === null || _chainInfo$substrateI11 === void 0 ? void 0 : _chainInfo$substrateI11.includes(_AssetType.PSP22)) || false;
196
196
  }
197
+ export function _isAssetHubChain(chainInfo) {
198
+ return ['statemint', 'statemine'].includes(chainInfo.slug);
199
+ }
200
+ export function _isAssetHubToken(token) {
201
+ return ['statemint', 'statemine'].includes(token.originChain);
202
+ }
197
203
  export function _isChainSupportGRC20(chainInfo) {
198
204
  var _chainInfo$substrateI12, _chainInfo$substrateI13;
199
205
  return ((_chainInfo$substrateI12 = chainInfo.substrateInfo) === null || _chainInfo$substrateI12 === void 0 ? void 0 : (_chainInfo$substrateI13 = _chainInfo$substrateI12.supportSmartContract) === null || _chainInfo$substrateI13 === void 0 ? void 0 : _chainInfo$substrateI13.includes(_AssetType.GRC20)) || false;
@@ -240,6 +246,9 @@ export function _getTokenTypesSupportedByChain(chainInfo) {
240
246
  }
241
247
  });
242
248
  }
249
+ if (['statemint', 'statemine'].includes(chainInfo.slug)) {
250
+ result.push(_AssetType.LOCAL);
251
+ }
243
252
  return result;
244
253
  }
245
254
  export function _getChainNativeTokenBasicInfo(chainInfo) {
@@ -393,6 +402,11 @@ export function _parseMetadataForSmartContractAsset(contractAddress) {
393
402
  contractAddress
394
403
  };
395
404
  }
405
+ export function _parseMetadataForAssetId(assetId) {
406
+ return {
407
+ assetId
408
+ };
409
+ }
396
410
  export function _isChainTestNet(chainInfo) {
397
411
  return chainInfo.isTestnet || false;
398
412
  }
@@ -45,6 +45,8 @@ export default abstract class BasePoolHandler {
45
45
  protected abstract getDescription(amount?: string): string;
46
46
  protected get maintainBalance(): string;
47
47
  get metadataInfo(): Omit<BaseYieldPoolMetadata, 'description'>;
48
+ createWithdrawNotifications(unstakingInfos: UnstakingInfo[], tokenInfo: _ChainAsset, address: string): Promise<void>;
49
+ createClaimNotification(claimItemInfo: EarningRewardItem, tokenInfo: _ChainAsset): Promise<void>;
48
50
  /** Can mint when haven't enough native token (use input token for fee) */
49
51
  get isPoolSupportAlternativeFee(): boolean;
50
52
  getPoolInfo(): Promise<YieldPoolInfo | undefined>;
@@ -4,6 +4,7 @@
4
4
  import { ChainType } from '@subwallet/extension-base/background/KoniTypes';
5
5
  import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
6
6
  import { DEFAULT_YIELD_FIRST_STEP } from '@subwallet/extension-base/services/earning-service/constants';
7
+ import { createClaimNotification, createWithdrawNotifications } from '@subwallet/extension-base/services/inapp-notification-service/utils';
7
8
  import { formatNumber, reformatAddress } from '@subwallet/extension-base/utils';
8
9
  import { BN, BN_TEN } from '@polkadot/util';
9
10
 
@@ -93,6 +94,14 @@ export default class BasePoolHandler {
93
94
  availableMethod: this.availableMethod
94
95
  };
95
96
  }
97
+ async createWithdrawNotifications(unstakingInfos, tokenInfo, address) {
98
+ const notifications = createWithdrawNotifications(unstakingInfos, tokenInfo, address, this.baseInfo.slug, this.type);
99
+ await this.state.inappNotificationService.validateAndWriteNotificationsToDB(notifications, address);
100
+ }
101
+ async createClaimNotification(claimItemInfo, tokenInfo) {
102
+ const notification = createClaimNotification(claimItemInfo, tokenInfo);
103
+ await this.state.inappNotificationService.validateAndWriteNotificationsToDB([notification], claimItemInfo.address);
104
+ }
96
105
 
97
106
  /** Can mint when haven't enough native token (use input token for fee) */
98
107
  get isPoolSupportAlternativeFee() {