Skip to content

Commit b3b46ff

Browse files
committed
bump version
1 parent fbe0bb5 commit b3b46ff

7 files changed

Lines changed: 359 additions & 205 deletions

File tree

solend-sdk/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ scripts.ts
22
__tests__/scripts.test.ts
33
dist/
44
node_modules/
5+
.cursorrules
6+
.cursor

solend-sdk/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@solendprotocol/solend-sdk",
3-
"version": "0.14.8",
3+
"version": "0.14.27",
44
"private": true,
55
"main": "src/index.ts",
66
"module": "src/index.ts",
@@ -10,6 +10,7 @@
1010
],
1111
"license": "MIT",
1212
"scripts": {
13+
"tsc": "tsc",
1314
"docs": "typedoc",
1415
"build": "rm -rf dist/; yarn tsc",
1516
"test": "yarn jest",
@@ -29,7 +30,7 @@
2930
"@solana/web3.js": "=1.92.3",
3031
"@solendprotocol/token2022-wrapper-sdk": "^1.0.1",
3132
"@solflare-wallet/utl-sdk": "^1.4.0",
32-
"@switchboard-xyz/on-demand": "1.2.43",
33+
"@switchboard-xyz/on-demand": "^2.14.5",
3334
"@switchboard-xyz/sbv2-lite": "^0.2.4",
3435
"axios": "^0.24.0",
3536
"bignumber.js": "^9.0.2",
@@ -40,7 +41,7 @@
4041
"hot-shots": "^9.3.0",
4142
"isomorphic-fetch": "^3.0.0",
4243
"jsbi": "^4.3.0",
43-
"rpc-websockets": "7.11.0",
44+
"rpc-websockets": "^9.1.3",
4445
"typedoc-plugin-cname": "^1.0.1"
4546
},
4647
"devDependencies": {
@@ -61,6 +62,6 @@
6162
"ts-jest": "^28.0.7",
6263
"ts-node": "^10.9.1",
6364
"typedoc": "^0.22.10",
64-
"typescript": "~5.3.3"
65+
"typescript": "~5.4.3"
6566
}
6667
}

solend-sdk/src/core/actions.ts

Lines changed: 98 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import {
4949
withdrawExact,
5050
liquidateObligationAndRedeemReserveCollateral,
5151
} from "../instructions";
52-
import { NULL_ORACLE, POSITION_LIMIT } from "./constants";
52+
import { FEE_RECEIVER_AUTHORITY, NULL_ORACLE, POSITION_LIMIT } from "./constants";
5353
import { EnvironmentType } from "./types";
5454
import { getProgramId, U64_MAX, WAD } from "./constants";
5555
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
@@ -58,7 +58,6 @@ import {
5858
loadLookupTables,
5959
PullFeed,
6060
ON_DEMAND_MAINNET_PID,
61-
CrossbarClient,
6261
} from "@switchboard-xyz/on-demand";
6362
import {
6463
createDepositAndMintWrapperTokensInstruction,
@@ -114,35 +113,37 @@ type SupportType =
114113
| "wrapRepay"
115114
| "wsol";
116115

117-
const ACTION_SUPPORT_REQUIREMENTS: {
118-
[Property in ActionType]: Array<SupportType>;
119-
} = {
120-
deposit: ["wsol", "wrap", "createObligation", "cAta"],
121-
borrow: ["wsol", "ata", "refreshReserves", "refreshObligation", "unwrap"],
122-
withdraw: [
123-
"wsol",
124-
"ata",
125-
"cAta",
126-
"refreshReserves",
127-
"refreshObligation",
128-
"unwrap",
129-
],
130-
repay: ["wsol", "wrap"],
131-
mint: ["wsol", "wrap", "cAta"],
132-
redeem: ["wsol", "ata", "refreshReserve", "unwrap"],
133-
depositCollateral: ["createObligation"],
134-
withdrawCollateral: ["cAta", "refreshReserves", "refreshObligation"],
135-
forgive: ["refreshReserves", "refreshObligation"],
136-
liquidate: [
137-
"wsol",
138-
"ata",
139-
"cAta",
140-
"wrapRepay",
141-
"unwrap",
142-
"refreshReserves",
143-
"refreshObligation",
144-
],
145-
};
116+
function getSupportRequirementsForAction(action: ActionType, hasBorrows: boolean): Array<SupportType> {
117+
const actionSupportRequirements: { [Property in ActionType]: Array<SupportType> } = {
118+
deposit: ["wsol", "wrap", "createObligation", "cAta"],
119+
borrow: ["wsol", "ata", "refreshReserves", "refreshObligation", "unwrap"],
120+
withdraw: [
121+
"wsol",
122+
"ata",
123+
"cAta",
124+
hasBorrows ? "refreshReserves" : undefined,
125+
hasBorrows ? "refreshObligation" : undefined,
126+
"unwrap",
127+
].filter((support) => support !== undefined) as Array<SupportType>,
128+
repay: ["wsol", "wrap"],
129+
mint: ["wsol", "wrap", "cAta"],
130+
redeem: ["wsol", "ata", hasBorrows ? "refreshReserve" : undefined, "unwrap"].filter((support) => support !== undefined) as Array<SupportType>,
131+
depositCollateral: ["createObligation"],
132+
withdrawCollateral: ["cAta", hasBorrows ? "refreshReserves" : undefined, hasBorrows ? "refreshObligation" : undefined].filter((support) => support !== undefined) as Array<SupportType>,
133+
forgive: ["refreshReserves", "refreshObligation"],
134+
liquidate: [
135+
"wsol",
136+
"ata",
137+
"cAta",
138+
"wrapRepay",
139+
"unwrap",
140+
"refreshReserves",
141+
"refreshObligation",
142+
],
143+
};
144+
145+
return actionSupportRequirements[action];
146+
}
146147

147148
export const toHexString = (byteArray: number[]) => {
148149
return (
@@ -187,6 +188,8 @@ export type InstructionWithSigners = {
187188
signers?: Array<Signer>;
188189
lookupTableAccounts?: AddressLookupTableAccount[];
189190
computeUnits: number;
191+
groupIndex?: number;
192+
index0?: boolean;
190193
};
191194

192195
export const createDepositAndMintWrapperTokensInstructionComputeUnits = 55_154;
@@ -669,7 +672,7 @@ export class SolendActionCore {
669672
);
670673

671674
await axn.addSupportIxs("withdrawCollateral");
672-
await axn.addWithdrawIx();
675+
await axn.addWithdrawObligationCollateralIx();
673676

674677
return axn;
675678
}
@@ -970,7 +973,7 @@ export class SolendActionCore {
970973
this.publicKey, // transferAuthority
971974
this.programId
972975
),
973-
computeUnits: 44_207
976+
computeUnits: 100_000
974977
}
975978
);
976979
}
@@ -1018,9 +1021,9 @@ export class SolendActionCore {
10181021
);
10191022
}
10201023

1021-
addBorrowIx() {
1024+
async addBorrowIx() {
10221025
if (this.debug) console.log("adding borrow ix to lending txn");
1023-
if (this.hostAta && this.hostPublicKey) {
1026+
if (this.hostAta && this.hostPublicKey && (this.hostPublicKey.toBase58() !== this.publicKey.toBase58())) {
10241027
this.preTxnIxs.push(
10251028
{
10261029
instruction: createAssociatedTokenAccountIdempotentInstruction(
@@ -1033,6 +1036,20 @@ export class SolendActionCore {
10331036
}
10341037
);
10351038
}
1039+
const liquidityFeeReceiverAccount = await this.connection.getAccountInfo(new PublicKey(this.reserve.liquidityFeeReceiverAddress));
1040+
if (!liquidityFeeReceiverAccount) {
1041+
this.preTxnIxs.push(
1042+
{
1043+
instruction: createAssociatedTokenAccountIdempotentInstruction(
1044+
this.publicKey,
1045+
new PublicKey(this.reserve.liquidityFeeReceiverAddress),
1046+
FEE_RECEIVER_AUTHORITY,
1047+
new PublicKey(this.reserve.mintAddress)
1048+
),
1049+
computeUnits: 21_845
1050+
}
1051+
);
1052+
}
10361053
this.lendingIxs.push(
10371054
{
10381055
lookupTableAccounts: this.lookupTableAccount ? [this.lookupTableAccount] : undefined,
@@ -1163,7 +1180,7 @@ export class SolendActionCore {
11631180
}
11641181

11651182
async addSupportIxs(action: ActionType) {
1166-
const supports = ACTION_SUPPORT_REQUIREMENTS[action];
1183+
const supports = getSupportRequirementsForAction(action, this.borrowReserves.length > 0);
11671184

11681185
for (const support of supports) {
11691186
switch (support) {
@@ -1244,9 +1261,9 @@ export class SolendActionCore {
12441261
{
12451262
instruction: createAssociatedTokenAccountIdempotentInstruction(
12461263
this.publicKey,
1247-
this.wrappedAta,
1248-
this.publicKey,
1249-
this.token2022Mint,
1264+
this.wrappedAta,
1265+
this.publicKey,
1266+
this.token2022Mint,
12501267
TOKEN_2022_PROGRAM_ID
12511268
),
12521269
computeUnits: createAssociatedTokenAccountIdempotentInstructionComputeUnits
@@ -1296,13 +1313,14 @@ export class SolendActionCore {
12961313
}
12971314

12981315
static async buildPullPriceIxsStatic(
1299-
oracleKeys: Array<string>,
1316+
unfilteredOracleKeys: Array<string>,
13001317
connection: Connection,
13011318
wallet: SaveWallet,
13021319
computeUnitPriceMicroLamports?: number,
13031320
environment?: EnvironmentType,
13041321
debug?: boolean,
13051322
) {
1323+
const oracleKeys = unfilteredOracleKeys.filter(k => k !== 'nu11111111111111111111111111111111111111111' && k !== '11111111111111111111111111111111');
13061324
let oracleIxs: InstructionWithSigners[] = [];
13071325
let pullPriceTxns: VersionedTransaction[] = [];
13081326
let pythIxGroups: Array<Array<InstructionWithSigners>> = [];
@@ -1313,10 +1331,10 @@ export class SolendActionCore {
13131331
units: 1_000_000,
13141332
});
13151333

1316-
const oracleAccounts = await connection.getMultipleAccountsInfo(
1334+
const oracleAccounts = (await connection.getMultipleAccountsInfo(
13171335
oracleKeys.map((o) => new PublicKey(o)),
13181336
"processed"
1319-
);
1337+
));
13201338

13211339
const provider = new AnchorProvider(connection, {
13221340
publicKey: wallet.publicKey,
@@ -1327,7 +1345,6 @@ export class SolendActionCore {
13271345

13281346
if (environment === "production" || environment === "beta") {
13291347
const sbod = new Program(idl, provider);
1330-
console.log(oracleAccounts);
13311348
const sbPulledOracles = oracleKeys.filter(
13321349
(_o, index) =>
13331350
oracleAccounts[index]?.owner.toBase58() === sbod.programId.toBase58()
@@ -1351,61 +1368,63 @@ export class SolendActionCore {
13511368
1
13521369
);
13531370

1354-
const res = sbPulledOracles.reduce((acc, _curr, i) => {
1371+
const res = feedAccounts.reduce((acc, _curr, i) => {
13551372
if (!(i % 3)) {
13561373
// if index is 0 or can be divided by the `size`...
1357-
acc.push(sbPulledOracles.slice(i, i + 3)); // ..push a chunk of the original array to the accumulator
1374+
acc.push(feedAccounts.slice(i, i + 3)); // ..push a chunk of the original array to the accumulator
13581375
}
13591376
return acc;
1360-
}, [] as string[][]);
1377+
}, [] as PullFeed[][]);
1378+
1379+
const signatureInstructionIdxRaw =
1380+
typeof localStorage !== "undefined"
1381+
? localStorage.getItem("signatureInstructionIdx")
1382+
: null;
1383+
const signatureInstructionIdx = signatureInstructionIdxRaw
1384+
? parseInt(signatureInstructionIdxRaw)
1385+
: undefined;
13611386

1362-
const crossbar = new CrossbarClient(CROSSBAR_URL2);
13631387
await Promise.all(
1364-
res.map(async (oracleGroup) => {
1365-
const [ix, accountLookups, responses] =
1388+
res.map(async (feedAccountGroup, groupIndex) => {
1389+
const gateway = await feedAccountGroup[0].fetchGatewayUrl();
1390+
const [ix, accountLookups] =
13661391
await PullFeed.fetchUpdateManyIx(sbod as any, {
1367-
feeds: oracleGroup.map((p) => new PublicKey(p)),
1368-
crossbarClient: crossbar,
1369-
1370-
numSignatures,
1371-
});
1372-
1373-
// responses?.oracle_responses.forEach((response) => {
1374-
// response?.errors.forEach((error) => {
1375-
// if (error) {
1376-
// console.error(error);
1377-
// }
1378-
// });
1379-
// });
1380-
1381-
console.log('updated');
1392+
chain: "solana",
1393+
network: "mainnet-beta",
1394+
feeds: feedAccountGroup,
1395+
numSignatures,
1396+
gateway,
1397+
signatureInstructionIdx,
1398+
},
1399+
);
13821400

13831401
const lookupTables = (await loadLookupTables(feedAccounts)).concat(
13841402
accountLookups
13851403
);
13861404

1387-
const instructions = [priorityFeeIx, modifyComputeUnits, ix];
1405+
const instructions = [priorityFeeIx, modifyComputeUnits, ...ix];
13881406

1389-
// Get the latest context
13901407
const {
13911408
value: { blockhash },
13921409
} = await connection.getLatestBlockhashAndContext();
13931410

1394-
// Get Transaction Message
13951411
const message = new TransactionMessage({
13961412
payerKey: wallet.publicKey,
13971413
recentBlockhash: blockhash,
13981414
instructions,
13991415
}).compileToV0Message(lookupTables);
14001416

1401-
// Get Versioned Transaction
14021417
const vtx = new VersionedTransaction(message);
14031418

14041419
if (debug) console.log("adding sbod ix to pullPriceTxns");
1405-
oracleIxs.push({
1406-
instruction: ix,
1407-
lookupTableAccounts: lookupTables,
1408-
computeUnits: 400_000 + sbPulledOracles.length * 100_000,
1420+
ix.forEach((ixn, index) => {
1421+
oracleIxs.push({
1422+
instruction: ixn,
1423+
lookupTableAccounts: lookupTables,
1424+
computeUnits: index === 0 ? 400_000 + sbPulledOracles.length * 100_000 : 10_000,
1425+
groupIndex,
1426+
index0: true
1427+
});
14091428
});
14101429
pullPriceTxns.push(vtx);
14111430
})
@@ -1458,8 +1477,8 @@ export class SolendActionCore {
14581477
priceFeedId: string;
14591478
}>
14601479
)
1461-
.sort((a, b) => a.key - b.key)
1462-
.map((x) => x.priceFeedId);
1480+
.sort((a, b) => a.key - b.key)
1481+
.map((x) => x.priceFeedId);
14631482

14641483
if (shuffledPriceIds.length) {
14651484
if (debug) console.log("Feed accounts", shuffledPriceIds);
@@ -1472,39 +1491,33 @@ export class SolendActionCore {
14721491
0 // shardId of 0
14731492
);
14741493

1475-
transactionBuilder.addInstructions([
1476-
{ instruction: priorityFeeIx, signers: [] },
1477-
{ instruction: modifyComputeUnits, signers: [] },
1478-
]);
1479-
14801494
const transactionsWithSigners =
14811495
await transactionBuilder.buildVersionedTransactions({});
14821496

1483-
for (const transaction of transactionsWithSigners) {
1497+
for (const [index, transaction] of transactionsWithSigners.entries()) {
14841498
const signers = transaction.signers;
14851499
const tx = transaction.tx;
14861500
const lookupTables = await Promise.all(tx.message.addressTableLookups.map((lookup) => connection.getAddressLookupTable(lookup.accountKey)));
14871501

14881502
if (signers) {
14891503
tx.sign(signers);
14901504
}
1491-
pythIxGroups.push(transactionBuilder.transactionInstructions.flatMap((ixs, index1) => ixs.instructions.map(
1505+
pythIxGroups.push(transactionBuilder.transactionInstructions[index].instructions.map(
14921506
(ix, index2) => {
14931507
let computeUnits = 0;
1494-
if (index1 === 0 && index2 === 0) {
1508+
if (index2 === 0) {
14951509
computeUnits = 355_787;
14961510
}
14971511
if (ix.programId.toBase58() === 'pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT') {
14981512
computeUnits = 43825;
14991513
}
1500-
15011514
return ({
15021515
instruction: ix,
1503-
signers: ixs.signers,
1516+
signers: transactionBuilder.transactionInstructions[index].signers,
15041517
lookupTables: lookupTables,
15051518
computeUnits,
15061519
})}
1507-
)));
1520+
));
15081521
pullPriceTxns.push(tx);
15091522
}
15101523
console.log(

0 commit comments

Comments
 (0)