UNPKG

rubic-sdk

Version:
186 lines • 8.63 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SolanaWeb3Public = void 0; const spl_token_1 = require("@solana/spl-token"); const web3_js_1 = require("@solana/web3.js"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const utils_1 = require("ethers/lib/utils"); const rxjs_1 = require("rxjs"); const native_tokens_1 = require("../../../../../common/tokens/constants/native-tokens"); const native_solana_mint_address_1 = require("../../../constants/solana/native-solana-mint-address"); const blockchain_name_1 = require("../../../models/blockchain-name"); const tx_status_1 = require("../models/tx-status"); const web3_public_1 = require("../web3-public"); const solana_web3_pure_1 = require("../../../web3-pure/typed-web3-pure/solana-web3-pure/solana-web3-pure"); const injector_1 = require("../../../../injector/injector"); const solana_tokens_service_1 = require("./services/solana-tokens-service"); /** * Class containing methods for calling contracts in order to obtain information from the blockchain. * To send transaction or execute contract method use {@link Web3Private}. */ class SolanaWeb3Public extends web3_public_1.Web3Public { constructor(connection) { super(blockchain_name_1.BLOCKCHAIN_NAME.SOLANA); this.connection = connection; this.HELIUS_API_URL = 'https://mainnet.helius-rpc.com'; } /** * @returns ComputedUnitsLimit - like gasLimit in evm */ async getConsumedUnitsLimit(tx) { const DEFAULT_CU_LIMIT = 600000; try { const resp = await this.connection.simulateTransaction(tx, { replaceRecentBlockhash: true }); return resp.value.unitsConsumed ? resp.value.unitsConsumed * 1.2 : DEFAULT_CU_LIMIT; } catch (err) { console.error('Solana_simulateTransaction_Error ==> ', err); return DEFAULT_CU_LIMIT; } } /** * @returns ComputedUnitsPrice - like gasPrice in evm */ async getConsumedUnitsPrice(tx) { const resp = await injector_1.Injector.httpClient.post(`${this.HELIUS_API_URL}/?api-key=f6b96e37-e267-4b67-8790-84bdf8748c39`, { jsonrpc: '2.0', id: '1', method: 'getPriorityFeeEstimate', params: [ { transaction: utils_1.base58.encode(tx.serialize()), // Pass the serialized transaction in Base58 options: { priorityLevel: 'Medium' } } ] }); return resp.result.priorityFeeEstimate; } getBlockNumber() { return this.connection.getBlockHeight('finalized'); } multicallContractsMethods(_contractAbi, _contractsData) { throw new Error('Method multicall is not supported'); } async getTransactionStatus(hash) { try { const transaction = await this.connection.getTransaction(hash, { maxSupportedTransactionVersion: 1 }); if (transaction?.meta?.err) { return tx_status_1.TX_STATUS.FAIL; } if (transaction?.blockTime) { return tx_status_1.TX_STATUS.SUCCESS; } return tx_status_1.TX_STATUS.PENDING; } catch { return tx_status_1.TX_STATUS.PENDING; } } async callForTokenInfo(tokenAddress, tokenFields = ['decimals', 'symbol', 'name', 'image']) { return (await this.callForTokensInfo([tokenAddress], tokenFields))[0]; } async callForTokensInfo(tokenAddresses, tokenFields = ['decimals', 'symbol', 'name', 'image']) { const nativeTokenIndex = tokenAddresses.findIndex(address => this.Web3Pure.isNativeAddress(address)); const filteredTokenAddresses = tokenAddresses.filter((_, index) => index !== nativeTokenIndex); const blockchainNativeToken = native_tokens_1.nativeTokensList[this.blockchainName]; const nativeToken = { ...blockchainNativeToken, decimals: blockchainNativeToken.decimals.toString() }; // only native token in array if (!filteredTokenAddresses.length && nativeTokenIndex !== -1) { return [nativeToken]; } const mints = filteredTokenAddresses.map(address => new web3_js_1.PublicKey(address)); const tokensMint = await new solana_tokens_service_1.SolanaTokensService(this.connection).fetchTokensData(mints); const tokens = tokensMint.map(token => { const data = tokenFields.reduce((acc, fieldName) => ({ ...acc, [fieldName]: fieldName === 'image' ? token.logoURI : token[fieldName] }), {}); return data; }); if (nativeTokenIndex === -1) { return tokens; } tokens.splice(nativeTokenIndex, 0, nativeToken); return tokens; } async getBalance(userAddress, tokenAddress) { const isToken = tokenAddress && !solana_web3_pure_1.SolanaWeb3Pure.isNativeAddress(tokenAddress); if (isToken) { const balance = await this.getTokensBalances(userAddress, [tokenAddress]); return balance?.[0] || new bignumber_js_1.default(0); } const balance = await this.connection.getBalanceAndContext(new web3_js_1.PublicKey(userAddress), 'confirmed'); return new bignumber_js_1.default(balance.value.toString()); } async getTokenBalance(address, tokenAddress) { const balance = await this.getTokensBalances(address, [tokenAddress]); return balance?.[0] || new bignumber_js_1.default(0); } async callContractMethod(_contractAddress, _contractAbi, _methodName, _methodArguments = [], _options = {}) { throw new Error('Method call is not supported'); } healthCheck(timeoutMs = 4000) { const request = this.connection.getBalanceAndContext(new web3_js_1.PublicKey('DVLwQbEaw5txuduQwvfbNP3sXvjawHqaoMuGMKZx15bQ'), 'confirmed'); return (0, rxjs_1.firstValueFrom)((0, rxjs_1.from)(request).pipe((0, rxjs_1.timeout)(timeoutMs), (0, rxjs_1.map)(result => Boolean(result)), (0, rxjs_1.catchError)((err) => { if (err?.name === 'TimeoutError') { console.debug(`Solana node healthcheck timeout (${timeoutMs}ms) has occurred.`); } else { console.debug(`Solana node healthcheck fail: ${err}`); } return (0, rxjs_1.of)(false); }))); } /** * Gets balance of multiple tokens. * @param address Wallet address. * @param tokensAddresses Tokens addresses. */ async getTokensBalances(address, tokensAddresses) { const resp = await this.connection._rpcRequest('getTokenAccountsByOwner', [ address, { programId: spl_token_1.TOKEN_PROGRAM_ID }, { encoding: 'jsonParsed' } ]); const tokenInfo = new Map(resp.result.value.map(el => { const { mint, tokenAmount } = el.account.data.parsed.info; return [mint, tokenAmount.amount]; })); const nativeSolBalance = await this.connection.getBalanceAndContext(new web3_js_1.PublicKey(address), 'confirmed'); return tokensAddresses.map(tokenAddress => { if (tokenAddress === native_solana_mint_address_1.NATIVE_SOLANA_MINT_ADDRESS) { return new bignumber_js_1.default(nativeSolBalance.value.toString()); } const tokenWithBalance = tokenInfo.get(tokenAddress); return new bignumber_js_1.default(tokenWithBalance || NaN); }); } async getAllowance() { return new bignumber_js_1.default(Infinity); } setProvider(_provider) { return; } async getRecentBlockhash() { return this.connection.getLatestBlockhash(); } async getAtaAddress(walletAddress, tokenAddress) { const tokenKey = new web3_js_1.PublicKey(tokenAddress); const walletKey = new web3_js_1.PublicKey(walletAddress); const ataAddress = await (0, spl_token_1.getAssociatedTokenAddress)(tokenKey, walletKey, false, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID); const accountInfo = await this.connection.getAccountInfo(ataAddress); return accountInfo ? ataAddress.toString() : null; } } exports.SolanaWeb3Public = SolanaWeb3Public; //# sourceMappingURL=solana-web3-public.js.map