@haven-fi/solauto-sdk 1.0.9 → 1.0.11
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/clients/solautoClient.d.ts +5 -4
- package/dist/clients/solautoClient.d.ts.map +1 -1
- package/dist/clients/solautoClient.js +17 -47
- package/dist/clients/solautoMarginfiClient.d.ts.map +1 -1
- package/dist/clients/solautoMarginfiClient.js +2 -3
- package/dist/constants/solautoConstants.d.ts +0 -3
- package/dist/constants/solautoConstants.d.ts.map +1 -1
- package/dist/constants/solautoConstants.js +1 -8
- package/dist/transactions/transactionUtils.d.ts +2 -2
- package/dist/transactions/transactionUtils.d.ts.map +1 -1
- package/dist/transactions/transactionUtils.js +9 -10
- package/dist/transactions/transactionsManager.d.ts.map +1 -1
- package/dist/transactions/transactionsManager.js +6 -7
- package/dist/utils/generalUtils.d.ts +2 -2
- package/dist/utils/generalUtils.d.ts.map +1 -1
- package/dist/utils/generalUtils.js +3 -3
- package/dist/utils/marginfiUtils.d.ts +4 -3
- package/dist/utils/marginfiUtils.d.ts.map +1 -1
- package/dist/utils/marginfiUtils.js +17 -16
- package/dist/utils/solanaUtils.d.ts +6 -7
- package/dist/utils/solanaUtils.d.ts.map +1 -1
- package/dist/utils/solanaUtils.js +20 -21
- package/dist/utils/solauto/generalUtils.d.ts +4 -4
- package/dist/utils/solauto/generalUtils.d.ts.map +1 -1
- package/dist/utils/solauto/generalUtils.js +50 -7
- package/package.json +1 -1
- package/src/clients/solautoClient.ts +42 -77
- package/src/clients/solautoMarginfiClient.ts +3 -6
- package/src/constants/solautoConstants.ts +1 -11
- package/src/transactions/transactionUtils.ts +11 -11
- package/src/transactions/transactionsManager.ts +11 -7
- package/src/utils/generalUtils.ts +5 -5
- package/src/utils/marginfiUtils.ts +28 -12
- package/src/utils/solanaUtils.ts +28 -23
- package/src/utils/solauto/generalUtils.ts +91 -14
- package/tests/transactions/solautoMarginfi.ts +1 -1
@@ -10,16 +10,15 @@ const umi_web3js_adapters_1 = require("@metaplex-foundation/umi-web3js-adapters"
|
|
10
10
|
const web3_js_1 = require("@solana/web3.js");
|
11
11
|
const spl_token_1 = require("@solana/spl-token");
|
12
12
|
const accountUtils_1 = require("./accountUtils");
|
13
|
-
const solautoConstants_1 = require("../constants/solautoConstants");
|
14
13
|
const generalUtils_1 = require("./generalUtils");
|
15
14
|
const marginfi_sdk_1 = require("../marginfi-sdk");
|
16
|
-
async function currentUnixSecondsSolana() {
|
15
|
+
async function currentUnixSecondsSolana(umi) {
|
17
16
|
return await (0, generalUtils_1.retryWithExponentialBackoff)(async () => {
|
18
|
-
const blockTime = await
|
17
|
+
const blockTime = await umi.rpc.getBlockTime(await umi.rpc.getSlot());
|
19
18
|
if (blockTime === null) {
|
20
19
|
throw new Error("Unable to retrieve block time");
|
21
20
|
}
|
22
|
-
return blockTime;
|
21
|
+
return Number(blockTime);
|
23
22
|
});
|
24
23
|
}
|
25
24
|
exports.currentUnixSecondsSolana = currentUnixSecondsSolana;
|
@@ -63,8 +62,8 @@ function splTokenTransferUmiIx(signer, fromTa, toTa, authority, amount) {
|
|
63
62
|
return getWrappedInstruction(signer, (0, spl_token_1.createTransferInstruction)(fromTa, toTa, authority, amount));
|
64
63
|
}
|
65
64
|
exports.splTokenTransferUmiIx = splTokenTransferUmiIx;
|
66
|
-
async function getAdressLookupInputs(lookupTableAddresses) {
|
67
|
-
const addressLookupTableAccountInfos = await
|
65
|
+
async function getAdressLookupInputs(umi, lookupTableAddresses) {
|
66
|
+
const addressLookupTableAccountInfos = await umi.rpc.getAccounts(lookupTableAddresses.map((key) => (0, umi_1.publicKey)(key)));
|
68
67
|
return addressLookupTableAccountInfos.reduce((acc, accountInfo, index) => {
|
69
68
|
const addressLookupTableAddress = lookupTableAddresses[index];
|
70
69
|
if (accountInfo.exists) {
|
@@ -119,8 +118,8 @@ function assembleFinalTransaction(signer, tx, computeUnitPrice, computeUnitLimit
|
|
119
118
|
return tx;
|
120
119
|
}
|
121
120
|
exports.assembleFinalTransaction = assembleFinalTransaction;
|
122
|
-
async function simulateTransaction(transaction) {
|
123
|
-
const simulationResult = await
|
121
|
+
async function simulateTransaction(connection, transaction) {
|
122
|
+
const simulationResult = await connection.simulateTransaction(transaction, {
|
124
123
|
sigVerify: true,
|
125
124
|
});
|
126
125
|
if (simulationResult.value.err) {
|
@@ -131,10 +130,10 @@ async function simulateTransaction(transaction) {
|
|
131
130
|
}
|
132
131
|
return simulationResult;
|
133
132
|
}
|
134
|
-
async function getComputeUnitPriceEstimate(tx, attemptNum) {
|
135
|
-
const web3Transaction = (0, umi_web3js_adapters_1.toWeb3JsTransaction)((await tx.setLatestBlockhash(
|
133
|
+
async function getComputeUnitPriceEstimate(umi, tx, attemptNum) {
|
134
|
+
const web3Transaction = (0, umi_web3js_adapters_1.toWeb3JsTransaction)((await tx.setLatestBlockhash(umi, { commitment: "finalized" })).build(umi));
|
136
135
|
const serializedTransaction = bs58_1.default.encode(web3Transaction.serialize());
|
137
|
-
const resp = await
|
136
|
+
const resp = await umi.rpc.call("getPriorityFeeEstimate", [
|
138
137
|
{
|
139
138
|
transaction: serializedTransaction,
|
140
139
|
options: { priorityLevel: attemptNum && attemptNum > 0 ? "VeryHigh" : "High" },
|
@@ -144,24 +143,24 @@ async function getComputeUnitPriceEstimate(tx, attemptNum) {
|
|
144
143
|
return feeEstimate;
|
145
144
|
}
|
146
145
|
exports.getComputeUnitPriceEstimate = getComputeUnitPriceEstimate;
|
147
|
-
async function sendSingleOptimizedTransaction(
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
const feeEstimate = await getComputeUnitPriceEstimate(tx, attemptNum);
|
152
|
-
|
153
|
-
const simulationResult = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await simulateTransaction((0, umi_web3js_adapters_1.toWeb3JsTransaction)(await (await assembleFinalTransaction(
|
146
|
+
async function sendSingleOptimizedTransaction(umi, connection, tx, simulateOnly, attemptNum) {
|
147
|
+
console.log("Sending single optimized transaction...");
|
148
|
+
console.log("Instructions: ", tx.getInstructions().length);
|
149
|
+
console.log("Serialized transaction size: ", tx.getTransactionSize(umi));
|
150
|
+
const feeEstimate = await getComputeUnitPriceEstimate(umi, tx, attemptNum);
|
151
|
+
console.log("Compute unit price: ", feeEstimate);
|
152
|
+
const simulationResult = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await simulateTransaction(connection, (0, umi_web3js_adapters_1.toWeb3JsTransaction)(await (await assembleFinalTransaction(umi.identity, tx, feeEstimate, 1400000).setLatestBlockhash(umi)).buildAndSign(umi))));
|
154
153
|
const computeUnitLimit = Math.round(simulationResult.value.unitsConsumed * 1.15);
|
155
|
-
|
154
|
+
console.log("Compute unit limit: ", computeUnitLimit);
|
156
155
|
if (!simulateOnly) {
|
157
|
-
const result = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await assembleFinalTransaction(
|
156
|
+
const result = await (0, generalUtils_1.retryWithExponentialBackoff)(async () => await assembleFinalTransaction(umi.identity, tx, feeEstimate, computeUnitLimit).sendAndConfirm(umi, {
|
158
157
|
send: {
|
159
158
|
skipPreflight: true,
|
160
159
|
commitment: "finalized",
|
161
160
|
},
|
162
161
|
confirm: { commitment: "finalized" },
|
163
162
|
}));
|
164
|
-
|
163
|
+
console.log(`https://solscan.io/tx/${bs58_1.default.encode(result.signature)}`);
|
165
164
|
if (result.result.value.err !== null) {
|
166
165
|
throw new Error(result.result.value.err.toString());
|
167
166
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { PublicKey } from "@metaplex-foundation/umi";
|
1
|
+
import { PublicKey, Umi } from "@metaplex-foundation/umi";
|
2
2
|
import { AutomationSettings, DCASettings, DCASettingsInpArgs, FeeType, LendingPlatform, PositionState, SolautoSettingsParameters, SolautoSettingsParametersInpArgs } from "../../generated";
|
3
3
|
export declare function nextAutomationPeriodTimestamp(automation: AutomationSettings): number;
|
4
4
|
export declare function eligibleForNextAutomationPeriod(automation: AutomationSettings): boolean;
|
@@ -14,13 +14,13 @@ export declare function maxRepayFrom(maxLtvBps: number, liqThresholdBps: number)
|
|
14
14
|
export declare function maxRepayTo(maxLtvBps: number, liqThresholdBps: number): number;
|
15
15
|
export declare function eligibileForRebalance(positionState: PositionState, positionSettings: SolautoSettingsParameters, positionDca: DCASettings): boolean;
|
16
16
|
export declare function eligibleForRefresh(positionState: PositionState, positionSettings: SolautoSettingsParameters): boolean;
|
17
|
-
export declare function getSolautoManagedPositions(authority?: PublicKey): Promise<{
|
17
|
+
export declare function getSolautoManagedPositions(umi: Umi, authority?: PublicKey): Promise<{
|
18
18
|
authority: PublicKey;
|
19
19
|
positionId: number;
|
20
20
|
lendingPlatform: LendingPlatform;
|
21
21
|
}[]>;
|
22
|
-
export declare function getAllReferralStates(): Promise<PublicKey[]>;
|
23
|
-
export declare function getReferralsByUser(user: PublicKey): Promise<PublicKey[]>;
|
22
|
+
export declare function getAllReferralStates(umi: Umi): Promise<PublicKey[]>;
|
23
|
+
export declare function getReferralsByUser(umi: Umi, user: PublicKey): Promise<PublicKey[]>;
|
24
24
|
type PositionAdjustment = {
|
25
25
|
type: "supply";
|
26
26
|
value: bigint;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/generalUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,MAAM,0BAA0B,CAAC;
|
1
|
+
{"version":3,"file":"generalUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/solauto/generalUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,eAAe,EACf,aAAa,EAEb,yBAAyB,EACzB,gCAAgC,EAIjC,MAAM,iBAAiB,CAAC;AA6BzB,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,kBAAkB,GAC7B,MAAM,CAKR;AAED,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,kBAAkB,GAC7B,OAAO,CAET;AAED,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,kBAAkB,EAC9B,oBAAoB,EAAE,MAAM,UAY7B;AAED,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,yBAAyB,EACnC,kBAAkB,EAAE,MAAM,GACzB,yBAAyB,CAgB3B;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,OAAO,GACf;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAYA;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,MAAM,CAER;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAKtE;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,UAKpE;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,yBAAyB,EAC3C,WAAW,EAAE,WAAW,GACvB,OAAO,CA+BT;AAED,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,yBAAyB,GAC1C,OAAO,CAST;AAED,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,GAAG,EACR,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CACR;IACE,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,eAAe,CAAC;CAClC,EAAE,CACJ,CAkDA;AAED,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAezE;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,SAAS,EAAE,CAAC,CA2BtB;AA4DD,KAAK,kBAAkB,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,gCAAgC,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,CAAC;AAE/C,qBAAa,mBAAmB;IACvB,gBAAgB,EAAE,MAAM,CAAa;IACrC,cAAc,EAAE,MAAM,CAAa;IACnC,uBAAuB,EAAE,MAAM,CAAa;IAC5C,QAAQ,EAAE,yBAAyB,GAAG,SAAS,CAAa;IAC5D,SAAS,EAAE,WAAW,GAAG,SAAS,CAAa;IAEtD,GAAG,CAAC,MAAM,EAAE,kBAAkB;IAyD9B,KAAK;IAQL,UAAU,IAAI,OAAO;CAQtB"}
|
@@ -8,6 +8,8 @@ const numberUtils_1 = require("../numberUtils");
|
|
8
8
|
const solautoConstants_1 = require("../../constants/solautoConstants");
|
9
9
|
const accountUtils_1 = require("../accountUtils");
|
10
10
|
const umi_web3js_adapters_1 = require("@metaplex-foundation/umi-web3js-adapters");
|
11
|
+
const constants_1 = require("../../constants");
|
12
|
+
const marginfiUtils_1 = require("../marginfiUtils");
|
11
13
|
function newPeriodsPassed(automation, currentUnixTimestamp) {
|
12
14
|
return Math.min(automation.targetPeriods, automation.periodsPassed +
|
13
15
|
Math.floor((currentUnixTimestamp - Number(automation.unixStartDate)) /
|
@@ -95,18 +97,19 @@ function eligibleForRefresh(positionState, positionSettings) {
|
|
95
97
|
return eligibleForNextAutomationPeriod(positionSettings.automation);
|
96
98
|
}
|
97
99
|
else {
|
98
|
-
return (0, generalUtils_1.currentUnixSeconds)() - Number(positionState.lastUpdated) >
|
100
|
+
return ((0, generalUtils_1.currentUnixSeconds)() - Number(positionState.lastUpdated) >
|
101
|
+
60 * 60 * 24 * 7);
|
99
102
|
}
|
100
103
|
}
|
101
104
|
exports.eligibleForRefresh = eligibleForRefresh;
|
102
|
-
async function getSolautoManagedPositions(authority) {
|
105
|
+
async function getSolautoManagedPositions(umi, authority) {
|
103
106
|
// bump: [u8; 1]
|
104
107
|
// position_id: [u8; 1]
|
105
108
|
// self_managed: u8 - (1 for true, 0 for false)
|
106
109
|
// padding: [u8; 5]
|
107
110
|
// authority: Pubkey
|
108
111
|
// lending_platform: u8
|
109
|
-
const accounts = await
|
112
|
+
const accounts = await umi.rpc.getProgramAccounts(generated_1.SOLAUTO_PROGRAM_ID, {
|
110
113
|
commitment: "finalized",
|
111
114
|
dataSlice: {
|
112
115
|
offset: 0,
|
@@ -147,8 +150,8 @@ async function getSolautoManagedPositions(authority) {
|
|
147
150
|
});
|
148
151
|
}
|
149
152
|
exports.getSolautoManagedPositions = getSolautoManagedPositions;
|
150
|
-
async function getAllReferralStates() {
|
151
|
-
const accounts = await
|
153
|
+
async function getAllReferralStates(umi) {
|
154
|
+
const accounts = await umi.rpc.getProgramAccounts(generated_1.SOLAUTO_PROGRAM_ID, {
|
152
155
|
commitment: "finalized",
|
153
156
|
dataSlice: {
|
154
157
|
offset: 0,
|
@@ -163,13 +166,13 @@ async function getAllReferralStates() {
|
|
163
166
|
return accounts.map((x) => x.publicKey);
|
164
167
|
}
|
165
168
|
exports.getAllReferralStates = getAllReferralStates;
|
166
|
-
async function getReferralsByUser(user) {
|
169
|
+
async function getReferralsByUser(umi, user) {
|
167
170
|
// bump: [u8; 1],
|
168
171
|
// padding: [u8; 7],
|
169
172
|
// authority: Pubkey,
|
170
173
|
// referred_by_state: Pubkey,
|
171
174
|
const userReferralState = await (0, accountUtils_1.getReferralState)((0, umi_web3js_adapters_1.toWeb3JsPublicKey)(user));
|
172
|
-
const accounts = await
|
175
|
+
const accounts = await umi.rpc.getProgramAccounts(generated_1.SOLAUTO_PROGRAM_ID, {
|
173
176
|
commitment: "finalized",
|
174
177
|
dataSlice: {
|
175
178
|
offset: 0,
|
@@ -190,6 +193,46 @@ async function getReferralsByUser(user) {
|
|
190
193
|
return accounts.map((x) => x.publicKey);
|
191
194
|
}
|
192
195
|
exports.getReferralsByUser = getReferralsByUser;
|
196
|
+
async function positionStateWithLatestPrices(umi, state, protocolAccount, lendingPlatform) {
|
197
|
+
if ((0, generalUtils_1.currentUnixSeconds)() - Number(state.lastUpdated) > 60 * 60 * 24 * 7) {
|
198
|
+
if (lendingPlatform === generated_1.LendingPlatform.Marginfi) {
|
199
|
+
return await (0, marginfiUtils_1.getMarginfiAccountPositionState)(umi, (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.supply.mint), (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.debt.mint), (0, umi_web3js_adapters_1.toWeb3JsPublicKey)(protocolAccount));
|
200
|
+
}
|
201
|
+
else {
|
202
|
+
throw new Error("Lending platorm not yet supported");
|
203
|
+
}
|
204
|
+
}
|
205
|
+
const [supplyPrice, debtPrice] = await (0, generalUtils_1.getTokenPrices)([
|
206
|
+
(0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.supply.mint),
|
207
|
+
(0, umi_web3js_adapters_1.toWeb3JsPublicKey)(state.debt.mint),
|
208
|
+
]);
|
209
|
+
const supplyUsd = (0, numberUtils_1.fromBaseUnit)(state.supply.amountUsed.baseUnit, state.supply.decimals) *
|
210
|
+
supplyPrice;
|
211
|
+
const debtUsd = (0, numberUtils_1.fromBaseUnit)(state.debt.amountUsed.baseUnit, state.debt.decimals) *
|
212
|
+
debtPrice;
|
213
|
+
return {
|
214
|
+
...state,
|
215
|
+
liqUtilizationRateBps: (0, numberUtils_1.getLiqUtilzationRateBps)(supplyUsd, debtUsd, state.liqThresholdBps),
|
216
|
+
netWorth: {
|
217
|
+
...state.netWorth,
|
218
|
+
baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(supplyUsd - debtUsd, constants_1.USD_DECIMALS),
|
219
|
+
},
|
220
|
+
supply: {
|
221
|
+
...state.supply,
|
222
|
+
amountUsed: {
|
223
|
+
...state.supply.amountUsed,
|
224
|
+
baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(supplyUsd, constants_1.USD_DECIMALS),
|
225
|
+
},
|
226
|
+
},
|
227
|
+
debt: {
|
228
|
+
...state.debt,
|
229
|
+
amountUsed: {
|
230
|
+
...state.debt.amountUsed,
|
231
|
+
baseAmountUsdValue: (0, numberUtils_1.toBaseUnit)(debtUsd, constants_1.USD_DECIMALS),
|
232
|
+
},
|
233
|
+
},
|
234
|
+
};
|
235
|
+
}
|
193
236
|
class LivePositionUpdates {
|
194
237
|
constructor() {
|
195
238
|
this.supplyAdjustment = BigInt(0);
|
package/package.json
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
import "rpc-websockets/dist/lib/client";
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
AddressLookupTableProgram,
|
4
|
+
Connection,
|
5
|
+
PublicKey,
|
6
|
+
} from "@solana/web3.js";
|
3
7
|
import {
|
4
8
|
Signer,
|
5
9
|
TransactionBuilder,
|
@@ -13,7 +17,10 @@ import {
|
|
13
17
|
some,
|
14
18
|
} from "@metaplex-foundation/umi";
|
15
19
|
import { toWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters";
|
16
|
-
import {
|
20
|
+
import {
|
21
|
+
WalletAdapter,
|
22
|
+
walletAdapterIdentity,
|
23
|
+
} from "@metaplex-foundation/umi-signer-wallet-adapters";
|
17
24
|
import {
|
18
25
|
DCASettings,
|
19
26
|
DCASettingsInpArgs,
|
@@ -29,6 +36,7 @@ import {
|
|
29
36
|
cancelDCA,
|
30
37
|
claimReferralFees,
|
31
38
|
closePosition,
|
39
|
+
createSolautoProgram,
|
32
40
|
safeFetchReferralState,
|
33
41
|
safeFetchSolautoPosition,
|
34
42
|
updatePosition,
|
@@ -39,10 +47,7 @@ import {
|
|
39
47
|
getSolautoPositionAccount,
|
40
48
|
getTokenAccount,
|
41
49
|
} from "../utils/accountUtils";
|
42
|
-
import {
|
43
|
-
SOLAUTO_FEES_WALLET,
|
44
|
-
USD_DECIMALS,
|
45
|
-
} from "../constants/generalAccounts";
|
50
|
+
import { SOLAUTO_FEES_WALLET } from "../constants/generalAccounts";
|
46
51
|
import { JupSwapDetails } from "../utils/jupiterUtils";
|
47
52
|
import {
|
48
53
|
getWrappedInstruction,
|
@@ -50,18 +55,10 @@ import {
|
|
50
55
|
} from "../utils/solanaUtils";
|
51
56
|
import { FlashLoanDetails } from "../utils/solauto/rebalanceUtils";
|
52
57
|
import { NATIVE_MINT } from "@solana/spl-token";
|
53
|
-
import {
|
54
|
-
|
55
|
-
MIN_POSITION_STATE_FRESHNESS_SECS,
|
56
|
-
UMI,
|
57
|
-
} from "../constants/solautoConstants";
|
58
|
-
import { currentUnixSeconds, getTokenPrices } from "../utils/generalUtils";
|
58
|
+
import { MIN_POSITION_STATE_FRESHNESS_SECS } from "../constants/solautoConstants";
|
59
|
+
import { currentUnixSeconds } from "../utils/generalUtils";
|
59
60
|
import { LivePositionUpdates } from "../utils/solauto/generalUtils";
|
60
|
-
import {
|
61
|
-
fromBaseUnit,
|
62
|
-
getLiqUtilzationRateBps,
|
63
|
-
toBaseUnit,
|
64
|
-
} from "../utils/numberUtils";
|
61
|
+
import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
|
65
62
|
|
66
63
|
export interface SolautoClientArgs {
|
67
64
|
authority?: PublicKey;
|
@@ -77,9 +74,8 @@ export interface SolautoClientArgs {
|
|
77
74
|
}
|
78
75
|
|
79
76
|
export abstract class SolautoClient {
|
80
|
-
public localTest: boolean;
|
81
|
-
|
82
77
|
public umi!: Umi;
|
78
|
+
public connection!: Connection;
|
83
79
|
public lendingPlatform!: LendingPlatform;
|
84
80
|
|
85
81
|
public authority!: PublicKey;
|
@@ -116,19 +112,37 @@ export abstract class SolautoClient {
|
|
116
112
|
|
117
113
|
public livePositionUpdates: LivePositionUpdates = new LivePositionUpdates();
|
118
114
|
|
119
|
-
constructor(
|
120
|
-
|
115
|
+
constructor(
|
116
|
+
private heliusApiKey: string,
|
117
|
+
public localTest?: boolean
|
118
|
+
) {
|
119
|
+
this.connection = new Connection(
|
120
|
+
`https://mainnet.helius-rpc.com/?api-key=${this.heliusApiKey}`,
|
121
|
+
"finalized"
|
122
|
+
);
|
123
|
+
this.umi = createUmi(this.connection).use({
|
124
|
+
install(umi) {
|
125
|
+
umi.programs.add(createSolautoProgram(), false);
|
126
|
+
},
|
127
|
+
});
|
121
128
|
}
|
122
129
|
|
123
|
-
async initialize(
|
124
|
-
|
130
|
+
async initialize(
|
131
|
+
args: SolautoClientArgs,
|
132
|
+
lendingPlatform: LendingPlatform,
|
133
|
+
) {
|
125
134
|
if (!args.signer && !args.wallet) {
|
126
135
|
throw new Error("Signer or wallet must be provided");
|
127
136
|
}
|
128
|
-
this.umi =
|
129
|
-
|
137
|
+
this.umi = this.umi.use(
|
138
|
+
args.signer
|
139
|
+
? signerIdentity(args.signer)
|
140
|
+
: walletAdapterIdentity(args.wallet!, true)
|
141
|
+
);
|
142
|
+
|
130
143
|
this.signer = this.umi.identity;
|
131
|
-
this.authority =
|
144
|
+
this.authority =
|
145
|
+
args.authority ?? toWeb3JsPublicKey(this.umi.identity.publicKey);
|
132
146
|
|
133
147
|
this.positionId = args.positionId;
|
134
148
|
this.selfManaged = this.positionId === 0;
|
@@ -282,7 +296,7 @@ export abstract class SolautoClient {
|
|
282
296
|
|
283
297
|
async fetchExistingAuthorityLutAccounts(): Promise<PublicKey[]> {
|
284
298
|
const lookupTable = this.authorityLutAddress
|
285
|
-
? await
|
299
|
+
? await this.connection.getAddressLookupTable(this.authorityLutAddress)
|
286
300
|
: null;
|
287
301
|
if (lookupTable === null) {
|
288
302
|
this.authorityLutAddress = undefined;
|
@@ -312,7 +326,7 @@ export abstract class SolautoClient {
|
|
312
326
|
AddressLookupTableProgram.createLookupTable({
|
313
327
|
authority: this.authority,
|
314
328
|
payer: toWeb3JsPublicKey(this.signer.publicKey),
|
315
|
-
recentSlot: await
|
329
|
+
recentSlot: await this.umi.rpc.getSlot({ commitment: "finalized" }),
|
316
330
|
});
|
317
331
|
this.authorityLutAddress = lookupTableAddress;
|
318
332
|
tx = tx.add(getWrappedInstruction(this.signer, createLookupTableInst));
|
@@ -626,55 +640,6 @@ export abstract class SolautoClient {
|
|
626
640
|
limitGapBps?: number
|
627
641
|
): TransactionBuilder;
|
628
642
|
|
629
|
-
async positionStateWithLatestPrices(): Promise<PositionState | undefined> {
|
630
|
-
if (!this.solautoPositionData) {
|
631
|
-
return undefined;
|
632
|
-
}
|
633
|
-
|
634
|
-
const state = this.solautoPositionState ?? this.solautoPositionData.state;
|
635
|
-
if (currentUnixSeconds() - Number(state.lastUpdated) > 60 * 60 * 24 * 7) {
|
636
|
-
return this.getFreshPositionState();
|
637
|
-
}
|
638
|
-
|
639
|
-
const [supplyPrice, debtPrice] = await getTokenPrices([
|
640
|
-
toWeb3JsPublicKey(state.supply.mint),
|
641
|
-
toWeb3JsPublicKey(state.debt.mint),
|
642
|
-
]);
|
643
|
-
|
644
|
-
const supplyUsd =
|
645
|
-
fromBaseUnit(state.supply.amountUsed.baseUnit, state.supply.decimals) *
|
646
|
-
supplyPrice;
|
647
|
-
const debtUsd =
|
648
|
-
fromBaseUnit(state.debt.amountUsed.baseUnit, state.debt.decimals) *
|
649
|
-
debtPrice;
|
650
|
-
return {
|
651
|
-
...state,
|
652
|
-
liqUtilizationRateBps: getLiqUtilzationRateBps(
|
653
|
-
supplyUsd,
|
654
|
-
debtUsd,
|
655
|
-
state.liqThresholdBps
|
656
|
-
),
|
657
|
-
netWorth: {
|
658
|
-
...state.netWorth,
|
659
|
-
baseAmountUsdValue: toBaseUnit(supplyUsd - debtUsd, USD_DECIMALS),
|
660
|
-
},
|
661
|
-
supply: {
|
662
|
-
...state.supply,
|
663
|
-
amountUsed: {
|
664
|
-
...state.supply.amountUsed,
|
665
|
-
baseAmountUsdValue: toBaseUnit(supplyUsd, USD_DECIMALS),
|
666
|
-
},
|
667
|
-
},
|
668
|
-
debt: {
|
669
|
-
...state.debt,
|
670
|
-
amountUsed: {
|
671
|
-
...state.debt.amountUsed,
|
672
|
-
baseAmountUsdValue: toBaseUnit(debtUsd, USD_DECIMALS),
|
673
|
-
},
|
674
|
-
},
|
675
|
-
};
|
676
|
-
}
|
677
|
-
|
678
643
|
async getFreshPositionState(): Promise<PositionState | undefined> {
|
679
644
|
if (
|
680
645
|
Boolean(this.solautoPositionState) &&
|
@@ -135,6 +135,7 @@ export class SolautoMarginfiClient extends SolautoClient {
|
|
135
135
|
})!;
|
136
136
|
|
137
137
|
const existingMarginfiAccounts = await getAllMarginfiAccountsByAuthority(
|
138
|
+
this.umi,
|
138
139
|
toWeb3JsPublicKey(this.signer.publicKey)
|
139
140
|
);
|
140
141
|
const emptyMarginfiAccounts = existingMarginfiAccounts.filter(
|
@@ -481,15 +482,11 @@ export class SolautoMarginfiClient extends SolautoClient {
|
|
481
482
|
return state;
|
482
483
|
}
|
483
484
|
|
484
|
-
const marginfiAccount = await safeFetchMarginfiAccount(
|
485
|
-
this.umi,
|
486
|
-
publicKey(this.marginfiAccountPk)
|
487
|
-
);
|
488
|
-
|
489
485
|
const freshState = await getMarginfiAccountPositionState(
|
486
|
+
this.umi,
|
490
487
|
this.supplyLiquidityMint,
|
491
488
|
this.debtLiquidityMint,
|
492
|
-
|
489
|
+
this.marginfiAccountPk,
|
493
490
|
this.livePositionUpdates
|
494
491
|
);
|
495
492
|
this.log(freshState);
|
@@ -12,7 +12,7 @@ import {
|
|
12
12
|
TOKEN_PROGRAM_ID,
|
13
13
|
} from "@solana/spl-token";
|
14
14
|
// import { JitoRpcConnection } from "jito-ts";
|
15
|
-
import {
|
15
|
+
import { SOLAUTO_PROGRAM_ID } from "../generated";
|
16
16
|
import { SOLAUTO_MANAGER } from "./generalAccounts";
|
17
17
|
|
18
18
|
export const DEFAULT_RISK_AVERSION_BPS = 1500;
|
@@ -20,21 +20,11 @@ export const DEFAULT_LIMIT_GAP_BPS = 1000;
|
|
20
20
|
export const MIN_POSITION_STATE_FRESHNESS_SECS = 5;
|
21
21
|
export const MAX_REPAY_GAP_BPS = 100;
|
22
22
|
|
23
|
-
export const CONNECTION = new Connection(
|
24
|
-
`https://mainnet.helius-rpc.com/?api-key=${process.env.HELIUS_API_KEY}`,
|
25
|
-
"finalized"
|
26
|
-
);
|
27
|
-
|
28
23
|
// export const JITO_BLOCK_ENGINE = "ny.mainnet.block-engine.jito.wtf";
|
29
24
|
// export const JITO_CONNECTION = new JitoRpcConnection(
|
30
25
|
// `https://${JITO_BLOCK_ENGINE}`,
|
31
26
|
// "finalized"
|
32
27
|
// );
|
33
|
-
export const UMI = createUmi(CONNECTION).use({
|
34
|
-
install(umi) {
|
35
|
-
umi.programs.add(createSolautoProgram(), false);
|
36
|
-
},
|
37
|
-
});
|
38
28
|
|
39
29
|
export const PRICES: { [key: string]: { price: number; time: number; } } = {};
|
40
30
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import {
|
2
2
|
Signer,
|
3
3
|
TransactionBuilder,
|
4
|
+
Umi,
|
4
5
|
publicKey,
|
5
6
|
transactionBuilder,
|
6
7
|
} from "@metaplex-foundation/umi";
|
@@ -39,7 +40,6 @@ import {
|
|
39
40
|
rpcAccountCreated,
|
40
41
|
} from "../utils/generalUtils";
|
41
42
|
import { SolautoMarginfiClient } from "../clients/solautoMarginfiClient";
|
42
|
-
import { UMI } from "../constants/solautoConstants";
|
43
43
|
import { uint8ArrayToBigInt } from "../utils/numberUtils";
|
44
44
|
import {
|
45
45
|
eligibileForRebalance,
|
@@ -121,7 +121,7 @@ async function transactionChoresBefore(
|
|
121
121
|
undefined
|
122
122
|
);
|
123
123
|
if (wSolUsage !== undefined) {
|
124
|
-
if (!getSolanaAccountCreated(wSolUsage.wSolTokenAccount)) {
|
124
|
+
if (!getSolanaAccountCreated(client.umi, wSolUsage.wSolTokenAccount)) {
|
125
125
|
client.log(`Closing signer wSol TA`);
|
126
126
|
chores = chores.add(
|
127
127
|
closeTokenAccountUmiIx(
|
@@ -150,7 +150,7 @@ async function transactionChoresBefore(
|
|
150
150
|
if (amountToTransfer > 0) {
|
151
151
|
const amount =
|
152
152
|
amountToTransfer +
|
153
|
-
(await
|
153
|
+
(await client.umi.rpc.getRent(TOKEN_ACCOUNT_SIZE)).basisPoints;
|
154
154
|
client.log(`Transferring ${amount} lamports to signer wSol TA`);
|
155
155
|
chores = chores.add(
|
156
156
|
systemTransferUmiIx(client.signer, wSolUsage.wSolTokenAccount, amount)
|
@@ -183,7 +183,7 @@ async function transactionChoresBefore(
|
|
183
183
|
continue;
|
184
184
|
}
|
185
185
|
|
186
|
-
if (!getSolanaAccountCreated(tokenAccount)) {
|
186
|
+
if (!getSolanaAccountCreated(client.umi, tokenAccount)) {
|
187
187
|
chores = chores.add(
|
188
188
|
createAssociatedTokenAccountUmiIx(
|
189
189
|
client.signer,
|
@@ -229,7 +229,7 @@ export async function rebalanceChoresBefore(
|
|
229
229
|
];
|
230
230
|
|
231
231
|
const [referredBySupplyTa, solautoFeesSupplyTa, intermediaryMarginfiAccount] =
|
232
|
-
await
|
232
|
+
await client.umi.rpc.getAccounts(
|
233
233
|
accountsNeeded.map((x) => publicKey(x ?? PublicKey.default))
|
234
234
|
);
|
235
235
|
|
@@ -482,12 +482,12 @@ export async function buildSolautoRebalanceTransaction(
|
|
482
482
|
}
|
483
483
|
|
484
484
|
export async function convertReferralFeesToDestination(
|
485
|
+
umi: Umi,
|
485
486
|
referralState: ReferralState,
|
486
487
|
tokenAccount: SplTokenAccount,
|
487
|
-
signer: Signer
|
488
488
|
): Promise<[TransactionBuilder, string[]]> {
|
489
489
|
const { lookupTableAddresses, setupInstructions, swapIx } =
|
490
|
-
await getJupSwapTransaction(
|
490
|
+
await getJupSwapTransaction(umi.identity, {
|
491
491
|
amount: tokenAccount.amount,
|
492
492
|
destinationWallet: toWeb3JsPublicKey(referralState.publicKey),
|
493
493
|
inputMint: tokenAccount.mint,
|
@@ -499,12 +499,12 @@ export async function convertReferralFeesToDestination(
|
|
499
499
|
let tx = transactionBuilder()
|
500
500
|
.add(setupInstructions)
|
501
501
|
.add(
|
502
|
-
convertReferralFees(
|
503
|
-
signer,
|
502
|
+
convertReferralFees(umi, {
|
503
|
+
signer: umi.identity,
|
504
504
|
intermediaryTa: publicKey(
|
505
505
|
getTokenAccount(
|
506
|
-
toWeb3JsPublicKey(
|
507
|
-
|
506
|
+
toWeb3JsPublicKey(umi.identity.publicKey),
|
507
|
+
tokenAccount.mint
|
508
508
|
)
|
509
509
|
),
|
510
510
|
ixsSysvar: publicKey(SYSVAR_INSTRUCTIONS_PUBKEY),
|
@@ -9,7 +9,6 @@ import {
|
|
9
9
|
getAdressLookupInputs,
|
10
10
|
sendSingleOptimizedTransaction,
|
11
11
|
} from "../utils/solanaUtils";
|
12
|
-
import { UMI } from "../constants/solautoConstants";
|
13
12
|
import { retryWithExponentialBackoff } from "../utils/generalUtils";
|
14
13
|
import { getTransactionChores } from "./transactionUtils";
|
15
14
|
// import { sendJitoBundledTransactions } from "../utils/jitoUtils";
|
@@ -35,7 +34,10 @@ class LookupTables {
|
|
35
34
|
(x) => !currentCacheAddresses.includes(x)
|
36
35
|
);
|
37
36
|
if (missingAddresses) {
|
38
|
-
const additionalInputs = await getAdressLookupInputs(
|
37
|
+
const additionalInputs = await getAdressLookupInputs(
|
38
|
+
this.client.umi,
|
39
|
+
missingAddresses
|
40
|
+
);
|
39
41
|
this.cache.push(...additionalInputs);
|
40
42
|
}
|
41
43
|
|
@@ -110,7 +112,7 @@ class TransactionSet {
|
|
110
112
|
...item.lookupTableAddresses,
|
111
113
|
])
|
112
114
|
)
|
113
|
-
.fitsInOneTransaction(
|
115
|
+
.fitsInOneTransaction(this.client.umi);
|
114
116
|
}
|
115
117
|
|
116
118
|
add(...items: TransactionItem[]) {
|
@@ -202,9 +204,9 @@ export class TransactionsManager {
|
|
202
204
|
const transaction = item.tx.setAddressLookupTables(
|
203
205
|
await this.lookupTables.getLutInputs(item.lookupTableAddresses)
|
204
206
|
);
|
205
|
-
if (!transaction.fitsInOneTransaction(
|
207
|
+
if (!transaction.fitsInOneTransaction(this.client.umi)) {
|
206
208
|
throw new Error(
|
207
|
-
`Transaction exceeds max transaction size (${transaction.getTransactionSize(
|
209
|
+
`Transaction exceeds max transaction size (${transaction.getTransactionSize(this.client.umi)})`
|
208
210
|
);
|
209
211
|
} else {
|
210
212
|
let newSet = new TransactionSet(this.client, this.lookupTables, [item]);
|
@@ -246,7 +248,8 @@ export class TransactionsManager {
|
|
246
248
|
await retryWithExponentialBackoff(
|
247
249
|
async (attemptNum) =>
|
248
250
|
await sendSingleOptimizedTransaction(
|
249
|
-
this.client,
|
251
|
+
this.client.umi,
|
252
|
+
this.client.connection,
|
250
253
|
updateLookupTable.updateLutTx,
|
251
254
|
this.simulateOnly,
|
252
255
|
attemptNum
|
@@ -353,7 +356,8 @@ export class TransactionsManager {
|
|
353
356
|
} else {
|
354
357
|
this.updateStatus(itemSet.name(), TransactionStatus.Processing);
|
355
358
|
const txSig = await sendSingleOptimizedTransaction(
|
356
|
-
this.client,
|
359
|
+
this.client.umi,
|
360
|
+
this.client.connection,
|
357
361
|
tx,
|
358
362
|
this.simulateOnly,
|
359
363
|
attemptNum
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { PublicKey } from "@solana/web3.js";
|
2
|
-
import { MaybeRpcAccount, publicKey } from "@metaplex-foundation/umi";
|
2
|
+
import { MaybeRpcAccount, publicKey, Umi } from "@metaplex-foundation/umi";
|
3
3
|
import { PYTH_PRICE_FEED_IDS } from "../constants/pythConstants";
|
4
4
|
import { fromBaseUnit, toBaseUnit } from "./numberUtils";
|
5
|
-
import { PRICES
|
5
|
+
import { PRICES } from "../constants/solautoConstants";
|
6
6
|
|
7
7
|
export function generateRandomU8(): number {
|
8
8
|
return Math.floor(Math.random() * 255 + 1);
|
@@ -21,8 +21,8 @@ export function currentUnixSeconds(): number {
|
|
21
21
|
return Math.round(new Date().getTime() / 1000);
|
22
22
|
}
|
23
23
|
|
24
|
-
export async function getSolanaAccountCreated(pk: PublicKey): Promise<boolean> {
|
25
|
-
const account = await
|
24
|
+
export async function getSolanaAccountCreated(umi: Umi, pk: PublicKey): Promise<boolean> {
|
25
|
+
const account = await umi.rpc.getAccount(publicKey(pk));
|
26
26
|
return rpcAccountCreated(account);
|
27
27
|
}
|
28
28
|
|
@@ -44,7 +44,7 @@ export function arraysAreEqual(arrayA: number[], arrayB: number[]): boolean {
|
|
44
44
|
|
45
45
|
export async function getTokenPrices(mints: PublicKey[]): Promise<number[]> {
|
46
46
|
const currentTime = currentUnixSeconds();
|
47
|
-
if (!mints.some(mint => !(mint.toString() in PRICES) || currentTime - PRICES[mint.toString()].time >
|
47
|
+
if (!mints.some(mint => !(mint.toString() in PRICES) || currentTime - PRICES[mint.toString()].time > 5)) {
|
48
48
|
console.log("Accessing price cache");
|
49
49
|
return mints.map(mint => PRICES[mint.toString()].price);
|
50
50
|
}
|