diff --git a/solend-lite/package.json b/solend-lite/package.json
index 65516ad9..ff788690 100644
--- a/solend-lite/package.json
+++ b/solend-lite/package.json
@@ -15,6 +15,7 @@
"@chakra-ui/react": "^2.4.9",
"@chakra-ui/styled-system": "^2.5.1",
"@chakra-ui/theme-tools": "^2.0.16",
+ "@coral-xyz/anchor": "^0.30.1",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@next/font": "13.0.7",
diff --git a/solend-lite/public/og_image.png b/solend-lite/public/og_image.png
new file mode 100644
index 00000000..fb1c61f8
Binary files /dev/null and b/solend-lite/public/og_image.png differ
diff --git a/solend-lite/src/components/AccountMetrics/AccountMetrics.tsx b/solend-lite/src/components/AccountMetrics/AccountMetrics.tsx
index b755aa6c..ae40932a 100644
--- a/solend-lite/src/components/AccountMetrics/AccountMetrics.tsx
+++ b/solend-lite/src/components/AccountMetrics/AccountMetrics.tsx
@@ -24,27 +24,21 @@ function AccountMetrics(): ReactElement {
diff --git a/solend-lite/src/components/TransactionTakeover/TransactionTakeover.tsx b/solend-lite/src/components/TransactionTakeover/TransactionTakeover.tsx
index fd6d678b..42f14ba8 100644
--- a/solend-lite/src/components/TransactionTakeover/TransactionTakeover.tsx
+++ b/solend-lite/src/components/TransactionTakeover/TransactionTakeover.tsx
@@ -28,13 +28,15 @@ import Result, { ResultConfigType } from 'components/Result/Result';
import BigNumber from 'bignumber.js';
import { connectionAtom, refreshPageAtom } from 'stores/settings';
import { rateLimiterAtom, selectedPoolAtom } from 'stores/pools';
-import { useWallet } from '@solana/wallet-adapter-react';
+import { useAnchorWallet, useWallet } from '@solana/wallet-adapter-react';
import { U64_MAX } from '@solendprotocol/solend-sdk';
import { SKIP_PREFLIGHT } from 'common/config';
import { selectedModalTabAtom, selectedReserveAtom } from 'stores/modal';
+import { Wallet } from '@coral-xyz/anchor';
export default function TransactionTakeover() {
const { sendTransaction, signAllTransactions } = useWallet();
+ const anchorWallet = useAnchorWallet();
const [publicKey] = useAtom(publicKeyAtom);
const [connection] = useAtom(connectionAtom);
const [rateLimiter] = useAtom(rateLimiterAtom);
@@ -143,7 +145,7 @@ export default function TransactionTakeover() {
new BigNumber(value)
.shiftedBy(selectedReserve.decimals)
.toFixed(0),
- publicKey,
+ anchorWallet as Wallet,
selectedPool,
selectedReserve,
connection,
@@ -185,7 +187,7 @@ export default function TransactionTakeover() {
: new BigNumber(value)
.shiftedBy(selectedReserve.decimals)
.toFixed(0),
- publicKey,
+ anchorWallet as Wallet,
selectedPool,
selectedReserve,
connection,
@@ -229,7 +231,7 @@ export default function TransactionTakeover() {
: new BigNumber(value)
.shiftedBy(selectedReserve.decimals)
.toFixed(0),
- publicKey,
+ anchorWallet as Wallet,
selectedPool,
selectedReserve,
connection,
@@ -273,7 +275,7 @@ export default function TransactionTakeover() {
: new BigNumber(value)
.shiftedBy(selectedReserve.decimals)
.toFixed(0),
- publicKey,
+ anchorWallet as Wallet,
selectedPool,
selectedReserve,
connection,
diff --git a/solend-lite/src/components/TransactionTakeover/configs.tsx b/solend-lite/src/components/TransactionTakeover/configs.tsx
index df443e68..d0782788 100644
--- a/solend-lite/src/components/TransactionTakeover/configs.tsx
+++ b/solend-lite/src/components/TransactionTakeover/configs.tsx
@@ -14,6 +14,7 @@ import { getAssociatedTokenAddress, NATIVE_MINT } from '@solana/spl-token';
import { ENVIRONMENT, HOST_ATA } from 'common/config';
import { sendAndConfirmStrategy } from 'components/TransactionTakeover/util';
import { WalletContextState } from '@solana/wallet-adapter-react';
+import { Wallet } from '@coral-xyz/anchor';
const SOL_PADDING_FOR_RENT_AND_FEE = 0.02;
@@ -28,7 +29,7 @@ export function sufficientSOLForTransaction(wallet: WalletType) {
export const supplyConfigs = {
action: async (
value: string,
- publicKey: string,
+ wallet: Wallet,
pool: PoolType,
selectedReserve: SelectedReserveType,
connection: Connection,
@@ -45,8 +46,10 @@ export const supplyConfigs = {
selectedReserve,
connection,
value,
- new PublicKey(publicKey),
- ENVIRONMENT,
+ wallet,
+ {
+ environment: ENVIRONMENT,
+ }
);
return sendAndConfirmStrategy(
@@ -158,7 +161,7 @@ export const supplyConfigs = {
export const borrowConfigs = {
action: async (
value: string,
- publicKey: string,
+ wallet: Wallet,
pool: PoolType,
selectedReserve: SelectedReserveType,
connection: Connection,
@@ -191,10 +194,11 @@ export const borrowConfigs = {
selectedReserve,
connection,
value,
- new PublicKey(publicKey),
- ENVIRONMENT,
- undefined,
- hostAta,
+ wallet,
+ {
+ environment: ENVIRONMENT,
+ hostAta,
+ }
);
return sendAndConfirmStrategy(
@@ -359,7 +363,7 @@ export const borrowConfigs = {
export const withdrawConfigs = {
action: async (
value: string,
- publicKey: string,
+ wallet: Wallet,
pool: PoolType,
selectedReserve: SelectedReserveType,
connection: Connection,
@@ -376,8 +380,10 @@ export const withdrawConfigs = {
selectedReserve,
connection,
value,
- new PublicKey(publicKey),
- ENVIRONMENT,
+ wallet,
+ {
+ environment: ENVIRONMENT,
+ }
);
return sendAndConfirmStrategy(
@@ -552,7 +558,7 @@ export const withdrawConfigs = {
export const repayConfigs = {
action: async (
value: string,
- publicKey: string,
+ wallet: Wallet,
pool: PoolType,
selectedReserve: SelectedReserveType,
connection: Connection,
@@ -569,8 +575,10 @@ export const repayConfigs = {
selectedReserve,
connection,
value,
- new PublicKey(publicKey),
- ENVIRONMENT,
+ wallet,
+ {
+ environment: ENVIRONMENT,
+ },
);
return sendAndConfirmStrategy(
diff --git a/solend-lite/src/pages/index.tsx b/solend-lite/src/pages/index.tsx
index 4485f361..6c344633 100644
--- a/solend-lite/src/pages/index.tsx
+++ b/solend-lite/src/pages/index.tsx
@@ -25,10 +25,7 @@ export default function Index() {
property='og:title'
content='Solend | Lend and borrow on Solana'
/>
-
+
diff --git a/solend-lite/src/stores/pools.ts b/solend-lite/src/stores/pools.ts
index dd08a5ab..45cf6841 100644
--- a/solend-lite/src/stores/pools.ts
+++ b/solend-lite/src/stores/pools.ts
@@ -26,12 +26,12 @@ import { atomWithRefresh } from './shared';
export type ReserveWithMetadataType = ReserveType & {
symbol: string;
- logo: string | null;
+ logo: string | undefined;
};
export type SelectedReserveType = ReserveType & {
symbol: string;
- logo: string | null;
+ logo: string | undefined;
};
export type SelectedPoolType = {
diff --git a/solend-sdk/.gitignore b/solend-sdk/.gitignore
index 1eae0cf6..8e01851b 100644
--- a/solend-sdk/.gitignore
+++ b/solend-sdk/.gitignore
@@ -1,2 +1,3 @@
+__tests__/scripts.test.ts
dist/
node_modules/
diff --git a/solend-sdk/package.json b/solend-sdk/package.json
index 34fdaeda..6bef58da 100644
--- a/solend-sdk/package.json
+++ b/solend-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@solendprotocol/solend-sdk",
- "version": "0.12.11",
+ "version": "0.13.5",
"private": true,
"main": "src/index.ts",
"module": "src/index.ts",
@@ -27,8 +27,9 @@
"@solana/buffer-layout": "=4.0.1",
"@solana/spl-token": "^0.3.7",
"@solana/web3.js": "=1.92.3",
+ "@solendprotocol/token2022-wrapper-sdk": "^1.0.1",
"@solflare-wallet/utl-sdk": "^1.4.0",
- "@switchboard-xyz/on-demand": "^1.2.20",
+ "@switchboard-xyz/on-demand": "1.2.27",
"@switchboard-xyz/sbv2-lite": "^0.2.4",
"axios": "^0.24.0",
"bignumber.js": "^9.0.2",
diff --git a/solend-sdk/src/core/actions.ts b/solend-sdk/src/core/actions.ts
index 38603561..6f061a21 100644
--- a/solend-sdk/src/core/actions.ts
+++ b/solend-sdk/src/core/actions.ts
@@ -13,10 +13,12 @@ import {
import {
NATIVE_MINT,
getAssociatedTokenAddress,
+ getAssociatedTokenAddressSync,
createAssociatedTokenAccountInstruction,
getMinimumBalanceForRentExemptAccount,
createCloseAccountInstruction,
TOKEN_2022_PROGRAM_ID,
+ createAssociatedTokenAccountIdempotentInstruction,
} from "@solana/spl-token";
import BN from "bn.js";
import BigNumber from "bignumber.js";
@@ -47,7 +49,7 @@ import {
liquidateObligationAndRedeemReserveCollateral,
} from "../instructions";
import { NULL_ORACLE, POSITION_LIMIT } from "./constants";
-import { EnvironmentType, PoolType, ReserveType } from "./types";
+import { EnvironmentType, PoolType } from "./types";
import { getProgramId, U64_MAX, WAD } from "./constants";
import { PriceServiceConnection } from "@pythnetwork/price-service-client";
import { AnchorProvider, Program } from "@coral-xyz/anchor-30";
@@ -55,39 +57,70 @@ import {
CrossbarClient,
loadLookupTables,
PullFeed,
- SB_ON_DEMAND_PID,
+ ON_DEMAND_MAINNET_PID,
} from "@switchboard-xyz/on-demand";
import { Wallet } from "@coral-xyz/anchor";
+import {
+ createDepositAndMintWrapperTokensInstruction,
+ createWithdrawAndBurnWrapperTokensInstruction,
+} from "@solendprotocol/token2022-wrapper-sdk";
+import { ReserveType } from "./utils";
const SOL_PADDING_FOR_INTEREST = "1000000";
-const MAPPING_2022 = {
- '123': '321',
+type ActionConfigType = {
+ environment?: EnvironmentType,
+ customObligationAddress?: PublicKey,
+ hostAta?: PublicKey,
+ customObligationSeed?: string,
+ lookupTableAddress?: PublicKey,
+ tipAmount?: number,
+ repayReserve?: ReserveType,
+ token2022Mint?: string,
+ repayToken2022Mint?: string
+ debug?: boolean
}
-type SupportType =
- 'wrap'
- | 'unwrap'
- | 'refreshReserves'
- | 'refreshObligation'
- | 'createObligation'
- | 'cAta'
- | 'ata'
- | 'wrapUnwrapLiquidate'
- | 'wsol';
-
-const ACTION_SUPPORT_REQUIREMENTS: {[Property in ActionType]: Array} = {
- deposit: ['wsol', 'wrap', 'createObligation', 'cAta'],
- borrow: ['wsol', 'ata', 'refreshReserves', 'refreshObligation', 'unwrap'],
- withdraw: ['wsol', 'ata', 'cAta', 'refreshReserves', 'refreshObligation', 'unwrap'],
- repay: ['wsol', 'wrap'],
- mint: ['wsol', 'wrap', 'cAta'],
- redeem: ['wsol', 'ata', 'refreshReserves', 'refreshObligation', 'unwrap'],
- depositCollateral: ['createObligation'],
- withdrawCollateral: ['cAta', 'refreshReserves', 'refreshObligation'],
- forgive: [],
- liquidate: ['wsol', 'ata', 'cAta', 'wrapUnwrapLiquidate', 'refreshReserves', 'refreshObligation'],
-}
+type SupportType =
+ | "wrap"
+ | "unwrap"
+ | "refreshReserves"
+ | "refreshObligation"
+ | "createObligation"
+ | "cAta"
+ | "ata"
+ | "wrapRepay"
+ | "wsol";
+
+const ACTION_SUPPORT_REQUIREMENTS: {
+ [Property in ActionType]: Array;
+} = {
+ deposit: ["wsol", "wrap", "createObligation", "cAta"],
+ borrow: ["wsol", "ata", "refreshReserves", "refreshObligation", "unwrap"],
+ withdraw: [
+ "wsol",
+ "ata",
+ "cAta",
+ "refreshReserves",
+ "refreshObligation",
+ "unwrap",
+ ],
+ repay: ["wsol", "wrap"],
+ mint: ["wsol", "wrap", "cAta"],
+ redeem: ["wsol", "ata", "refreshReserves", "unwrap"],
+ depositCollateral: ["createObligation"],
+ withdrawCollateral: ["cAta", "refreshReserves", "refreshObligation"],
+ forgive: ["refreshReserves", "refreshObligation"],
+ liquidate: [
+ "wsol",
+ "ata",
+ "cAta",
+ "wrapRepay",
+ "unwrap",
+ "refreshReserves",
+ "refreshObligation",
+ ],
+};
export const toHexString = (byteArray: number[]) => {
return (
@@ -160,11 +193,20 @@ export class SolendActionCore {
wallet: Wallet;
- userRepayTokenAccountAddress?: PublicKey;
+ debug: boolean;
- userRepayCollateralAccountAddress?: PublicKey;
-
- is2022?: boolean;
+ repayInfo?: {
+ userRepayTokenAccountAddress: PublicKey;
+ userRepayCollateralAccountAddress: PublicKey;
+ repayToken2022Mint?: PublicKey;
+ repayWrappedAta?: PublicKey;
+ repayMint: PublicKey;
+ reserveAddress: PublicKey;
+ };
+
+ token2022Mint?: PublicKey;
+
+ wrappedAta?: PublicKey;
private constructor(
programId: PublicKey,
@@ -181,19 +223,29 @@ export class SolendActionCore {
amount: BN,
depositReserves: Array,
borrowReserves: Array,
- hostAta?: PublicKey,
- lookupTableAccount?: AddressLookupTableAccount,
- tipAmount?: number,
- userRepayTokenAccountAddress?: PublicKey,
- userRepayCollateralAccountAddress?: PublicKey,
- is2022?: boolean
+ config?: {
+ hostAta?: PublicKey,
+ lookupTableAccount?: AddressLookupTableAccount,
+ tipAmount?: number,
+ repayInfo?: {
+ userRepayTokenAccountAddress: PublicKey;
+ userRepayCollateralAccountAddress: PublicKey;
+ repayToken2022Mint?: PublicKey;
+ repayWrappedAta?: PublicKey;
+ repayMint: PublicKey;
+ reserveAddress: PublicKey;
+ },
+ token2022Mint?: PublicKey,
+ wrappedAta?: PublicKey,
+ debug?: boolean;
+ }
) {
this.programId = programId;
this.connection = connection;
this.publicKey = wallet.publicKey;
this.amount = new BN(amount);
this.positions = positions;
- this.hostAta = hostAta;
+ this.hostAta = config?.hostAta;
this.obligationAccountInfo = obligationAccountInfo;
this.pool = pool;
this.seed = seed;
@@ -209,13 +261,14 @@ export class SolendActionCore {
this.postTxnIxs = [];
this.depositReserves = depositReserves;
this.borrowReserves = borrowReserves;
- this.lookupTableAccount = lookupTableAccount;
- this.jitoTipAmount = tipAmount ?? 1000;
+ this.lookupTableAccount = config?.lookupTableAccount;
+ this.jitoTipAmount = config?.tipAmount ?? 9000;
this.wallet = wallet;
- this.userRepayTokenAccountAddress = userRepayTokenAccountAddress;
- this.userRepayCollateralAccountAddress =
- userRepayCollateralAccountAddress;
- this.is2022 = is2022;
+ this.repayInfo = config?.repayInfo;
+ this.token2022Mint = config?.token2022Mint;
+ this.wrappedAta = config?.wrappedAta;
+ // temporarily default to true
+ this.debug = config?.debug ?? true;
}
static async initialize(
@@ -225,19 +278,13 @@ export class SolendActionCore {
amount: BN,
wallet: Wallet,
connection: Connection,
- environment: EnvironmentType = "production",
- customObligationAddress?: PublicKey,
- hostAta?: PublicKey,
- customObligationSeed?: string,
- lookupTableAddress?: PublicKey,
- tipAmount?: number,
- repayReserve?: ReserveType
+ config: ActionConfigType
) {
- const seed = customObligationSeed ?? pool.address.slice(0, 32);
- const programId = getProgramId(environment);
+ const seed = config.customObligationSeed ?? pool.address.slice(0, 32);
+ const programId = getProgramId(config.environment ?? 'production');
const obligationAddress =
- customObligationAddress ??
+ config.customObligationAddress ??
(await PublicKey.createWithSeed(wallet.publicKey, seed, programId));
const obligationAccountInfo = await connection.getAccountInfo(
@@ -264,8 +311,6 @@ export class SolendActionCore {
});
}
- const supports = ACTION_SUPPORT_REQUIREMENTS[action];
-
// Union of addresses
const distinctReserveCount =
Array.from(
@@ -287,16 +332,6 @@ export class SolendActionCore {
);
}
- let is2022 = false;
- if (supports.includes('wrap') || supports.includes('unwrap')) {
- const mintAccount = await connection.getAccountInfo(
- new PublicKey(reserve.mintAddress)
- );
- if (mintAccount?.owner.equals(TOKEN_2022_PROGRAM_ID)) {
- is2022 = true;
- }
- }
-
const userTokenAccountAddress = await getAssociatedTokenAddress(
new PublicKey(reserve.mintAddress),
wallet.publicKey,
@@ -308,23 +343,25 @@ export class SolendActionCore {
true
);
- const lookupTableAccount = lookupTableAddress
- ? (await connection.getAddressLookupTable(lookupTableAddress)).value
+ const lookupTableAccount = config.lookupTableAddress
+ ? (await connection.getAddressLookupTable(config.lookupTableAddress)).value
: undefined;
- const userRepayTokenAccountAddress = repayReserve
+ const userRepayTokenAccountAddress = config.repayReserve
? await getAssociatedTokenAddress(
- new PublicKey(repayReserve.mintAddress),
+ new PublicKey(config.repayReserve.mintAddress),
wallet.publicKey,
true
)
: undefined;
- const userRepayCollateralAccountAddress = repayReserve ? await getAssociatedTokenAddress(
- new PublicKey(repayReserve.cTokenMint),
- wallet.publicKey,
- true
- ) : undefined;
+ const userRepayCollateralAccountAddress = config.repayReserve
+ ? await getAssociatedTokenAddress(
+ new PublicKey(config.repayReserve.cTokenMint),
+ wallet.publicKey,
+ true
+ )
+ : undefined;
return new SolendActionCore(
programId,
@@ -341,13 +378,41 @@ export class SolendActionCore {
amount,
depositReserves,
borrowReserves,
- hostAta,
- lookupTableAccount ?? undefined,
- tipAmount,
- userRepayTokenAccountAddress,
- userRepayCollateralAccountAddress,
- is2022
- );
+
+{
+ hostAta: config.hostAta,
+ lookupTableAccount: lookupTableAccount ?? undefined,
+ tipAmount: config.tipAmount,
+ repayInfo: config.repayReserve
+ ? {
+ userRepayTokenAccountAddress: userRepayTokenAccountAddress!,
+ userRepayCollateralAccountAddress:
+ userRepayCollateralAccountAddress!,
+ repayToken2022Mint: config.repayToken2022Mint
+ ? new PublicKey(config.repayToken2022Mint)
+ : undefined,
+ repayWrappedAta: config.repayToken2022Mint
+ ? getAssociatedTokenAddressSync(
+ new PublicKey(config.repayToken2022Mint),
+ wallet.publicKey,
+ true,
+ TOKEN_2022_PROGRAM_ID
+ )
+ : undefined,
+ repayMint: new PublicKey(config.repayReserve.mintAddress),
+ reserveAddress: new PublicKey(config.repayReserve.address),
+ }
+ : undefined,
+ token2022Mint: config.token2022Mint ? new PublicKey(config.token2022Mint) : undefined,
+ wrappedAta: config.token2022Mint
+ ? getAssociatedTokenAddressSync(
+ new PublicKey(config.token2022Mint),
+ wallet.publicKey,
+ true,
+ TOKEN_2022_PROGRAM_ID
+ )
+ : undefined
+ })
}
static async buildForgiveTxns(
@@ -357,8 +422,7 @@ export class SolendActionCore {
amount: string,
wallet: Wallet,
obligationAddress: PublicKey,
- environment: EnvironmentType = "production",
- lookupTableAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -367,11 +431,10 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- obligationAddress,
- undefined,
- undefined,
- lookupTableAddress
+ {
+ ...config,
+ customObligationAddress: obligationAddress
+ }
);
await axn.addSupportIxs("forgive");
@@ -386,10 +449,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- obligationAddress?: PublicKey,
- obligationSeed?: string,
- lookupTableAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -398,11 +458,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- obligationAddress,
- undefined,
- obligationSeed,
- lookupTableAddress
+ config
);
await axn.addSupportIxs("deposit");
@@ -417,11 +473,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- customObligationAddress?: PublicKey,
- hostAta?: PublicKey,
- lookupTableAddress?: PublicKey,
- tipAmount?: number
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -430,12 +482,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- customObligationAddress,
- hostAta,
- undefined,
- lookupTableAddress,
- tipAmount
+ config
);
await axn.addSupportIxs("borrow");
@@ -449,8 +496,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- lookupTableAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -459,11 +505,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- undefined,
- undefined,
- undefined,
- lookupTableAddress
+ config
);
await axn.addSupportIxs("mint");
await axn.addDepositReserveLiquidityIx();
@@ -476,8 +518,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- lookupTableAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -486,11 +527,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- undefined,
- undefined,
- undefined,
- lookupTableAddress
+ config
);
await axn.addSupportIxs("redeem");
await axn.addRedeemReserveCollateralIx();
@@ -503,9 +540,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- lookupTableAddress?: PublicKey,
- customObligationAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -514,11 +549,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- customObligationAddress,
- undefined,
- undefined,
- lookupTableAddress
+ config
);
await axn.addSupportIxs("depositCollateral");
await axn.addDepositObligationCollateralIx();
@@ -531,9 +562,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- lookupTableAddress?: PublicKey,
- customObligationAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -542,11 +571,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- customObligationAddress,
- undefined,
- undefined,
- lookupTableAddress
+ config
);
await axn.addSupportIxs("withdrawCollateral");
@@ -561,11 +586,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- obligationAddress?: PublicKey,
- obligationSeed?: string,
- lookupTableAddress?: PublicKey,
- tipAmount?: number
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -574,12 +595,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- obligationAddress,
- undefined,
- obligationSeed,
- lookupTableAddress,
- tipAmount
+ config
);
await axn.addSupportIxs("withdraw");
@@ -594,9 +610,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- customObligationAddress?: PublicKey,
- lookupTableAddress?: PublicKey
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -605,11 +619,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- customObligationAddress,
- undefined,
- undefined,
- lookupTableAddress
+ config
);
await axn.addSupportIxs("repay");
@@ -625,10 +635,7 @@ export class SolendActionCore {
connection: Connection,
amount: string,
wallet: Wallet,
- environment: EnvironmentType = "production",
- customObligationAddress?: PublicKey,
- lookupTableAddress?: PublicKey,
- tipAmount?: number
+ config: ActionConfigType
) {
const axn = await SolendActionCore.initialize(
pool,
@@ -637,13 +644,7 @@ export class SolendActionCore {
new BN(amount),
wallet,
connection,
- environment,
- customObligationAddress,
- undefined,
- undefined,
- lookupTableAddress,
- tipAmount,
- repayReserve,
+ config
);
await axn.addSupportIxs("liquidate");
@@ -758,6 +759,7 @@ export class SolendActionCore {
const tip = this.getTipIx();
if (tip && this.pullPriceTxns.length >= 5) {
+ if (this.debug) console.log('adding tip ix to lending txn');
instructions.push(tip);
}
@@ -796,6 +798,7 @@ export class SolendActionCore {
}
addForgiveIx() {
+ if (this.debug) console.log('adding forgive ix to lending txn');
this.lendingIxs.push(
forgiveDebtInstruction(
this.obligationAddress,
@@ -809,6 +812,7 @@ export class SolendActionCore {
}
addDepositIx() {
+ if (this.debug) console.log('adding deposit ix to lending txn');
this.lendingIxs.push(
this.amount.toString() === U64_MAX
? depositMaxReserveLiquidityAndObligationCollateralInstruction(
@@ -848,6 +852,7 @@ export class SolendActionCore {
}
addDepositReserveLiquidityIx() {
+ if (this.debug) console.log('adding mint ix to lending txn');
this.lendingIxs.push(
depositReserveLiquidityInstruction(
this.amount,
@@ -865,6 +870,7 @@ export class SolendActionCore {
}
addRedeemReserveCollateralIx() {
+ if (this.debug) console.log('adding redeem ix to lending txn');
this.lendingIxs.push(
redeemReserveCollateralInstruction(
this.amount,
@@ -882,6 +888,7 @@ export class SolendActionCore {
}
async addWithdrawObligationCollateralIx() {
+ if (this.debug) console.log('adding withdrawCollateral ix to lending txn');
this.lendingIxs.push(
withdrawObligationCollateralInstruction(
this.amount,
@@ -899,6 +906,7 @@ export class SolendActionCore {
}
addDepositObligationCollateralIx() {
+ if (this.debug) console.log('adding depositCollateral ix to lending txn');
this.lendingIxs.push(
depositObligationCollateralInstruction(
this.amount,
@@ -915,6 +923,7 @@ export class SolendActionCore {
}
addBorrowIx() {
+ if (this.debug) console.log('adding borrow ix to lending txn');
this.lendingIxs.push(
borrowObligationLiquidityInstruction(
this.amount,
@@ -934,6 +943,7 @@ export class SolendActionCore {
}
async addWithdrawIx() {
+ if (this.debug) console.log('adding withdraw ix to lending txn');
this.lendingIxs.push(
this.amount.eq(new BN(U64_MAX))
? withdrawObligationCollateralAndRedeemReserveLiquidity(
@@ -972,6 +982,7 @@ export class SolendActionCore {
}
async addRepayIx() {
+ if (this.debug) console.log('adding repay ix to lending txn');
this.lendingIxs.push(
this.amount.toString() === U64_MAX
? repayMaxObligationLiquidityInstruction(
@@ -997,16 +1008,17 @@ export class SolendActionCore {
}
async addLiquidateIx(repayReserve: ReserveType) {
+ if (this.debug) console.log('adding liquidate ix to lending txn');
if (
- !this.userRepayCollateralAccountAddress ||
- !this.userRepayTokenAccountAddress
+ !this.repayInfo?.userRepayCollateralAccountAddress ||
+ !this.repayInfo?.userRepayTokenAccountAddress
) {
throw Error("Not correctly initialized with a withdraw reserve.");
}
this.lendingIxs.push(
liquidateObligationAndRedeemReserveCollateral(
this.amount,
- this.userRepayTokenAccountAddress,
+ this.repayInfo.userRepayTokenAccountAddress,
this.userCollateralAccountAddress,
this.userTokenAccountAddress,
new PublicKey(repayReserve.address),
@@ -1025,110 +1037,116 @@ export class SolendActionCore {
);
}
-// if (
-// action === "liquidate" &&
-// this.userWithdrawCollateralAccountAddress &&
-// this.userWithdrawTokenAccountAddress
-// ) {
-// const userWithdrawTokenAccountInfo = await this.connection.getAccountInfo(
-// this.userWithdrawTokenAccountAddress
-// );
-// if (!userWithdrawTokenAccountInfo) {
-// const createUserWithdrawTokenAccountIx =
-// createAssociatedTokenAccountInstruction(
-// this.publicKey,
-// this.userWithdrawTokenAccountAddress,
-// this.publicKey,
-// new PublicKey(this.reserve.mintAddress)
-// );
-
-// if (
-// this.positions === POSITION_LIMIT &&
-// this.hostAta &&
-// !this.lookupTableAccount
-// ) {
-// this.preTxnIxs.push(createUserWithdrawTokenAccountIx);
-// } else {
-// this.setupIxs.push(createUserWithdrawTokenAccountIx);
-// }
-// }
-
-// const userWithdrawCollateralAccountInfo =
-// await this.connection.getAccountInfo(
-// this.userWithdrawCollateralAccountAddress
-// );
-// if (!userWithdrawCollateralAccountInfo) {
-// const createUserWithdrawCollateralAccountIx =
-// createAssociatedTokenAccountInstruction(
-// this.publicKey,
-// this.userWithdrawCollateralAccountAddress,
-// this.publicKey,
-// new PublicKey(this.reserve.cTokenMint)
-// );
-
-// if (
-// this.positions === POSITION_LIMIT &&
-// this.hostAta &&
-// !this.lookupTableAccount
-// ) {
-// this.preTxnIxs.push(createUserWithdrawCollateralAccountIx);
-// } else {
-// this.setupIxs.push(createUserWithdrawCollateralAccountIx);
-// }
-// }
-// }
-// }
-
async addSupportIxs(action: ActionType) {
const supports = ACTION_SUPPORT_REQUIREMENTS[action];
for (const support of supports) {
- switch(support) {
- case 'createObligation':
+ switch (support) {
+ case "createObligation":
await this.addObligationIxs();
break;
- case 'wrap':
- if (this.is2022) {
+ case "wrap":
+ if (this.wrappedAta) {
await this.addWrapIx();
}
break;
- case 'unwrap':
- if (this.is2022) {
+ case "unwrap":
+ if (this.wrappedAta) {
await this.addUnwrapIx();
}
break;
- case 'refreshReserves':
+ case "refreshReserves":
await this.addRefreshReservesIxs();
break;
- case 'refreshObligation':
+ case "refreshObligation":
await this.addRefreshObligationIxs();
break;
- case 'cAta':
+ case "cAta":
await this.addCAtaIxs();
break;
- case 'ata':
+ case "ata":
await this.addAtaIxs();
break;
- case 'wrapUnwrapLiquidate':
- await this.addWrapUnwrapLiquidateIxs();
+ case "wrapRepay":
+ if (this.repayInfo?.repayWrappedAta) {
+ await this.addWrapRepayIx();
+ }
break;
- case 'wsol':
+ case "wsol":
await this.updateWSOLAccount(action);
break;
- }
+ }
}
}
private async addWrapIx() {
+ if (!this.wrappedAta || !this.token2022Mint)
+ throw new Error("Wrapped ATA not initialized");
+ if (this.debug) console.log('adding wrap ix to preTxnIxs');
+ this.preTxnIxs.push(
+ createAssociatedTokenAccountIdempotentInstruction(
+ this.publicKey,
+ this.userTokenAccountAddress,
+ this.publicKey,
+ new PublicKey(this.reserve.mintAddress)
+ )
+ );
+ this.preTxnIxs.push(
+ await createDepositAndMintWrapperTokensInstruction(
+ this.publicKey,
+ this.wrappedAta,
+ this.token2022Mint,
+ this.amount
+ )
+ );
}
private async addUnwrapIx() {
-
+ if (!this.wrappedAta || !this.token2022Mint)
+ throw new Error("Wrapped ATA not initialized");
+ if (this.debug) console.log('adding wrap ix to preTxnIxs');
+ this.preTxnIxs.push(
+ createAssociatedTokenAccountIdempotentInstruction(
+ this.publicKey,
+ this.wrappedAta,
+ this.publicKey,
+ this.token2022Mint,
+ TOKEN_2022_PROGRAM_ID
+ )
+ );
+
+ if (this.debug) console.log('adding wrap ix to postTxnIxs');
+ this.postTxnIxs.push(
+ await createWithdrawAndBurnWrapperTokensInstruction(
+ this.publicKey,
+ this.wrappedAta,
+ this.token2022Mint,
+ new BN(U64_MAX)
+ )
+ );
}
- private async addWrapUnwrapLiquidateIxs() {
+ private async addWrapRepayIx() {
+ if (!this.repayInfo?.repayWrappedAta || !this.repayInfo?.repayToken2022Mint)
+ throw new Error("Wrapped ATA not initialized");
+ this.preTxnIxs.push(
+ createAssociatedTokenAccountIdempotentInstruction(
+ this.publicKey,
+ this.repayInfo.userRepayTokenAccountAddress,
+ this.publicKey,
+ new PublicKey(this.repayInfo.repayMint)
+ )
+ );
+ this.preTxnIxs.push(
+ await createDepositAndMintWrapperTokensInstruction(
+ this.publicKey,
+ this.repayInfo.repayWrappedAta,
+ this.repayInfo.repayToken2022Mint,
+ this.amount
+ )
+ );
}
private async buildPullPriceTxns(oracleKeys: Array) {
@@ -1148,39 +1166,52 @@ export class SolendActionCore {
});
const provider = new AnchorProvider(this.connection, this.wallet, {});
- const idl = (await Program.fetchIdl(SB_ON_DEMAND_PID, provider))!;
+ const idl = (await Program.fetchIdl(ON_DEMAND_MAINNET_PID, provider))!;
const sbod = new Program(idl, provider);
const sbPulledOracles = oracleKeys.filter(
(_o, index) =>
oracleAccounts[index]?.owner.toBase58() === sbod.programId.toBase58()
);
- const feedAccounts = sbPulledOracles.map(
- (oracleKey) => new PullFeed(sbod as any, oracleKey)
- );
- const crossbar = new CrossbarClient(
- "https://crossbar.switchboard.xyz/"
+ if (sbPulledOracles.length) {
+ const feedAccounts = await Promise.all(
+ sbPulledOracles.map((oracleKey) => new PullFeed(sbod as any, oracleKey))
+ );
+ if (this.debug) console.log("Feed accounts", sbPulledOracles);
+ const loadedFeedAccounts = await Promise.all(
+ feedAccounts.map((acc) => acc.loadData())
);
- // Responses is Array<[pullIx, responses, success]>
- const responses = await Promise.all(
- feedAccounts.map((feedAccount) =>
- feedAccount.fetchUpdateIx({
- crossbarClient: crossbar,
- })
- )
+ const numSignatures = Math.max(
+ ...loadedFeedAccounts.map(
+ (f) => f.minSampleSize + Math.ceil(f.minSampleSize / 3)
+ ),
+ 1
);
- const oracles = responses.flatMap((x) => x[1].map((y) => y.oracle));
- const lookupTables = await loadLookupTables([...oracles, ...feedAccounts]);
+ const crossbar = new CrossbarClient("https://crossbar.switchboard.xyz/");
+
+ const [ix, accountLookups] = await PullFeed.fetchUpdateManyIx(sbod, {
+ feeds: sbPulledOracles.map((p) => new PublicKey(p)),
+ numSignatures,
+ crossbarClient: crossbar,
+ });
+
+ const lookupTables = (await loadLookupTables(feedAccounts)).concat(
+ accountLookups
+ );
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 1_000_000,
});
+ const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
+ units: 1_000_000,
+ });
- const instructions = [priorityFeeIx, ...responses.map((r) => r[0]!)];
+ const instructions = [priorityFeeIx, modifyComputeUnits, ix];
+ if (this.debug) console.log('adding tip ix to pullPriceTxns for sbod');
instructions.push(this.getTipIx());
// Get the latest context
@@ -1198,8 +1229,9 @@ export class SolendActionCore {
// Get Versioned Transaction
const vtx = new VersionedTransaction(message);
+ if (this.debug) console.log('adding sbod ix to pullPriceTxns');
this.pullPriceTxns.push(vtx);
-
+ }
const pythPulledOracles = oracleAccounts.filter(
(o) =>
o?.owner.toBase58() === pythSolanaReceiver.receiver.programId.toBase58()
@@ -1208,27 +1240,27 @@ export class SolendActionCore {
const shuffledPriceIds = (
pythPulledOracles
.map((pythOracleData, index) => {
- if (!pythOracleData) {
- throw new Error(`Could not find oracle data at index ${index}`);
- }
- const priceUpdate =
- pythSolanaReceiver.receiver.account.priceUpdateV2.coder.accounts.decode(
- "priceUpdateV2",
- pythOracleData.data
- );
-
- const needUpdate =
- Date.now() / 1000 -
- Number(priceUpdate.priceMessage.publishTime.toString()) >
- 30;
-
- return needUpdate
- ? {
- key: Math.random(),
- priceFeedId: toHexString(priceUpdate.priceMessage.feedId),
- }
- : undefined;
- })
+ if (!pythOracleData) {
+ throw new Error(`Could not find oracle data at index ${index}`);
+ }
+ const priceUpdate =
+ pythSolanaReceiver.receiver.account.priceUpdateV2.coder.accounts.decode(
+ "priceUpdateV2",
+ pythOracleData.data
+ );
+
+ const needUpdate =
+ Date.now() / 1000 -
+ Number(priceUpdate.priceMessage.publishTime.toString()) >
+ 80;
+
+ return needUpdate
+ ? {
+ key: Math.random(),
+ priceFeedId: toHexString(priceUpdate.priceMessage.feedId),
+ }
+ : undefined;
+ })
.filter(Boolean) as Array<{
key: number;
priceFeedId: string;
@@ -1238,6 +1270,7 @@ export class SolendActionCore {
.map((x) => x.priceFeedId);
if (shuffledPriceIds.length) {
+ if (this.debug) console.log("Feed accounts", shuffledPriceIds);
const priceFeedUpdateData = await priceServiceConnection.getLatestVaas(
shuffledPriceIds
);
@@ -1263,6 +1296,7 @@ export class SolendActionCore {
}
this.pullPriceTxns.push(tx);
}
+ console.log(`adding ${transactionsWithSigners.length} txns to pullPriceTxns`);
}
}
@@ -1281,6 +1315,8 @@ export class SolendActionCore {
])
);
+ console.log(allReserveAddresses);
+
await this.buildPullPriceTxns([
...allReserveAddresses.map((address) => reserveMap[address].pythOracle),
...allReserveAddresses.map(
@@ -1323,12 +1359,14 @@ export class SolendActionCore {
}
private async addObligationIxs() {
+ if (this.debug) console.log('addObligationIxs');
if (!this.obligationAccountInfo) {
const obligationAccountInfoRentExempt =
await this.connection.getMinimumBalanceForRentExemption(
OBLIGATION_SIZE
);
+ if (this.debug) console.log('adding createAccount and initObligation ix to setup txn');
this.setupIxs.push(
SystemProgram.createAccountWithSeed({
fromPubkey: this.publicKey,
@@ -1369,73 +1407,93 @@ export class SolendActionCore {
this.hostAta &&
!this.lookupTableAccount
) {
+ if (this.debug) console.log('adding createAta ix to pre txn');
this.preTxnIxs.push(createUserTokenAccountIx);
} else {
+ if (this.debug) console.log('adding createAta ix to setup txn');
this.setupIxs.push(createUserTokenAccountIx);
}
}
}
}
- private async addCAtaIxs() {
- const userCollateralAccountInfo = await this.connection.getAccountInfo(
- this.userCollateralAccountAddress
- );
+ private async addCAtaIxs() {
+ const userCollateralAccountInfo = await this.connection.getAccountInfo(
+ this.userCollateralAccountAddress
+ );
- if (!userCollateralAccountInfo) {
- const createUserCollateralAccountIx =
- createAssociatedTokenAccountInstruction(
- this.publicKey,
- this.userCollateralAccountAddress,
- this.publicKey,
- new PublicKey(this.reserve.cTokenMint)
- );
+ if (!userCollateralAccountInfo) {
+ const createUserCollateralAccountIx =
+ createAssociatedTokenAccountInstruction(
+ this.publicKey,
+ this.userCollateralAccountAddress,
+ this.publicKey,
+ new PublicKey(this.reserve.cTokenMint)
+ );
- if (
- this.positions === POSITION_LIMIT &&
- this.hostAta &&
- !this.lookupTableAccount
- ) {
- this.preTxnIxs.push(createUserCollateralAccountIx);
- } else {
- this.setupIxs.push(createUserCollateralAccountIx);
- }
+ if (
+ this.positions === POSITION_LIMIT &&
+ this.hostAta &&
+ !this.lookupTableAccount
+ ) {
+ if (this.debug) console.log('adding createCAta ix to pre txn');
+ this.preTxnIxs.push(createUserCollateralAccountIx);
+ } else {
+ if (this.debug) console.log('adding createCAta ix to setup txn');
+ this.setupIxs.push(createUserCollateralAccountIx);
}
}
+ }
private async updateWSOLAccount(action: ActionType) {
- if (this.reserve.mintAddress !== NATIVE_MINT.toBase58()) return;
+ if (
+ ![
+ this.reserve.mintAddress,
+ this.repayInfo?.repayMint.toString(),
+ ].includes(NATIVE_MINT.toBase58())
+ )
+ return;
const preIxs: Array = [];
const postIxs: Array = [];
let safeRepay = new BN(this.amount);
+ const liquidateWithSol =
+ action === "liquidate" &&
+ this.repayInfo?.repayMint.toString() === NATIVE_MINT.toBase58();
+
+ const solAccountAddress = liquidateWithSol
+ ? this.repayInfo!.userRepayTokenAccountAddress
+ : this.userTokenAccountAddress;
+ const borrowReserveAddress = liquidateWithSol
+ ? this.repayInfo!.reserveAddress.toBase58()
+ : this.reserve.address;
if (
this.obligationAccountInfo &&
- action === "repay" &&
+ (action === "repay" || liquidateWithSol) &&
this.amount.eq(new BN(U64_MAX))
) {
const buffer = await this.connection.getAccountInfo(
- new PublicKey(this.reserve.address),
+ new PublicKey(borrowReserveAddress),
"processed"
);
if (!buffer) {
- throw Error(`Unable to fetch reserve data for ${this.reserve.address}`);
+ throw Error(`Unable to fetch reserve data for ${borrowReserveAddress}`);
}
const parsedData = parseReserve(
- new PublicKey(this.reserve.address),
+ new PublicKey(borrowReserveAddress),
buffer
)?.info;
if (!parsedData) {
- throw Error(`Unable to parse data of reserve ${this.reserve.address}`);
+ throw Error(`Unable to parse data of reserve ${borrowReserveAddress}`);
}
const borrow = this.obligationAccountInfo.borrows.find(
- (borrow) => borrow.borrowReserve.toBase58() === this.reserve.address
+ (borrow) => borrow.borrowReserve.toBase58() === borrowReserveAddress
);
if (!borrow) {
@@ -1459,7 +1517,7 @@ export class SolendActionCore {
}
const userWSOLAccountInfo = await this.connection.getAccountInfo(
- this.userTokenAccountAddress
+ solAccountAddress
);
const rentExempt = await getMinimumBalanceForRentExemptAccount(
@@ -1467,38 +1525,46 @@ export class SolendActionCore {
);
const sendAction =
- action === "deposit" || action === "repay" || action === "mint";
+ action === "deposit" ||
+ action === "repay" ||
+ action === "mint" ||
+ liquidateWithSol;
const transferLamportsIx = SystemProgram.transfer({
fromPubkey: this.publicKey,
- toPubkey: this.userTokenAccountAddress,
+ toPubkey: solAccountAddress,
lamports:
(userWSOLAccountInfo ? 0 : rentExempt) +
(sendAction ? parseInt(safeRepay.toString(), 10) : 0),
});
+ if (this.debug) console.log('adding transferLamports ix');
preIxs.push(transferLamportsIx);
const closeWSOLAccountIx = createCloseAccountInstruction(
- this.userTokenAccountAddress,
+ solAccountAddress,
this.publicKey,
this.publicKey,
[]
);
if (userWSOLAccountInfo) {
- const syncIx = syncNative(this.userTokenAccountAddress);
+ const syncIx = syncNative(solAccountAddress);
if (sendAction) {
+ if (this.debug) console.log('adding syncIx ix');
preIxs.push(syncIx);
} else {
+ if (this.debug) console.log('adding closeWSOLAccountIx ix');
postIxs.push(closeWSOLAccountIx);
}
} else {
const createUserWSOLAccountIx = createAssociatedTokenAccountInstruction(
this.publicKey,
- this.userTokenAccountAddress,
+ solAccountAddress,
this.publicKey,
NATIVE_MINT
);
+ if (this.debug) console.log('adding createUserWSOLAccountIx ix');
preIxs.push(createUserWSOLAccountIx);
+ if (this.debug) console.log('adding closeWSOLAccountIx ix');
postIxs.push(closeWSOLAccountIx);
}
@@ -1507,9 +1573,11 @@ export class SolendActionCore {
this.hostAta &&
!this.lookupTableAccount
) {
+ if (this.debug) console.log('adding above ixs to pre and post txn');
this.preTxnIxs.push(...preIxs);
this.postTxnIxs.push(...postIxs);
} else {
+ if (this.debug) console.log('adding above ixs to lending txn');
this.setupIxs.push(...preIxs);
this.cleanupIxs.push(...postIxs);
}
diff --git a/solend-sdk/src/core/constants.ts b/solend-sdk/src/core/constants.ts
index ecc80683..ea9a0630 100644
--- a/solend-sdk/src/core/constants.ts
+++ b/solend-sdk/src/core/constants.ts
@@ -1,6 +1,5 @@
import { Cluster, PublicKey } from "@solana/web3.js";
import BigNumber from "bignumber.js";
-import { ObligationType } from "./types";
export const WAD = "1".concat(Array(18 + 1).join("0"));
export const POSITION_LIMIT = 6;
export const SOL_PADDING_FOR_INTEREST = "1000000";
@@ -46,28 +45,3 @@ export function getProgramId(environment?: Cluster | "beta" | "production") {
}
export const BigZero = new BigNumber(0);
-
-export const EmptyObligation: ObligationType = {
- address: "empty",
- positions: 0,
- deposits: [],
- borrows: [],
- poolAddress: "",
- totalSupplyValue: BigZero,
- totalBorrowValue: BigZero,
- borrowLimit: BigZero,
- liquidationThreshold: BigZero,
- netAccountValue: BigZero,
- liquidationThresholdFactor: BigZero,
- borrowLimitFactor: BigZero,
- borrowUtilization: BigZero,
- weightedConservativeBorrowUtilization: BigZero,
- weightedBorrowUtilization: BigZero,
- isBorrowLimitReached: false,
- borrowOverSupply: BigZero,
- weightedTotalBorrowValue: BigZero,
- minPriceUserTotalSupply: BigZero,
- minPriceBorrowLimit: BigZero,
- maxPriceUserTotalWeightedBorrow: BigZero,
- netApy: BigZero,
-};
diff --git a/solend-sdk/src/core/margin.ts b/solend-sdk/src/core/margin.ts
index 0a5bbbfe..71a23d03 100644
--- a/solend-sdk/src/core/margin.ts
+++ b/solend-sdk/src/core/margin.ts
@@ -411,10 +411,12 @@ export class Margin {
this.connection,
depositCollateralConfig.amount,
this.wallet,
- "production",
- this.obligationAddress,
- this.obligationSeed,
- lookupTableAccount?.key
+ {
+ environment: "production",
+ customObligationAddress: this.obligationAddress,
+ customObligationSeed: this.obligationSeed,
+ lookupTableAddress: lookupTableAccount?.key
+ }
);
const { preLendingTxn, lendingTxn } =
await solendAction.getLegacyTransactions();
diff --git a/solend-sdk/src/core/types.ts b/solend-sdk/src/core/types.ts
index 0f1d74ed..d43f24b8 100644
--- a/solend-sdk/src/core/types.ts
+++ b/solend-sdk/src/core/types.ts
@@ -1,7 +1,7 @@
-import { Cluster } from "@solana/web3.js";
+import { Cluster, PublicKey } from "@solana/web3.js";
import BigNumber from "bignumber.js";
-import { formatReserve } from "./utils/pools";
-import { formatObligation } from "./utils";
+import { ReserveType } from "./utils";
+import BN from "bn.js";
export type PoolMetadataCoreType = {
name: string | null;
@@ -21,7 +21,7 @@ export type EnvironmentType = Cluster | "production" | "beta";
export type TokenMetadata = {
[mintAddress: string]: {
symbol: string;
- logoUri: string | null;
+ logoUri: string | undefined;
decimals: number;
};
};
@@ -34,15 +34,6 @@ export type PoolType = {
reserves: Array;
};
-export type ReserveType = Omit<
- Awaited>,
- "symbol"
-> & {
- symbol: string | undefined;
-};
-
-export type ObligationType = Awaited>;
-
export type WalletAssetType = {
amount: BigNumber;
mintAddress: string;
@@ -53,3 +44,33 @@ export type WalletAssetType = {
};
export type WalletType = Array;
+
+export type InputReserveConfigParams = {
+ optimalUtilizationRate: number;
+ maxUtilizationRate: number;
+ loanToValueRatio: number;
+ liquidationBonus: number;
+ liquidationThreshold: number;
+ minBorrowRate: number;
+ optimalBorrowRate: number;
+ maxBorrowRate: number;
+ superMaxBorrowRate: BN;
+ fees: {
+ borrowFeeWad: BN;
+ flashLoanFeeWad: BN;
+ hostFeePercentage: number;
+ };
+ depositLimit: BN;
+ borrowLimit: BN;
+ feeReceiver: PublicKey;
+ protocolLiquidationFee: number;
+ protocolTakeRate: number;
+ addedBorrowWeightBPS: BN;
+ reserveType: number;
+ maxLiquidationBonus: number;
+ maxLiquidationThreshold: number;
+ scaledPriceOffsetBPS: BN;
+ extraOracle?: PublicKey;
+ attributedBorrowLimitOpen: BN;
+ attributedBorrowLimitClose: BN;
+}
diff --git a/solend-sdk/src/core/utils/obligations.ts b/solend-sdk/src/core/utils/obligations.ts
index aa923701..6cc63ec6 100644
--- a/solend-sdk/src/core/utils/obligations.ts
+++ b/solend-sdk/src/core/utils/obligations.ts
@@ -1,12 +1,12 @@
import { Connection, PublicKey } from "@solana/web3.js";
import BigNumber from "bignumber.js";
import { Obligation, OBLIGATION_SIZE, parseObligation } from "../../state";
-import { ReserveType } from "../types";
import { sha256 as sha256$1 } from "js-sha256";
import { getBatchMultipleAccountsInfo } from "./utils";
import { U64_MAX } from "../constants";
+import { ReserveType } from "./pools";
-export type FormattedObligation = ReturnType;
+export type ObligationType = ReturnType;
export function formatObligation(
obligation: { pubkey: PublicKey; info: Obligation },
@@ -39,6 +39,7 @@ export function formatObligation(
return {
liquidationThreshold: reserve.liquidationThreshold,
+ maxLiquidationThreshold: reserve.maxLiquidationThreshold,
loanToValueRatio: reserve.loanToValueRatio,
symbol: reserve.symbol,
price: reserve.price,
@@ -112,6 +113,10 @@ export function formatObligation(
(acc, d) => d.amountUsd.times(d.liquidationThreshold).plus(acc),
BigNumber(0)
);
+ const superUnhealthyBorrowValue = deposits.reduce(
+ (acc, d) => d.amountUsd.times(d.maxLiquidationThreshold).plus(acc),
+ BigNumber(0)
+ );
const netAccountValue = totalSupplyValue.minus(totalBorrowValue);
const liquidationThresholdFactor = totalSupplyValue.isZero()
? new BigNumber(0)
@@ -154,6 +159,8 @@ export function formatObligation(
.div(netAccountValue.toString());
return {
address: obligation.pubkey.toBase58(),
+ owner: obligation.info.owner.toBase58(),
+ closeable: obligation.info.closeable,
positions,
deposits,
borrows,
@@ -164,6 +171,7 @@ export function formatObligation(
liquidationThreshold,
netAccountValue,
liquidationThresholdFactor,
+ superUnhealthyBorrowValue,
borrowLimitFactor,
borrowUtilization,
weightedConservativeBorrowUtilization,
diff --git a/solend-sdk/src/core/utils/pools.ts b/solend-sdk/src/core/utils/pools.ts
index 2a5018c7..3906e1bf 100644
--- a/solend-sdk/src/core/utils/pools.ts
+++ b/solend-sdk/src/core/utils/pools.ts
@@ -3,7 +3,7 @@ import BigNumber from "bignumber.js";
import SwitchboardProgram from "@switchboard-xyz/sbv2-lite";
import { fetchPrices } from "./prices";
import { calculateBorrowInterest, calculateSupplyInterest } from "./rates";
-import { PoolType, ReserveType } from "../types";
+import { PoolType } from "../types";
import { parseReserve, Reserve } from "../../state";
import { parseRateLimiter } from "./utils";
@@ -49,18 +49,22 @@ export async function fetchPools(
return pools;
}
+export type ReserveType = ReturnType;
+
export function formatReserve(
reserve: {
pubkey: PublicKey;
info: Reserve;
},
- price:
- | {
- spotPrice: number;
- emaPrice: number;
- }
- | undefined,
- currentSlot: number
+ price?: {
+ spotPrice: number;
+ emaPrice: number;
+ },
+ currentSlot?: number,
+ metadata?: {
+ symbol: string;
+ logo: string;
+ }
) {
const decimals = reserve.info.liquidity.mintDecimals;
const availableAmount = new BigNumber(
@@ -147,7 +151,8 @@ export function formatReserve(
address,
mintAddress: reserve.info.liquidity.mintPubkey.toBase58(),
decimals,
- symbol: undefined,
+ symbol: metadata?.symbol,
+ logo: metadata?.logo,
price: priceResolved,
poolAddress: reserve.info.lendingMarket.toBase58(),
pythOracle: reserve.info.liquidity.pythOracle.toBase58(),
diff --git a/solend-sdk/src/core/utils/utils.ts b/solend-sdk/src/core/utils/utils.ts
index 6c0a925b..0082b1fc 100644
--- a/solend-sdk/src/core/utils/utils.ts
+++ b/solend-sdk/src/core/utils/utils.ts
@@ -8,7 +8,7 @@ export const OUTFLOW_BUFFER = 0.985;
export const parseRateLimiter = (
rateLimiter: RateLimiter,
- currentSlot: number
+ currentSlot?: number
) => {
const convertedRateLimiter = {
config: {
@@ -27,7 +27,9 @@ export const parseRateLimiter = (
};
return {
...convertedRateLimiter,
- remainingOutflow: remainingOutflow(currentSlot, convertedRateLimiter),
+ remainingOutflow: currentSlot
+ ? remainingOutflow(currentSlot, convertedRateLimiter)
+ : null,
};
};
diff --git a/solend-sdk/src/core/utils/wallet.ts b/solend-sdk/src/core/utils/wallet.ts
index e66a1fcb..a42d4bc5 100644
--- a/solend-sdk/src/core/utils/wallet.ts
+++ b/solend-sdk/src/core/utils/wallet.ts
@@ -1,6 +1,7 @@
import {
getAssociatedTokenAddress,
NATIVE_MINT,
+ TOKEN_2022_PROGRAM_ID,
unpackAccount,
} from "@solana/spl-token";
import { Connection, LAMPORTS_PER_SOL, PublicKey } from "@solana/web3.js";
@@ -42,7 +43,7 @@ export function formatWalletAssets(
address: wSolAddress,
amount: nativeSolBalance,
mintAddress: NATIVE_MINT.toBase58(),
- logo: 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png',
+ logo: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png",
},
]);
}
@@ -54,12 +55,21 @@ export async function fetchWalletAssets(
debug?: boolean
) {
if (debug) console.log("fetchWalletAssets", uniqueAssets.length);
+
+ const uniqueAssetAccounts = await getBatchMultipleAccountsInfo(
+ uniqueAssets.map((asset) => new PublicKey(asset)),
+ connection
+ );
+
const userTokenAssociatedAddresses = await Promise.all(
- uniqueAssets.map(async (asset) => {
+ uniqueAssetAccounts.map(async (asset, index) => {
const userTokenAccount = await getAssociatedTokenAddress(
- new PublicKey(asset),
+ new PublicKey(uniqueAssets[index]),
new PublicKey(publicKey),
- true
+ true,
+ asset?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()
+ ? TOKEN_2022_PROGRAM_ID
+ : undefined
);
return userTokenAccount;
})
@@ -82,7 +92,13 @@ export async function fetchWalletAssets(
userAssociatedTokenAccounts: userAssociatedTokenAccounts.map(
(account, index) =>
account
- ? unpackAccount(userTokenAssociatedAddresses[index], account)
+ ? unpackAccount(
+ userTokenAssociatedAddresses[index],
+ account,
+ account?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()
+ ? TOKEN_2022_PROGRAM_ID
+ : undefined
+ )
: null
),
nativeSolBalance: new BigNumber(nativeSolBalance).dividedBy(
diff --git a/solend-sdk/src/instructions/initReserve.ts b/solend-sdk/src/instructions/initReserve.ts
index 329bf3e9..7ea4bbcc 100644
--- a/solend-sdk/src/instructions/initReserve.ts
+++ b/solend-sdk/src/instructions/initReserve.ts
@@ -6,14 +6,14 @@ import {
} from "@solana/web3.js";
import BN from "bn.js";
import * as Layout from "../layout";
-import { ReserveConfig } from "../state";
import { LendingInstruction } from "./instruction";
+import { InputReserveConfigParams, NULL_ORACLE } from "../core";
const BufferLayout = require("buffer-layout");
export const initReserveInstruction = (
liquidityAmount: number | BN,
- config: ReserveConfig,
+ config: InputReserveConfigParams,
sourceLiquidity: PublicKey,
destinationCollateral: PublicKey,
reserve: PublicKey,
@@ -22,7 +22,6 @@ export const initReserveInstruction = (
liquidityFeeReceiver: PublicKey,
collateralMint: PublicKey,
collateralSupply: PublicKey,
- pythProduct: PublicKey,
pythPrice: PublicKey,
switchboardFeed: PublicKey,
lendingMarket: PublicKey,
@@ -72,7 +71,7 @@ export const initReserveInstruction = (
instruction: LendingInstruction.InitReserve,
liquidityAmount: new BN(liquidityAmount),
optimalUtilizationRate: config.optimalUtilizationRate,
- maxUtilizationRate: config.maxUtilizationRate,
+ maxUtilizationRate: config.maxUtilizationRate,
loanToValueRatio: config.loanToValueRatio,
liquidationBonus: config.liquidationBonus,
liquidationThreshold: config.liquidationThreshold,
@@ -110,7 +109,8 @@ export const initReserveInstruction = (
{ pubkey: liquidityFeeReceiver, isSigner: false, isWritable: true },
{ pubkey: collateralMint, isSigner: false, isWritable: true },
{ pubkey: collateralSupply, isSigner: false, isWritable: true },
- { pubkey: pythProduct, isSigner: false, isWritable: false },
+ // Doesn't matter what we pass in as long as it's not null
+ { pubkey: pythPrice, isSigner: false, isWritable: false },
{ pubkey: pythPrice, isSigner: false, isWritable: false },
{ pubkey: switchboardFeed, isSigner: false, isWritable: false },
{ pubkey: lendingMarket, isSigner: false, isWritable: true },
diff --git a/solend-sdk/src/instructions/liquidateObligationAndRedeemReserveCollateral.ts b/solend-sdk/src/instructions/liquidateObligationAndRedeemReserveCollateral.ts
index b7fb89e4..d0121f08 100644
--- a/solend-sdk/src/instructions/liquidateObligationAndRedeemReserveCollateral.ts
+++ b/solend-sdk/src/instructions/liquidateObligationAndRedeemReserveCollateral.ts
@@ -1,3 +1,4 @@
+// @ts-nocheck
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import BN from "bn.js";
diff --git a/solend-sdk/src/instructions/updateReserveConfig.ts b/solend-sdk/src/instructions/updateReserveConfig.ts
index df7a515c..a7f0fd13 100644
--- a/solend-sdk/src/instructions/updateReserveConfig.ts
+++ b/solend-sdk/src/instructions/updateReserveConfig.ts
@@ -1,8 +1,8 @@
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import { RateLimiterConfig } from "../state/rateLimiter";
-import { ReserveConfig } from "../state/reserve";
import * as Layout from "../layout";
import { LendingInstruction } from "./instruction";
+import { NULL_ORACLE, InputReserveConfigParams } from "../core";
const BufferLayout = require("buffer-layout");
@@ -22,10 +22,9 @@ export const updateReserveConfig = (
lendingMarket: PublicKey,
lendingMarketAuthority: PublicKey,
lendingMarketOwner: PublicKey,
- pythProduct: PublicKey,
pythPrice: PublicKey,
switchboardOracle: PublicKey,
- reserveConfig: ReserveConfig,
+ reserveConfig: InputReserveConfigParams,
rateLimiterConfig: RateLimiterConfig,
solendProgramAddress: PublicKey
): TransactionInstruction => {
@@ -107,7 +106,7 @@ export const updateReserveConfig = (
{ pubkey: lendingMarket, isSigner: false, isWritable: false },
{ pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
{ pubkey: lendingMarketOwner, isSigner: true, isWritable: false },
- { pubkey: pythProduct, isSigner: false, isWritable: false },
+ { pubkey: NULL_ORACLE, isSigner: false, isWritable: false },
{ pubkey: pythPrice, isSigner: false, isWritable: false },
{ pubkey: switchboardOracle, isSigner: false, isWritable: false },
];
diff --git a/solend-sdk/src/state/lendingMarket.ts b/solend-sdk/src/state/lendingMarket.ts
index 8fe4f0ce..6733d882 100644
--- a/solend-sdk/src/state/lendingMarket.ts
+++ b/solend-sdk/src/state/lendingMarket.ts
@@ -18,6 +18,8 @@ export interface LendingMarket {
riskAuthority: PublicKey;
}
+export type ParsedLendingMarket = ReturnType;
+
export const LendingMarketLayout: typeof BufferLayout.Structure =
BufferLayout.struct([
BufferLayout.u8("version"),
diff --git a/solend-sdk/src/state/obligation.ts b/solend-sdk/src/state/obligation.ts
index fa60574b..4ddfcb82 100644
--- a/solend-sdk/src/state/obligation.ts
+++ b/solend-sdk/src/state/obligation.ts
@@ -20,8 +20,10 @@ export interface Obligation {
borrowedValueUpperBound: BN; // decimals
allowedBorrowValue: BN; // decimals
unhealthyBorrowValue: BN; // decimals
- superUnhealthyBorrowValue: BN; // decimals
borrowingIsolatedAsset: boolean;
+ unweightedBorrowValue: BN; // decimals
+ superUnhealthyBorrowValue: BN; // decimals
+ closeable: boolean;
pubkey: PublicKey; // add on
}
@@ -79,7 +81,9 @@ export const ObligationLayout: typeof BufferLayout.Structure =
Layout.uint128("borrowedValueUpperBound"),
BufferLayout.u8("borrowingIsolatedAsset"),
Layout.uint128("superUnhealthyBorrowValue"),
- BufferLayout.blob(31, "_padding"),
+ Layout.uint128("unweightedBorrowValue"),
+ BufferLayout.u8("closeable"),
+ BufferLayout.blob(14, "_padding"),
BufferLayout.u8("depositsLen"),
BufferLayout.u8("borrowsLen"),
@@ -118,6 +122,10 @@ export interface ProtoObligation {
allowedBorrowValue: BN; // decimals
unhealthyBorrowValue: BN; // decimals
borrowedValueUpperBound: BN; // decimals
+ borrowingIsolatedAsset: boolean;
+ unweightedBorrowValue: BN; // decimals
+ superUnhealthyBorrowValue: BN; // decimals
+ closeable: boolean;
depositsLen: number;
borrowsLen: number;
dataFlat: Buffer;
@@ -143,6 +151,10 @@ export const parseObligation = (
allowedBorrowValue,
unhealthyBorrowValue,
borrowedValueUpperBound,
+ borrowingIsolatedAsset,
+ unweightedBorrowValue,
+ superUnhealthyBorrowValue,
+ closeable,
depositsLen,
borrowsLen,
dataFlat,
@@ -181,6 +193,10 @@ export const parseObligation = (
allowedBorrowValue,
unhealthyBorrowValue,
borrowedValueUpperBound,
+ borrowingIsolatedAsset,
+ unweightedBorrowValue,
+ superUnhealthyBorrowValue,
+ closeable,
deposits,
borrows,
pubkey,
diff --git a/yarn.lock b/yarn.lock
index 859e9d9c..ab5f78fd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1015,6 +1015,13 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@brokerloop/ttlcache@^3.2.3":
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/@brokerloop/ttlcache/-/ttlcache-3.2.3.tgz#bc3c79bb381f7b43f83745eb96e86673f75d3d11"
+ integrity sha512-kZWoyJGBYTv1cL5oHBYEixlJysJBf2RVnub3gbclD+dwaW9aKubbHzbZ9q1q6bONosxaOqMsoBorOrZKzBDiqg==
+ dependencies:
+ "@soncodi/signal" "~2.0.7"
+
"@bundlr-network/client@^0.7.14":
version "0.7.17"
resolved "https://registry.yarnpkg.com/@bundlr-network/client/-/client-0.7.17.tgz#0a4c41534640f9038e5d7d1d8cf1cc2571b185b7"
@@ -1861,7 +1868,7 @@
exec-sh "^0.3.2"
minimist "^1.2.0"
-"@coral-xyz/anchor-30@npm:@coral-xyz/anchor@0.30.1":
+"@coral-xyz/anchor-30@npm:@coral-xyz/anchor@0.30.1", "@coral-xyz/anchor@^0.30.1":
version "0.30.1"
resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.30.1.tgz#17f3e9134c28cd0ea83574c6bab4e410bcecec5d"
integrity sha512-gDXFoF5oHgpriXAaLpxyWBHdCs8Awgf/gLHIo6crv7Aqm937CNdY+x+6hoj7QR5vaJV7MxWSQ0NGFzL3kPbWEQ==
@@ -3525,6 +3532,32 @@
bn.js "^5.2.0"
debug "^4.3.4"
+"@metaplex-foundation/rustbin@^0.3.0", "@metaplex-foundation/rustbin@^0.3.1":
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/@metaplex-foundation/rustbin/-/rustbin-0.3.5.tgz#56d028afd96c2b56ad3bbea22ff454adde900e8c"
+ integrity sha512-m0wkRBEQB/8krwMwKBvFugufZtYwMXiGHud2cTDAv+aGXK4M90y0Hx67/wpu+AqqoQfdV8VM9YezUOHKD+Z5kA==
+ dependencies:
+ debug "^4.3.3"
+ semver "^7.3.7"
+ text-table "^0.2.0"
+ toml "^3.0.0"
+
+"@metaplex-foundation/solita@^0.12.2":
+ version "0.12.2"
+ resolved "https://registry.yarnpkg.com/@metaplex-foundation/solita/-/solita-0.12.2.tgz#13ef213ac183c986f6d01c5d981c44e59a900834"
+ integrity sha512-oczMfE43NNHWweSqhXPTkQBUbap/aAiwjDQw8zLKNnd/J8sXr/0+rKcN5yJIEgcHeKRkp90eTqkmt2WepQc8yw==
+ dependencies:
+ "@metaplex-foundation/beet" "^0.4.0"
+ "@metaplex-foundation/beet-solana" "^0.3.0"
+ "@metaplex-foundation/rustbin" "^0.3.0"
+ "@solana/web3.js" "^1.36.0"
+ camelcase "^6.2.1"
+ debug "^4.3.3"
+ js-sha256 "^0.9.0"
+ prettier "^2.5.1"
+ snake-case "^3.0.4"
+ spok "^1.4.3"
+
"@mithraic-labs/psy-american@^0.2.1":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@mithraic-labs/psy-american/-/psy-american-0.2.3.tgz#a6f3a62f96ec01f94463a7b12f5bf71a003c9942"
@@ -5666,6 +5699,21 @@
jsbi "^4.3.0"
typedoc-plugin-cname "^1.0.1"
+"@solendprotocol/token2022-wrapper-sdk@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@solendprotocol/token2022-wrapper-sdk/-/token2022-wrapper-sdk-1.0.1.tgz#47158a0c4c6fa3c7f9b2740c7d07101e0191abd0"
+ integrity sha512-+1fLbH5XSJo2/+vyPqVhEjuQzUbG+JQ54M3lSYuSe4h83q6udI0JdUxzW/hPxm6BvNlp+2acmy/gRuKrSEk4NA==
+ dependencies:
+ "@metaplex-foundation/beet" "^0.7.1"
+ "@metaplex-foundation/rustbin" "^0.3.1"
+ "@metaplex-foundation/solita" "^0.12.2"
+ "@solana/spl-token" "^0.3.7"
+ bn.js "^5.2.1"
+ borsh "^0.7.0"
+ bs58 "^5.0.0"
+ buffer-layout "^1.2.2"
+ zstddec "^0.0.2"
+
"@solflare-wallet/metamask-sdk@^1.0.2":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@solflare-wallet/metamask-sdk/-/metamask-sdk-1.0.3.tgz#3baaa22de2c86515e6ba6025285cd1f5d74b04e5"
@@ -5711,6 +5759,11 @@
decimal.js "^10.4.0"
typescript "^4.8.2"
+"@soncodi/signal@~2.0.7":
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/@soncodi/signal/-/signal-2.0.7.tgz#0a2c361b02dbfdbcf4e66b78e5f711e0a13d6e83"
+ integrity sha512-zA2oZluZmVvgZEDjF243KWD1S2J+1SH1MVynI0O1KRgDt1lU8nqk7AK3oQfW/WpwT51L5waGSU0xKF/9BTP5Cw==
+
"@stablelib/aead@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@stablelib/aead/-/aead-1.0.1.tgz#c4b1106df9c23d1b867eb9b276d8f42d5fc4c0c3"
@@ -5881,20 +5934,20 @@
protobufjs "^7.2.6"
yaml "^2.2.1"
-"@switchboard-xyz/on-demand@^1.2.20":
- version "1.2.20"
- resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.2.20.tgz#11dcd876cbf8bb1893f22f7895baaf63fe118d76"
- integrity sha512-RC52eNZVGaRbPdb8GYc1H4nm4YRCToX2LMI8flWjV9cf7jOIkcjtPyLH/Spg8LJPe2Pa30wJlqaqSXfqYB47Xw==
+"@switchboard-xyz/on-demand@1.2.27":
+ version "1.2.27"
+ resolved "https://registry.yarnpkg.com/@switchboard-xyz/on-demand/-/on-demand-1.2.27.tgz#8591d2a424a7a9a9256a996df35f408c0167fe40"
+ integrity sha512-acrIngoQRv6M6PiNooEFQP+0FExseKkCMecGDP1nLRz7C1hLMTgWWeUqmmfrxJh6uCafM4Cl4lpKk3pGd01XBg==
dependencies:
+ "@brokerloop/ttlcache" "^3.2.3"
"@coral-xyz/anchor-30" "npm:@coral-xyz/anchor@0.30.1"
"@solana/web3.js" "^1.95.0"
"@solworks/soltoolkit-sdk" "^0.0.23"
"@switchboard-xyz/common" "^2.4.2"
- axios "^1.2.0"
+ axios "^1.7.4"
big.js "^6.2.1"
bs58 "^5.0.0"
js-yaml "^4.1.0"
- node-cache "^5.1.2"
protobufjs "^7.2.6"
"@switchboard-xyz/sbv2-lite@^0.1.0":
@@ -7297,7 +7350,7 @@ ansi-styles@^6.1.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
-ansicolors@^0.3.2:
+ansicolors@^0.3.2, ansicolors@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==
@@ -7661,7 +7714,7 @@ axios@^0.27.2:
follow-redirects "^1.14.9"
form-data "^4.0.0"
-axios@^1.2.0, axios@^1.5.1, axios@^1.7.2:
+axios@^1.5.1, axios@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621"
integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==
@@ -7670,6 +7723,15 @@ axios@^1.2.0, axios@^1.5.1, axios@^1.7.2:
form-data "^4.0.0"
proxy-from-env "^1.1.0"
+axios@^1.7.4:
+ version "1.7.7"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
+ integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
+ dependencies:
+ follow-redirects "^1.15.6"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
axobject-query@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a"
@@ -8290,7 +8352,7 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-camelcase@^6.0.0, camelcase@^6.2.0, camelcase@^6.3.0:
+camelcase@^6.0.0, camelcase@^6.2.0, camelcase@^6.2.1, camelcase@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
@@ -8525,11 +8587,6 @@ clone-response@^1.0.2:
dependencies:
mimic-response "^1.0.0"
-clone@2.x:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
- integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
-
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
@@ -8604,6 +8661,11 @@ commander@^2.20.3:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+commander@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
+ integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
+
commander@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
@@ -10385,6 +10447,15 @@ filter-obj@^1.1.0:
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
+find-process@^1.4.7:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/find-process/-/find-process-1.4.7.tgz#8c76962259216c381ef1099371465b5b439ea121"
+ integrity sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==
+ dependencies:
+ chalk "^4.0.0"
+ commander "^5.1.0"
+ debug "^4.1.1"
+
find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
@@ -13540,13 +13611,6 @@ node-addon-api@^8.0.0:
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.0.0.tgz#5453b7ad59dd040d12e0f1a97a6fa1c765c5c9d2"
integrity sha512-ipO7rsHEBqa9STO5C5T10fj732ml+5kLN1cAG8/jdHd56ldQeGj3Q7+scUS+VHK/qy1zLEwC4wMK5+yM0btPvw==
-node-cache@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d"
- integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==
- dependencies:
- clone "2.x"
-
node-fetch-native@^1.6.1, node-fetch-native@^1.6.2, node-fetch-native@^1.6.3:
version "1.6.4"
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e"
@@ -15191,6 +15255,11 @@ semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
+semver@^7.3.7:
+ version "7.6.3"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
+ integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
+
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -15514,6 +15583,14 @@ split@0.3:
dependencies:
through "2"
+spok@^1.4.3:
+ version "1.5.5"
+ resolved "https://registry.yarnpkg.com/spok/-/spok-1.5.5.tgz#a51f7f290a53131d7b7a922dfedc461dda0aed72"
+ integrity sha512-IrJIXY54sCNFASyHPOY+jEirkiJ26JDqsGiI0Dvhwcnkl0PEWi1PSsrkYql0rzDw8LFVTcA7rdUCAJdE2HE+2Q==
+ dependencies:
+ ansicolors "~0.3.2"
+ find-process "^1.4.7"
+
sprintf-js@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
@@ -17133,3 +17210,8 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+zstddec@^0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.0.2.tgz#57e2f28dd1ff56b750e07d158a43f0611ad9eeb4"
+ integrity sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==