rubic-sdk
Version:
Simplify dApp creation
186 lines • 8.63 kB
JavaScript
;
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