Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bump version
Browse files Browse the repository at this point in the history
0xodia committed Jul 19, 2024
1 parent 87b8182 commit 64bb9c4
Showing 4 changed files with 98 additions and 75 deletions.
93 changes: 50 additions & 43 deletions solend-sdk/__tests__/oracle.test.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ import {
Connection,
Keypair,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
@@ -12,13 +13,15 @@ import {
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { AnchorProvider, Program } from "@coral-xyz/anchor-30";
import { CrossbarClient, loadLookupTables, PullFeed, SB_ON_DEMAND_PID } from "@switchboard-xyz/on-demand";
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";

jest.setTimeout(50_000);

describe("check", function () {
const connection = new Connection("https://api.mainnet-beta.solana.com");
const testKey = [];

describe("pulls sb oracles", function () {
it("pulls switchboard oracle", async function () {
const connection = new Connection("https://api.mainnet-beta.solana.com");
const testKey = []
if (testKey.length === 0) {
throw Error('Best tested with a throwaway mainnet test account.')
}
@@ -31,22 +34,28 @@ import {

const sbPulledOracles = [
'2F9M59yYc28WMrAymNWceaBEk8ZmDAjUAKULp8seAJF3',
'AZcoqpWhMJUaKEDUfKsfzCr3Y96gSQwv43KSQ6KpeyQ1'
'AZcoqpWhMJUaKEDUfKsfzCr3Y96gSQwv43KSQ6KpeyQ1',
'Ai2GsLRioGKwVgWX8dtbLF5rJJEZX17SteGEDqrpzBv3',
'4sPZ75ipUH9W2CC7gfpipLpPLN5m7RD2FES9SfegfZbP',
'AJkAFiXdbMonys8rTXZBrRnuUiLcDFdkyoPuvrVKXhex',
// '65J9bVEMhNbtbsNgArNV1K4krzcsomjho4bgR51sZXoj'
];

// Example usage
const feedAccounts = sbPulledOracles.map((oracleKey) => new PullFeed(sbod as any, oracleKey));
const crossbar = new CrossbarClient("https://crossbar.switchboard.xyz");
const crossbar = new CrossbarClient("https://crossbar-fvumormova-uc.a.run.app");

// Responses is Array<[pullIx, responses, success]>
const responses = await Promise.all(feedAccounts.map((feedAccount) => feedAccount.fetchUpdateIx({ numSignatures: 1, crossbarClient: crossbar })));
const responses = await Promise.all(feedAccounts.map((feedAccount) => feedAccount.fetchUpdateIx({ numSignatures: 1, crossbarClient: crossbar,
gateway: 'https://xoracle-1-mn.switchboard.xyz' })));
const oracles = responses.flatMap((x) => x[1].map(y => y.oracle));
const lookupTables = await loadLookupTables([...oracles, ...feedAccounts]);

// Get the latest context
const {
value: { blockhash },
} = await connection.getLatestBlockhashAndContext();

// Get Transaction Message
const message = new TransactionMessage({
payerKey: provider.publicKey,
@@ -62,50 +71,48 @@ import {
});

it("pulls pyth oracles", async function () {
const connection = new Connection("https://api.mainnet-beta.solana.com");
const testKey = []
if (testKey.length === 0) {
throw Error('Best tested with a throwaway mainnet test account.')
}
const priceServiceConnection = new PriceServiceConnection("https://hermes.pyth.network");
const pythSolanaReceiver = new PythSolanaReceiver({
connection: connection,
wallet: new NodeWallet(Keypair.fromSecretKey(new Uint8Array(
testKey
)))
});
const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
closeUpdateAccounts: true,
});

let priceFeedUpdateData;
priceFeedUpdateData = await priceServiceConnection.getLatestVaas(
[
'0x93c3def9b169f49eed14c9d73ed0e942c666cf0e1290657ec82038ebb792c2a8', // BLZE
'0xf2fc1dfcf51867abfa70874c929e920edc649e4997cbac88f280094df8c72bcd', // EUROE
]
);

await transactionBuilder.addUpdatePriceFeed(
priceFeedUpdateData,
0 // shardId of 0
);

const transactionsWithSigners = await transactionBuilder.buildVersionedTransactions({
tightComputeBudget: true,
});

const pullPriceTxns = [] as Array<VersionedTransaction>;
const priceServiceConnection = new PriceServiceConnection("https://hermes.pyth.network");
const pythSolanaReceiver = new PythSolanaReceiver({
connection: connection,
wallet: new NodeWallet(Keypair.fromSecretKey(new Uint8Array(
testKey
)))
});
const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
closeUpdateAccounts: true,
});

let priceFeedUpdateData;
priceFeedUpdateData = await priceServiceConnection.getLatestVaas(
[
'eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a', // USDC
]
);

await transactionBuilder.addUpdatePriceFeed(
priceFeedUpdateData,
0 // shardId of 0
);

const transactionsWithSigners = await transactionBuilder.buildVersionedTransactions({
tightComputeBudget: true,
jitoTipLamports: 10

for (const transaction of transactionsWithSigners) {
});

const pullPriceTxns = [] as Array<VersionedTransaction>;

for (const transaction of transactionsWithSigners) {
const signers = transaction.signers;
let tx = transaction.tx;

if (signers) {
if (signers) {
tx.sign(signers);
}
pullPriceTxns.push(tx);
}
}
}

pythSolanaReceiver.wallet.signAllTransactions(pullPriceTxns)

3 changes: 2 additions & 1 deletion solend-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@solendprotocol/solend-sdk",
"version": "0.10.11",
"version": "0.11.10",
"private": true,
"main": "src/index.ts",
"module": "src/index.ts",
@@ -19,6 +19,7 @@
"release": "yarn build; ts-node ./prepublish.ts; yarn --cwd ./dist publish"
},
"dependencies": {
"@coral-xyz/anchor-30": "npm:@coral-xyz/anchor@0.30.1",
"@project-serum/anchor": "^0.24.2",
"@pythnetwork/client": "^2.12.0",
"@pythnetwork/price-service-client": "^1.9.0",
75 changes: 44 additions & 31 deletions solend-sdk/src/core/actions.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ import {
BlockhashWithExpiryBlockHeight,
ComputeBudgetProgram,
Connection,
Keypair,
PublicKey,
SystemProgram,
Transaction,
@@ -48,7 +47,6 @@ import {
import { NULL_ORACLE, POSITION_LIMIT } from "./constants";
import { EnvironmentType, PoolType, ReserveType } from "./types";
import { getProgramId, U64_MAX, WAD } from "./constants";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { AnchorProvider, Program } from "@coral-xyz/anchor-30";
import {
@@ -150,7 +148,8 @@ export class SolendActionCore {
borrowReserves: Array<PublicKey>,
hostAta?: PublicKey,
lookupTableAccount?: AddressLookupTableAccount,
ownerPublicKey?: PublicKey
ownerPublicKey?: PublicKey,
tipAmount?: number
) {
this.programId = programId;
this.connection = connection;
@@ -175,7 +174,7 @@ export class SolendActionCore {
this.borrowReserves = borrowReserves;
this.lookupTableAccount = lookupTableAccount;
this.ownerPublicKey = ownerPublicKey;
this.jitoTipAmount = 1000;
this.jitoTipAmount = tipAmount ?? 1000;
this.wallet = wallet;
}

@@ -191,7 +190,8 @@ export class SolendActionCore {
hostAta?: PublicKey,
customObligationSeed?: string,
lookupTableAddress?: PublicKey,
ownerPublicKey?: PublicKey
ownerPublicKey?: PublicKey,
tipAmount?: number
) {
const seed = customObligationSeed ?? pool.address.slice(0, 32);
const programId = getProgramId(environment);
@@ -277,7 +277,8 @@ export class SolendActionCore {
borrowReserves,
hostAta,
lookupTableAccount ?? undefined,
ownerPublicKey
ownerPublicKey,
tipAmount
);
}

@@ -351,7 +352,8 @@ export class SolendActionCore {
environment: EnvironmentType = "production",
customObligationAddress?: PublicKey,
hostAta?: PublicKey,
lookupTableAddress?: PublicKey
lookupTableAddress?: PublicKey,
tipAmount?: number
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -364,7 +366,9 @@ export class SolendActionCore {
customObligationAddress,
hostAta,
undefined,
lookupTableAddress
lookupTableAddress,
undefined,
tipAmount
);

await axn.addSupportIxs("borrow");
@@ -493,7 +497,8 @@ export class SolendActionCore {
environment: EnvironmentType = "production",
obligationAddress?: PublicKey,
obligationSeed?: string,
lookupTableAddress?: PublicKey
lookupTableAddress?: PublicKey,
tipAmount?: number
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -507,7 +512,8 @@ export class SolendActionCore {
undefined,
obligationSeed,
lookupTableAddress,
undefined
undefined,
tipAmount
);

await axn.addSupportIxs("withdraw");
@@ -597,8 +603,6 @@ export class SolendActionCore {
}

private getTipIx() {
if (!this.jitoTipAmount) return;

const tipAccounts = [
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe",
@@ -923,11 +927,7 @@ export class SolendActionCore {
closeUpdateAccounts: true,
});

const provider = new AnchorProvider(
this.connection,
new NodeWallet(Keypair.fromSeed(new Uint8Array(32).fill(1))),
{}
);
const provider = new AnchorProvider(this.connection, this.wallet, {});
const idl = (await Program.fetchIdl(SB_ON_DEMAND_PID, provider))!;
const sbod = new Program(idl, provider);

@@ -939,14 +939,17 @@ export class SolendActionCore {
const feedAccounts = sbPulledOracles.map(
(oracleKey) => new PullFeed(sbod as any, oracleKey)
);
const crossbar = new CrossbarClient("https://crossbar.switchboard.xyz");
const crossbar = new CrossbarClient(
"https://crossbar-fvumormova-uc.a.run.app"
);

// Responses is Array<[pullIx, responses, success]>
const responses = await Promise.all(
feedAccounts.map((feedAccount) =>
feedAccount.fetchUpdateIx({
numSignatures: 1,
crossbarClient: crossbar,
gateway: "https://xoracle-1-mn.switchboard.xyz",
})
)
);
@@ -962,10 +965,7 @@ export class SolendActionCore {

const instructions = [priorityFeeIx, ...responses.map((r) => r[0]!)];

const tip = this.getTipIx();
if (tip) {
instructions.push(tip);
}
instructions.push(this.getTipIx());

// Get the latest context
const {
@@ -990,8 +990,8 @@ export class SolendActionCore {
o?.owner.toBase58() === pythSolanaReceiver.receiver.programId.toBase58()
);

if (pythPulledOracles.length) {
const shuffledPriceIds = pythPulledOracles
const shuffledPriceIds = (
pythPulledOracles
.map((pythOracleData, index) => {
if (!pythOracleData) {
throw new Error(`Could not find oracle data at index ${index}`);
@@ -1002,14 +1002,27 @@ export class SolendActionCore {
pythOracleData.data
);

return {
key: Math.random(),
priceFeedId: toHexString(priceUpdate.priceMessage.feedId),
};
const needUpdate =
Date.now() / 1000 -
Number(priceUpdate.priceMessage.publishTime.toString()) >
70;

return needUpdate
? {
key: Math.random(),
priceFeedId: toHexString(priceUpdate.priceMessage.feedId),
}
: undefined;
})
.sort((a, b) => a.key - b.key)
.map((x) => x.priceFeedId);

.filter(Boolean) as Array<{
key: number;
priceFeedId: string;
}>
)
.sort((a, b) => a.key - b.key)
.map((x) => x.priceFeedId);

if (shuffledPriceIds.length) {
const priceFeedUpdateData = await priceServiceConnection.getLatestVaas(
shuffledPriceIds
);
2 changes: 2 additions & 0 deletions solend-sdk/src/instructions/instruction.ts
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ export enum LendingInstruction {
DepositReserveLiquidityAndObligationCollateral = 14,
WithdrawObligationCollateralAndRedeemReserveLiquidity = 15,
UpdateReserveConfig = 16,
LiquidateObligationAndRedeemReserveCollateral = 17,
RedeemFees = 18,
FlashBorrowReserveLiquidity = 19,
FlashRepayReserveLiquidity = 20,
ForgiveDebt = 21,

0 comments on commit 64bb9c4

Please sign in to comment.