diff --git a/README.md b/README.md index 0d072f6..d8c1e49 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,14 @@ 1. **No backend server, all data is stored locally by default** 2. Support Binance and OKX. How to create api key: [Binance](https://www.binance.com/en-BH/support/faq/how-to-create-api-360002502072), [OKX](https://use.autoview.com/hc/en-us/articles/360004576632-OKEx-Creating-an-API) -3. Support BTC, ETH, BNB, SOL and Doge. +3. Support BTC, ETH, BNB, SOL and Doge ( Base Users ). 4. Support dozens of charts to analyze data such as wallet proportion, proportion of each currency asset, changes, etc. 5. Support Cloud Sync, users can sync their data to cloud and restore it on another device. +## Pro Users + +1. Support 15+ ERC20 Chains: Ethereum, BSC, Polygon, Fantom, Arbitrum, Avalanche, Gnosis, Celo, OKC, Cronos, Optimism, Cardano, Terra 2.0, Cosmos, Osmosis, Base. + ## Installation [Download In Release Page](https://github.com/domechn/track3/releases) diff --git a/src/components/asset-change.tsx b/src/components/asset-change.tsx index 02b760f..0140ff4 100644 --- a/src/components/asset-change.tsx +++ b/src/components/asset-change.tsx @@ -38,7 +38,6 @@ const App = ({ autoSkip: false, labelOffset: -5, callback: function (val: number, index: number) { - console.log(index === 0 || index === _(data.timestamps).size() - 1); const total = _(data.timestamps).size() - 1; // only show start and end date diff --git a/src/middlelayers/configuration.ts b/src/middlelayers/configuration.ts index 34831ae..f1f8315 100644 --- a/src/middlelayers/configuration.ts +++ b/src/middlelayers/configuration.ts @@ -9,6 +9,7 @@ const prefix = "!ent:" const fixId = "1" const cloudSyncFixId = "2" const clientInfoFixId = "998" +const licenseFixId = "997" export async function getConfiguration(): Promise { const model = await getConfigurationById(fixId) @@ -120,3 +121,13 @@ async function getConfigurationModelById(id: string): Promise { + const model = await getConfigurationById(licenseFixId) + return model?.data +} diff --git a/src/middlelayers/data.ts b/src/middlelayers/data.ts index 7627a8e..09befb8 100644 --- a/src/middlelayers/data.ts +++ b/src/middlelayers/data.ts @@ -6,7 +6,7 @@ import { combineCoinLists } from './datafetch/utils/coins' import { DOGEAnalyzer } from './datafetch/coins/doge' import { OthersAnalyzer } from './datafetch/coins/others' import { SOLAnalyzer } from './datafetch/coins/sol' -import { ERC20Analyzer } from './datafetch/coins/erc20' +import { ERC20ProAnalyzer } from './datafetch/coins/erc20' import { CexAnalyzer } from './datafetch/coins/cex/cex' import { CacheCenter } from './datafetch/utils/cache' import { ASSETS_TABLE_NAME, queryHistoricalData } from './charts' @@ -39,7 +39,7 @@ export async function loadPortfolios(config: CexConfig & TokenConfig): Promise { - const anas = [ERC20Analyzer, CexAnalyzer, SOLAnalyzer, OthersAnalyzer, BTCAnalyzer, DOGEAnalyzer] + const anas = [ERC20ProAnalyzer, CexAnalyzer, SOLAnalyzer, OthersAnalyzer, BTCAnalyzer, DOGEAnalyzer] const coinLists = await bluebird.map(anas, async ana => { const a = new ana(config) diff --git a/src/middlelayers/datafetch/coins/erc20.ts b/src/middlelayers/datafetch/coins/erc20.ts index c56c550..6f5aeb7 100644 --- a/src/middlelayers/datafetch/coins/erc20.ts +++ b/src/middlelayers/datafetch/coins/erc20.ts @@ -5,6 +5,8 @@ import { sendHttpRequest } from '../utils/http' import { getAddressList } from '../utils/address' import bluebird from 'bluebird' import { invoke } from '@tauri-apps/api' +import { getLicenseIfIsPro } from '@/middlelayers/configuration' +import { getClientID } from '@/utils/app' type QueryAssetResp = { data: { @@ -112,8 +114,8 @@ class BscERC20Query extends DeBankERC20Query { } -export class ERC20Analyzer implements Analyzer { - private readonly config: Pick +export class ERC20NormalAnalyzer implements Analyzer { + protected readonly config: Pick private readonly queries = [new BscERC20Query(), new EthERC20Query()] private readonly errorResolver: DeBank429ErrorResolver = new DeBank429ErrorResolverImpl() @@ -174,3 +176,55 @@ export class ERC20Analyzer implements Analyzer { } } } + +export class ERC20ProAnalyzer extends ERC20NormalAnalyzer { + private readonly queryUrl = "https://track3-pro-api.domc.me/api/erc20/assetsBalances" + + constructor(config: Pick) { + super(config) + } + + async loadPortfolio(): Promise { + const license = await getLicenseIfIsPro() + + // if not pro license, use normal analyzer + if (!license) { + // return super.loadPortfolio() + console.debug("not pro license, fallback to normal erc20 analyzer") + return super.loadPortfolio() + } + + try { + const res = await this.loadPortfolioPro(license) + return res + } catch (e) { + // fallback to normal analyzer + console.error("failed to query pro erc20 assets, fallback to normal erc20 analyzer", e) + return super.loadPortfolio() + } + + } + + async loadPortfolioPro(license: string): Promise { + const wallets = getAddressList(this.config.erc20) + const resp = await sendHttpRequest<{ + data: { + wallet: string + assets: { + symbol: string + amount: number + }[] + }[] + }>("POST", this.queryUrl, 10000, { + "x-track3-client-id": await getClientID(), + 'x-track3-api-key': license + }, { + wallets, + }) + + return _(resp.data).map(d => _(d.assets).map(a => ({ + ...a, + wallet: d.wallet + })).value()).flatten().value() + } +}