diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 375af3b..479c5db 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -40,6 +40,7 @@ }, "devDependencies": { "@rollup/plugin-inject": "^5.0.5", + "@types/node": "^22.4.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/react-window": "^1.8.8", @@ -2964,11 +2965,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", - "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "version": "22.4.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.4.2.tgz", + "integrity": "sha512-nAvM3Ey230/XzxtyDcJ+VjvlzpzoHwLsF7JaDRfoI0ytO0mVheerNmM45CtA0yOILXwXXxOrcUWH3wltX+7PSw==", + "license": "MIT", "dependencies": { - "undici-types": "~6.13.0" + "undici-types": "~6.19.2" } }, "node_modules/@types/parse-json": { @@ -8235,9 +8237,10 @@ } }, "node_modules/undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, "node_modules/update-browserslist-db": { "version": "1.1.0", diff --git a/frontend/package.json b/frontend/package.json index 673c9fe..0803d28 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -43,6 +43,7 @@ }, "devDependencies": { "@rollup/plugin-inject": "^5.0.5", + "@types/node": "^22.4.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/react-window": "^1.8.8", diff --git a/frontend/src/components/Liquidity/Liquidity.tsx b/frontend/src/components/Liquidity/Liquidity.tsx index a7dc158..ea95f84 100644 --- a/frontend/src/components/Liquidity/Liquidity.tsx +++ b/frontend/src/components/Liquidity/Liquidity.tsx @@ -228,8 +228,6 @@ export const Liquidity: React.FC = ({ const [lastInput, setLastInput] = useState<'A' | 'B'>('A') - console.log('pi', poolIndex) - useEffect(() => { if (tokenAIndex !== null && tokenBIndex !== null) { if (lastInput === 'A') { diff --git a/frontend/src/store/consts/static.ts b/frontend/src/store/consts/static.ts index 26cbb85..934824f 100644 --- a/frontend/src/store/consts/static.ts +++ b/frontend/src/store/consts/static.ts @@ -272,7 +272,7 @@ export const ALL_FEE_TIERS_DATA = FEE_TIERS.map((tier, index) => ({ export const addressTickerMap: { [key: string]: string } = { WETH: 'So11111111111111111111111111111111111111112', - BTC: '3JXmQAzBPU66dkVQufSE1ChBMRAdCHp6T7ZMBKAwhmWw', - USDC: '5W3bmyYDww6p5XRZnCR6m2c75st6XyCxW1TgGS3wTq7S', + BTC: '2F5TprcNBqj2hXVr9oTssabKdf8Zbsf9xStqWjPm8yLo', + USDC: '5gFSyxjNsuQsZKn9g5L9Ky3cSUvJ6YXqWVuPzmSi8Trx', ETH: 'So11111111111111111111111111111111111111112' } diff --git a/frontend/src/store/sagas/wallet.ts b/frontend/src/store/sagas/wallet.ts index 8acfbaa..76766f8 100644 --- a/frontend/src/store/sagas/wallet.ts +++ b/frontend/src/store/sagas/wallet.ts @@ -10,7 +10,7 @@ import { } from 'typed-redux-saga' import { createLoaderKey } from '@utils/utils' import { closeSnackbar } from 'notistack' -import { actions, Status } from '@store/reducers/wallet' +import { actions, ITokenAccount, Status } from '@store/reducers/wallet' import { NetworkType, Token as StoreToken, @@ -21,7 +21,10 @@ import { WalletAdapter } from '@utils/web3/adapters/types' import { BN } from '@project-serum/anchor' import { disconnectWallet, getSolanaWallet } from '@utils/web3/wallet' import { + AccountInfo, + ParsedAccountData, PublicKey, + RpcResponseAndContext, Signer, SystemProgram, Transaction, @@ -31,6 +34,7 @@ import { import { getConnection } from './connection' import { ASSOCIATED_TOKEN_PROGRAM_ID, + Mint, TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, createMintToInstruction, @@ -46,6 +50,7 @@ import airdropAdmin from '@store/consts/airdropAdmin' import { getTokenDetails } from './token' import { openWalletSelectorModal } from '@utils/web3/selector' import { PayloadAction } from '@reduxjs/toolkit' +import { TOKEN_2022_PROGRAM_ID } from '@invariant-labs/sdk-eclipse' export function* getWallet(): SagaGenerator { const wallet = yield* call(getSolanaWallet) @@ -64,68 +69,83 @@ export function* handleBalance(): Generator { yield* put(actions.setIsBalanceLoading(true)) const balance = yield* call(getBalance, wallet.publicKey) yield* put(actions.setBalance(balance)) - // yield* call(fetchTokensAccounts) + yield* call(fetchTokensAccounts) yield* put(actions.setIsBalanceLoading(false)) } -// interface IparsedTokenInfo { -// mint: string -// owner: string -// tokenAmount: { -// amount: string -// decimals: number -// uiAmount: number -// } -// } -// export function* fetchTokensAccounts(): Generator { -// const connection = yield* call(getConnection) -// const wallet = yield* call(getWallet) -// const tokensAccounts = yield* call( -// [connection, connection.getParsedTokenAccountsByOwner], -// wallet.publicKey, -// { -// programId: TOKEN_PROGRAM_ID -// } -// ) -// const allTokens = yield* select(tokens) -// const newAccounts: ITokenAccount[] = [] -// const unknownTokens: Record = {} -// for (const account of tokensAccounts.value) { -// const info: IparsedTokenInfo = account.account.data.parsed.info -// newAccounts.push({ -// programId: new PublicKey(info.mint), -// balance: new BN(info.tokenAmount.amount), -// address: account.pubkey, -// decimals: info.tokenAmount.decimals -// }) - -// if (!allTokens[info.mint]) { -// unknownTokens[info.mint] = { -// name: info.mint, -// symbol: `${info.mint.slice(0, 4)}...${info.mint.slice(-4)}`, -// decimals: info.tokenAmount.decimals, -// address: new PublicKey(info.mint), -// logoURI: '/unknownToken.svg', -// isUnknown: true -// } -// } -// } - -// yield* put(actions.addTokenAccounts(newAccounts)) -// yield* put(poolsActions.addTokens(unknownTokens)) -// } - -// export function* getToken(tokenAddress: PublicKey): SagaGenerator { -// const connection = yield* call(getConnection) -// const token = new Token(connection, tokenAddress, TOKEN_PROGRAM_ID, new Account()) -// return token -// } - -export function* getToken(tokenAddress: PublicKey): SagaGenerator { +interface IparsedTokenInfo { + mint: string + owner: string + tokenAmount: { + amount: string + decimals: number + uiAmount: number + } +} + +interface TokenAccountInfo { + pubkey: PublicKey + account: AccountInfo +} +export function* fetchTokensAccounts(): Generator { const connection = yield* call(getConnection) + const wallet = yield* call(getWallet) + console.log(connection) + const splTokensAccounts: RpcResponseAndContext = yield* call( + [connection, connection.getParsedTokenAccountsByOwner], + wallet.publicKey, + { + programId: TOKEN_PROGRAM_ID + } + ) + console.log(splTokensAccounts) + const token2022TokensAccounts: RpcResponseAndContext = yield* call( + [connection, connection.getParsedTokenAccountsByOwner], + wallet.publicKey, + { + programId: TOKEN_2022_PROGRAM_ID + } + ) + console.log(token2022TokensAccounts) + const mergedAccounts: TokenAccountInfo[] = [ + ...splTokensAccounts.value, + ...token2022TokensAccounts.value + ] + console.log(mergedAccounts) + const allTokens = yield* select(tokens) + const newAccounts: ITokenAccount[] = [] + const unknownTokens: Record = {} + for (const account of mergedAccounts) { + const info: IparsedTokenInfo = account.account.data.parsed.info + newAccounts.push({ + programId: new PublicKey(info.mint), + balance: new BN(info.tokenAmount.amount), + address: account.pubkey, + decimals: info.tokenAmount.decimals + }) - const mintInfo = yield* call(getMint, connection, tokenAddress) + if (!allTokens[info.mint]) { + unknownTokens[info.mint] = { + name: info.mint, + symbol: `${info.mint.slice(0, 4)}...${info.mint.slice(-4)}`, + decimals: info.tokenAmount.decimals, + address: new PublicKey(info.mint), + logoURI: '/unknownToken.svg', + isUnknown: true + } + } + } + console.log(newAccounts) + console.log(unknownTokens) + yield* put(actions.addTokenAccounts(newAccounts)) + yield* put(poolsActions.addTokens(unknownTokens)) +} + +export function* getToken(tokenAddress: PublicKey): SagaGenerator { + const connection = yield* call(getConnection) + const mintInfo = yield* call(getMint, connection, tokenAddress) + console.log(mintInfo) return mintInfo } @@ -203,7 +223,7 @@ export function* setEmptyAccounts(collateralsAddresses: PublicKey[]): Generator ? tokensAccounts[collateral.toString()].address : null if (accountAddress == null) { - acc.push(collateralTokenProgram.publicKey) + acc.push(new PublicKey(collateralTokenProgram.address)) } } if (acc.length !== 0) { @@ -295,7 +315,7 @@ export function* getCollateralTokenAirdrop( export function* signAndSend(wallet: WalletAdapter, tx: Transaction): SagaGenerator { const connection = yield* call(getConnection) - const blockhash = yield* call([connection, connection.getLatestBlockhash]) + const blockhash = yield* call([connection, connection.getRecentBlockhash]) tx.feePayer = wallet.publicKey tx.recentBlockhash = blockhash.blockhash const signedTx = yield* call([wallet, wallet.signTransaction], tx) @@ -448,7 +468,7 @@ export function* init(isEagerConnect?: boolean): Generator { const balance = yield* call(getBalance, wallet.publicKey) yield* put(actions.setBalance(balance)) yield* put(actions.setStatus(Status.Initialized)) - // yield* call(fetchTokensAccounts) + yield* call(fetchTokensAccounts) yield* put(actions.setIsBalanceLoading(false)) } catch (error) { yield* put(actions.setStatus(Status.Uninitialized)) @@ -462,7 +482,6 @@ export function* handleReconnect(): Generator { yield* call(handleConnect, { type: actions.connect.type, payload: false }) } - export const sleep = (ms: number) => { return new Promise(resolve => setTimeout(resolve, ms)) } diff --git a/frontend/src/utils/utils.ts b/frontend/src/utils/utils.ts index d48b040..bd96bde 100644 --- a/frontend/src/utils/utils.ts +++ b/frontend/src/utils/utils.ts @@ -17,6 +17,7 @@ import { FormatNumberThreshold, PrefixConfig } from '@store/consts/types' import { getMint } from '@solana/spl-token' import mainnetList from '@store/consts/tokenLists/mainnet.json' import icons from '@static/icons' +import { getTokenProgramAddress } from '@invariant-labs/sdk-eclipse' export const createLoaderKey = () => (new Date().getMilliseconds() + Math.random()).toString() export const trimZeros = (amount: string) => { @@ -202,7 +203,7 @@ export const getNetworkTokensList = (networkType: NetworkType): Record = {} switch (networkType) { case NetworkType.MAINNET: - (mainnetList as any[]).forEach(token => { + ;(mainnetList as any[]).forEach(token => { obj[token.address] = { ...token, address: new PublicKey(token.address), @@ -261,3 +262,10 @@ export const tickerToAddress = (ticker: string): string => { export const parsePathFeeToFeeString = (pathFee: string): string => { return (+pathFee.replace('_', '') * Math.pow(10, 8)).toString() } + +export const getTokenProgramId = async ( + connection: Connection, + address: PublicKey +): Promise => { + return await getTokenProgramAddress(connection, address) +}