mirror of
https://github.com/alexgo-io/DefiLlama-Adapters.git
synced 2026-04-30 13:52:23 +08:00
remove: @solana/spl-token
This commit is contained in:
52
package-lock.json
generated
52
package-lock.json
generated
@@ -12,7 +12,6 @@
|
||||
"dependencies": {
|
||||
"@defillama/sdk": "latest",
|
||||
"@project-serum/anchor": "^0.25.0",
|
||||
"@solana/spl-token": "^0.3.0",
|
||||
"@solana/web3.js": "^1.36.0",
|
||||
"@solendprotocol/solend-sdk": "^0.6.2",
|
||||
"@supercharge/promise-pool": "^2.1.0",
|
||||
@@ -1081,36 +1080,6 @@
|
||||
"node": ">=5.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@solana/buffer-layout-utils": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz",
|
||||
"integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==",
|
||||
"dependencies": {
|
||||
"@solana/buffer-layout": "^4.0.0",
|
||||
"@solana/web3.js": "^1.32.0",
|
||||
"bigint-buffer": "^1.1.5",
|
||||
"bignumber.js": "^9.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@solana/spl-token": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.5.tgz",
|
||||
"integrity": "sha512-0bGC6n415lGjKu02gkLOIpP1wzndSP0SHwN9PefJ+wKAhmfU1rl3AV1Pa41uap2kzSCD6F9642ngNO8KXPvh/g==",
|
||||
"dependencies": {
|
||||
"@solana/buffer-layout": "^4.0.0",
|
||||
"@solana/buffer-layout-utils": "^0.2.0",
|
||||
"buffer": "^6.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@solana/web3.js": "^1.47.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@solana/web3.js": {
|
||||
"version": "1.63.1",
|
||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.63.1.tgz",
|
||||
@@ -3399,27 +3368,6 @@
|
||||
"buffer": "~6.0.3"
|
||||
}
|
||||
},
|
||||
"@solana/buffer-layout-utils": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz",
|
||||
"integrity": "sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==",
|
||||
"requires": {
|
||||
"@solana/buffer-layout": "^4.0.0",
|
||||
"@solana/web3.js": "^1.32.0",
|
||||
"bigint-buffer": "^1.1.5",
|
||||
"bignumber.js": "^9.0.1"
|
||||
}
|
||||
},
|
||||
"@solana/spl-token": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.3.5.tgz",
|
||||
"integrity": "sha512-0bGC6n415lGjKu02gkLOIpP1wzndSP0SHwN9PefJ+wKAhmfU1rl3AV1Pa41uap2kzSCD6F9642ngNO8KXPvh/g==",
|
||||
"requires": {
|
||||
"@solana/buffer-layout": "^4.0.0",
|
||||
"@solana/buffer-layout-utils": "^0.2.0",
|
||||
"buffer": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"@solana/web3.js": {
|
||||
"version": "1.63.1",
|
||||
"resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.63.1.tgz",
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
"dependencies": {
|
||||
"@defillama/sdk": "latest",
|
||||
"@project-serum/anchor": "^0.25.0",
|
||||
"@solana/spl-token": "^0.3.0",
|
||||
"@solana/web3.js": "^1.36.0",
|
||||
"@solendprotocol/solend-sdk": "^0.6.2",
|
||||
"@supercharge/promise-pool": "^2.1.0",
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
const BigNumber = require("bignumber.js");
|
||||
const { PublicKey } = require("@solana/web3.js");
|
||||
const { Program, utils } = require("@project-serum/anchor");
|
||||
const {
|
||||
getAssociatedTokenAddress,
|
||||
AccountLayout,
|
||||
u64,
|
||||
} = require("@solana/spl-token");
|
||||
const { toUSDTBalances } = require("../helper/balances");
|
||||
const { getProvider } = require("../helper/solana");
|
||||
const { getProvider, sumTokens2 } = require("../helper/solana");
|
||||
|
||||
const MAX_NUMBER_OF_ACCOUNT_INFOS = 99;
|
||||
const USDC_DECIMALS = 1_000_000;
|
||||
const MARKET_SEED = "credix-marketplace";
|
||||
const IDL = require("./credix.json");
|
||||
const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
|
||||
const programId = new PublicKey("CRDx2YkdtYtGZXGHZ59wNv1EwKHQndnRc1gT4p8i2vPX");
|
||||
const encodeSeedString = (seedString) =>
|
||||
Buffer.from(utils.bytes.utf8.encode(seedString));
|
||||
const encodeSeedString = (seedString) => Buffer.from(utils.bytes.utf8.encode(seedString));
|
||||
|
||||
const constructProgram = (provider) => {
|
||||
return new Program(IDL, programId, provider);
|
||||
@@ -36,26 +29,6 @@ const findSigningAuthorityPDA = async (globalMarketSeed) => {
|
||||
return findPDA(seeds);
|
||||
};
|
||||
|
||||
const getAssociatedBaseTokenAddressPK = async (publicKey) => {
|
||||
const baseMintPK = new PublicKey(
|
||||
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
||||
); //USDC
|
||||
return await getAssociatedTokenAddress(baseMintPK, publicKey, true);
|
||||
};
|
||||
|
||||
async function fetchLiquidityPoolBalance() {
|
||||
const provider = getProvider();
|
||||
const signingAuthorityKey = await findSigningAuthorityPDA(MARKET_SEED);
|
||||
const liquidityPoolKey = await getAssociatedBaseTokenAddressPK(
|
||||
signingAuthorityKey[0]
|
||||
);
|
||||
const liquidityPool = await provider.connection.getTokenAccountBalance(
|
||||
liquidityPoolKey
|
||||
);
|
||||
|
||||
return new BigNumber(liquidityPool.value.amount.toString());
|
||||
}
|
||||
|
||||
async function generateRepaymentSchedulePDA(deal) {
|
||||
const marketAdress = await findGlobalMarketStatePDA(MARKET_SEED);
|
||||
const seed = [
|
||||
@@ -150,23 +123,6 @@ function chunk(inputArray, perChunk) {
|
||||
return result;
|
||||
}
|
||||
|
||||
async function asyncMap(arr, map) {
|
||||
return Promise.all(arr.map(map));
|
||||
}
|
||||
|
||||
async function baseTokenAccount(deal) {
|
||||
const dealTokenAccount = encodeSeedString("deal-token-account");
|
||||
const marketAddress = await findGlobalMarketStatePDA(MARKET_SEED);
|
||||
const seeds = [
|
||||
marketAddress[0].toBuffer(),
|
||||
deal.publicKey.toBuffer(),
|
||||
dealTokenAccount,
|
||||
];
|
||||
|
||||
// TODO: just ignore the bump and return the public key
|
||||
return PublicKey.findProgramAddress(seeds, programId);
|
||||
}
|
||||
|
||||
async function fetchRepaymentScheduleForDeals(program, provider, deals) {
|
||||
const pdaPromises = deals.map((d) => generateRepaymentSchedulePDA(d));
|
||||
const pdas = await Promise.all(pdaPromises);
|
||||
@@ -189,87 +145,9 @@ async function fetchRepaymentScheduleForDeals(program, provider, deals) {
|
||||
return programVersions;
|
||||
}
|
||||
|
||||
// TODO: clean up
|
||||
async function tvl() {
|
||||
const provider = getProvider();
|
||||
const program = constructProgram(provider);
|
||||
const liquidityPoolBalanceTokenAmount = await fetchLiquidityPoolBalance();
|
||||
const allDeals = await program.account.deal.all();
|
||||
const allRepaymentSchedules = await fetchRepaymentScheduleForDeals(
|
||||
program,
|
||||
provider,
|
||||
allDeals
|
||||
);
|
||||
|
||||
const tvlDealSchedulePairs = (
|
||||
await allDeals.map((deal, index) => {
|
||||
const schedule = allRepaymentSchedules[index];
|
||||
|
||||
// Return early so we don't try to get the status of a deal without a schedule
|
||||
if (schedule === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const dealStatus = status(deal.account, schedule);
|
||||
|
||||
switch (dealStatus) {
|
||||
case "OPEN_FOR_FUNDING":
|
||||
case "IN_PROGRESS":
|
||||
case "CLOSED":
|
||||
return [deal, schedule, dealStatus];
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})
|
||||
).filter((pair) => pair !== null);
|
||||
|
||||
const tvlDeals = tvlDealSchedulePairs.map((p) => p[0]);
|
||||
|
||||
let dealsTokenAccountBalance = new BigNumber(0);
|
||||
let dealsAmountWithdrawn = new BigNumber(0);
|
||||
const schedulesPrincipal = tvlDealSchedulePairs.reduce(
|
||||
(principalSum, pair) => {
|
||||
if (pair[2] === "OPEN_FOR_FUNDING") {
|
||||
return principalSum;
|
||||
}
|
||||
|
||||
return principalSum.plus(totalPrincipal(pair[1]));
|
||||
},
|
||||
new BigNumber(0)
|
||||
);
|
||||
|
||||
//////// Temp solution
|
||||
// TODO: cleanup
|
||||
const tokenAccountAddresses = (
|
||||
await asyncMap(tvlDeals, (deal) => baseTokenAccount(deal))
|
||||
).map((pda) => pda[0]);
|
||||
const chunks = chunk(tokenAccountAddresses, MAX_NUMBER_OF_ACCOUNT_INFOS - 1);
|
||||
const tokenAccountInfos = (
|
||||
await asyncMap(chunks, (chunk) =>
|
||||
provider.connection.getMultipleAccountsInfo(chunk)
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
.filter((info) => info !== null);
|
||||
|
||||
dealsTokenAccountBalance = tokenAccountInfos
|
||||
.map((info) => AccountLayout.decode(info.data))
|
||||
.reduce(
|
||||
(total, info) => total.plus(new BigNumber(info.amount.toString())),
|
||||
new BigNumber(0)
|
||||
);
|
||||
/////////
|
||||
for (const deal of tvlDeals) {
|
||||
dealsAmountWithdrawn = dealsAmountWithdrawn.plus(
|
||||
new BigNumber(deal.account.amountWithdrawn.toString())
|
||||
);
|
||||
}
|
||||
const dealsLiquidity = dealsTokenAccountBalance.minus(
|
||||
schedulesPrincipal.minus(dealsAmountWithdrawn)
|
||||
);
|
||||
const tvl = liquidityPoolBalanceTokenAmount.plus(dealsLiquidity);
|
||||
|
||||
return toUSDTBalances(tvl.dividedBy(USDC_DECIMALS));
|
||||
const [signingAuthorityKey] = await findSigningAuthorityPDA(MARKET_SEED);
|
||||
return sumTokens2({ tokensAndOwners: [[USDC, signingAuthorityKey]] });
|
||||
}
|
||||
|
||||
async function borrowed() {
|
||||
@@ -295,7 +173,9 @@ async function borrowed() {
|
||||
.minus(principalRepaid(schedule));
|
||||
}, new BigNumber(0));
|
||||
|
||||
return toUSDTBalances(totalOutstandingCredit.dividedBy(USDC_DECIMALS));
|
||||
return {
|
||||
['solana:' + USDC]: totalOutstandingCredit.toString()
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const { getProvider, getConnection, sumTokens2, } = require("../helper/solana");
|
||||
const { parseReserve } = require("../solend/utils");
|
||||
const { getProvider, getConnection, sumTokens2, decodeAccount, } = require("../helper/solana");
|
||||
const { Program, } = require("@project-serum/anchor");
|
||||
const { PublicKey, } = require("@solana/web3.js");
|
||||
const sdk = require('@defillama/sdk');
|
||||
@@ -17,7 +16,7 @@ async function tvl() {
|
||||
const reserveInfo = {}
|
||||
for (const reserve of Object.values(reserves)) {
|
||||
const [info] = await connection.getMultipleAccountsInfo([new PublicKey(reserve)])
|
||||
const { info: { liquidity: { mintPubkey, marketPrice, }, collateral }} = parseReserve(info)
|
||||
const { info: { liquidity: { mintPubkey, marketPrice, }, collateral }} = decodeAccount('reserve', info)
|
||||
reserveInfo[collateral.mintPubkey.toString()] = { price: marketPrice/1e18, key: mintPubkey.toString(), }
|
||||
}
|
||||
const idl = await Program.fetchIdl(programId, provider)
|
||||
|
||||
@@ -6,6 +6,8 @@ const { Connection, PublicKey, Keypair } = require("@solana/web3.js")
|
||||
const { AnchorProvider: Provider, Wallet, } = require("@project-serum/anchor");
|
||||
const BufferLayout = require("@solana/buffer-layout")
|
||||
const { sleep, sliceIntoChunks, log, } = require('./utils')
|
||||
const { decodeAccount } = require('./utils/solana/layout')
|
||||
|
||||
const sdk = require('@defillama/sdk')
|
||||
const tokenMapping = tokens
|
||||
|
||||
@@ -416,4 +418,5 @@ module.exports = {
|
||||
getTokenList,
|
||||
getSolTokenMap,
|
||||
readBigUInt64LE,
|
||||
decodeAccount,
|
||||
};
|
||||
|
||||
485
projects/helper/utils/solana/layout.js
Normal file
485
projects/helper/utils/solana/layout.js
Normal file
@@ -0,0 +1,485 @@
|
||||
|
||||
const { deserializeUnchecked } = require('borsh');
|
||||
const BufferLayout = require("buffer-layout");
|
||||
const { PublicKey } = require("@solana/web3.js");
|
||||
const BN = require("bn.js");
|
||||
|
||||
const publicKey = (property = "publicKey") => {
|
||||
const publicKeyLayout = BufferLayout.blob(32, property);
|
||||
|
||||
const _decode = publicKeyLayout.decode.bind(publicKeyLayout);
|
||||
const _encode = publicKeyLayout.encode.bind(publicKeyLayout);
|
||||
|
||||
publicKeyLayout.decode = (buffer, offset) => {
|
||||
const data = _decode(buffer, offset);
|
||||
return new PublicKey(data);
|
||||
};
|
||||
|
||||
publicKeyLayout.encode = (key, buffer, offset) =>
|
||||
_encode(key.toBuffer(), buffer, offset);
|
||||
|
||||
return publicKeyLayout;
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a 64bit unsigned value
|
||||
*/
|
||||
const uint64 = (property = "uint64") => {
|
||||
const layout = BufferLayout.blob(8, property);
|
||||
|
||||
const _decode = layout.decode.bind(layout);
|
||||
const _encode = layout.encode.bind(layout);
|
||||
|
||||
layout.decode = (buffer, offset) => {
|
||||
const data = _decode(buffer, offset);
|
||||
return new BN(
|
||||
[...data]
|
||||
.reverse()
|
||||
.map((i) => `00${i.toString(16)}`.slice(-2))
|
||||
.join(""),
|
||||
16
|
||||
);
|
||||
};
|
||||
|
||||
layout.encode = (num, buffer, offset) => {
|
||||
const a = num.toArray().reverse();
|
||||
let b = Buffer.from(a);
|
||||
if (b.length !== 8) {
|
||||
const zeroPad = Buffer.alloc(8);
|
||||
b.copy(zeroPad);
|
||||
b = zeroPad;
|
||||
}
|
||||
return _encode(b, buffer, offset);
|
||||
};
|
||||
|
||||
return layout;
|
||||
};
|
||||
|
||||
const uint128 = (property = "uint128") => {
|
||||
const layout = BufferLayout.blob(16, property);
|
||||
|
||||
const _decode = layout.decode.bind(layout);
|
||||
const _encode = layout.encode.bind(layout);
|
||||
|
||||
layout.decode = (buffer, offset) => {
|
||||
const data = _decode(buffer, offset);
|
||||
return new BN(
|
||||
[...data]
|
||||
.reverse()
|
||||
.map((i) => `00${i.toString(16)}`.slice(-2))
|
||||
.join(""),
|
||||
16
|
||||
);
|
||||
};
|
||||
|
||||
layout.encode = (num, buffer, offset) => {
|
||||
const a = num.toArray().reverse();
|
||||
let b = Buffer.from(a);
|
||||
if (b.length !== 16) {
|
||||
const zeroPad = Buffer.alloc(16);
|
||||
b.copy(zeroPad);
|
||||
b = zeroPad;
|
||||
}
|
||||
|
||||
return _encode(b, buffer, offset);
|
||||
};
|
||||
|
||||
return layout;
|
||||
};
|
||||
const LastUpdateLayout = BufferLayout.struct(
|
||||
[uint64("slot"), BufferLayout.u8("stale")],
|
||||
"lastUpdate"
|
||||
);
|
||||
|
||||
const ReserveLayout = BufferLayout.struct([
|
||||
BufferLayout.u8("version"),
|
||||
|
||||
LastUpdateLayout,
|
||||
|
||||
publicKey("lendingMarket"),
|
||||
|
||||
BufferLayout.struct(
|
||||
[
|
||||
publicKey("mintPubkey"),
|
||||
BufferLayout.u8("mintDecimals"),
|
||||
publicKey("supplyPubkey"),
|
||||
// @FIXME: oracle option
|
||||
// TODO: replace u32 option with generic equivalent
|
||||
// BufferLayout.u32('oracleOption'),
|
||||
publicKey("pythOracle"),
|
||||
publicKey("switchboardOracle"),
|
||||
uint64("availableAmount"),
|
||||
uint128("borrowedAmountWads"),
|
||||
uint128("cumulativeBorrowRateWads"),
|
||||
uint128("marketPrice"),
|
||||
],
|
||||
"liquidity"
|
||||
),
|
||||
|
||||
BufferLayout.struct(
|
||||
[
|
||||
publicKey("mintPubkey"),
|
||||
uint64("mintTotalSupply"),
|
||||
publicKey("supplyPubkey"),
|
||||
],
|
||||
"collateral"
|
||||
),
|
||||
|
||||
BufferLayout.struct(
|
||||
[
|
||||
BufferLayout.u8("optimalUtilizationRate"),
|
||||
BufferLayout.u8("loanToValueRatio"),
|
||||
BufferLayout.u8("liquidationBonus"),
|
||||
BufferLayout.u8("liquidationThreshold"),
|
||||
BufferLayout.u8("minBorrowRate"),
|
||||
BufferLayout.u8("optimalBorrowRate"),
|
||||
BufferLayout.u8("maxBorrowRate"),
|
||||
BufferLayout.struct(
|
||||
[
|
||||
uint64("borrowFeeWad"),
|
||||
uint64("flashLoanFeeWad"),
|
||||
BufferLayout.u8("hostFeePercentage"),
|
||||
],
|
||||
"fees"
|
||||
),
|
||||
uint64("depositLimit"),
|
||||
uint64("borrowLimit"),
|
||||
publicKey("feeReceiver"),
|
||||
],
|
||||
"config"
|
||||
),
|
||||
|
||||
BufferLayout.blob(256, "padding"),
|
||||
]);
|
||||
|
||||
const MintLayout = BufferLayout.struct([
|
||||
BufferLayout.u32('mintAuthorityOption'),
|
||||
publicKey("mintAuthority"),
|
||||
uint64('supply'),
|
||||
BufferLayout.u8("decimals"),
|
||||
BufferLayout.u8("isInitialized"),
|
||||
BufferLayout.u32("freezeAuthorityOption"),
|
||||
publicKey("freezeAuthority"),
|
||||
]);
|
||||
|
||||
const AccountLayout = BufferLayout.struct([
|
||||
publicKey('mint'),
|
||||
publicKey('owner'),
|
||||
uint64('amount'),
|
||||
BufferLayout.u32('delegateOption'),
|
||||
publicKey('delegate'),
|
||||
BufferLayout.u8('state'),
|
||||
BufferLayout.u32('isNativeOption'),
|
||||
uint64('isNative'),
|
||||
uint64('delegatedAmount'),
|
||||
BufferLayout.u32('closeAuthorityOption'),
|
||||
publicKey('closeAuthority'),
|
||||
]);
|
||||
|
||||
const parseReserve = (info) => {
|
||||
const pubkey = PublicKey.default
|
||||
const { data } = info;
|
||||
const buffer = Buffer.from(data);
|
||||
const reserve = ReserveLayout.decode(buffer);
|
||||
|
||||
if (reserve.lastUpdate.slot.isZero()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const details = {
|
||||
pubkey,
|
||||
account: {
|
||||
...info,
|
||||
},
|
||||
info: reserve,
|
||||
};
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
const defaultParseLayout = Layout => info => {
|
||||
const { data } = info;
|
||||
const buffer = Buffer.from(data);
|
||||
return Layout.decode(buffer);
|
||||
}
|
||||
|
||||
class Lido {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class SeedRange {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Validator {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class PubKeyAndEntry {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class PubKeyAndEntryMaintainer {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class RewardDistribution {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class FeeRecipients {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Validators {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Maintainers {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class ExchangeRate {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Metrics {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class LamportsHistogram {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class WithdrawMetric {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
const schema = new Map([
|
||||
[
|
||||
ExchangeRate,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['computed_in_epoch', 'u64'],
|
||||
['st_sol_supply', 'u64'],
|
||||
['sol_balance', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
LamportsHistogram,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['counts1', 'u64'],
|
||||
['counts2', 'u64'],
|
||||
['counts3', 'u64'],
|
||||
['counts4', 'u64'],
|
||||
['counts5', 'u64'],
|
||||
['counts6', 'u64'],
|
||||
['counts7', 'u64'],
|
||||
['counts8', 'u64'],
|
||||
['counts9', 'u64'],
|
||||
['counts10', 'u64'],
|
||||
['counts11', 'u64'],
|
||||
['counts12', 'u64'],
|
||||
['total', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
WithdrawMetric,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['total_st_sol_amount', 'u64'],
|
||||
['total_sol_amount', 'u64'],
|
||||
['count', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Metrics,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['fee_treasury_sol_total', 'u64'],
|
||||
['fee_validation_sol_total', 'u64'],
|
||||
['fee_developer_sol_total', 'u64'],
|
||||
['st_sol_appreciation_sol_total', 'u64'],
|
||||
['fee_treasury_st_sol_total', 'u64'],
|
||||
['fee_validation_st_sol_total', 'u64'],
|
||||
['fee_developer_st_sol_total', 'u64'],
|
||||
['deposit_amount', LamportsHistogram],
|
||||
['withdraw_amount', WithdrawMetric],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
SeedRange,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['begin', 'u64'],
|
||||
['end', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Validator,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['fee_credit', 'u64'],
|
||||
['fee_address', 'u256'],
|
||||
['stake_seeds', SeedRange],
|
||||
['unstake_seeds', SeedRange],
|
||||
['stake_accounts_balance', 'u64'],
|
||||
['unstake_accounts_balance', 'u64'],
|
||||
['active', 'u8'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
PubKeyAndEntry,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['pubkey', 'u256'],
|
||||
['entry', Validator],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
PubKeyAndEntryMaintainer,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['pubkey', 'u256'],
|
||||
['entry', [0]],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
RewardDistribution,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['treasury_fee', 'u32'],
|
||||
['validation_fee', 'u32'],
|
||||
['developer_fee', 'u32'],
|
||||
['st_sol_appreciation', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
FeeRecipients,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['treasury_account', 'u256'],
|
||||
['developer_account', 'u256'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Validators,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['entries', [PubKeyAndEntry]],
|
||||
['maximum_entries', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Maintainers,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['entries', [PubKeyAndEntryMaintainer]],
|
||||
['maximum_entries', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Lido,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['lido_version', 'u8'],
|
||||
|
||||
['manager', 'u256'],
|
||||
|
||||
['st_sol_mint', 'u256'],
|
||||
|
||||
['exchange_rate', ExchangeRate],
|
||||
|
||||
['sol_reserve_authority_bump_seed', 'u8'],
|
||||
['stake_authority_bump_seed', 'u8'],
|
||||
['mint_authority_bump_seed', 'u8'],
|
||||
['rewards_withdraw_authority_bump_seed', 'u8'],
|
||||
|
||||
['reward_distribution', RewardDistribution],
|
||||
|
||||
['fee_recipients', FeeRecipients],
|
||||
|
||||
['metrics', Metrics],
|
||||
|
||||
['validators', Validators],
|
||||
|
||||
['maintainers', Maintainers],
|
||||
],
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const Layouts = {
|
||||
lido: Lido,
|
||||
}
|
||||
|
||||
const customDecoders = {
|
||||
reserve: parseReserve,
|
||||
mint: defaultParseLayout(MintLayout),
|
||||
account: defaultParseLayout(AccountLayout),
|
||||
}
|
||||
|
||||
function decodeAccount(layout, accountInfo) {
|
||||
if (!accountInfo.data) throw new Error('Missing account data')
|
||||
if (customDecoders[layout]) return customDecoders[layout](accountInfo)
|
||||
if (!Layouts[layout]) throw new Error('Layout not found')
|
||||
return deserializeUnchecked(schema, Layouts[layout], accountInfo.data);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Layouts,
|
||||
schema,
|
||||
decodeAccount,
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
class Lido {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class SeedRange {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Validator {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class PubKeyAndEntry {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class PubKeyAndEntryMaintainer {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class RewardDistribution {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class FeeRecipients {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Validators {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Maintainers {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class ExchangeRate {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class Metrics {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class LamportsHistogram {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
class WithdrawMetric {
|
||||
constructor(data) {
|
||||
Object.assign(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
const schema = new Map([
|
||||
[
|
||||
ExchangeRate,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['computed_in_epoch', 'u64'],
|
||||
['st_sol_supply', 'u64'],
|
||||
['sol_balance', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
LamportsHistogram,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['counts1', 'u64'],
|
||||
['counts2', 'u64'],
|
||||
['counts3', 'u64'],
|
||||
['counts4', 'u64'],
|
||||
['counts5', 'u64'],
|
||||
['counts6', 'u64'],
|
||||
['counts7', 'u64'],
|
||||
['counts8', 'u64'],
|
||||
['counts9', 'u64'],
|
||||
['counts10', 'u64'],
|
||||
['counts11', 'u64'],
|
||||
['counts12', 'u64'],
|
||||
['total', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
WithdrawMetric,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['total_st_sol_amount', 'u64'],
|
||||
['total_sol_amount', 'u64'],
|
||||
['count', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Metrics,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['fee_treasury_sol_total', 'u64'],
|
||||
['fee_validation_sol_total', 'u64'],
|
||||
['fee_developer_sol_total', 'u64'],
|
||||
['st_sol_appreciation_sol_total', 'u64'],
|
||||
['fee_treasury_st_sol_total', 'u64'],
|
||||
['fee_validation_st_sol_total', 'u64'],
|
||||
['fee_developer_st_sol_total', 'u64'],
|
||||
['deposit_amount', LamportsHistogram],
|
||||
['withdraw_amount', WithdrawMetric],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
SeedRange,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['begin', 'u64'],
|
||||
['end', 'u64'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Validator,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['fee_credit', 'u64'],
|
||||
['fee_address', 'u256'],
|
||||
['stake_seeds', SeedRange],
|
||||
['unstake_seeds', SeedRange],
|
||||
['stake_accounts_balance', 'u64'],
|
||||
['unstake_accounts_balance', 'u64'],
|
||||
['active', 'u8'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
PubKeyAndEntry,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['pubkey', 'u256'],
|
||||
['entry', Validator],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
PubKeyAndEntryMaintainer,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['pubkey', 'u256'],
|
||||
['entry', [0]],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
RewardDistribution,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['treasury_fee', 'u32'],
|
||||
['validation_fee', 'u32'],
|
||||
['developer_fee', 'u32'],
|
||||
['st_sol_appreciation', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
FeeRecipients,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['treasury_account', 'u256'],
|
||||
['developer_account', 'u256'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Validators,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['entries', [PubKeyAndEntry]],
|
||||
['maximum_entries', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Maintainers,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['entries', [PubKeyAndEntryMaintainer]],
|
||||
['maximum_entries', 'u32'],
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
Lido,
|
||||
{
|
||||
kind: 'struct',
|
||||
fields: [
|
||||
['lido_version', 'u8'],
|
||||
|
||||
['manager', 'u256'],
|
||||
|
||||
['st_sol_mint', 'u256'],
|
||||
|
||||
['exchange_rate', ExchangeRate],
|
||||
|
||||
['sol_reserve_authority_bump_seed', 'u8'],
|
||||
['stake_authority_bump_seed', 'u8'],
|
||||
['mint_authority_bump_seed', 'u8'],
|
||||
['rewards_withdraw_authority_bump_seed', 'u8'],
|
||||
|
||||
['reward_distribution', RewardDistribution],
|
||||
|
||||
['fee_recipients', FeeRecipients],
|
||||
|
||||
['metrics', Metrics],
|
||||
|
||||
['validators', Validators],
|
||||
|
||||
['maintainers', Maintainers],
|
||||
],
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
module.exports = {
|
||||
Lido,
|
||||
schema
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
const { Connection, PublicKey } = require('@solana/web3.js');
|
||||
const { deserializeUnchecked } = require('borsh');
|
||||
const { Lido, schema } = require('./Lido')
|
||||
const { PublicKey } = require('@solana/web3.js');
|
||||
const { decodeAccount } = require('../helper/solana')
|
||||
|
||||
const SOLIDO_ADDRESS = "49Yi1TKkNyYjPAFdR9LBvoHcUjuPX4Df5T5yv39w2XTn";
|
||||
const RESERVE_ACCOUNT_ADDRESS = "3Kwv3pEAuoe4WevPB4rgMBTZndGDb53XT7qwQKnvHPfX";
|
||||
|
||||
async function retrieveValidatorsBalance(connection) {
|
||||
const accountInfo = await connection.getAccountInfo(new PublicKey(SOLIDO_ADDRESS));
|
||||
const deserializedAccountInfo = deserializeUnchecked(
|
||||
schema,
|
||||
Lido,
|
||||
accountInfo.data,
|
||||
);
|
||||
const deserializedAccountInfo = decodeAccount('lido', accountInfo)
|
||||
return deserializedAccountInfo.validators.entries
|
||||
.map(pubKeyAndEntry => pubKeyAndEntry.entry)
|
||||
.map(validator => validator.stake_accounts_balance.toNumber())
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
const { PublicKey } =require("@solana/web3.js");
|
||||
const { AccountLayout, MintLayout } = require("@solana/spl-token")
|
||||
|
||||
const getAccountInfo = async (connection, pubKey) => {
|
||||
const info = await connection.getAccountInfo(pubKey);
|
||||
if (info === null) {
|
||||
throw new Error("Failed to find mint account");
|
||||
}
|
||||
|
||||
const buffer = Buffer.from(info.data);
|
||||
|
||||
const data = deserializeAccount(buffer);
|
||||
|
||||
const details = {
|
||||
pubkey: pubKey,
|
||||
account: {
|
||||
...info,
|
||||
},
|
||||
info: data,
|
||||
};
|
||||
|
||||
return details;
|
||||
};
|
||||
|
||||
const getMultipleAccountInfo = async (connection, pubKeys) => {
|
||||
let array = [];
|
||||
var pubList = pubKeys.reduce((resultArray, item, index) => {
|
||||
const chunkIndex = Math.floor(index/100)
|
||||
|
||||
if(!resultArray[chunkIndex]) {
|
||||
resultArray[chunkIndex] = [] // start a new chunk
|
||||
}
|
||||
|
||||
resultArray[chunkIndex].push(item)
|
||||
|
||||
return resultArray
|
||||
}, [])
|
||||
|
||||
for await (const subPubList of pubList) {
|
||||
const info = await connection.getMultipleAccountsInfo(subPubList);
|
||||
if (info === null) {
|
||||
throw new Error("Failed to find mint account");
|
||||
}
|
||||
|
||||
info.forEach(buf => {
|
||||
if (buf != null) {
|
||||
const buffer = Buffer.from(buf.data);
|
||||
const data = deserializeAccount(buffer);
|
||||
|
||||
const details = {
|
||||
pubkey: subPubList[info.indexOf(buf)],
|
||||
account: {
|
||||
...buf,
|
||||
},
|
||||
info: data,
|
||||
};
|
||||
|
||||
array.push(details);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
|
||||
// TODO: expose in spl package
|
||||
const deserializeAccount = (data) => {
|
||||
const accountInfo = AccountLayout.decode(data);
|
||||
accountInfo.mint = new PublicKey(accountInfo.mint);
|
||||
accountInfo.owner = new PublicKey(accountInfo.owner);
|
||||
|
||||
if (accountInfo.delegateOption === 0) {
|
||||
accountInfo.delegate = null;
|
||||
} else {
|
||||
accountInfo.delegate = new PublicKey(accountInfo.delegate);
|
||||
}
|
||||
|
||||
accountInfo.isInitialized = accountInfo.state !== 0;
|
||||
accountInfo.isFrozen = accountInfo.state === 2;
|
||||
|
||||
if (accountInfo.isNativeOption === 1) {
|
||||
accountInfo.rentExemptReserve = accountInfo.isNative;
|
||||
accountInfo.isNative = true;
|
||||
} else {
|
||||
accountInfo.rentExemptReserve = null;
|
||||
accountInfo.isNative = false;
|
||||
}
|
||||
|
||||
if (accountInfo.closeAuthorityOption === 0) {
|
||||
accountInfo.closeAuthority = null;
|
||||
} else {
|
||||
accountInfo.closeAuthority = new PublicKey(accountInfo.closeAuthority);
|
||||
}
|
||||
|
||||
return accountInfo;
|
||||
};
|
||||
|
||||
|
||||
const getMintInfo = async (connection, pubKey) => {
|
||||
const info = await connection.getAccountInfo(pubKey);
|
||||
if (info === null) {
|
||||
throw new Error("Failed to find mint account");
|
||||
}
|
||||
|
||||
const data = Buffer.from(info.data);
|
||||
|
||||
return deserializeMint(data);
|
||||
};
|
||||
|
||||
const getMultipleMintInfo = async (connection, pubKeys) => {
|
||||
const info = await connection.getMultipleAccountsInfo(pubKeys);
|
||||
if (info === null) {
|
||||
throw new Error("Failed to find mint account");
|
||||
}
|
||||
|
||||
return info.map(v => {
|
||||
if (v != null) {
|
||||
const data = Buffer.from(v.data);
|
||||
return {
|
||||
key: pubKeys[info.indexOf(v)].toBase58(),
|
||||
data: deserializeMint(data)
|
||||
};
|
||||
}
|
||||
return null;
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// TODO: expose in spl package
|
||||
const deserializeMint = (data) => {
|
||||
if (data.length !== MintLayout.span) {
|
||||
throw new Error("Not a valid Mint");
|
||||
}
|
||||
|
||||
const mintInfo = MintLayout.decode(data);
|
||||
|
||||
if (mintInfo.mintAuthorityOption === 0) {
|
||||
mintInfo.mintAuthority = null;
|
||||
} else {
|
||||
mintInfo.mintAuthority = new PublicKey(mintInfo.mintAuthority);
|
||||
}
|
||||
|
||||
mintInfo.isInitialized = mintInfo.isInitialized !== 0;
|
||||
|
||||
if (mintInfo.freezeAuthorityOption === 0) {
|
||||
mintInfo.freezeAuthority = null;
|
||||
} else {
|
||||
mintInfo.freezeAuthority = new PublicKey(mintInfo.freezeAuthority);
|
||||
}
|
||||
|
||||
return mintInfo;
|
||||
};
|
||||
|
||||
module.exports={ getMultipleAccountInfo, getMultipleMintInfo, deserializeAccount }
|
||||
@@ -1,7 +1,6 @@
|
||||
const {
|
||||
PublicKey,
|
||||
} = require("@solana/web3.js");
|
||||
const { deserializeAccount } = require("./accounts");
|
||||
const { Program } = require("@project-serum/anchor");
|
||||
const PsyAmericanIdl = require("./idl.json");
|
||||
const { getProvider, sumTokens2, } = require("../helper/solana");
|
||||
@@ -30,7 +29,7 @@ async function getPsyAmericanTokenAccounts(anchorProvider) {
|
||||
tokensAndOwners.push([market.underlyingAssetMint.toBase58(), market.key])
|
||||
tokensAndOwners.push([market.quoteAssetMint.toBase58(), market.key])
|
||||
});
|
||||
return { tokensAndOwners };
|
||||
return tokensAndOwners
|
||||
}
|
||||
|
||||
async function getTokenizedEurosControlledAccounts(anchorProvider) {
|
||||
@@ -45,25 +44,16 @@ async function getTokenizedEurosControlledAccounts(anchorProvider) {
|
||||
await anchorProvider.connection.getTokenAccountsByOwner(poolAuthority, {
|
||||
programId: TOKEN_PROGRAM_ID,
|
||||
});
|
||||
const tokensAndOwners = []
|
||||
tokenProgramAccounts.value.forEach((tokenProgramAccount) => {
|
||||
// Decode the account data buffer
|
||||
const dataBuffer = tokenProgramAccount.account.data;
|
||||
const decoded = deserializeAccount(dataBuffer);
|
||||
const mintAddress = decoded.mint.toBase58();
|
||||
tokensAndOwners.push([mintAddress, decoded.owner])
|
||||
});
|
||||
|
||||
return { tokensAndOwners, };
|
||||
return tokenProgramAccounts.value.map(i => i.pubkey.toString())
|
||||
}
|
||||
|
||||
async function tvl() {
|
||||
const anchorProvider = getProvider();
|
||||
const responses = await Promise.all([
|
||||
const [ tokensAndOwners, tokenAccounts, ] = await Promise.all([
|
||||
getPsyAmericanTokenAccounts(anchorProvider),
|
||||
getTokenizedEurosControlledAccounts(anchorProvider),
|
||||
]);
|
||||
return sumTokens2({ tokensAndOwners: responses.map(i => i.tokensAndOwners).flat()})
|
||||
return sumTokens2({ tokenAccounts, tokensAndOwners, })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
const anchor = require("@project-serum/anchor");
|
||||
const { PublicKey } = require("@solana/web3.js");
|
||||
const activePoolBases = require("./active-pools.json");
|
||||
const { getConnection } = require("../helper/solana");
|
||||
const { MintLayout } = require("@solana/spl-token");
|
||||
const { getConnection, decodeAccount } = require("../helper/solana");
|
||||
const sdk = require('@defillama/sdk')
|
||||
|
||||
const SCALLOP_PROGRAM_ID = new PublicKey("SCPv1LabixHirZbX6s7Zj3oiBogadWZvGUKRvXD3Zec");
|
||||
@@ -43,10 +42,10 @@ async function tvl() {
|
||||
if (curr === null)
|
||||
return;
|
||||
|
||||
if (curr.data.length !== MintLayout.span) // invalid mint
|
||||
if (curr.data.length !== 82) // invalid mint
|
||||
return;
|
||||
|
||||
const mintInfo = MintLayout.decode(curr.data);
|
||||
const mintInfo = decodeAccount('mint', curr);
|
||||
const geckoId = getTokenGeckoId(mintInfo.mintAuthority)
|
||||
if (!geckoId) return;
|
||||
const amount = (mintInfo.supply.toString() / Math.pow(10, mintInfo.decimals))
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const BigNumber = require("bignumber.js");
|
||||
const { PublicKey, } = require("@solana/web3.js");
|
||||
const { parseReserve } = require("./utils");
|
||||
const { sliceIntoChunks, } = require('../helper/utils')
|
||||
const { transformBalances, } = require('../helper/portedTokens')
|
||||
const { sumTokens, getConnection, } = require("../helper/solana");
|
||||
const { sumTokens, getConnection, decodeAccount, } = require("../helper/solana");
|
||||
const { fetchURL } = require('../helper/utils')
|
||||
const sdk = require('@defillama/sdk')
|
||||
|
||||
@@ -23,7 +22,7 @@ async function borrowed() {
|
||||
for (const chunk of chunks) {
|
||||
const infos = await connection.getMultipleAccountsInfo(chunk)
|
||||
infos.forEach(i => {
|
||||
const { info: { liquidity } } = parseReserve(i)
|
||||
const { info: { liquidity } } = decodeAccount('reserve', i)
|
||||
const amount = new BigNumber(liquidity.borrowedAmountWads.toString() / 1e18).toFixed(0);
|
||||
sdk.util.sumSingleBalance(balances, liquidity.mintPubkey.toString(), amount)
|
||||
})
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
const BufferLayout = require("buffer-layout");
|
||||
const { PublicKey } = require("@solana/web3.js");
|
||||
const BN = require("bn.js");
|
||||
|
||||
const publicKey = (property = "publicKey") => {
|
||||
const publicKeyLayout = BufferLayout.blob(32, property);
|
||||
|
||||
const _decode = publicKeyLayout.decode.bind(publicKeyLayout);
|
||||
const _encode = publicKeyLayout.encode.bind(publicKeyLayout);
|
||||
|
||||
publicKeyLayout.decode = (buffer, offset) => {
|
||||
const data = _decode(buffer, offset);
|
||||
return new PublicKey(data);
|
||||
};
|
||||
|
||||
publicKeyLayout.encode = (key, buffer, offset) =>
|
||||
_encode(key.toBuffer(), buffer, offset);
|
||||
|
||||
return publicKeyLayout;
|
||||
};
|
||||
|
||||
/**
|
||||
* Layout for a 64bit unsigned value
|
||||
*/
|
||||
const uint64 = (property = "uint64") => {
|
||||
const layout = BufferLayout.blob(8, property);
|
||||
|
||||
const _decode = layout.decode.bind(layout);
|
||||
const _encode = layout.encode.bind(layout);
|
||||
|
||||
layout.decode = (buffer, offset) => {
|
||||
const data = _decode(buffer, offset);
|
||||
return new BN(
|
||||
[...data]
|
||||
.reverse()
|
||||
.map((i) => `00${i.toString(16)}`.slice(-2))
|
||||
.join(""),
|
||||
16
|
||||
);
|
||||
};
|
||||
|
||||
layout.encode = (num, buffer, offset) => {
|
||||
const a = num.toArray().reverse();
|
||||
let b = Buffer.from(a);
|
||||
if (b.length !== 8) {
|
||||
const zeroPad = Buffer.alloc(8);
|
||||
b.copy(zeroPad);
|
||||
b = zeroPad;
|
||||
}
|
||||
return _encode(b, buffer, offset);
|
||||
};
|
||||
|
||||
return layout;
|
||||
};
|
||||
|
||||
const uint128 = (property = "uint128") => {
|
||||
const layout = BufferLayout.blob(16, property);
|
||||
|
||||
const _decode = layout.decode.bind(layout);
|
||||
const _encode = layout.encode.bind(layout);
|
||||
|
||||
layout.decode = (buffer, offset) => {
|
||||
const data = _decode(buffer, offset);
|
||||
return new BN(
|
||||
[...data]
|
||||
.reverse()
|
||||
.map((i) => `00${i.toString(16)}`.slice(-2))
|
||||
.join(""),
|
||||
16
|
||||
);
|
||||
};
|
||||
|
||||
layout.encode = (num, buffer, offset) => {
|
||||
const a = num.toArray().reverse();
|
||||
let b = Buffer.from(a);
|
||||
if (b.length !== 16) {
|
||||
const zeroPad = Buffer.alloc(16);
|
||||
b.copy(zeroPad);
|
||||
b = zeroPad;
|
||||
}
|
||||
|
||||
return _encode(b, buffer, offset);
|
||||
};
|
||||
|
||||
return layout;
|
||||
};
|
||||
const LastUpdateLayout = BufferLayout.struct(
|
||||
[uint64("slot"), BufferLayout.u8("stale")],
|
||||
"lastUpdate"
|
||||
);
|
||||
|
||||
const ReserveLayout = BufferLayout.struct([
|
||||
BufferLayout.u8("version"),
|
||||
|
||||
LastUpdateLayout,
|
||||
|
||||
publicKey("lendingMarket"),
|
||||
|
||||
BufferLayout.struct(
|
||||
[
|
||||
publicKey("mintPubkey"),
|
||||
BufferLayout.u8("mintDecimals"),
|
||||
publicKey("supplyPubkey"),
|
||||
// @FIXME: oracle option
|
||||
// TODO: replace u32 option with generic equivalent
|
||||
// BufferLayout.u32('oracleOption'),
|
||||
publicKey("pythOracle"),
|
||||
publicKey("switchboardOracle"),
|
||||
uint64("availableAmount"),
|
||||
uint128("borrowedAmountWads"),
|
||||
uint128("cumulativeBorrowRateWads"),
|
||||
uint128("marketPrice"),
|
||||
],
|
||||
"liquidity"
|
||||
),
|
||||
|
||||
BufferLayout.struct(
|
||||
[
|
||||
publicKey("mintPubkey"),
|
||||
uint64("mintTotalSupply"),
|
||||
publicKey("supplyPubkey"),
|
||||
],
|
||||
"collateral"
|
||||
),
|
||||
|
||||
BufferLayout.struct(
|
||||
[
|
||||
BufferLayout.u8("optimalUtilizationRate"),
|
||||
BufferLayout.u8("loanToValueRatio"),
|
||||
BufferLayout.u8("liquidationBonus"),
|
||||
BufferLayout.u8("liquidationThreshold"),
|
||||
BufferLayout.u8("minBorrowRate"),
|
||||
BufferLayout.u8("optimalBorrowRate"),
|
||||
BufferLayout.u8("maxBorrowRate"),
|
||||
BufferLayout.struct(
|
||||
[
|
||||
uint64("borrowFeeWad"),
|
||||
uint64("flashLoanFeeWad"),
|
||||
BufferLayout.u8("hostFeePercentage"),
|
||||
],
|
||||
"fees"
|
||||
),
|
||||
uint64("depositLimit"),
|
||||
uint64("borrowLimit"),
|
||||
publicKey("feeReceiver"),
|
||||
],
|
||||
"config"
|
||||
),
|
||||
|
||||
BufferLayout.blob(256, "padding"),
|
||||
]);
|
||||
|
||||
const parseReserve = (info) => {
|
||||
const pubkey = PublicKey.default
|
||||
const { data } = info;
|
||||
const buffer = Buffer.from(data);
|
||||
const reserve = ReserveLayout.decode(buffer);
|
||||
|
||||
if (reserve.lastUpdate.slot.isZero()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const details = {
|
||||
pubkey,
|
||||
account: {
|
||||
...info,
|
||||
},
|
||||
info: reserve,
|
||||
};
|
||||
|
||||
return details;
|
||||
};
|
||||
module.exports = {
|
||||
parseReserve,
|
||||
};
|
||||
@@ -1,13 +1,12 @@
|
||||
const { PublicKey } = require("@solana/web3.js");
|
||||
const { getConnection } = require("../helper/solana");
|
||||
const { MintLayout } = require("@solana/spl-token");
|
||||
const { getConnection, decodeAccount, } = require("../helper/solana");
|
||||
|
||||
async function tvl() {
|
||||
const connection = getConnection()
|
||||
const mint = await connection.getAccountInfo(new PublicKey('7kbnvuGBxxj8AG9qp8Scn56muWGaRaFqxg1FsRp3PaFT'));
|
||||
const mintInfo = MintLayout.decode(mint.data);
|
||||
const mintInfo = decodeAccount('mint', mint)
|
||||
return {
|
||||
'uxd-stablecoin': mintInfo.supply.toString()/ (10**mintInfo.decimals)
|
||||
'uxd-stablecoin': mintInfo.supply.toString() / (10 ** mintInfo.decimals)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user