@0dotxyz/p0-ts-sdk 2.2.0-alpha.4 → 2.2.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2302 -917
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +284 -72
- package/dist/index.d.ts +284 -72
- package/dist/index.js +2288 -918
- package/dist/index.js.map +1 -1
- package/dist/vendor.cjs +349 -0
- package/dist/vendor.cjs.map +1 -1
- package/dist/vendor.d.cts +288 -3
- package/dist/vendor.d.ts +288 -3
- package/dist/vendor.js +340 -2
- package/dist/vendor.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@ import { Buffer as Buffer$1 } from 'buffer';
|
|
|
10
10
|
import { deserialize } from 'borsh';
|
|
11
11
|
import * as borsh from '@coral-xyz/borsh';
|
|
12
12
|
import { struct as struct$1, bool as bool$1, publicKey as publicKey$1, array as array$1, u64 as u64$1, u8 as u8$1, u32 as u32$1, u128 } from '@coral-xyz/borsh';
|
|
13
|
+
import WebSocket from 'ws';
|
|
14
|
+
import { Encoder, Decoder } from '@msgpack/msgpack';
|
|
13
15
|
import { SwapApi, Configuration, createJupiterApiClient } from '@jup-ag/api';
|
|
14
16
|
import { AnchorUtils, PullFeed } from '@switchboard-xyz/on-demand';
|
|
15
17
|
import { CrossbarClient } from '@switchboard-xyz/common';
|
|
@@ -91,10 +93,14 @@ function getConfig(environment = "production", overrides) {
|
|
|
91
93
|
var TransactionBuildingErrorCode = /* @__PURE__ */ ((TransactionBuildingErrorCode2) => {
|
|
92
94
|
TransactionBuildingErrorCode2["JUPITER_SWAP_SIZE_EXCEEDED_REPAY"] = "JUPITER_SWAP_SIZE_EXCEEDED_REPAY";
|
|
93
95
|
TransactionBuildingErrorCode2["JUPITER_SWAP_SIZE_EXCEEDED_LOOP"] = "JUPITER_SWAP_SIZE_EXCEEDED_LOOP";
|
|
96
|
+
TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_LOOP"] = "SWAP_SIZE_EXCEEDED_LOOP";
|
|
97
|
+
TransactionBuildingErrorCode2["SWAP_SIZE_EXCEEDED_REPAY"] = "SWAP_SIZE_EXCEEDED_REPAY";
|
|
94
98
|
TransactionBuildingErrorCode2["ORACLE_CRANK_FAILED"] = "ORACLE_CRANK_FAILED";
|
|
95
99
|
TransactionBuildingErrorCode2["KAMINO_RESERVE_NOT_FOUND"] = "KAMINO_RESERVE_NOT_FOUND";
|
|
96
100
|
TransactionBuildingErrorCode2["DRIFT_STATE_NOT_FOUND"] = "DRIFT_STATE_NOT_FOUND";
|
|
97
101
|
TransactionBuildingErrorCode2["JUPLEND_STATE_NOT_FOUND"] = "JUPLEND_STATE_NOT_FOUND";
|
|
102
|
+
TransactionBuildingErrorCode2["SWITCHBOARD_FEED_UPDATE_FAILED"] = "SWITCHBOARD_FEED_UPDATE_FAILED";
|
|
103
|
+
TransactionBuildingErrorCode2["SWAP_QUOTE_FAILED"] = "SWAP_QUOTE_FAILED";
|
|
98
104
|
return TransactionBuildingErrorCode2;
|
|
99
105
|
})(TransactionBuildingErrorCode || {});
|
|
100
106
|
var TransactionBuildingError = class _TransactionBuildingError extends Error {
|
|
@@ -126,6 +132,20 @@ var TransactionBuildingError = class _TransactionBuildingError extends Error {
|
|
|
126
132
|
{ bytes, accountKeys }
|
|
127
133
|
);
|
|
128
134
|
}
|
|
135
|
+
static swapSizeExceededLoop(bytes, accountKeys, provider) {
|
|
136
|
+
return new _TransactionBuildingError(
|
|
137
|
+
"SWAP_SIZE_EXCEEDED_LOOP" /* SWAP_SIZE_EXCEEDED_LOOP */,
|
|
138
|
+
`${provider ?? "Swap"} instruction size exceeds available transaction size`,
|
|
139
|
+
{ bytes, accountKeys, provider }
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
static swapSizeExceededRepay(bytes, accountKeys, provider) {
|
|
143
|
+
return new _TransactionBuildingError(
|
|
144
|
+
"SWAP_SIZE_EXCEEDED_REPAY" /* SWAP_SIZE_EXCEEDED_REPAY */,
|
|
145
|
+
`${provider ?? "Swap"} instruction size exceeds available transaction size`,
|
|
146
|
+
{ bytes, accountKeys, provider }
|
|
147
|
+
);
|
|
148
|
+
}
|
|
129
149
|
/**
|
|
130
150
|
* Failed to crank oracles for one or more banks
|
|
131
151
|
*/
|
|
@@ -167,6 +187,26 @@ var TransactionBuildingError = class _TransactionBuildingError extends Error {
|
|
|
167
187
|
{ bankAddress, bankMint, bankSymbol }
|
|
168
188
|
);
|
|
169
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Failed to update Switchboard price feeds
|
|
192
|
+
*/
|
|
193
|
+
static switchboardFeedUpdateFailed(oracleKeys, reason) {
|
|
194
|
+
return new _TransactionBuildingError(
|
|
195
|
+
"SWITCHBOARD_FEED_UPDATE_FAILED" /* SWITCHBOARD_FEED_UPDATE_FAILED */,
|
|
196
|
+
`Switchboard feed update failed: ${reason}`,
|
|
197
|
+
{ oracleKeys, reason }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Failed to get a swap quote from any provider
|
|
202
|
+
*/
|
|
203
|
+
static swapQuoteFailed(provider, inputMint, outputMint, reason) {
|
|
204
|
+
return new _TransactionBuildingError(
|
|
205
|
+
"SWAP_QUOTE_FAILED" /* SWAP_QUOTE_FAILED */,
|
|
206
|
+
`${provider} swap quote failed for ${inputMint} \u2192 ${outputMint}: ${reason}`,
|
|
207
|
+
{ provider, inputMint, outputMint, reason }
|
|
208
|
+
);
|
|
209
|
+
}
|
|
170
210
|
/**
|
|
171
211
|
* Generic escape hatch for custom errors
|
|
172
212
|
*/
|
|
@@ -319,6 +359,7 @@ var MAX_U64 = BigInt("18446744073709551615").toString();
|
|
|
319
359
|
|
|
320
360
|
// src/constants/transaction.consts.ts
|
|
321
361
|
var MAX_TX_SIZE = 1232;
|
|
362
|
+
var MAX_ACCOUNT_LOCKS = 64;
|
|
322
363
|
var BUNDLE_TX_SIZE = 81;
|
|
323
364
|
var PRIORITY_TX_SIZE = 44;
|
|
324
365
|
var WSOL_MINT = new PublicKey("So11111111111111111111111111111111111111112");
|
|
@@ -14867,8 +14908,40 @@ function getTxSize(tx) {
|
|
|
14867
14908
|
const signaturesSize = (numRequiredSignatures - numSigners) * 64 + 1;
|
|
14868
14909
|
try {
|
|
14869
14910
|
const baseTxSize = isVersioned ? tx.serialize().length : tx.serialize({ requireAllSignatures: false, verifySignatures: false }).length;
|
|
14870
|
-
|
|
14871
|
-
|
|
14911
|
+
const totalSize = baseTxSize + feePayerSize + signaturesSize;
|
|
14912
|
+
if (isVersioned && totalSize > 1232) {
|
|
14913
|
+
const { header, staticAccountKeys, addressTableLookups } = tx.message;
|
|
14914
|
+
const lutWritable = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
|
|
14915
|
+
const lutReadonly = addressTableLookups.reduce((s, l) => s + l.readonlyIndexes.length, 0);
|
|
14916
|
+
console.warn("[getTxSize] oversized TX", {
|
|
14917
|
+
totalSize,
|
|
14918
|
+
overshoot: totalSize - 1232,
|
|
14919
|
+
staticKeys: staticAccountKeys.length,
|
|
14920
|
+
numSignatures: header.numRequiredSignatures,
|
|
14921
|
+
numLuts: addressTableLookups.length,
|
|
14922
|
+
lutWritable,
|
|
14923
|
+
lutReadonly,
|
|
14924
|
+
totalAccounts: staticAccountKeys.length + lutWritable + lutReadonly
|
|
14925
|
+
});
|
|
14926
|
+
}
|
|
14927
|
+
return totalSize;
|
|
14928
|
+
} catch (err) {
|
|
14929
|
+
if (isVersioned) {
|
|
14930
|
+
const { header, staticAccountKeys, addressTableLookups } = tx.message;
|
|
14931
|
+
const lutWritable = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
|
|
14932
|
+
const lutReadonly = addressTableLookups.reduce((s, l) => s + l.readonlyIndexes.length, 0);
|
|
14933
|
+
console.warn("[getTxSize] serialize failed", {
|
|
14934
|
+
error: err.message,
|
|
14935
|
+
staticKeys: staticAccountKeys.length,
|
|
14936
|
+
numSignatures: header.numRequiredSignatures,
|
|
14937
|
+
numLuts: addressTableLookups.length,
|
|
14938
|
+
lutWritable,
|
|
14939
|
+
lutReadonly,
|
|
14940
|
+
totalAccounts: staticAccountKeys.length + lutWritable + lutReadonly
|
|
14941
|
+
});
|
|
14942
|
+
} else {
|
|
14943
|
+
console.warn("[getTxSize] serialize failed", { error: err.message });
|
|
14944
|
+
}
|
|
14872
14945
|
return 9999;
|
|
14873
14946
|
}
|
|
14874
14947
|
}
|
|
@@ -14883,6 +14956,47 @@ function getAccountKeys(tx, lookupTableAccounts) {
|
|
|
14883
14956
|
} else {
|
|
14884
14957
|
return tx.compileMessage().getAccountKeys().length;
|
|
14885
14958
|
}
|
|
14959
|
+
} catch (err) {
|
|
14960
|
+
console.warn("[getAccountKeys] decompile failed", { error: err.message });
|
|
14961
|
+
return 9999;
|
|
14962
|
+
}
|
|
14963
|
+
}
|
|
14964
|
+
function getWritableAccountKeys(tx) {
|
|
14965
|
+
const isVersioned = isV0Tx(tx);
|
|
14966
|
+
try {
|
|
14967
|
+
if (isVersioned) {
|
|
14968
|
+
const { header, staticAccountKeys, addressTableLookups } = tx.message;
|
|
14969
|
+
const writableStatic = staticAccountKeys.length - header.numReadonlySignedAccounts - header.numReadonlyUnsignedAccounts;
|
|
14970
|
+
const writableLut = addressTableLookups.reduce(
|
|
14971
|
+
(sum, lookup) => sum + lookup.writableIndexes.length,
|
|
14972
|
+
0
|
|
14973
|
+
);
|
|
14974
|
+
return writableStatic + writableLut;
|
|
14975
|
+
} else {
|
|
14976
|
+
const message = tx.compileMessage();
|
|
14977
|
+
const { numRequiredSignatures, numReadonlySignedAccounts, numReadonlyUnsignedAccounts } = message.header;
|
|
14978
|
+
const totalKeys = message.accountKeys.length;
|
|
14979
|
+
const writableSigned = numRequiredSignatures - numReadonlySignedAccounts;
|
|
14980
|
+
const writableUnsigned = totalKeys - numRequiredSignatures - numReadonlyUnsignedAccounts;
|
|
14981
|
+
return writableSigned + writableUnsigned;
|
|
14982
|
+
}
|
|
14983
|
+
} catch {
|
|
14984
|
+
return 9999;
|
|
14985
|
+
}
|
|
14986
|
+
}
|
|
14987
|
+
function getTotalAccountKeys(tx) {
|
|
14988
|
+
const isVersioned = isV0Tx(tx);
|
|
14989
|
+
try {
|
|
14990
|
+
if (isVersioned) {
|
|
14991
|
+
const { staticAccountKeys, addressTableLookups } = tx.message;
|
|
14992
|
+
const lutAccounts = addressTableLookups.reduce(
|
|
14993
|
+
(sum, lookup) => sum + lookup.writableIndexes.length + lookup.readonlyIndexes.length,
|
|
14994
|
+
0
|
|
14995
|
+
);
|
|
14996
|
+
return staticAccountKeys.length + lutAccounts;
|
|
14997
|
+
} else {
|
|
14998
|
+
return tx.compileMessage().accountKeys.length;
|
|
14999
|
+
}
|
|
14886
15000
|
} catch {
|
|
14887
15001
|
return 9999;
|
|
14888
15002
|
}
|
|
@@ -20120,6 +20234,14 @@ var HealthCacheSimulationError = class _HealthCacheSimulationError extends Error
|
|
|
20120
20234
|
}
|
|
20121
20235
|
};
|
|
20122
20236
|
|
|
20237
|
+
// src/services/account/types/action.types.ts
|
|
20238
|
+
var SwapProvider = /* @__PURE__ */ ((SwapProvider2) => {
|
|
20239
|
+
SwapProvider2["JUPITER"] = "JUPITER";
|
|
20240
|
+
SwapProvider2["TITAN"] = "TITAN";
|
|
20241
|
+
SwapProvider2["DFLOW"] = "DFLOW";
|
|
20242
|
+
return SwapProvider2;
|
|
20243
|
+
})(SwapProvider || {});
|
|
20244
|
+
|
|
20123
20245
|
// src/services/account/utils/deserialize.utils.ts
|
|
20124
20246
|
var EMPTY_HEALTH_CACHE = {
|
|
20125
20247
|
assetValue: {
|
|
@@ -44168,6 +44290,330 @@ function makeUpdateJupLendRate({ lendingState }) {
|
|
|
44168
44290
|
lendingState.rewardsRateModel
|
|
44169
44291
|
);
|
|
44170
44292
|
}
|
|
44293
|
+
var SUBPROTOCOL = "v1.api.titan.ag";
|
|
44294
|
+
var UINT64_MAX = (1n << 64n) - 1n;
|
|
44295
|
+
function toBigInt(value) {
|
|
44296
|
+
if (typeof value === "bigint") {
|
|
44297
|
+
if (value < 0n || value > UINT64_MAX) {
|
|
44298
|
+
throw new RangeError(`Amount out of uint64 range: ${value}`);
|
|
44299
|
+
}
|
|
44300
|
+
return value;
|
|
44301
|
+
}
|
|
44302
|
+
if (!Number.isInteger(value)) {
|
|
44303
|
+
throw new TypeError(`Amount must be a whole number, got ${value}`);
|
|
44304
|
+
}
|
|
44305
|
+
if (value < 0) {
|
|
44306
|
+
throw new RangeError(`Amount must be non-negative, got ${value}`);
|
|
44307
|
+
}
|
|
44308
|
+
return BigInt(value);
|
|
44309
|
+
}
|
|
44310
|
+
var ConnectionClosed = class _ConnectionClosed extends Error {
|
|
44311
|
+
code;
|
|
44312
|
+
reason;
|
|
44313
|
+
constructor(code, reason) {
|
|
44314
|
+
super(`Client WebSocket closed with code ${code}: ${reason}`);
|
|
44315
|
+
this.name = "ConnectionClosed";
|
|
44316
|
+
Object.setPrototypeOf(this, _ConnectionClosed.prototype);
|
|
44317
|
+
this.code = code;
|
|
44318
|
+
this.reason = reason;
|
|
44319
|
+
}
|
|
44320
|
+
};
|
|
44321
|
+
var ErrorResponse = class _ErrorResponse extends Error {
|
|
44322
|
+
response;
|
|
44323
|
+
constructor(response) {
|
|
44324
|
+
super(`Request ${response.requestId} failed with code ${response.code}: ${response.message}`);
|
|
44325
|
+
this.name = "ErrorResponse";
|
|
44326
|
+
Object.setPrototypeOf(this, _ErrorResponse.prototype);
|
|
44327
|
+
this.response = response;
|
|
44328
|
+
}
|
|
44329
|
+
};
|
|
44330
|
+
var StreamError = class _StreamError extends Error {
|
|
44331
|
+
streamId;
|
|
44332
|
+
errorCode;
|
|
44333
|
+
errorMessage;
|
|
44334
|
+
constructor(packet) {
|
|
44335
|
+
const code = packet.errorCode ?? 0;
|
|
44336
|
+
const message = packet.errorMessage ?? "";
|
|
44337
|
+
super(`Stream ${packet.id} ended with error code ${code}: ${message}`);
|
|
44338
|
+
this.name = "StreamError";
|
|
44339
|
+
Object.setPrototypeOf(this, _StreamError.prototype);
|
|
44340
|
+
this.streamId = packet.id;
|
|
44341
|
+
this.errorCode = code;
|
|
44342
|
+
this.errorMessage = message;
|
|
44343
|
+
}
|
|
44344
|
+
};
|
|
44345
|
+
var encoder = new Encoder({ useBigInt64: true });
|
|
44346
|
+
var decoder = new Decoder({ useBigInt64: true });
|
|
44347
|
+
var V1Client = class _V1Client {
|
|
44348
|
+
socket;
|
|
44349
|
+
nextId = 0;
|
|
44350
|
+
_closed = false;
|
|
44351
|
+
_closing = false;
|
|
44352
|
+
pending = /* @__PURE__ */ new Map();
|
|
44353
|
+
streams = /* @__PURE__ */ new Map();
|
|
44354
|
+
streamStopping = /* @__PURE__ */ new Map();
|
|
44355
|
+
closeListeners = [];
|
|
44356
|
+
// --- Static connect ---
|
|
44357
|
+
static connect(url) {
|
|
44358
|
+
return new Promise((resolve, reject) => {
|
|
44359
|
+
const ws = new WebSocket(url, [SUBPROTOCOL]);
|
|
44360
|
+
ws.binaryType = "arraybuffer";
|
|
44361
|
+
ws.on("open", () => {
|
|
44362
|
+
resolve(new _V1Client(ws));
|
|
44363
|
+
});
|
|
44364
|
+
ws.on("error", (err) => {
|
|
44365
|
+
reject(err);
|
|
44366
|
+
});
|
|
44367
|
+
});
|
|
44368
|
+
}
|
|
44369
|
+
// --- Constructor ---
|
|
44370
|
+
constructor(socket) {
|
|
44371
|
+
this.socket = socket;
|
|
44372
|
+
this.socket.on("message", (data) => {
|
|
44373
|
+
this.handleMessage(data);
|
|
44374
|
+
});
|
|
44375
|
+
this.socket.on("close", (code, reason) => {
|
|
44376
|
+
this.handleClose(code, reason.toString());
|
|
44377
|
+
});
|
|
44378
|
+
this.socket.on("error", (err) => {
|
|
44379
|
+
this.handleError(err);
|
|
44380
|
+
});
|
|
44381
|
+
}
|
|
44382
|
+
nextRequestId() {
|
|
44383
|
+
return this.nextId++;
|
|
44384
|
+
}
|
|
44385
|
+
// --- Public API ---
|
|
44386
|
+
get closed() {
|
|
44387
|
+
return this._closed;
|
|
44388
|
+
}
|
|
44389
|
+
close() {
|
|
44390
|
+
if (this._closed) return Promise.resolve();
|
|
44391
|
+
return new Promise((resolve, reject) => {
|
|
44392
|
+
this.closeListeners.push({ resolve, reject });
|
|
44393
|
+
if (!this._closing) {
|
|
44394
|
+
this._closing = true;
|
|
44395
|
+
this.socket.close();
|
|
44396
|
+
}
|
|
44397
|
+
});
|
|
44398
|
+
}
|
|
44399
|
+
newSwapQuoteStream(params) {
|
|
44400
|
+
const requestId = this.nextRequestId();
|
|
44401
|
+
const promise = new Promise(
|
|
44402
|
+
(resolve, reject) => {
|
|
44403
|
+
this.pending.set(requestId, {
|
|
44404
|
+
resolve,
|
|
44405
|
+
reject,
|
|
44406
|
+
kind: "NewSwapQuoteStream"
|
|
44407
|
+
});
|
|
44408
|
+
}
|
|
44409
|
+
);
|
|
44410
|
+
const normalized = {
|
|
44411
|
+
...params,
|
|
44412
|
+
swap: { ...params.swap, amount: toBigInt(params.swap.amount) }
|
|
44413
|
+
};
|
|
44414
|
+
const message = {
|
|
44415
|
+
id: requestId,
|
|
44416
|
+
data: { NewSwapQuoteStream: normalized }
|
|
44417
|
+
};
|
|
44418
|
+
this.send(message);
|
|
44419
|
+
return promise;
|
|
44420
|
+
}
|
|
44421
|
+
stopStream(streamId) {
|
|
44422
|
+
const requestId = this.nextRequestId();
|
|
44423
|
+
const promise = new Promise((resolve, reject) => {
|
|
44424
|
+
this.pending.set(requestId, {
|
|
44425
|
+
resolve,
|
|
44426
|
+
reject,
|
|
44427
|
+
kind: "StopStream"
|
|
44428
|
+
});
|
|
44429
|
+
});
|
|
44430
|
+
const message = {
|
|
44431
|
+
id: requestId,
|
|
44432
|
+
data: { StopStream: { id: streamId } }
|
|
44433
|
+
};
|
|
44434
|
+
this.send(message);
|
|
44435
|
+
return promise;
|
|
44436
|
+
}
|
|
44437
|
+
// --- Send ---
|
|
44438
|
+
send(message) {
|
|
44439
|
+
try {
|
|
44440
|
+
const encoded = encoder.encode(message);
|
|
44441
|
+
this.socket.send(encoded);
|
|
44442
|
+
} catch (err) {
|
|
44443
|
+
const req = this.pending.get(message.id);
|
|
44444
|
+
if (req) {
|
|
44445
|
+
this.pending.delete(message.id);
|
|
44446
|
+
req.reject(err);
|
|
44447
|
+
}
|
|
44448
|
+
}
|
|
44449
|
+
}
|
|
44450
|
+
// --- Message handling ---
|
|
44451
|
+
handleMessage(raw) {
|
|
44452
|
+
let buf;
|
|
44453
|
+
if (raw instanceof ArrayBuffer) {
|
|
44454
|
+
buf = new Uint8Array(raw);
|
|
44455
|
+
} else if (Buffer.isBuffer(raw)) {
|
|
44456
|
+
buf = new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
44457
|
+
} else if (Array.isArray(raw)) {
|
|
44458
|
+
buf = new Uint8Array(Buffer.concat(raw));
|
|
44459
|
+
} else {
|
|
44460
|
+
return;
|
|
44461
|
+
}
|
|
44462
|
+
let message;
|
|
44463
|
+
try {
|
|
44464
|
+
message = decoder.decode(buf);
|
|
44465
|
+
} catch {
|
|
44466
|
+
this.socket.close(3002, "failed to decode message");
|
|
44467
|
+
return;
|
|
44468
|
+
}
|
|
44469
|
+
if ("Response" in message) {
|
|
44470
|
+
this.handleResponse(message.Response);
|
|
44471
|
+
} else if ("Error" in message) {
|
|
44472
|
+
this.handleResponseError(message.Error);
|
|
44473
|
+
} else if ("StreamData" in message) {
|
|
44474
|
+
this.handleStreamData(message.StreamData);
|
|
44475
|
+
} else if ("StreamEnd" in message) {
|
|
44476
|
+
this.handleStreamEnd(message.StreamEnd);
|
|
44477
|
+
}
|
|
44478
|
+
}
|
|
44479
|
+
handleResponse(msg) {
|
|
44480
|
+
const req = this.pending.get(msg.requestId);
|
|
44481
|
+
if (!req) return;
|
|
44482
|
+
this.pending.delete(msg.requestId);
|
|
44483
|
+
if ("NewSwapQuoteStream" in msg.data && req.kind === "NewSwapQuoteStream") {
|
|
44484
|
+
const streamInfo = msg.stream;
|
|
44485
|
+
if (!streamInfo) {
|
|
44486
|
+
req.reject(new Error("No stream associated with NewSwapQuoteStream response"));
|
|
44487
|
+
return;
|
|
44488
|
+
}
|
|
44489
|
+
const stream = new ReadableStream({
|
|
44490
|
+
start: (controller) => {
|
|
44491
|
+
this.streams.set(streamInfo.id, controller);
|
|
44492
|
+
},
|
|
44493
|
+
cancel: () => {
|
|
44494
|
+
return this.cancelStream(streamInfo.id);
|
|
44495
|
+
}
|
|
44496
|
+
});
|
|
44497
|
+
const result = {
|
|
44498
|
+
response: msg.data.NewSwapQuoteStream,
|
|
44499
|
+
stream,
|
|
44500
|
+
streamId: streamInfo.id
|
|
44501
|
+
};
|
|
44502
|
+
req.resolve(result);
|
|
44503
|
+
} else if ("StreamStopped" in msg.data && req.kind === "StopStream") {
|
|
44504
|
+
req.resolve(msg.data.StreamStopped);
|
|
44505
|
+
} else {
|
|
44506
|
+
req.reject(new Error(`Unexpected response type for ${req.kind}`));
|
|
44507
|
+
}
|
|
44508
|
+
}
|
|
44509
|
+
handleResponseError(error) {
|
|
44510
|
+
const req = this.pending.get(error.requestId);
|
|
44511
|
+
if (!req) return;
|
|
44512
|
+
this.pending.delete(error.requestId);
|
|
44513
|
+
req.reject(new ErrorResponse(error));
|
|
44514
|
+
}
|
|
44515
|
+
handleStreamData(packet) {
|
|
44516
|
+
const controller = this.streams.get(packet.id);
|
|
44517
|
+
if (!controller) return;
|
|
44518
|
+
if (packet.payload.SwapQuotes !== void 0) {
|
|
44519
|
+
controller.enqueue(packet.payload.SwapQuotes);
|
|
44520
|
+
}
|
|
44521
|
+
}
|
|
44522
|
+
handleStreamEnd(packet) {
|
|
44523
|
+
const controller = this.streams.get(packet.id);
|
|
44524
|
+
if (!controller) return;
|
|
44525
|
+
this.streams.delete(packet.id);
|
|
44526
|
+
this.streamStopping.delete(packet.id);
|
|
44527
|
+
if (packet.errorCode !== void 0) {
|
|
44528
|
+
controller.error(new StreamError(packet));
|
|
44529
|
+
} else {
|
|
44530
|
+
controller.close();
|
|
44531
|
+
}
|
|
44532
|
+
}
|
|
44533
|
+
async cancelStream(streamId) {
|
|
44534
|
+
if (this.streamStopping.get(streamId) || !this.streams.has(streamId)) return;
|
|
44535
|
+
this.streamStopping.set(streamId, true);
|
|
44536
|
+
await this.stopStream(streamId);
|
|
44537
|
+
}
|
|
44538
|
+
// --- Connection lifecycle ---
|
|
44539
|
+
rejectAll(error) {
|
|
44540
|
+
for (const req of this.pending.values()) {
|
|
44541
|
+
req.reject(error);
|
|
44542
|
+
}
|
|
44543
|
+
this.pending.clear();
|
|
44544
|
+
for (const controller of this.streams.values()) {
|
|
44545
|
+
controller.error(error);
|
|
44546
|
+
}
|
|
44547
|
+
this.streams.clear();
|
|
44548
|
+
this.streamStopping.clear();
|
|
44549
|
+
}
|
|
44550
|
+
handleClose(code, reason) {
|
|
44551
|
+
this._closed = true;
|
|
44552
|
+
this.rejectAll(new ConnectionClosed(code, reason));
|
|
44553
|
+
for (const listener of this.closeListeners) {
|
|
44554
|
+
listener.resolve();
|
|
44555
|
+
}
|
|
44556
|
+
this.closeListeners = [];
|
|
44557
|
+
}
|
|
44558
|
+
handleError(err) {
|
|
44559
|
+
this.rejectAll(err);
|
|
44560
|
+
this.socket.close(3002);
|
|
44561
|
+
}
|
|
44562
|
+
};
|
|
44563
|
+
function deserializeSerializedInstruction(ix) {
|
|
44564
|
+
return new TransactionInstruction({
|
|
44565
|
+
programId: new PublicKey(Buffer.from(ix.p, "base64")),
|
|
44566
|
+
keys: ix.a.map((account) => ({
|
|
44567
|
+
pubkey: new PublicKey(Buffer.from(account.p, "base64")),
|
|
44568
|
+
isSigner: account.s,
|
|
44569
|
+
isWritable: account.w
|
|
44570
|
+
})),
|
|
44571
|
+
data: Buffer.from(ix.d, "base64")
|
|
44572
|
+
});
|
|
44573
|
+
}
|
|
44574
|
+
function selectBestRoute(quotes, swapMode) {
|
|
44575
|
+
const routes = Object.values(quotes);
|
|
44576
|
+
if (routes.length === 0) return null;
|
|
44577
|
+
return routes.reduce((best, route) => {
|
|
44578
|
+
if (swapMode === "ExactIn") {
|
|
44579
|
+
return route.outAmount > best.outAmount ? route : best;
|
|
44580
|
+
} else {
|
|
44581
|
+
return route.inAmount < best.inAmount ? route : best;
|
|
44582
|
+
}
|
|
44583
|
+
});
|
|
44584
|
+
}
|
|
44585
|
+
function buildSwapQuoteResult(route, swapMode) {
|
|
44586
|
+
const slippageBps = route.slippageBps;
|
|
44587
|
+
let otherAmountThreshold;
|
|
44588
|
+
if (swapMode === "ExactIn") {
|
|
44589
|
+
otherAmountThreshold = String(Math.floor(route.outAmount * (1 - slippageBps / 1e4)));
|
|
44590
|
+
} else {
|
|
44591
|
+
otherAmountThreshold = String(Math.ceil(route.inAmount * (1 + slippageBps / 1e4)));
|
|
44592
|
+
}
|
|
44593
|
+
return {
|
|
44594
|
+
inAmount: String(route.inAmount),
|
|
44595
|
+
outAmount: String(route.outAmount),
|
|
44596
|
+
otherAmountThreshold,
|
|
44597
|
+
slippageBps,
|
|
44598
|
+
platformFee: route.platformFee ? {
|
|
44599
|
+
amount: String(route.platformFee.amount),
|
|
44600
|
+
feeBps: route.platformFee.fee_bps
|
|
44601
|
+
} : void 0,
|
|
44602
|
+
contextSlot: route.contextSlot,
|
|
44603
|
+
timeTaken: route.timeTaken
|
|
44604
|
+
};
|
|
44605
|
+
}
|
|
44606
|
+
async function resolveLookupTables(connection, lutPubkeys) {
|
|
44607
|
+
if (lutPubkeys.length === 0) return [];
|
|
44608
|
+
const lutAccountsRaw = await connection.getMultipleAccountsInfo(lutPubkeys);
|
|
44609
|
+
return lutAccountsRaw.map((accountInfo, index) => {
|
|
44610
|
+
if (!accountInfo) return null;
|
|
44611
|
+
return new AddressLookupTableAccount({
|
|
44612
|
+
key: lutPubkeys[index],
|
|
44613
|
+
state: AddressLookupTableAccount.deserialize(accountInfo.data)
|
|
44614
|
+
});
|
|
44615
|
+
}).filter((account) => account !== null);
|
|
44616
|
+
}
|
|
44171
44617
|
|
|
44172
44618
|
// src/vendor/klend/utils/klend/interest-rate.utils.ts
|
|
44173
44619
|
function getKaminoTotalSupply(reserve) {
|
|
@@ -46457,116 +46903,81 @@ async function makeJuplendDepositTx(params) {
|
|
|
46457
46903
|
});
|
|
46458
46904
|
return solanaTx;
|
|
46459
46905
|
}
|
|
46460
|
-
async function
|
|
46461
|
-
|
|
46462
|
-
|
|
46463
|
-
|
|
46464
|
-
|
|
46465
|
-
|
|
46466
|
-
|
|
46467
|
-
|
|
46468
|
-
|
|
46906
|
+
async function makeRepayIx3({
|
|
46907
|
+
program,
|
|
46908
|
+
bank,
|
|
46909
|
+
tokenProgram,
|
|
46910
|
+
amount,
|
|
46911
|
+
authority,
|
|
46912
|
+
accountAddress,
|
|
46913
|
+
repayAll = false,
|
|
46914
|
+
isSync = false,
|
|
46915
|
+
opts = {}
|
|
46916
|
+
}) {
|
|
46917
|
+
const wrapAndUnwrapSol = opts.wrapAndUnwrapSol ?? true;
|
|
46918
|
+
const wSolBalanceUi = opts.wSolBalanceUi ?? 0;
|
|
46919
|
+
const repayIxs = [];
|
|
46920
|
+
const userAta = getAssociatedTokenAddressSync(bank.mint, authority, true, tokenProgram);
|
|
46921
|
+
const remainingAccounts = tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? [{ pubkey: bank.mint, isSigner: false, isWritable: false }] : [];
|
|
46922
|
+
if (bank.mint.equals(NATIVE_MINT) && wrapAndUnwrapSol) {
|
|
46923
|
+
repayIxs.push(...makeWrapSolIxs(authority, new BigNumber(amount).minus(wSolBalanceUi)));
|
|
46924
|
+
}
|
|
46925
|
+
const repayIx = !isSync || !opts.overrideInferAccounts?.group ? await instructions_default.makeRepayIx(
|
|
46469
46926
|
program,
|
|
46470
46927
|
{
|
|
46471
|
-
marginfiAccount:
|
|
46472
|
-
|
|
46928
|
+
marginfiAccount: accountAddress,
|
|
46929
|
+
signerTokenAccount: userAta,
|
|
46930
|
+
bank: bank.address,
|
|
46931
|
+
tokenProgram,
|
|
46932
|
+
authority: opts.overrideInferAccounts?.authority ?? authority,
|
|
46933
|
+
group: opts.overrideInferAccounts?.group,
|
|
46934
|
+
liquidityVault: opts.overrideInferAccounts?.liquidityVault
|
|
46473
46935
|
},
|
|
46474
|
-
{
|
|
46475
|
-
|
|
46476
|
-
|
|
46477
|
-
}
|
|
46478
|
-
async function makeEndFlashLoanIx3(program, marginfiAccountPk, projectedActiveBanks, authority, isSync) {
|
|
46479
|
-
const remainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
46480
|
-
const ix = isSync && authority ? sync_instructions_default.makeEndFlashLoanIx(
|
|
46936
|
+
{ amount: uiToNative(amount, bank.mintDecimals), repayAll },
|
|
46937
|
+
remainingAccounts
|
|
46938
|
+
) : sync_instructions_default.makeRepayIx(
|
|
46481
46939
|
program.programId,
|
|
46482
46940
|
{
|
|
46483
|
-
marginfiAccount:
|
|
46484
|
-
|
|
46485
|
-
|
|
46486
|
-
|
|
46487
|
-
|
|
46488
|
-
|
|
46489
|
-
isWritable: false
|
|
46490
|
-
}))
|
|
46491
|
-
) : await instructions_default.makeEndFlashLoanIx(
|
|
46492
|
-
program,
|
|
46493
|
-
{
|
|
46494
|
-
marginfiAccount: marginfiAccountPk,
|
|
46495
|
-
authority
|
|
46941
|
+
marginfiAccount: accountAddress,
|
|
46942
|
+
signerTokenAccount: userAta,
|
|
46943
|
+
bank: bank.address,
|
|
46944
|
+
tokenProgram,
|
|
46945
|
+
authority: opts.overrideInferAccounts?.authority ?? authority,
|
|
46946
|
+
group: opts.overrideInferAccounts?.group
|
|
46496
46947
|
},
|
|
46497
|
-
|
|
46498
|
-
|
|
46499
|
-
isSigner: false,
|
|
46500
|
-
isWritable: false
|
|
46501
|
-
}))
|
|
46948
|
+
{ amount: uiToNative(amount, bank.mintDecimals), repayAll },
|
|
46949
|
+
remainingAccounts
|
|
46502
46950
|
);
|
|
46503
|
-
|
|
46951
|
+
repayIxs.push(repayIx);
|
|
46952
|
+
return {
|
|
46953
|
+
instructions: repayIxs,
|
|
46954
|
+
keys: []
|
|
46955
|
+
};
|
|
46504
46956
|
}
|
|
46505
|
-
async function
|
|
46506
|
-
|
|
46507
|
-
|
|
46508
|
-
ixs
|
|
46509
|
-
|
|
46510
|
-
|
|
46511
|
-
|
|
46512
|
-
|
|
46513
|
-
|
|
46514
|
-
}) {
|
|
46515
|
-
const endIndex = ixs.length + 1;
|
|
46516
|
-
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
46517
|
-
marginfiAccount.balances,
|
|
46518
|
-
ixs,
|
|
46519
|
-
program
|
|
46520
|
-
);
|
|
46521
|
-
const projectedActiveBanks = projectedActiveBanksKeys.map((account) => {
|
|
46522
|
-
const b = bankMap.get(account.toBase58());
|
|
46523
|
-
if (!b) throw Error(`Bank ${account.toBase58()} not found, in makeFlashLoanTx function`);
|
|
46524
|
-
return b;
|
|
46525
|
-
});
|
|
46526
|
-
const beginFlashLoanIx = await makeBeginFlashLoanIx3(
|
|
46527
|
-
program,
|
|
46528
|
-
marginfiAccount.address,
|
|
46529
|
-
endIndex,
|
|
46530
|
-
marginfiAccount.authority,
|
|
46531
|
-
isSync
|
|
46532
|
-
);
|
|
46533
|
-
const endFlashLoanIx = await makeEndFlashLoanIx3(
|
|
46534
|
-
program,
|
|
46535
|
-
marginfiAccount.address,
|
|
46536
|
-
projectedActiveBanks,
|
|
46537
|
-
marginfiAccount.authority,
|
|
46538
|
-
isSync
|
|
46539
|
-
);
|
|
46540
|
-
const message = new TransactionMessage({
|
|
46541
|
-
payerKey: marginfiAccount.authority,
|
|
46542
|
-
recentBlockhash: blockhash,
|
|
46543
|
-
instructions: [...beginFlashLoanIx.instructions, ...ixs, ...endFlashLoanIx.instructions]
|
|
46544
|
-
}).compileToV0Message(addressLookupTableAccounts);
|
|
46545
|
-
const tx = addTransactionMetadata(new VersionedTransaction(message), {
|
|
46546
|
-
addressLookupTables: addressLookupTableAccounts,
|
|
46547
|
-
type: "FLASHLOAN" /* FLASHLOAN */,
|
|
46548
|
-
signers
|
|
46957
|
+
async function makeRepayTx(params) {
|
|
46958
|
+
const { luts, ...depositIxParams } = params;
|
|
46959
|
+
const ixs = await makeRepayIx3(depositIxParams);
|
|
46960
|
+
const tx = new Transaction().add(...ixs.instructions);
|
|
46961
|
+
tx.feePayer = params.authority;
|
|
46962
|
+
const solanaTx = addTransactionMetadata(tx, {
|
|
46963
|
+
type: "REPAY" /* REPAY */,
|
|
46964
|
+
signers: ixs.keys,
|
|
46965
|
+
addressLookupTables: luts
|
|
46549
46966
|
});
|
|
46550
|
-
|
|
46551
|
-
tx.sign(signers);
|
|
46552
|
-
}
|
|
46553
|
-
return tx;
|
|
46967
|
+
return solanaTx;
|
|
46554
46968
|
}
|
|
46555
|
-
|
|
46556
|
-
// src/services/account/actions/loop.ts
|
|
46557
|
-
async function makeLoopTx(params) {
|
|
46969
|
+
async function makeRepayWithCollatTx(params) {
|
|
46558
46970
|
const {
|
|
46559
46971
|
program,
|
|
46560
46972
|
marginfiAccount,
|
|
46561
46973
|
bankMap,
|
|
46562
|
-
|
|
46563
|
-
|
|
46974
|
+
withdrawOpts,
|
|
46975
|
+
repayOpts,
|
|
46564
46976
|
bankMetadataMap,
|
|
46565
46977
|
addressLookupTableAccounts,
|
|
46566
46978
|
connection,
|
|
46567
46979
|
oraclePrices,
|
|
46568
|
-
crossbarUrl
|
|
46569
|
-
additionalIxs = []
|
|
46980
|
+
crossbarUrl
|
|
46570
46981
|
} = params;
|
|
46571
46982
|
const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
46572
46983
|
const setupIxs = await makeSetupIx({
|
|
@@ -46574,34 +46985,34 @@ async function makeLoopTx(params) {
|
|
|
46574
46985
|
authority: marginfiAccount.authority,
|
|
46575
46986
|
tokens: [
|
|
46576
46987
|
{
|
|
46577
|
-
mint:
|
|
46578
|
-
tokenProgram:
|
|
46988
|
+
mint: repayOpts.repayBank.mint,
|
|
46989
|
+
tokenProgram: repayOpts.tokenProgram
|
|
46579
46990
|
},
|
|
46580
46991
|
{
|
|
46581
|
-
mint:
|
|
46582
|
-
tokenProgram:
|
|
46992
|
+
mint: withdrawOpts.withdrawBank.mint,
|
|
46993
|
+
tokenProgram: withdrawOpts.tokenProgram
|
|
46583
46994
|
}
|
|
46584
46995
|
]
|
|
46585
46996
|
});
|
|
46586
|
-
const
|
|
46587
|
-
|
|
46588
|
-
|
|
46589
|
-
[
|
|
46590
|
-
|
|
46997
|
+
const updateJuplendMarketIxs = makeUpdateJupLendRateIxs(
|
|
46998
|
+
marginfiAccount,
|
|
46999
|
+
bankMap,
|
|
47000
|
+
[withdrawOpts.withdrawBank.address],
|
|
47001
|
+
bankMetadataMap
|
|
46591
47002
|
);
|
|
46592
47003
|
const updateDriftMarketIxs = makeUpdateDriftMarketIxs(
|
|
46593
|
-
|
|
46594
|
-
|
|
46595
|
-
[
|
|
46596
|
-
|
|
47004
|
+
marginfiAccount,
|
|
47005
|
+
bankMap,
|
|
47006
|
+
[withdrawOpts.withdrawBank.address],
|
|
47007
|
+
bankMetadataMap
|
|
46597
47008
|
);
|
|
46598
47009
|
const kaminoRefreshIxs = makeRefreshKaminoBanksIxs(
|
|
46599
47010
|
marginfiAccount,
|
|
46600
47011
|
bankMap,
|
|
46601
|
-
[
|
|
47012
|
+
[withdrawOpts.withdrawBank.address, repayOpts.repayBank.address],
|
|
46602
47013
|
bankMetadataMap
|
|
46603
47014
|
);
|
|
46604
|
-
const { flashloanTx, setupInstructions, swapQuote,
|
|
47015
|
+
const { flashloanTx, setupInstructions, swapQuote, amountToRepay, withdrawIxs, repayIxs } = await buildRepayWithCollatFlashloanTx({
|
|
46605
47016
|
...params,
|
|
46606
47017
|
blockhash
|
|
46607
47018
|
});
|
|
@@ -46611,7 +47022,7 @@ async function makeLoopTx(params) {
|
|
|
46611
47022
|
}
|
|
46612
47023
|
if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
|
|
46613
47024
|
const mintKey = ix.keys[3]?.pubkey;
|
|
46614
|
-
if (mintKey?.equals(
|
|
47025
|
+
if (mintKey?.equals(withdrawOpts.withdrawBank.mint) || mintKey?.equals(repayOpts.repayBank.mint)) {
|
|
46615
47026
|
return false;
|
|
46616
47027
|
}
|
|
46617
47028
|
}
|
|
@@ -46623,24 +47034,18 @@ async function makeLoopTx(params) {
|
|
|
46623
47034
|
bankMap,
|
|
46624
47035
|
oraclePrices,
|
|
46625
47036
|
assetShareValueMultiplierByBank: params.assetShareValueMultiplierByBank,
|
|
46626
|
-
instructions: [...
|
|
47037
|
+
instructions: [...withdrawIxs.instructions, ...repayIxs.instructions],
|
|
46627
47038
|
program,
|
|
46628
47039
|
connection,
|
|
46629
47040
|
crossbarUrl
|
|
46630
47041
|
});
|
|
46631
47042
|
let additionalTxs = [];
|
|
46632
|
-
if (
|
|
46633
|
-
setupIxs.push(
|
|
46634
|
-
...makeWrapSolIxs(marginfiAccount.authority, new BigNumber(depositOpts.inputDepositAmount))
|
|
46635
|
-
);
|
|
46636
|
-
}
|
|
46637
|
-
if (setupIxs.length > 0 || additionalIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJupLendRateIxs.instructions.length > 0) {
|
|
47043
|
+
if (setupIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJuplendMarketIxs.instructions.length > 0) {
|
|
46638
47044
|
const ixs = [
|
|
46639
|
-
...additionalIxs,
|
|
46640
47045
|
...setupIxs,
|
|
46641
47046
|
...kaminoRefreshIxs.instructions,
|
|
46642
47047
|
...updateDriftMarketIxs.instructions,
|
|
46643
|
-
...
|
|
47048
|
+
...updateJuplendMarketIxs.instructions
|
|
46644
47049
|
];
|
|
46645
47050
|
const txs = splitInstructionsToFitTransactions([], ixs, {
|
|
46646
47051
|
blockhash,
|
|
@@ -46670,300 +47075,835 @@ async function makeLoopTx(params) {
|
|
|
46670
47075
|
);
|
|
46671
47076
|
}
|
|
46672
47077
|
const transactions = [...additionalTxs, flashloanTx];
|
|
46673
|
-
return {
|
|
46674
|
-
transactions,
|
|
46675
|
-
actionTxIndex: transactions.length - 1,
|
|
46676
|
-
quoteResponse: swapQuote
|
|
46677
|
-
};
|
|
47078
|
+
return { transactions, swapQuote, amountToRepay };
|
|
46678
47079
|
}
|
|
46679
|
-
async function
|
|
47080
|
+
async function buildRepayWithCollatFlashloanTx({
|
|
46680
47081
|
program,
|
|
46681
47082
|
marginfiAccount,
|
|
46682
47083
|
bankMap,
|
|
46683
|
-
|
|
46684
|
-
|
|
47084
|
+
withdrawOpts,
|
|
47085
|
+
repayOpts,
|
|
46685
47086
|
bankMetadataMap,
|
|
47087
|
+
assetShareValueMultiplierByBank,
|
|
46686
47088
|
addressLookupTableAccounts,
|
|
46687
47089
|
connection,
|
|
46688
47090
|
swapOpts,
|
|
46689
47091
|
overrideInferAccounts,
|
|
46690
47092
|
blockhash
|
|
46691
47093
|
}) {
|
|
46692
|
-
const swapResult = [];
|
|
46693
47094
|
const cuRequestIxs = [
|
|
46694
47095
|
ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
46695
47096
|
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
46696
47097
|
];
|
|
46697
|
-
|
|
46698
|
-
|
|
46699
|
-
|
|
46700
|
-
|
|
46701
|
-
|
|
46702
|
-
|
|
46703
|
-
|
|
47098
|
+
let amountToRepay;
|
|
47099
|
+
let swapInstructions = [];
|
|
47100
|
+
let setupInstructions = [];
|
|
47101
|
+
let swapLookupTables = [];
|
|
47102
|
+
let swapQuote;
|
|
47103
|
+
let sizeConstraintUsed = 0;
|
|
47104
|
+
if (repayOpts.repayBank.mint.equals(withdrawOpts.withdrawBank.mint)) {
|
|
47105
|
+
amountToRepay = withdrawOpts.withdrawAmount;
|
|
46704
47106
|
} else {
|
|
46705
47107
|
const destinationTokenAccount = getAssociatedTokenAddressSync(
|
|
46706
|
-
new PublicKey(
|
|
47108
|
+
new PublicKey(repayOpts.repayBank.mint),
|
|
46707
47109
|
marginfiAccount.authority,
|
|
46708
47110
|
true,
|
|
46709
|
-
|
|
47111
|
+
repayOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
|
|
46710
47112
|
);
|
|
46711
|
-
const
|
|
46712
|
-
|
|
46713
|
-
|
|
46714
|
-
|
|
46715
|
-
|
|
46716
|
-
|
|
46717
|
-
|
|
46718
|
-
|
|
46719
|
-
|
|
46720
|
-
|
|
47113
|
+
const swapConstraints = await computeFlashloanSwapConstraints({
|
|
47114
|
+
program,
|
|
47115
|
+
marginfiAccount,
|
|
47116
|
+
bankMap,
|
|
47117
|
+
bankMetadataMap,
|
|
47118
|
+
addressLookupTableAccounts: addressLookupTableAccounts ?? [],
|
|
47119
|
+
primaryIx: {
|
|
47120
|
+
type: "withdraw",
|
|
47121
|
+
bank: withdrawOpts.withdrawBank,
|
|
47122
|
+
tokenProgram: withdrawOpts.tokenProgram
|
|
47123
|
+
},
|
|
47124
|
+
secondaryIx: {
|
|
47125
|
+
type: "repay",
|
|
47126
|
+
bank: repayOpts.repayBank,
|
|
47127
|
+
tokenProgram: repayOpts.tokenProgram
|
|
46721
47128
|
},
|
|
47129
|
+
overrideInferAccounts
|
|
47130
|
+
});
|
|
47131
|
+
const swapResponse = await getSwapIxsForFlashloan({
|
|
47132
|
+
inputMint: withdrawOpts.withdrawBank.mint.toBase58(),
|
|
47133
|
+
outputMint: repayOpts.repayBank.mint.toBase58(),
|
|
47134
|
+
amount: uiToNative(
|
|
47135
|
+
withdrawOpts.withdrawAmount,
|
|
47136
|
+
withdrawOpts.withdrawBank.mintDecimals
|
|
47137
|
+
).toNumber(),
|
|
47138
|
+
swapMode: "ExactIn",
|
|
46722
47139
|
authority: marginfiAccount.authority,
|
|
46723
47140
|
connection,
|
|
46724
47141
|
destinationTokenAccount,
|
|
46725
|
-
|
|
47142
|
+
swapOpts,
|
|
47143
|
+
sizeConstraint: swapConstraints.sizeConstraint,
|
|
47144
|
+
maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
|
|
46726
47145
|
});
|
|
46727
|
-
|
|
46728
|
-
|
|
46729
|
-
|
|
46730
|
-
|
|
46731
|
-
|
|
46732
|
-
|
|
46733
|
-
|
|
46734
|
-
|
|
46735
|
-
|
|
46736
|
-
|
|
46737
|
-
|
|
46738
|
-
|
|
47146
|
+
sizeConstraintUsed = swapConstraints.sizeConstraint;
|
|
47147
|
+
const { quoteResponse } = swapResponse;
|
|
47148
|
+
const outAmount = nativeToUi(quoteResponse.outAmount, repayOpts.repayBank.mintDecimals);
|
|
47149
|
+
const outAmountThreshold = nativeToUi(
|
|
47150
|
+
quoteResponse.otherAmountThreshold,
|
|
47151
|
+
repayOpts.repayBank.mintDecimals
|
|
47152
|
+
);
|
|
47153
|
+
amountToRepay = outAmount > repayOpts.totalPositionAmount ? repayOpts.totalPositionAmount : outAmountThreshold;
|
|
47154
|
+
swapInstructions = swapResponse.swapInstructions;
|
|
47155
|
+
swapLookupTables = swapResponse.addressLookupTableAddresses;
|
|
47156
|
+
swapQuote = quoteResponse;
|
|
47157
|
+
}
|
|
47158
|
+
let withdrawIxs;
|
|
47159
|
+
switch (withdrawOpts.withdrawBank.config.assetTag) {
|
|
47160
|
+
case 3 /* KAMINO */: {
|
|
47161
|
+
const reserve = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47162
|
+
if (!reserve) {
|
|
47163
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47164
|
+
withdrawOpts.withdrawBank.address.toBase58(),
|
|
47165
|
+
withdrawOpts.withdrawBank.mint.toBase58(),
|
|
47166
|
+
withdrawOpts.withdrawBank.tokenSymbol
|
|
47167
|
+
);
|
|
47168
|
+
}
|
|
47169
|
+
const multiplier = assetShareValueMultiplierByBank.get(withdrawOpts.withdrawBank.address.toBase58()) ?? new BigNumber(1);
|
|
47170
|
+
const adjustedAmount = new BigNumber(withdrawOpts.withdrawAmount).div(multiplier).times(1.0001).toNumber();
|
|
47171
|
+
withdrawIxs = await makeKaminoWithdrawIx3({
|
|
47172
|
+
program,
|
|
47173
|
+
bank: withdrawOpts.withdrawBank,
|
|
47174
|
+
bankMap,
|
|
47175
|
+
tokenProgram: withdrawOpts.tokenProgram,
|
|
47176
|
+
cTokenAmount: adjustedAmount,
|
|
47177
|
+
marginfiAccount,
|
|
47178
|
+
authority: marginfiAccount.authority,
|
|
47179
|
+
reserve,
|
|
47180
|
+
withdrawAll: isWholePosition(
|
|
47181
|
+
{
|
|
47182
|
+
amount: withdrawOpts.totalPositionAmount,
|
|
47183
|
+
isLending: true
|
|
47184
|
+
},
|
|
47185
|
+
withdrawOpts.withdrawAmount,
|
|
47186
|
+
withdrawOpts.withdrawBank.mintDecimals
|
|
47187
|
+
),
|
|
47188
|
+
isSync: false,
|
|
47189
|
+
opts: {
|
|
47190
|
+
createAtas: false,
|
|
47191
|
+
wrapAndUnwrapSol: false,
|
|
47192
|
+
overrideInferAccounts
|
|
47193
|
+
}
|
|
46739
47194
|
});
|
|
46740
|
-
|
|
47195
|
+
break;
|
|
47196
|
+
}
|
|
47197
|
+
case 4 /* DRIFT */: {
|
|
47198
|
+
const driftState = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.driftStates;
|
|
47199
|
+
if (!driftState) {
|
|
47200
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
47201
|
+
withdrawOpts.withdrawBank.address.toBase58(),
|
|
47202
|
+
withdrawOpts.withdrawBank.mint.toBase58(),
|
|
47203
|
+
withdrawOpts.withdrawBank.tokenSymbol
|
|
47204
|
+
);
|
|
47205
|
+
}
|
|
47206
|
+
withdrawIxs = await makeDriftWithdrawIx3({
|
|
47207
|
+
program,
|
|
47208
|
+
bank: withdrawOpts.withdrawBank,
|
|
47209
|
+
bankMap,
|
|
47210
|
+
tokenProgram: withdrawOpts.tokenProgram,
|
|
47211
|
+
amount: withdrawOpts.withdrawAmount,
|
|
47212
|
+
marginfiAccount,
|
|
47213
|
+
authority: marginfiAccount.authority,
|
|
47214
|
+
driftSpotMarket: driftState.spotMarketState,
|
|
47215
|
+
userRewards: driftState.userRewards,
|
|
47216
|
+
withdrawAll: isWholePosition(
|
|
47217
|
+
{
|
|
47218
|
+
amount: withdrawOpts.totalPositionAmount,
|
|
47219
|
+
isLending: true
|
|
47220
|
+
},
|
|
47221
|
+
withdrawOpts.withdrawAmount,
|
|
47222
|
+
withdrawOpts.withdrawBank.mintDecimals
|
|
47223
|
+
),
|
|
47224
|
+
isSync: false,
|
|
47225
|
+
opts: {
|
|
47226
|
+
createAtas: false,
|
|
47227
|
+
wrapAndUnwrapSol: false,
|
|
47228
|
+
overrideInferAccounts
|
|
47229
|
+
}
|
|
47230
|
+
});
|
|
47231
|
+
break;
|
|
47232
|
+
}
|
|
47233
|
+
case 6 /* JUPLEND */: {
|
|
47234
|
+
const jupLendState = bankMetadataMap[withdrawOpts.withdrawBank.address.toBase58()]?.jupLendStates;
|
|
47235
|
+
if (!jupLendState) {
|
|
47236
|
+
throw TransactionBuildingError.jupLendStateNotFound(
|
|
47237
|
+
withdrawOpts.withdrawBank.address.toBase58(),
|
|
47238
|
+
withdrawOpts.withdrawBank.mint.toBase58(),
|
|
47239
|
+
withdrawOpts.withdrawBank.tokenSymbol
|
|
47240
|
+
);
|
|
47241
|
+
}
|
|
47242
|
+
withdrawIxs = await makeJuplendWithdrawIx2({
|
|
47243
|
+
program,
|
|
47244
|
+
bank: withdrawOpts.withdrawBank,
|
|
47245
|
+
bankMap,
|
|
47246
|
+
tokenProgram: withdrawOpts.tokenProgram,
|
|
47247
|
+
amount: withdrawOpts.withdrawAmount,
|
|
47248
|
+
marginfiAccount,
|
|
47249
|
+
authority: marginfiAccount.authority,
|
|
47250
|
+
jupLendingState: jupLendState.jupLendingState,
|
|
47251
|
+
withdrawAll: isWholePosition(
|
|
47252
|
+
{
|
|
47253
|
+
amount: withdrawOpts.totalPositionAmount,
|
|
47254
|
+
isLending: true
|
|
47255
|
+
},
|
|
47256
|
+
withdrawOpts.withdrawAmount,
|
|
47257
|
+
withdrawOpts.withdrawBank.mintDecimals
|
|
47258
|
+
),
|
|
47259
|
+
opts: {
|
|
47260
|
+
createAtas: false,
|
|
47261
|
+
wrapAndUnwrapSol: false,
|
|
47262
|
+
overrideInferAccounts
|
|
47263
|
+
}
|
|
47264
|
+
});
|
|
47265
|
+
break;
|
|
47266
|
+
}
|
|
47267
|
+
default: {
|
|
47268
|
+
withdrawIxs = await makeWithdrawIx3({
|
|
47269
|
+
program,
|
|
47270
|
+
bank: withdrawOpts.withdrawBank,
|
|
47271
|
+
bankMap,
|
|
47272
|
+
tokenProgram: withdrawOpts.tokenProgram,
|
|
47273
|
+
amount: withdrawOpts.withdrawAmount,
|
|
47274
|
+
marginfiAccount,
|
|
47275
|
+
authority: marginfiAccount.authority,
|
|
47276
|
+
withdrawAll: isWholePosition(
|
|
47277
|
+
{
|
|
47278
|
+
amount: withdrawOpts.totalPositionAmount,
|
|
47279
|
+
isLending: true
|
|
47280
|
+
},
|
|
47281
|
+
withdrawOpts.withdrawAmount,
|
|
47282
|
+
withdrawOpts.withdrawBank.mintDecimals
|
|
47283
|
+
),
|
|
47284
|
+
isSync: false,
|
|
47285
|
+
opts: {
|
|
47286
|
+
createAtas: false,
|
|
47287
|
+
wrapAndUnwrapSol: false,
|
|
47288
|
+
overrideInferAccounts
|
|
47289
|
+
}
|
|
47290
|
+
});
|
|
47291
|
+
break;
|
|
47292
|
+
}
|
|
46741
47293
|
}
|
|
46742
|
-
const
|
|
47294
|
+
const repayIxs = await makeRepayIx3({
|
|
46743
47295
|
program,
|
|
46744
|
-
bank:
|
|
46745
|
-
|
|
46746
|
-
|
|
46747
|
-
|
|
46748
|
-
marginfiAccount,
|
|
47296
|
+
bank: repayOpts.repayBank,
|
|
47297
|
+
tokenProgram: repayOpts.tokenProgram,
|
|
47298
|
+
amount: amountToRepay,
|
|
47299
|
+
accountAddress: marginfiAccount.address,
|
|
46749
47300
|
authority: marginfiAccount.authority,
|
|
47301
|
+
repayAll: isWholePosition(
|
|
47302
|
+
{
|
|
47303
|
+
amount: repayOpts.totalPositionAmount,
|
|
47304
|
+
isLending: true
|
|
47305
|
+
},
|
|
47306
|
+
amountToRepay,
|
|
47307
|
+
repayOpts.repayBank.mintDecimals
|
|
47308
|
+
),
|
|
46750
47309
|
isSync: false,
|
|
46751
47310
|
opts: {
|
|
46752
|
-
createAtas: false,
|
|
46753
47311
|
wrapAndUnwrapSol: false,
|
|
46754
47312
|
overrideInferAccounts
|
|
46755
47313
|
}
|
|
46756
47314
|
});
|
|
46757
|
-
|
|
46758
|
-
|
|
46759
|
-
|
|
46760
|
-
|
|
46761
|
-
|
|
46762
|
-
|
|
46763
|
-
|
|
46764
|
-
|
|
46765
|
-
|
|
46766
|
-
|
|
46767
|
-
|
|
46768
|
-
|
|
46769
|
-
|
|
46770
|
-
|
|
46771
|
-
|
|
46772
|
-
|
|
46773
|
-
|
|
46774
|
-
|
|
46775
|
-
|
|
46776
|
-
|
|
46777
|
-
|
|
46778
|
-
|
|
46779
|
-
|
|
46780
|
-
|
|
46781
|
-
|
|
46782
|
-
|
|
46783
|
-
|
|
46784
|
-
|
|
46785
|
-
|
|
46786
|
-
|
|
46787
|
-
|
|
46788
|
-
|
|
46789
|
-
|
|
46790
|
-
|
|
46791
|
-
|
|
46792
|
-
|
|
46793
|
-
|
|
46794
|
-
|
|
46795
|
-
|
|
46796
|
-
|
|
46797
|
-
|
|
46798
|
-
|
|
46799
|
-
|
|
46800
|
-
|
|
46801
|
-
|
|
46802
|
-
|
|
46803
|
-
|
|
46804
|
-
|
|
46805
|
-
|
|
46806
|
-
|
|
46807
|
-
|
|
46808
|
-
|
|
46809
|
-
|
|
46810
|
-
|
|
46811
|
-
|
|
46812
|
-
|
|
46813
|
-
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46817
|
-
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
|
|
46821
|
-
|
|
46822
|
-
|
|
46823
|
-
|
|
46824
|
-
|
|
46825
|
-
|
|
46826
|
-
|
|
46827
|
-
authority: marginfiAccount.authority,
|
|
46828
|
-
group: marginfiAccount.group,
|
|
46829
|
-
opts: {
|
|
46830
|
-
wrapAndUnwrapSol: false,
|
|
46831
|
-
overrideInferAccounts
|
|
46832
|
-
}
|
|
46833
|
-
});
|
|
46834
|
-
break;
|
|
47315
|
+
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
47316
|
+
const allNonFlIxs = [
|
|
47317
|
+
...cuRequestIxs,
|
|
47318
|
+
...withdrawIxs.instructions,
|
|
47319
|
+
...swapInstructions,
|
|
47320
|
+
...repayIxs.instructions
|
|
47321
|
+
];
|
|
47322
|
+
if (swapInstructions.length > 0) {
|
|
47323
|
+
compileFlashloanPrecheck({
|
|
47324
|
+
allIxs: allNonFlIxs,
|
|
47325
|
+
payer: marginfiAccount.authority,
|
|
47326
|
+
luts,
|
|
47327
|
+
sizeConstraint: sizeConstraintUsed,
|
|
47328
|
+
swapIxCount: swapInstructions.length,
|
|
47329
|
+
swapLutCount: swapLookupTables.length
|
|
47330
|
+
});
|
|
47331
|
+
}
|
|
47332
|
+
const flashloanTx = await makeFlashLoanTx({
|
|
47333
|
+
program,
|
|
47334
|
+
marginfiAccount,
|
|
47335
|
+
bankMap,
|
|
47336
|
+
addressLookupTableAccounts: luts,
|
|
47337
|
+
blockhash,
|
|
47338
|
+
ixs: allNonFlIxs,
|
|
47339
|
+
isSync: true
|
|
47340
|
+
});
|
|
47341
|
+
const txSize = getTxSize(flashloanTx);
|
|
47342
|
+
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
47343
|
+
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
47344
|
+
throw TransactionBuildingError.swapSizeExceededRepay(
|
|
47345
|
+
txSize,
|
|
47346
|
+
totalKeys,
|
|
47347
|
+
swapOpts.swapConfig?.provider
|
|
47348
|
+
);
|
|
47349
|
+
}
|
|
47350
|
+
return {
|
|
47351
|
+
flashloanTx,
|
|
47352
|
+
setupInstructions,
|
|
47353
|
+
swapQuote,
|
|
47354
|
+
withdrawIxs,
|
|
47355
|
+
repayIxs,
|
|
47356
|
+
amountToRepay
|
|
47357
|
+
};
|
|
47358
|
+
}
|
|
47359
|
+
|
|
47360
|
+
// src/services/account/utils/flashloan-size.utils.ts
|
|
47361
|
+
var SWAP_MERGE_OVERHEAD = 150;
|
|
47362
|
+
var FL_IX_OVERHEAD = 52;
|
|
47363
|
+
function compactU16Size(n) {
|
|
47364
|
+
return n < 128 ? 1 : n < 16384 ? 2 : 3;
|
|
47365
|
+
}
|
|
47366
|
+
function computeV0TxSize(ixs, payerKey, luts) {
|
|
47367
|
+
const keyMap = /* @__PURE__ */ new Map();
|
|
47368
|
+
const payerStr = payerKey.toBase58();
|
|
47369
|
+
keyMap.set(payerStr, { isSigner: true, isWritable: true });
|
|
47370
|
+
const programIds = /* @__PURE__ */ new Set();
|
|
47371
|
+
for (const ix of ixs) {
|
|
47372
|
+
const progStr = ix.programId.toBase58();
|
|
47373
|
+
programIds.add(progStr);
|
|
47374
|
+
if (!keyMap.has(progStr)) {
|
|
47375
|
+
keyMap.set(progStr, { isSigner: false, isWritable: false });
|
|
47376
|
+
}
|
|
47377
|
+
for (const meta of ix.keys) {
|
|
47378
|
+
const keyStr = meta.pubkey.toBase58();
|
|
47379
|
+
const existing = keyMap.get(keyStr);
|
|
47380
|
+
if (existing) {
|
|
47381
|
+
existing.isSigner = existing.isSigner || meta.isSigner;
|
|
47382
|
+
existing.isWritable = existing.isWritable || meta.isWritable;
|
|
47383
|
+
} else {
|
|
47384
|
+
keyMap.set(keyStr, { isSigner: meta.isSigner, isWritable: meta.isWritable });
|
|
46835
47385
|
}
|
|
46836
|
-
|
|
46837
|
-
|
|
46838
|
-
|
|
46839
|
-
|
|
46840
|
-
|
|
46841
|
-
|
|
46842
|
-
|
|
46843
|
-
|
|
46844
|
-
|
|
46845
|
-
opts: {
|
|
46846
|
-
wrapAndUnwrapSol: false,
|
|
46847
|
-
overrideInferAccounts
|
|
46848
|
-
}
|
|
46849
|
-
});
|
|
46850
|
-
break;
|
|
47386
|
+
}
|
|
47387
|
+
}
|
|
47388
|
+
const lutLookup = /* @__PURE__ */ new Map();
|
|
47389
|
+
for (let li = 0; li < luts.length; li++) {
|
|
47390
|
+
const addresses = luts[li].state.addresses;
|
|
47391
|
+
for (let ai = 0; ai < addresses.length; ai++) {
|
|
47392
|
+
const addrStr = addresses[ai].toBase58();
|
|
47393
|
+
if (!lutLookup.has(addrStr)) {
|
|
47394
|
+
lutLookup.set(addrStr, { lutIdx: li, addrIdx: ai });
|
|
46851
47395
|
}
|
|
46852
47396
|
}
|
|
46853
|
-
|
|
46854
|
-
|
|
46855
|
-
|
|
46856
|
-
|
|
46857
|
-
|
|
46858
|
-
|
|
46859
|
-
|
|
46860
|
-
|
|
46861
|
-
|
|
46862
|
-
|
|
46863
|
-
|
|
46864
|
-
|
|
46865
|
-
|
|
46866
|
-
|
|
46867
|
-
|
|
46868
|
-
]
|
|
46869
|
-
});
|
|
46870
|
-
const txSize = getTxSize(flashloanTx);
|
|
46871
|
-
const keySize = getAccountKeys(flashloanTx, luts);
|
|
46872
|
-
const isLast = index === swapResult.length - 1;
|
|
46873
|
-
if (txSize > MAX_TX_SIZE || keySize > 64) {
|
|
46874
|
-
if (isLast) {
|
|
46875
|
-
throw TransactionBuildingError.jupiterSwapSizeExceededLoop(txSize, keySize);
|
|
47397
|
+
}
|
|
47398
|
+
let numStaticKeys = 0;
|
|
47399
|
+
let numWritableStaticKeys = 0;
|
|
47400
|
+
const lutWritableIdxs = luts.map(() => /* @__PURE__ */ new Set());
|
|
47401
|
+
const lutReadonlyIdxs = luts.map(() => /* @__PURE__ */ new Set());
|
|
47402
|
+
for (const [keyStr, props] of keyMap) {
|
|
47403
|
+
if (props.isSigner || programIds.has(keyStr)) {
|
|
47404
|
+
numStaticKeys++;
|
|
47405
|
+
if (props.isWritable) numWritableStaticKeys++;
|
|
47406
|
+
continue;
|
|
47407
|
+
}
|
|
47408
|
+
const lutEntry = lutLookup.get(keyStr);
|
|
47409
|
+
if (lutEntry) {
|
|
47410
|
+
if (props.isWritable) {
|
|
47411
|
+
lutWritableIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
|
|
46876
47412
|
} else {
|
|
46877
|
-
|
|
47413
|
+
lutReadonlyIdxs[lutEntry.lutIdx].add(lutEntry.addrIdx);
|
|
46878
47414
|
}
|
|
46879
47415
|
} else {
|
|
46880
|
-
|
|
46881
|
-
|
|
46882
|
-
setupInstructions,
|
|
46883
|
-
swapQuote: quoteResponse,
|
|
46884
|
-
borrowIxs,
|
|
46885
|
-
depositIxs,
|
|
46886
|
-
amountToDeposit
|
|
46887
|
-
};
|
|
47416
|
+
numStaticKeys++;
|
|
47417
|
+
if (props.isWritable) numWritableStaticKeys++;
|
|
46888
47418
|
}
|
|
46889
47419
|
}
|
|
46890
|
-
|
|
46891
|
-
|
|
46892
|
-
|
|
47420
|
+
const fixedOverhead = 101;
|
|
47421
|
+
const staticKeysSection = compactU16Size(numStaticKeys) + numStaticKeys * 32;
|
|
47422
|
+
let ixSection = compactU16Size(ixs.length);
|
|
47423
|
+
for (const ix of ixs) {
|
|
47424
|
+
const numAccounts = ix.keys.length;
|
|
47425
|
+
ixSection += 1 + // programId index
|
|
47426
|
+
compactU16Size(numAccounts) + numAccounts + // account key indexes
|
|
47427
|
+
compactU16Size(ix.data.length) + ix.data.length;
|
|
47428
|
+
}
|
|
47429
|
+
let numUsedLuts = 0;
|
|
47430
|
+
let lutSection = 0;
|
|
47431
|
+
for (let li = 0; li < luts.length; li++) {
|
|
47432
|
+
const wCount = lutWritableIdxs[li].size;
|
|
47433
|
+
const rCount = lutReadonlyIdxs[li].size;
|
|
47434
|
+
if (wCount === 0 && rCount === 0) continue;
|
|
47435
|
+
numUsedLuts++;
|
|
47436
|
+
lutSection += 32 + // LUT address
|
|
47437
|
+
compactU16Size(wCount) + wCount + // writable indexes
|
|
47438
|
+
compactU16Size(rCount) + rCount;
|
|
47439
|
+
}
|
|
47440
|
+
lutSection += compactU16Size(numUsedLuts);
|
|
47441
|
+
let totalLutKeys = 0;
|
|
47442
|
+
for (let li = 0; li < luts.length; li++) {
|
|
47443
|
+
totalLutKeys += lutWritableIdxs[li].size + lutReadonlyIdxs[li].size;
|
|
47444
|
+
}
|
|
47445
|
+
const accountCount = numStaticKeys + totalLutKeys;
|
|
47446
|
+
let totalLutWritableKeys = 0;
|
|
47447
|
+
for (let li = 0; li < luts.length; li++) {
|
|
47448
|
+
totalLutWritableKeys += lutWritableIdxs[li].size;
|
|
47449
|
+
}
|
|
47450
|
+
const writableAccountCount = numWritableStaticKeys + totalLutWritableKeys;
|
|
47451
|
+
const size = fixedOverhead + staticKeysSection + ixSection + lutSection + 1;
|
|
47452
|
+
return { size, accountCount, writableAccountCount };
|
|
47453
|
+
}
|
|
47454
|
+
function computeFlashLoanNonSwapBudget({
|
|
46893
47455
|
program,
|
|
46894
|
-
|
|
46895
|
-
|
|
46896
|
-
|
|
46897
|
-
|
|
46898
|
-
accountAddress,
|
|
46899
|
-
repayAll = false,
|
|
46900
|
-
isSync = false,
|
|
46901
|
-
opts = {}
|
|
47456
|
+
marginfiAccount,
|
|
47457
|
+
ixs,
|
|
47458
|
+
bankMap,
|
|
47459
|
+
addressLookupTableAccounts
|
|
46902
47460
|
}) {
|
|
46903
|
-
const
|
|
46904
|
-
|
|
46905
|
-
|
|
46906
|
-
|
|
46907
|
-
|
|
46908
|
-
|
|
46909
|
-
|
|
47461
|
+
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
47462
|
+
marginfiAccount.balances,
|
|
47463
|
+
ixs,
|
|
47464
|
+
program
|
|
47465
|
+
);
|
|
47466
|
+
const projectedActiveBanks = projectedActiveBanksKeys.map((key) => {
|
|
47467
|
+
const b = bankMap.get(key.toBase58());
|
|
47468
|
+
if (!b) throw new Error(`Bank ${key.toBase58()} not found in computeFlashLoanNonSwapBudget`);
|
|
47469
|
+
return b;
|
|
47470
|
+
});
|
|
47471
|
+
const endIndex = ixs.length + 1;
|
|
47472
|
+
const beginFlIx = sync_instructions_default.makeBeginFlashLoanIx(
|
|
47473
|
+
program.programId,
|
|
47474
|
+
{ marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
|
|
47475
|
+
{ endIndex: new BN11(endIndex) }
|
|
47476
|
+
);
|
|
47477
|
+
const endFlRemainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
47478
|
+
const endFlIx = sync_instructions_default.makeEndFlashLoanIx(
|
|
47479
|
+
program.programId,
|
|
47480
|
+
{ marginfiAccount: marginfiAccount.address, authority: marginfiAccount.authority },
|
|
47481
|
+
endFlRemainingAccounts.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false }))
|
|
47482
|
+
);
|
|
47483
|
+
const allNonSwapIxs = [beginFlIx, ...ixs, endFlIx];
|
|
47484
|
+
const nonSwapMsg = new TransactionMessage({
|
|
47485
|
+
payerKey: marginfiAccount.authority,
|
|
47486
|
+
recentBlockhash: PublicKey.default.toBase58(),
|
|
47487
|
+
instructions: allNonSwapIxs
|
|
47488
|
+
}).compileToV0Message(addressLookupTableAccounts);
|
|
47489
|
+
const nonSwapSize = new VersionedTransaction(nonSwapMsg).serialize().length;
|
|
47490
|
+
const { header, staticAccountKeys, addressTableLookups } = nonSwapMsg;
|
|
47491
|
+
const nonSwapTotal = staticAccountKeys.length + addressTableLookups.reduce(
|
|
47492
|
+
(s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
|
|
47493
|
+
0
|
|
47494
|
+
);
|
|
47495
|
+
const sizeConstraint = MAX_TX_SIZE - nonSwapSize - SWAP_MERGE_OVERHEAD;
|
|
47496
|
+
const maxSwapTotalAccounts = MAX_ACCOUNT_LOCKS - nonSwapTotal;
|
|
47497
|
+
console.log("[flashloan-budget]", {
|
|
47498
|
+
method: "compiled",
|
|
47499
|
+
nonSwapSize,
|
|
47500
|
+
nonSwapTotal,
|
|
47501
|
+
sizeConstraint,
|
|
47502
|
+
maxSwapTotalAccounts
|
|
47503
|
+
});
|
|
47504
|
+
return { sizeConstraint, maxSwapTotalAccounts };
|
|
47505
|
+
}
|
|
47506
|
+
function compileFlashloanPrecheck({
|
|
47507
|
+
allIxs,
|
|
47508
|
+
payer,
|
|
47509
|
+
luts,
|
|
47510
|
+
sizeConstraint,
|
|
47511
|
+
swapIxCount,
|
|
47512
|
+
swapLutCount
|
|
47513
|
+
}) {
|
|
47514
|
+
const msg = new TransactionMessage({
|
|
47515
|
+
payerKey: payer,
|
|
47516
|
+
recentBlockhash: PublicKey.default.toBase58(),
|
|
47517
|
+
instructions: allIxs
|
|
47518
|
+
}).compileToV0Message(luts);
|
|
47519
|
+
const rawSize = new VersionedTransaction(msg).serialize().length;
|
|
47520
|
+
const fullTxSize = rawSize + FL_IX_OVERHEAD;
|
|
47521
|
+
const overshoot = fullTxSize - MAX_TX_SIZE;
|
|
47522
|
+
const { header, staticAccountKeys, addressTableLookups } = msg;
|
|
47523
|
+
const writableStatic = staticAccountKeys.length - header.numReadonlySignedAccounts - header.numReadonlyUnsignedAccounts;
|
|
47524
|
+
const writableLut = addressTableLookups.reduce((s, l) => s + l.writableIndexes.length, 0);
|
|
47525
|
+
const writableAccounts = writableStatic + writableLut;
|
|
47526
|
+
const totalAccounts = staticAccountKeys.length + addressTableLookups.reduce(
|
|
47527
|
+
(s, l) => s + l.writableIndexes.length + l.readonlyIndexes.length,
|
|
47528
|
+
0
|
|
47529
|
+
);
|
|
47530
|
+
console.log("[flashloan-precheck]", {
|
|
47531
|
+
fullTxSize,
|
|
47532
|
+
overshoot,
|
|
47533
|
+
sizeConstraint,
|
|
47534
|
+
writableAccounts,
|
|
47535
|
+
totalAccounts,
|
|
47536
|
+
staticKeys: staticAccountKeys.length,
|
|
47537
|
+
numLuts: addressTableLookups.length,
|
|
47538
|
+
swapIxCount,
|
|
47539
|
+
swapLutCount
|
|
47540
|
+
});
|
|
47541
|
+
return { fullTxSize, overshoot, writableAccounts, totalAccounts };
|
|
47542
|
+
}
|
|
47543
|
+
async function buildBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
|
|
47544
|
+
const { bank, tokenProgram } = config;
|
|
47545
|
+
switch (config.type) {
|
|
47546
|
+
case "borrow":
|
|
47547
|
+
return makeBorrowIx3({
|
|
47548
|
+
program,
|
|
47549
|
+
bank,
|
|
47550
|
+
bankMap,
|
|
47551
|
+
tokenProgram,
|
|
47552
|
+
amount: 1,
|
|
47553
|
+
marginfiAccount,
|
|
47554
|
+
authority: marginfiAccount.authority,
|
|
47555
|
+
isSync: true,
|
|
47556
|
+
opts: { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts }
|
|
47557
|
+
});
|
|
47558
|
+
case "repay":
|
|
47559
|
+
return makeRepayIx3({
|
|
47560
|
+
program,
|
|
47561
|
+
bank,
|
|
47562
|
+
tokenProgram,
|
|
47563
|
+
amount: 1,
|
|
47564
|
+
accountAddress: marginfiAccount.address,
|
|
47565
|
+
authority: marginfiAccount.authority,
|
|
47566
|
+
repayAll: false,
|
|
47567
|
+
isSync: true,
|
|
47568
|
+
opts: { wrapAndUnwrapSol: false, overrideInferAccounts }
|
|
47569
|
+
});
|
|
47570
|
+
case "deposit":
|
|
47571
|
+
return buildDepositBudgetIx(
|
|
47572
|
+
config,
|
|
47573
|
+
program,
|
|
47574
|
+
marginfiAccount,
|
|
47575
|
+
bankMetadataMap,
|
|
47576
|
+
overrideInferAccounts
|
|
47577
|
+
);
|
|
47578
|
+
case "withdraw":
|
|
47579
|
+
return buildWithdrawBudgetIx(
|
|
47580
|
+
config,
|
|
47581
|
+
program,
|
|
47582
|
+
marginfiAccount,
|
|
47583
|
+
bankMap,
|
|
47584
|
+
bankMetadataMap,
|
|
47585
|
+
overrideInferAccounts
|
|
47586
|
+
);
|
|
46910
47587
|
}
|
|
46911
|
-
|
|
47588
|
+
}
|
|
47589
|
+
async function buildDepositBudgetIx(config, program, marginfiAccount, bankMetadataMap, overrideInferAccounts) {
|
|
47590
|
+
const { bank, tokenProgram } = config;
|
|
47591
|
+
const opts = { wrapAndUnwrapSol: false, overrideInferAccounts };
|
|
47592
|
+
switch (bank.config.assetTag) {
|
|
47593
|
+
case 3 /* KAMINO */: {
|
|
47594
|
+
const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47595
|
+
if (!reserve) {
|
|
47596
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47597
|
+
bank.address.toBase58(),
|
|
47598
|
+
bank.mint.toBase58(),
|
|
47599
|
+
bank.tokenSymbol
|
|
47600
|
+
);
|
|
47601
|
+
}
|
|
47602
|
+
return makeKaminoDepositIx3({
|
|
47603
|
+
program,
|
|
47604
|
+
bank,
|
|
47605
|
+
tokenProgram,
|
|
47606
|
+
amount: 1,
|
|
47607
|
+
accountAddress: marginfiAccount.address,
|
|
47608
|
+
authority: marginfiAccount.authority,
|
|
47609
|
+
group: marginfiAccount.group,
|
|
47610
|
+
reserve,
|
|
47611
|
+
isSync: true,
|
|
47612
|
+
opts
|
|
47613
|
+
});
|
|
47614
|
+
}
|
|
47615
|
+
case 4 /* DRIFT */: {
|
|
47616
|
+
const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
|
|
47617
|
+
if (!driftState) {
|
|
47618
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
47619
|
+
bank.address.toBase58(),
|
|
47620
|
+
bank.mint.toBase58(),
|
|
47621
|
+
bank.tokenSymbol
|
|
47622
|
+
);
|
|
47623
|
+
}
|
|
47624
|
+
return makeDriftDepositIx3({
|
|
47625
|
+
program,
|
|
47626
|
+
bank,
|
|
47627
|
+
tokenProgram,
|
|
47628
|
+
amount: 1,
|
|
47629
|
+
accountAddress: marginfiAccount.address,
|
|
47630
|
+
authority: marginfiAccount.authority,
|
|
47631
|
+
group: marginfiAccount.group,
|
|
47632
|
+
driftMarketIndex: driftState.spotMarketState.marketIndex,
|
|
47633
|
+
driftOracle: driftState.spotMarketState.oracle,
|
|
47634
|
+
isSync: true,
|
|
47635
|
+
opts
|
|
47636
|
+
});
|
|
47637
|
+
}
|
|
47638
|
+
case 6 /* JUPLEND */: {
|
|
47639
|
+
return makeJuplendDepositIx2({
|
|
47640
|
+
program,
|
|
47641
|
+
bank,
|
|
47642
|
+
tokenProgram,
|
|
47643
|
+
amount: 1,
|
|
47644
|
+
accountAddress: marginfiAccount.address,
|
|
47645
|
+
authority: marginfiAccount.authority,
|
|
47646
|
+
group: marginfiAccount.group,
|
|
47647
|
+
isSync: true,
|
|
47648
|
+
opts
|
|
47649
|
+
});
|
|
47650
|
+
}
|
|
47651
|
+
default: {
|
|
47652
|
+
return makeDepositIx3({
|
|
47653
|
+
program,
|
|
47654
|
+
bank,
|
|
47655
|
+
tokenProgram,
|
|
47656
|
+
amount: 1,
|
|
47657
|
+
accountAddress: marginfiAccount.address,
|
|
47658
|
+
authority: marginfiAccount.authority,
|
|
47659
|
+
group: marginfiAccount.group,
|
|
47660
|
+
isSync: true,
|
|
47661
|
+
opts
|
|
47662
|
+
});
|
|
47663
|
+
}
|
|
47664
|
+
}
|
|
47665
|
+
}
|
|
47666
|
+
async function buildWithdrawBudgetIx(config, program, marginfiAccount, bankMap, bankMetadataMap, overrideInferAccounts) {
|
|
47667
|
+
const { bank, tokenProgram } = config;
|
|
47668
|
+
const opts = { createAtas: false, wrapAndUnwrapSol: false, overrideInferAccounts };
|
|
47669
|
+
switch (bank.config.assetTag) {
|
|
47670
|
+
case 3 /* KAMINO */: {
|
|
47671
|
+
const reserve = bankMetadataMap[bank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47672
|
+
if (!reserve) {
|
|
47673
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47674
|
+
bank.address.toBase58(),
|
|
47675
|
+
bank.mint.toBase58(),
|
|
47676
|
+
bank.tokenSymbol
|
|
47677
|
+
);
|
|
47678
|
+
}
|
|
47679
|
+
return makeKaminoWithdrawIx3({
|
|
47680
|
+
program,
|
|
47681
|
+
bank,
|
|
47682
|
+
bankMap,
|
|
47683
|
+
tokenProgram,
|
|
47684
|
+
cTokenAmount: 1,
|
|
47685
|
+
marginfiAccount,
|
|
47686
|
+
authority: marginfiAccount.authority,
|
|
47687
|
+
reserve,
|
|
47688
|
+
withdrawAll: false,
|
|
47689
|
+
isSync: true,
|
|
47690
|
+
opts
|
|
47691
|
+
});
|
|
47692
|
+
}
|
|
47693
|
+
case 4 /* DRIFT */: {
|
|
47694
|
+
const driftState = bankMetadataMap[bank.address.toBase58()]?.driftStates;
|
|
47695
|
+
if (!driftState) {
|
|
47696
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
47697
|
+
bank.address.toBase58(),
|
|
47698
|
+
bank.mint.toBase58(),
|
|
47699
|
+
bank.tokenSymbol
|
|
47700
|
+
);
|
|
47701
|
+
}
|
|
47702
|
+
return makeDriftWithdrawIx3({
|
|
47703
|
+
program,
|
|
47704
|
+
bank,
|
|
47705
|
+
bankMap,
|
|
47706
|
+
tokenProgram,
|
|
47707
|
+
amount: 1,
|
|
47708
|
+
marginfiAccount,
|
|
47709
|
+
authority: marginfiAccount.authority,
|
|
47710
|
+
driftSpotMarket: driftState.spotMarketState,
|
|
47711
|
+
userRewards: driftState.userRewards,
|
|
47712
|
+
withdrawAll: false,
|
|
47713
|
+
isSync: true,
|
|
47714
|
+
opts
|
|
47715
|
+
});
|
|
47716
|
+
}
|
|
47717
|
+
case 6 /* JUPLEND */: {
|
|
47718
|
+
const jupLendState = bankMetadataMap[bank.address.toBase58()]?.jupLendStates;
|
|
47719
|
+
if (!jupLendState) {
|
|
47720
|
+
throw TransactionBuildingError.jupLendStateNotFound(
|
|
47721
|
+
bank.address.toBase58(),
|
|
47722
|
+
bank.mint.toBase58(),
|
|
47723
|
+
bank.tokenSymbol
|
|
47724
|
+
);
|
|
47725
|
+
}
|
|
47726
|
+
return makeJuplendWithdrawIx2({
|
|
47727
|
+
program,
|
|
47728
|
+
bank,
|
|
47729
|
+
bankMap,
|
|
47730
|
+
tokenProgram,
|
|
47731
|
+
amount: 1,
|
|
47732
|
+
marginfiAccount,
|
|
47733
|
+
authority: marginfiAccount.authority,
|
|
47734
|
+
jupLendingState: jupLendState.jupLendingState,
|
|
47735
|
+
withdrawAll: false,
|
|
47736
|
+
opts
|
|
47737
|
+
});
|
|
47738
|
+
}
|
|
47739
|
+
default: {
|
|
47740
|
+
return makeWithdrawIx3({
|
|
47741
|
+
program,
|
|
47742
|
+
bank,
|
|
47743
|
+
bankMap,
|
|
47744
|
+
tokenProgram,
|
|
47745
|
+
amount: 1,
|
|
47746
|
+
marginfiAccount,
|
|
47747
|
+
authority: marginfiAccount.authority,
|
|
47748
|
+
withdrawAll: false,
|
|
47749
|
+
isSync: true,
|
|
47750
|
+
opts
|
|
47751
|
+
});
|
|
47752
|
+
}
|
|
47753
|
+
}
|
|
47754
|
+
}
|
|
47755
|
+
async function computeFlashloanSwapConstraints({
|
|
47756
|
+
program,
|
|
47757
|
+
marginfiAccount,
|
|
47758
|
+
bankMap,
|
|
47759
|
+
addressLookupTableAccounts,
|
|
47760
|
+
bankMetadataMap,
|
|
47761
|
+
primaryIx,
|
|
47762
|
+
secondaryIx,
|
|
47763
|
+
overrideInferAccounts
|
|
47764
|
+
}) {
|
|
47765
|
+
const cuRequestIxs = [
|
|
47766
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
47767
|
+
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
47768
|
+
];
|
|
47769
|
+
const [primaryResult, secondaryResult] = await Promise.all([
|
|
47770
|
+
buildBudgetIx(
|
|
47771
|
+
primaryIx,
|
|
47772
|
+
program,
|
|
47773
|
+
marginfiAccount,
|
|
47774
|
+
bankMap,
|
|
47775
|
+
bankMetadataMap,
|
|
47776
|
+
overrideInferAccounts
|
|
47777
|
+
),
|
|
47778
|
+
buildBudgetIx(
|
|
47779
|
+
secondaryIx,
|
|
47780
|
+
program,
|
|
47781
|
+
marginfiAccount,
|
|
47782
|
+
bankMap,
|
|
47783
|
+
bankMetadataMap,
|
|
47784
|
+
overrideInferAccounts
|
|
47785
|
+
)
|
|
47786
|
+
]);
|
|
47787
|
+
return computeFlashLoanNonSwapBudget({
|
|
46912
47788
|
program,
|
|
47789
|
+
marginfiAccount,
|
|
47790
|
+
bankMap,
|
|
47791
|
+
addressLookupTableAccounts,
|
|
47792
|
+
ixs: [...cuRequestIxs, ...primaryResult.instructions, ...secondaryResult.instructions]
|
|
47793
|
+
});
|
|
47794
|
+
}
|
|
47795
|
+
|
|
47796
|
+
// src/services/account/actions/flash-loan.ts
|
|
47797
|
+
async function makeBeginFlashLoanIx3(program, marginfiAccountPk, endIndex, authority, isSync) {
|
|
47798
|
+
const ix = isSync && authority ? sync_instructions_default.makeBeginFlashLoanIx(
|
|
47799
|
+
program.programId,
|
|
46913
47800
|
{
|
|
46914
|
-
marginfiAccount:
|
|
46915
|
-
|
|
46916
|
-
bank: bank.address,
|
|
46917
|
-
tokenProgram,
|
|
46918
|
-
authority: opts.overrideInferAccounts?.authority ?? authority,
|
|
46919
|
-
group: opts.overrideInferAccounts?.group,
|
|
46920
|
-
liquidityVault: opts.overrideInferAccounts?.liquidityVault
|
|
47801
|
+
marginfiAccount: marginfiAccountPk,
|
|
47802
|
+
authority
|
|
46921
47803
|
},
|
|
46922
|
-
{
|
|
46923
|
-
|
|
46924
|
-
|
|
47804
|
+
{ endIndex: new BN11(endIndex) }
|
|
47805
|
+
) : await instructions_default.makeBeginFlashLoanIx(
|
|
47806
|
+
program,
|
|
47807
|
+
{
|
|
47808
|
+
marginfiAccount: marginfiAccountPk,
|
|
47809
|
+
authority
|
|
47810
|
+
},
|
|
47811
|
+
{ endIndex: new BN11(endIndex) }
|
|
47812
|
+
);
|
|
47813
|
+
return { instructions: [ix], keys: [] };
|
|
47814
|
+
}
|
|
47815
|
+
async function makeEndFlashLoanIx3(program, marginfiAccountPk, projectedActiveBanks, authority, isSync) {
|
|
47816
|
+
const remainingAccounts = computeHealthAccountMetas(projectedActiveBanks);
|
|
47817
|
+
const ix = isSync && authority ? sync_instructions_default.makeEndFlashLoanIx(
|
|
46925
47818
|
program.programId,
|
|
46926
47819
|
{
|
|
46927
|
-
marginfiAccount:
|
|
46928
|
-
|
|
46929
|
-
bank: bank.address,
|
|
46930
|
-
tokenProgram,
|
|
46931
|
-
authority: opts.overrideInferAccounts?.authority ?? authority,
|
|
46932
|
-
group: opts.overrideInferAccounts?.group
|
|
47820
|
+
marginfiAccount: marginfiAccountPk,
|
|
47821
|
+
authority
|
|
46933
47822
|
},
|
|
46934
|
-
|
|
46935
|
-
|
|
47823
|
+
remainingAccounts.map((account) => ({
|
|
47824
|
+
pubkey: account,
|
|
47825
|
+
isSigner: false,
|
|
47826
|
+
isWritable: false
|
|
47827
|
+
}))
|
|
47828
|
+
) : await instructions_default.makeEndFlashLoanIx(
|
|
47829
|
+
program,
|
|
47830
|
+
{
|
|
47831
|
+
marginfiAccount: marginfiAccountPk,
|
|
47832
|
+
authority
|
|
47833
|
+
},
|
|
47834
|
+
remainingAccounts.map((account) => ({
|
|
47835
|
+
pubkey: account,
|
|
47836
|
+
isSigner: false,
|
|
47837
|
+
isWritable: false
|
|
47838
|
+
}))
|
|
46936
47839
|
);
|
|
46937
|
-
|
|
46938
|
-
return {
|
|
46939
|
-
instructions: repayIxs,
|
|
46940
|
-
keys: []
|
|
46941
|
-
};
|
|
47840
|
+
return { instructions: [ix], keys: [] };
|
|
46942
47841
|
}
|
|
46943
|
-
async function
|
|
46944
|
-
|
|
46945
|
-
|
|
46946
|
-
|
|
46947
|
-
|
|
46948
|
-
|
|
46949
|
-
|
|
46950
|
-
|
|
46951
|
-
|
|
47842
|
+
async function makeFlashLoanTx({
|
|
47843
|
+
program,
|
|
47844
|
+
marginfiAccount,
|
|
47845
|
+
ixs,
|
|
47846
|
+
bankMap,
|
|
47847
|
+
blockhash,
|
|
47848
|
+
addressLookupTableAccounts,
|
|
47849
|
+
signers,
|
|
47850
|
+
isSync
|
|
47851
|
+
}) {
|
|
47852
|
+
const endIndex = ixs.length + 1;
|
|
47853
|
+
const projectedActiveBanksKeys = computeProjectedActiveBanksNoCpi(
|
|
47854
|
+
marginfiAccount.balances,
|
|
47855
|
+
ixs,
|
|
47856
|
+
program
|
|
47857
|
+
);
|
|
47858
|
+
const projectedActiveBanks = projectedActiveBanksKeys.map((account) => {
|
|
47859
|
+
const b = bankMap.get(account.toBase58());
|
|
47860
|
+
if (!b) throw Error(`Bank ${account.toBase58()} not found, in makeFlashLoanTx function`);
|
|
47861
|
+
return b;
|
|
46952
47862
|
});
|
|
46953
|
-
|
|
47863
|
+
const beginFlashLoanIx = await makeBeginFlashLoanIx3(
|
|
47864
|
+
program,
|
|
47865
|
+
marginfiAccount.address,
|
|
47866
|
+
endIndex,
|
|
47867
|
+
marginfiAccount.authority,
|
|
47868
|
+
isSync
|
|
47869
|
+
);
|
|
47870
|
+
const endFlashLoanIx = await makeEndFlashLoanIx3(
|
|
47871
|
+
program,
|
|
47872
|
+
marginfiAccount.address,
|
|
47873
|
+
projectedActiveBanks,
|
|
47874
|
+
marginfiAccount.authority,
|
|
47875
|
+
isSync
|
|
47876
|
+
);
|
|
47877
|
+
const message = new TransactionMessage({
|
|
47878
|
+
payerKey: marginfiAccount.authority,
|
|
47879
|
+
recentBlockhash: blockhash,
|
|
47880
|
+
instructions: [...beginFlashLoanIx.instructions, ...ixs, ...endFlashLoanIx.instructions]
|
|
47881
|
+
}).compileToV0Message(addressLookupTableAccounts);
|
|
47882
|
+
const tx = addTransactionMetadata(new VersionedTransaction(message), {
|
|
47883
|
+
addressLookupTables: addressLookupTableAccounts,
|
|
47884
|
+
type: "FLASHLOAN" /* FLASHLOAN */,
|
|
47885
|
+
signers
|
|
47886
|
+
});
|
|
47887
|
+
if (signers) {
|
|
47888
|
+
tx.sign(signers);
|
|
47889
|
+
}
|
|
47890
|
+
return tx;
|
|
46954
47891
|
}
|
|
46955
|
-
|
|
47892
|
+
|
|
47893
|
+
// src/services/account/actions/loop.ts
|
|
47894
|
+
async function makeLoopTx(params) {
|
|
46956
47895
|
const {
|
|
46957
47896
|
program,
|
|
46958
47897
|
marginfiAccount,
|
|
46959
47898
|
bankMap,
|
|
46960
|
-
|
|
46961
|
-
|
|
47899
|
+
depositOpts,
|
|
47900
|
+
borrowOpts,
|
|
46962
47901
|
bankMetadataMap,
|
|
46963
47902
|
addressLookupTableAccounts,
|
|
46964
47903
|
connection,
|
|
46965
47904
|
oraclePrices,
|
|
46966
|
-
crossbarUrl
|
|
47905
|
+
crossbarUrl,
|
|
47906
|
+
additionalIxs = []
|
|
46967
47907
|
} = params;
|
|
46968
47908
|
const blockhash = (await connection.getLatestBlockhash("confirmed")).blockhash;
|
|
46969
47909
|
const setupIxs = await makeSetupIx({
|
|
@@ -46971,34 +47911,34 @@ async function makeRepayWithCollatTx(params) {
|
|
|
46971
47911
|
authority: marginfiAccount.authority,
|
|
46972
47912
|
tokens: [
|
|
46973
47913
|
{
|
|
46974
|
-
mint:
|
|
46975
|
-
tokenProgram:
|
|
47914
|
+
mint: borrowOpts.borrowBank.mint,
|
|
47915
|
+
tokenProgram: borrowOpts.tokenProgram
|
|
46976
47916
|
},
|
|
46977
47917
|
{
|
|
46978
|
-
mint:
|
|
46979
|
-
tokenProgram:
|
|
47918
|
+
mint: depositOpts.depositBank.mint,
|
|
47919
|
+
tokenProgram: depositOpts.tokenProgram
|
|
46980
47920
|
}
|
|
46981
47921
|
]
|
|
46982
47922
|
});
|
|
46983
|
-
const
|
|
46984
|
-
marginfiAccount,
|
|
46985
|
-
bankMap,
|
|
46986
|
-
[
|
|
46987
|
-
bankMetadataMap
|
|
47923
|
+
const updateJupLendRateIxs = makeUpdateJupLendRateIxs(
|
|
47924
|
+
params.marginfiAccount,
|
|
47925
|
+
params.bankMap,
|
|
47926
|
+
[depositOpts.depositBank.address],
|
|
47927
|
+
params.bankMetadataMap
|
|
46988
47928
|
);
|
|
46989
47929
|
const updateDriftMarketIxs = makeUpdateDriftMarketIxs(
|
|
46990
|
-
marginfiAccount,
|
|
46991
|
-
bankMap,
|
|
46992
|
-
[
|
|
46993
|
-
bankMetadataMap
|
|
47930
|
+
params.marginfiAccount,
|
|
47931
|
+
params.bankMap,
|
|
47932
|
+
[depositOpts.depositBank.address],
|
|
47933
|
+
params.bankMetadataMap
|
|
46994
47934
|
);
|
|
46995
47935
|
const kaminoRefreshIxs = makeRefreshKaminoBanksIxs(
|
|
46996
47936
|
marginfiAccount,
|
|
46997
47937
|
bankMap,
|
|
46998
|
-
[
|
|
47938
|
+
[borrowOpts.borrowBank.address, depositOpts.depositBank.address],
|
|
46999
47939
|
bankMetadataMap
|
|
47000
47940
|
);
|
|
47001
|
-
const { flashloanTx, setupInstructions, swapQuote,
|
|
47941
|
+
const { flashloanTx, setupInstructions, swapQuote, amountToDeposit, depositIxs, borrowIxs } = await buildLoopFlashloanTx({
|
|
47002
47942
|
...params,
|
|
47003
47943
|
blockhash
|
|
47004
47944
|
});
|
|
@@ -47008,7 +47948,7 @@ async function makeRepayWithCollatTx(params) {
|
|
|
47008
47948
|
}
|
|
47009
47949
|
if (ix.programId.equals(ASSOCIATED_TOKEN_PROGRAM_ID)) {
|
|
47010
47950
|
const mintKey = ix.keys[3]?.pubkey;
|
|
47011
|
-
if (mintKey?.equals(
|
|
47951
|
+
if (mintKey?.equals(depositOpts.depositBank.mint) || mintKey?.equals(borrowOpts.borrowBank.mint)) {
|
|
47012
47952
|
return false;
|
|
47013
47953
|
}
|
|
47014
47954
|
}
|
|
@@ -47020,18 +47960,24 @@ async function makeRepayWithCollatTx(params) {
|
|
|
47020
47960
|
bankMap,
|
|
47021
47961
|
oraclePrices,
|
|
47022
47962
|
assetShareValueMultiplierByBank: params.assetShareValueMultiplierByBank,
|
|
47023
|
-
instructions: [...
|
|
47963
|
+
instructions: [...borrowIxs.instructions, ...depositIxs.instructions],
|
|
47024
47964
|
program,
|
|
47025
47965
|
connection,
|
|
47026
47966
|
crossbarUrl
|
|
47027
47967
|
});
|
|
47028
47968
|
let additionalTxs = [];
|
|
47029
|
-
if (
|
|
47969
|
+
if (depositOpts.depositBank.mint.equals(NATIVE_MINT) && depositOpts.inputDepositAmount) {
|
|
47970
|
+
setupIxs.push(
|
|
47971
|
+
...makeWrapSolIxs(marginfiAccount.authority, new BigNumber(depositOpts.inputDepositAmount))
|
|
47972
|
+
);
|
|
47973
|
+
}
|
|
47974
|
+
if (setupIxs.length > 0 || additionalIxs.length > 0 || kaminoRefreshIxs.instructions.length > 0 || updateDriftMarketIxs.instructions.length > 0 || updateJupLendRateIxs.instructions.length > 0) {
|
|
47030
47975
|
const ixs = [
|
|
47976
|
+
...additionalIxs,
|
|
47031
47977
|
...setupIxs,
|
|
47032
47978
|
...kaminoRefreshIxs.instructions,
|
|
47033
47979
|
...updateDriftMarketIxs.instructions,
|
|
47034
|
-
...
|
|
47980
|
+
...updateJupLendRateIxs.instructions
|
|
47035
47981
|
];
|
|
47036
47982
|
const txs = splitInstructionsToFitTransactions([], ixs, {
|
|
47037
47983
|
blockhash,
|
|
@@ -47061,110 +48007,121 @@ async function makeRepayWithCollatTx(params) {
|
|
|
47061
48007
|
);
|
|
47062
48008
|
}
|
|
47063
48009
|
const transactions = [...additionalTxs, flashloanTx];
|
|
47064
|
-
return {
|
|
48010
|
+
return {
|
|
48011
|
+
transactions,
|
|
48012
|
+
actionTxIndex: transactions.length - 1,
|
|
48013
|
+
quoteResponse: swapQuote
|
|
48014
|
+
};
|
|
47065
48015
|
}
|
|
47066
|
-
async function
|
|
48016
|
+
async function buildLoopFlashloanTx({
|
|
47067
48017
|
program,
|
|
47068
48018
|
marginfiAccount,
|
|
47069
48019
|
bankMap,
|
|
47070
|
-
|
|
47071
|
-
|
|
48020
|
+
borrowOpts,
|
|
48021
|
+
depositOpts,
|
|
47072
48022
|
bankMetadataMap,
|
|
47073
|
-
assetShareValueMultiplierByBank,
|
|
47074
48023
|
addressLookupTableAccounts,
|
|
47075
48024
|
connection,
|
|
47076
48025
|
swapOpts,
|
|
47077
48026
|
overrideInferAccounts,
|
|
47078
48027
|
blockhash
|
|
47079
48028
|
}) {
|
|
47080
|
-
const swapResult = [];
|
|
47081
48029
|
const cuRequestIxs = [
|
|
47082
48030
|
ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
47083
48031
|
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
47084
48032
|
];
|
|
47085
|
-
|
|
47086
|
-
|
|
47087
|
-
|
|
47088
|
-
|
|
47089
|
-
|
|
47090
|
-
|
|
47091
|
-
|
|
48033
|
+
let amountToDeposit;
|
|
48034
|
+
let swapInstructions = [];
|
|
48035
|
+
let setupInstructions = [];
|
|
48036
|
+
let swapLookupTables = [];
|
|
48037
|
+
let swapQuote;
|
|
48038
|
+
let sizeConstraintUsed = 0;
|
|
48039
|
+
if (depositOpts.depositBank.mint.equals(borrowOpts.borrowBank.mint)) {
|
|
48040
|
+
amountToDeposit = borrowOpts.borrowAmount + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
|
|
47092
48041
|
} else {
|
|
47093
48042
|
const destinationTokenAccount = getAssociatedTokenAddressSync(
|
|
47094
|
-
new PublicKey(
|
|
48043
|
+
new PublicKey(depositOpts.depositBank.mint),
|
|
47095
48044
|
marginfiAccount.authority,
|
|
47096
48045
|
true,
|
|
47097
|
-
|
|
48046
|
+
depositOpts.tokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
|
|
47098
48047
|
);
|
|
47099
|
-
const
|
|
47100
|
-
|
|
47101
|
-
|
|
47102
|
-
|
|
47103
|
-
|
|
47104
|
-
|
|
47105
|
-
|
|
47106
|
-
|
|
47107
|
-
|
|
47108
|
-
|
|
47109
|
-
|
|
47110
|
-
|
|
47111
|
-
|
|
48048
|
+
const swapConstraints = await computeFlashloanSwapConstraints({
|
|
48049
|
+
program,
|
|
48050
|
+
marginfiAccount,
|
|
48051
|
+
bankMap,
|
|
48052
|
+
bankMetadataMap,
|
|
48053
|
+
addressLookupTableAccounts: addressLookupTableAccounts ?? [],
|
|
48054
|
+
primaryIx: {
|
|
48055
|
+
type: "borrow",
|
|
48056
|
+
bank: borrowOpts.borrowBank,
|
|
48057
|
+
tokenProgram: borrowOpts.tokenProgram
|
|
48058
|
+
},
|
|
48059
|
+
secondaryIx: {
|
|
48060
|
+
type: "deposit",
|
|
48061
|
+
bank: depositOpts.depositBank,
|
|
48062
|
+
tokenProgram: depositOpts.tokenProgram
|
|
47112
48063
|
},
|
|
48064
|
+
overrideInferAccounts
|
|
48065
|
+
});
|
|
48066
|
+
const swapResponse = await getSwapIxsForFlashloan({
|
|
48067
|
+
inputMint: borrowOpts.borrowBank.mint.toBase58(),
|
|
48068
|
+
outputMint: depositOpts.depositBank.mint.toBase58(),
|
|
48069
|
+
amount: uiToNative(borrowOpts.borrowAmount, borrowOpts.borrowBank.mintDecimals).toNumber(),
|
|
48070
|
+
swapMode: "ExactIn",
|
|
47113
48071
|
authority: marginfiAccount.authority,
|
|
47114
48072
|
connection,
|
|
47115
48073
|
destinationTokenAccount,
|
|
47116
|
-
|
|
47117
|
-
|
|
47118
|
-
|
|
47119
|
-
const { swapInstruction, addressLookupTableAddresses, quoteResponse } = response;
|
|
47120
|
-
const outAmount = nativeToUi(quoteResponse.outAmount, repayOpts.repayBank.mintDecimals);
|
|
47121
|
-
const outAmountThreshold = nativeToUi(
|
|
47122
|
-
quoteResponse.otherAmountThreshold,
|
|
47123
|
-
repayOpts.repayBank.mintDecimals
|
|
47124
|
-
);
|
|
47125
|
-
const amountToRepay = outAmount > repayOpts.totalPositionAmount ? repayOpts.totalPositionAmount : outAmountThreshold;
|
|
47126
|
-
swapResult.push({
|
|
47127
|
-
amountToRepay,
|
|
47128
|
-
swapInstructions: [swapInstruction],
|
|
47129
|
-
setupInstructions: [],
|
|
47130
|
-
swapLookupTables: addressLookupTableAddresses,
|
|
47131
|
-
quoteResponse
|
|
47132
|
-
});
|
|
48074
|
+
swapOpts,
|
|
48075
|
+
sizeConstraint: swapConstraints.sizeConstraint,
|
|
48076
|
+
maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
|
|
47133
48077
|
});
|
|
48078
|
+
sizeConstraintUsed = swapConstraints.sizeConstraint;
|
|
48079
|
+
const outAmountThreshold = nativeToUi(
|
|
48080
|
+
swapResponse.quoteResponse.otherAmountThreshold,
|
|
48081
|
+
depositOpts.depositBank.mintDecimals
|
|
48082
|
+
);
|
|
48083
|
+
amountToDeposit = outAmountThreshold + (depositOpts.loopMode === "DEPOSIT" ? depositOpts.inputDepositAmount : 0);
|
|
48084
|
+
swapInstructions = swapResponse.swapInstructions;
|
|
48085
|
+
setupInstructions = swapResponse.setupInstructions;
|
|
48086
|
+
swapLookupTables = swapResponse.addressLookupTableAddresses;
|
|
48087
|
+
swapQuote = swapResponse.quoteResponse;
|
|
47134
48088
|
}
|
|
47135
|
-
|
|
47136
|
-
|
|
48089
|
+
const borrowIxs = await makeBorrowIx3({
|
|
48090
|
+
program,
|
|
48091
|
+
bank: borrowOpts.borrowBank,
|
|
48092
|
+
bankMap,
|
|
48093
|
+
tokenProgram: borrowOpts.tokenProgram,
|
|
48094
|
+
amount: borrowOpts.borrowAmount,
|
|
48095
|
+
marginfiAccount,
|
|
48096
|
+
authority: marginfiAccount.authority,
|
|
48097
|
+
isSync: false,
|
|
48098
|
+
opts: {
|
|
48099
|
+
createAtas: false,
|
|
48100
|
+
wrapAndUnwrapSol: false,
|
|
48101
|
+
overrideInferAccounts
|
|
48102
|
+
}
|
|
48103
|
+
});
|
|
48104
|
+
let depositIxs;
|
|
48105
|
+
switch (depositOpts.depositBank.config.assetTag) {
|
|
47137
48106
|
case 3 /* KAMINO */: {
|
|
47138
|
-
const reserve = bankMetadataMap[
|
|
48107
|
+
const reserve = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47139
48108
|
if (!reserve) {
|
|
47140
48109
|
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47141
|
-
|
|
47142
|
-
|
|
47143
|
-
|
|
48110
|
+
depositOpts.depositBank.address.toBase58(),
|
|
48111
|
+
depositOpts.depositBank.mint.toBase58(),
|
|
48112
|
+
depositOpts.depositBank.tokenSymbol
|
|
47144
48113
|
);
|
|
47145
48114
|
}
|
|
47146
|
-
|
|
47147
|
-
const adjustedAmount = new BigNumber(withdrawOpts.withdrawAmount).div(multiplier).times(1.0001).toNumber();
|
|
47148
|
-
withdrawIxs = await makeKaminoWithdrawIx3({
|
|
48115
|
+
depositIxs = await makeKaminoDepositIx3({
|
|
47149
48116
|
program,
|
|
47150
|
-
bank:
|
|
47151
|
-
|
|
47152
|
-
|
|
47153
|
-
|
|
47154
|
-
marginfiAccount,
|
|
48117
|
+
bank: depositOpts.depositBank,
|
|
48118
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
48119
|
+
amount: amountToDeposit,
|
|
48120
|
+
accountAddress: marginfiAccount.address,
|
|
47155
48121
|
authority: marginfiAccount.authority,
|
|
48122
|
+
group: marginfiAccount.group,
|
|
47156
48123
|
reserve,
|
|
47157
|
-
withdrawAll: isWholePosition(
|
|
47158
|
-
{
|
|
47159
|
-
amount: withdrawOpts.totalPositionAmount,
|
|
47160
|
-
isLending: true
|
|
47161
|
-
},
|
|
47162
|
-
withdrawOpts.withdrawAmount,
|
|
47163
|
-
withdrawOpts.withdrawBank.mintDecimals
|
|
47164
|
-
),
|
|
47165
|
-
isSync: false,
|
|
47166
48124
|
opts: {
|
|
47167
|
-
createAtas: false,
|
|
47168
48125
|
wrapAndUnwrapSol: false,
|
|
47169
48126
|
overrideInferAccounts
|
|
47170
48127
|
}
|
|
@@ -47172,35 +48129,27 @@ async function buildRepayWithCollatFlashloanTx({
|
|
|
47172
48129
|
break;
|
|
47173
48130
|
}
|
|
47174
48131
|
case 4 /* DRIFT */: {
|
|
47175
|
-
const driftState = bankMetadataMap[
|
|
48132
|
+
const driftState = bankMetadataMap[depositOpts.depositBank.address.toBase58()]?.driftStates;
|
|
47176
48133
|
if (!driftState) {
|
|
47177
48134
|
throw TransactionBuildingError.driftStateNotFound(
|
|
47178
|
-
|
|
47179
|
-
|
|
47180
|
-
|
|
48135
|
+
depositOpts.depositBank.address.toBase58(),
|
|
48136
|
+
depositOpts.depositBank.mint.toBase58(),
|
|
48137
|
+
depositOpts.depositBank.tokenSymbol
|
|
47181
48138
|
);
|
|
47182
48139
|
}
|
|
47183
|
-
|
|
48140
|
+
const driftMarketIndex = driftState.spotMarketState.marketIndex;
|
|
48141
|
+
const driftOracle = driftState.spotMarketState.oracle;
|
|
48142
|
+
depositIxs = await makeDriftDepositIx3({
|
|
47184
48143
|
program,
|
|
47185
|
-
bank:
|
|
47186
|
-
|
|
47187
|
-
|
|
47188
|
-
|
|
47189
|
-
marginfiAccount,
|
|
48144
|
+
bank: depositOpts.depositBank,
|
|
48145
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
48146
|
+
amount: amountToDeposit,
|
|
48147
|
+
accountAddress: marginfiAccount.address,
|
|
47190
48148
|
authority: marginfiAccount.authority,
|
|
47191
|
-
|
|
47192
|
-
|
|
47193
|
-
|
|
47194
|
-
{
|
|
47195
|
-
amount: withdrawOpts.totalPositionAmount,
|
|
47196
|
-
isLending: true
|
|
47197
|
-
},
|
|
47198
|
-
withdrawOpts.withdrawAmount,
|
|
47199
|
-
withdrawOpts.withdrawBank.mintDecimals
|
|
47200
|
-
),
|
|
47201
|
-
isSync: false,
|
|
48149
|
+
group: marginfiAccount.group,
|
|
48150
|
+
driftMarketIndex,
|
|
48151
|
+
driftOracle,
|
|
47202
48152
|
opts: {
|
|
47203
|
-
createAtas: false,
|
|
47204
48153
|
wrapAndUnwrapSol: false,
|
|
47205
48154
|
overrideInferAccounts
|
|
47206
48155
|
}
|
|
@@ -47208,33 +48157,15 @@ async function buildRepayWithCollatFlashloanTx({
|
|
|
47208
48157
|
break;
|
|
47209
48158
|
}
|
|
47210
48159
|
case 6 /* JUPLEND */: {
|
|
47211
|
-
|
|
47212
|
-
if (!jupLendState) {
|
|
47213
|
-
throw TransactionBuildingError.jupLendStateNotFound(
|
|
47214
|
-
withdrawOpts.withdrawBank.address.toBase58(),
|
|
47215
|
-
withdrawOpts.withdrawBank.mint.toBase58(),
|
|
47216
|
-
withdrawOpts.withdrawBank.tokenSymbol
|
|
47217
|
-
);
|
|
47218
|
-
}
|
|
47219
|
-
withdrawIxs = await makeJuplendWithdrawIx2({
|
|
48160
|
+
depositIxs = await makeJuplendDepositIx2({
|
|
47220
48161
|
program,
|
|
47221
|
-
bank:
|
|
47222
|
-
|
|
47223
|
-
|
|
47224
|
-
|
|
47225
|
-
marginfiAccount,
|
|
48162
|
+
bank: depositOpts.depositBank,
|
|
48163
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
48164
|
+
amount: amountToDeposit,
|
|
48165
|
+
accountAddress: marginfiAccount.address,
|
|
47226
48166
|
authority: marginfiAccount.authority,
|
|
47227
|
-
|
|
47228
|
-
withdrawAll: isWholePosition(
|
|
47229
|
-
{
|
|
47230
|
-
amount: withdrawOpts.totalPositionAmount,
|
|
47231
|
-
isLending: true
|
|
47232
|
-
},
|
|
47233
|
-
withdrawOpts.withdrawAmount,
|
|
47234
|
-
withdrawOpts.withdrawBank.mintDecimals
|
|
47235
|
-
),
|
|
48167
|
+
group: marginfiAccount.group,
|
|
47236
48168
|
opts: {
|
|
47237
|
-
createAtas: false,
|
|
47238
48169
|
wrapAndUnwrapSol: false,
|
|
47239
48170
|
overrideInferAccounts
|
|
47240
48171
|
}
|
|
@@ -47242,25 +48173,15 @@ async function buildRepayWithCollatFlashloanTx({
|
|
|
47242
48173
|
break;
|
|
47243
48174
|
}
|
|
47244
48175
|
default: {
|
|
47245
|
-
|
|
48176
|
+
depositIxs = await makeDepositIx3({
|
|
47246
48177
|
program,
|
|
47247
|
-
bank:
|
|
47248
|
-
|
|
47249
|
-
|
|
47250
|
-
|
|
47251
|
-
marginfiAccount,
|
|
48178
|
+
bank: depositOpts.depositBank,
|
|
48179
|
+
tokenProgram: depositOpts.tokenProgram,
|
|
48180
|
+
amount: amountToDeposit,
|
|
48181
|
+
accountAddress: marginfiAccount.address,
|
|
47252
48182
|
authority: marginfiAccount.authority,
|
|
47253
|
-
|
|
47254
|
-
{
|
|
47255
|
-
amount: withdrawOpts.totalPositionAmount,
|
|
47256
|
-
isLending: true
|
|
47257
|
-
},
|
|
47258
|
-
withdrawOpts.withdrawAmount,
|
|
47259
|
-
withdrawOpts.withdrawBank.mintDecimals
|
|
47260
|
-
),
|
|
47261
|
-
isSync: false,
|
|
48183
|
+
group: marginfiAccount.group,
|
|
47262
48184
|
opts: {
|
|
47263
|
-
createAtas: false,
|
|
47264
48185
|
wrapAndUnwrapSol: false,
|
|
47265
48186
|
overrideInferAccounts
|
|
47266
48187
|
}
|
|
@@ -47268,68 +48189,48 @@ async function buildRepayWithCollatFlashloanTx({
|
|
|
47268
48189
|
break;
|
|
47269
48190
|
}
|
|
47270
48191
|
}
|
|
47271
|
-
|
|
47272
|
-
|
|
47273
|
-
|
|
47274
|
-
|
|
47275
|
-
|
|
47276
|
-
|
|
47277
|
-
|
|
47278
|
-
|
|
47279
|
-
|
|
47280
|
-
|
|
47281
|
-
|
|
47282
|
-
|
|
47283
|
-
|
|
47284
|
-
|
|
47285
|
-
|
|
47286
|
-
repayOpts.repayBank.mintDecimals
|
|
47287
|
-
),
|
|
47288
|
-
isSync: false,
|
|
47289
|
-
opts: {
|
|
47290
|
-
wrapAndUnwrapSol: false,
|
|
47291
|
-
overrideInferAccounts
|
|
47292
|
-
}
|
|
47293
|
-
});
|
|
47294
|
-
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
47295
|
-
const flashloanParams = {
|
|
47296
|
-
program,
|
|
47297
|
-
marginfiAccount,
|
|
47298
|
-
bankMap,
|
|
47299
|
-
addressLookupTableAccounts: luts,
|
|
47300
|
-
blockhash
|
|
47301
|
-
};
|
|
47302
|
-
const flashloanTx = await makeFlashLoanTx({
|
|
47303
|
-
...flashloanParams,
|
|
47304
|
-
ixs: [
|
|
47305
|
-
...cuRequestIxs,
|
|
47306
|
-
...withdrawIxs.instructions,
|
|
47307
|
-
...swapInstructions,
|
|
47308
|
-
...repayIxs.instructions
|
|
47309
|
-
],
|
|
47310
|
-
isSync: true
|
|
48192
|
+
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
48193
|
+
const allNonFlIxs = [
|
|
48194
|
+
...cuRequestIxs,
|
|
48195
|
+
...borrowIxs.instructions,
|
|
48196
|
+
...swapInstructions,
|
|
48197
|
+
...depositIxs.instructions
|
|
48198
|
+
];
|
|
48199
|
+
if (swapInstructions.length > 0) {
|
|
48200
|
+
compileFlashloanPrecheck({
|
|
48201
|
+
allIxs: allNonFlIxs,
|
|
48202
|
+
payer: marginfiAccount.authority,
|
|
48203
|
+
luts,
|
|
48204
|
+
sizeConstraint: sizeConstraintUsed,
|
|
48205
|
+
swapIxCount: swapInstructions.length,
|
|
48206
|
+
swapLutCount: swapLookupTables.length
|
|
47311
48207
|
});
|
|
47312
|
-
const txSize = getTxSize(flashloanTx);
|
|
47313
|
-
const keySize = getAccountKeys(flashloanTx, luts);
|
|
47314
|
-
const isLast = index === swapResult.length - 1;
|
|
47315
|
-
if (txSize > MAX_TX_SIZE || keySize > 64) {
|
|
47316
|
-
if (isLast) {
|
|
47317
|
-
throw TransactionBuildingError.jupiterSwapSizeExceededRepay(txSize, keySize);
|
|
47318
|
-
} else {
|
|
47319
|
-
continue;
|
|
47320
|
-
}
|
|
47321
|
-
} else {
|
|
47322
|
-
return {
|
|
47323
|
-
flashloanTx,
|
|
47324
|
-
setupInstructions,
|
|
47325
|
-
swapQuote: quoteResponse,
|
|
47326
|
-
withdrawIxs,
|
|
47327
|
-
repayIxs,
|
|
47328
|
-
amountToRepay
|
|
47329
|
-
};
|
|
47330
|
-
}
|
|
47331
48208
|
}
|
|
47332
|
-
|
|
48209
|
+
const flashloanTx = await makeFlashLoanTx({
|
|
48210
|
+
program,
|
|
48211
|
+
marginfiAccount,
|
|
48212
|
+
bankMap,
|
|
48213
|
+
addressLookupTableAccounts: luts,
|
|
48214
|
+
blockhash,
|
|
48215
|
+
ixs: allNonFlIxs
|
|
48216
|
+
});
|
|
48217
|
+
const txSize = getTxSize(flashloanTx);
|
|
48218
|
+
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
48219
|
+
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
48220
|
+
throw TransactionBuildingError.swapSizeExceededLoop(
|
|
48221
|
+
txSize,
|
|
48222
|
+
totalKeys,
|
|
48223
|
+
swapOpts.swapConfig?.provider
|
|
48224
|
+
);
|
|
48225
|
+
}
|
|
48226
|
+
return {
|
|
48227
|
+
flashloanTx,
|
|
48228
|
+
setupInstructions,
|
|
48229
|
+
swapQuote,
|
|
48230
|
+
borrowIxs,
|
|
48231
|
+
depositIxs,
|
|
48232
|
+
amountToDeposit
|
|
48233
|
+
};
|
|
47333
48234
|
}
|
|
47334
48235
|
|
|
47335
48236
|
// src/services/account/actions/emissions.ts
|
|
@@ -47483,11 +48384,16 @@ async function buildSwapCollateralFlashloanTx({
|
|
|
47483
48384
|
actualWithdrawAmount,
|
|
47484
48385
|
withdrawBank.mintDecimals
|
|
47485
48386
|
);
|
|
47486
|
-
const swapResult = [];
|
|
47487
48387
|
const cuRequestIxs = [
|
|
47488
48388
|
ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
47489
48389
|
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
47490
48390
|
];
|
|
48391
|
+
let amountToDeposit;
|
|
48392
|
+
let swapInstructions = [];
|
|
48393
|
+
let setupInstructions = [];
|
|
48394
|
+
let swapLookupTables = [];
|
|
48395
|
+
let swapQuote;
|
|
48396
|
+
let sizeConstraintUsed = 0;
|
|
47491
48397
|
let withdrawIxs;
|
|
47492
48398
|
switch (withdrawOpts.withdrawBank.config.assetTag) {
|
|
47493
48399
|
case 3 /* KAMINO */: {
|
|
@@ -47597,12 +48503,7 @@ async function buildSwapCollateralFlashloanTx({
|
|
|
47597
48503
|
}
|
|
47598
48504
|
}
|
|
47599
48505
|
if (depositBank.mint.equals(withdrawBank.mint)) {
|
|
47600
|
-
|
|
47601
|
-
amountToDeposit: actualWithdrawAmount,
|
|
47602
|
-
swapInstructions: [],
|
|
47603
|
-
setupInstructions: [],
|
|
47604
|
-
swapLookupTables: []
|
|
47605
|
-
});
|
|
48506
|
+
amountToDeposit = actualWithdrawAmount;
|
|
47606
48507
|
} else {
|
|
47607
48508
|
const destinationTokenAccount = getAssociatedTokenAddressSync(
|
|
47608
48509
|
depositBank.mint,
|
|
@@ -47610,175 +48511,168 @@ async function buildSwapCollateralFlashloanTx({
|
|
|
47610
48511
|
true,
|
|
47611
48512
|
depositTokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
|
|
47612
48513
|
);
|
|
47613
|
-
const
|
|
47614
|
-
|
|
47615
|
-
|
|
47616
|
-
|
|
47617
|
-
|
|
47618
|
-
|
|
47619
|
-
|
|
47620
|
-
|
|
47621
|
-
|
|
47622
|
-
|
|
47623
|
-
|
|
48514
|
+
const swapConstraints = await computeFlashloanSwapConstraints({
|
|
48515
|
+
program,
|
|
48516
|
+
marginfiAccount,
|
|
48517
|
+
bankMap,
|
|
48518
|
+
bankMetadataMap,
|
|
48519
|
+
addressLookupTableAccounts: addressLookupTableAccounts ?? [],
|
|
48520
|
+
primaryIx: { type: "withdraw", bank: withdrawBank, tokenProgram: withdrawTokenProgram },
|
|
48521
|
+
secondaryIx: { type: "deposit", bank: depositBank, tokenProgram: depositTokenProgram },
|
|
48522
|
+
overrideInferAccounts
|
|
48523
|
+
});
|
|
48524
|
+
const swapResponses = await getSwapIxsForFlashloan({
|
|
48525
|
+
inputMint: withdrawBank.mint.toBase58(),
|
|
48526
|
+
outputMint: depositBank.mint.toBase58(),
|
|
48527
|
+
amount: uiToNative(actualWithdrawAmount, withdrawBank.mintDecimals).toNumber(),
|
|
48528
|
+
swapMode: "ExactIn",
|
|
47624
48529
|
authority: marginfiAccount.authority,
|
|
47625
48530
|
connection,
|
|
47626
48531
|
destinationTokenAccount,
|
|
47627
|
-
|
|
48532
|
+
swapOpts,
|
|
48533
|
+
sizeConstraint: swapConstraints.sizeConstraint,
|
|
48534
|
+
maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
|
|
47628
48535
|
});
|
|
47629
|
-
|
|
47630
|
-
|
|
47631
|
-
|
|
47632
|
-
|
|
47633
|
-
);
|
|
47634
|
-
swapResult.push({
|
|
47635
|
-
amountToDeposit: outAmountThreshold,
|
|
47636
|
-
swapInstructions: [response.swapInstruction],
|
|
47637
|
-
setupInstructions: response.setupInstructions,
|
|
47638
|
-
swapLookupTables: response.addressLookupTableAddresses,
|
|
47639
|
-
quoteResponse: response.quoteResponse
|
|
47640
|
-
});
|
|
47641
|
-
});
|
|
47642
|
-
}
|
|
47643
|
-
if (swapResult.length === 0) {
|
|
47644
|
-
throw new Error(
|
|
47645
|
-
`No swap routes found for ${withdrawBank.mint.toBase58()} -> ${depositBank.mint.toBase58()}`
|
|
48536
|
+
sizeConstraintUsed = swapConstraints.sizeConstraint;
|
|
48537
|
+
amountToDeposit = nativeToUi(
|
|
48538
|
+
swapResponses.quoteResponse.otherAmountThreshold,
|
|
48539
|
+
depositBank.mintDecimals
|
|
47646
48540
|
);
|
|
48541
|
+
swapInstructions = swapResponses.swapInstructions;
|
|
48542
|
+
setupInstructions = swapResponses.setupInstructions;
|
|
48543
|
+
swapLookupTables = swapResponses.addressLookupTableAddresses;
|
|
48544
|
+
swapQuote = swapResponses.quoteResponse;
|
|
47647
48545
|
}
|
|
47648
|
-
|
|
47649
|
-
|
|
47650
|
-
|
|
47651
|
-
|
|
47652
|
-
|
|
47653
|
-
|
|
47654
|
-
|
|
47655
|
-
|
|
47656
|
-
|
|
47657
|
-
|
|
47658
|
-
case 3 /* KAMINO */: {
|
|
47659
|
-
const reserve = bankMetadataMap[depositBank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
47660
|
-
if (!reserve) {
|
|
47661
|
-
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
47662
|
-
depositBank.address.toBase58(),
|
|
47663
|
-
depositBank.mint.toBase58(),
|
|
47664
|
-
depositBank.tokenSymbol
|
|
47665
|
-
);
|
|
47666
|
-
}
|
|
47667
|
-
depositIxs = await makeKaminoDepositIx3({
|
|
47668
|
-
program,
|
|
47669
|
-
bank: depositBank,
|
|
47670
|
-
tokenProgram: depositTokenProgram,
|
|
47671
|
-
amount: amountToDeposit,
|
|
47672
|
-
accountAddress: marginfiAccount.address,
|
|
47673
|
-
authority: marginfiAccount.authority,
|
|
47674
|
-
group: marginfiAccount.group,
|
|
47675
|
-
reserve,
|
|
47676
|
-
opts: {
|
|
47677
|
-
wrapAndUnwrapSol: false,
|
|
47678
|
-
overrideInferAccounts
|
|
47679
|
-
}
|
|
47680
|
-
});
|
|
47681
|
-
break;
|
|
48546
|
+
let depositIxs;
|
|
48547
|
+
switch (depositBank.config.assetTag) {
|
|
48548
|
+
case 3 /* KAMINO */: {
|
|
48549
|
+
const reserve = bankMetadataMap[depositBank.address.toBase58()]?.kaminoStates?.reserveState;
|
|
48550
|
+
if (!reserve) {
|
|
48551
|
+
throw TransactionBuildingError.kaminoReserveNotFound(
|
|
48552
|
+
depositBank.address.toBase58(),
|
|
48553
|
+
depositBank.mint.toBase58(),
|
|
48554
|
+
depositBank.tokenSymbol
|
|
48555
|
+
);
|
|
47682
48556
|
}
|
|
47683
|
-
|
|
47684
|
-
|
|
47685
|
-
|
|
47686
|
-
|
|
47687
|
-
|
|
47688
|
-
|
|
47689
|
-
|
|
47690
|
-
|
|
48557
|
+
depositIxs = await makeKaminoDepositIx3({
|
|
48558
|
+
program,
|
|
48559
|
+
bank: depositBank,
|
|
48560
|
+
tokenProgram: depositTokenProgram,
|
|
48561
|
+
amount: amountToDeposit,
|
|
48562
|
+
accountAddress: marginfiAccount.address,
|
|
48563
|
+
authority: marginfiAccount.authority,
|
|
48564
|
+
group: marginfiAccount.group,
|
|
48565
|
+
reserve,
|
|
48566
|
+
opts: {
|
|
48567
|
+
wrapAndUnwrapSol: false,
|
|
48568
|
+
overrideInferAccounts
|
|
47691
48569
|
}
|
|
47692
|
-
|
|
47693
|
-
|
|
47694
|
-
depositIxs = await makeDriftDepositIx3({
|
|
47695
|
-
program,
|
|
47696
|
-
bank: depositBank,
|
|
47697
|
-
tokenProgram: depositTokenProgram,
|
|
47698
|
-
amount: amountToDeposit,
|
|
47699
|
-
accountAddress: marginfiAccount.address,
|
|
47700
|
-
authority: marginfiAccount.authority,
|
|
47701
|
-
group: marginfiAccount.group,
|
|
47702
|
-
driftMarketIndex,
|
|
47703
|
-
driftOracle,
|
|
47704
|
-
opts: {
|
|
47705
|
-
wrapAndUnwrapSol: false,
|
|
47706
|
-
overrideInferAccounts
|
|
47707
|
-
}
|
|
47708
|
-
});
|
|
47709
|
-
break;
|
|
47710
|
-
}
|
|
47711
|
-
case 6 /* JUPLEND */: {
|
|
47712
|
-
depositIxs = await makeJuplendDepositIx2({
|
|
47713
|
-
program,
|
|
47714
|
-
bank: depositBank,
|
|
47715
|
-
tokenProgram: depositTokenProgram,
|
|
47716
|
-
amount: amountToDeposit,
|
|
47717
|
-
accountAddress: marginfiAccount.address,
|
|
47718
|
-
authority: marginfiAccount.authority,
|
|
47719
|
-
group: marginfiAccount.group,
|
|
47720
|
-
opts: {
|
|
47721
|
-
wrapAndUnwrapSol: false,
|
|
47722
|
-
overrideInferAccounts
|
|
47723
|
-
}
|
|
47724
|
-
});
|
|
47725
|
-
break;
|
|
47726
|
-
}
|
|
47727
|
-
default: {
|
|
47728
|
-
depositIxs = await makeDepositIx3({
|
|
47729
|
-
program,
|
|
47730
|
-
bank: depositBank,
|
|
47731
|
-
tokenProgram: depositTokenProgram,
|
|
47732
|
-
amount: amountToDeposit,
|
|
47733
|
-
accountAddress: marginfiAccount.address,
|
|
47734
|
-
authority: marginfiAccount.authority,
|
|
47735
|
-
group: marginfiAccount.group,
|
|
47736
|
-
opts: {
|
|
47737
|
-
wrapAndUnwrapSol: false,
|
|
47738
|
-
overrideInferAccounts
|
|
47739
|
-
}
|
|
47740
|
-
});
|
|
47741
|
-
break;
|
|
47742
|
-
}
|
|
48570
|
+
});
|
|
48571
|
+
break;
|
|
47743
48572
|
}
|
|
47744
|
-
|
|
47745
|
-
|
|
47746
|
-
|
|
47747
|
-
|
|
47748
|
-
|
|
47749
|
-
|
|
47750
|
-
|
|
47751
|
-
|
|
47752
|
-
const flashloanTx = await makeFlashLoanTx({
|
|
47753
|
-
...flashloanParams,
|
|
47754
|
-
ixs: [
|
|
47755
|
-
...cuRequestIxs,
|
|
47756
|
-
...withdrawIxs.instructions,
|
|
47757
|
-
...swapInstructions,
|
|
47758
|
-
...depositIxs.instructions
|
|
47759
|
-
],
|
|
47760
|
-
isSync: true
|
|
47761
|
-
});
|
|
47762
|
-
const txSize = getTxSize(flashloanTx);
|
|
47763
|
-
const keySize = getAccountKeys(flashloanTx, luts);
|
|
47764
|
-
const isLast = index === swapResult.length - 1;
|
|
47765
|
-
if (txSize > MAX_TX_SIZE || keySize > 64) {
|
|
47766
|
-
if (isLast) {
|
|
47767
|
-
throw TransactionBuildingError.jupiterSwapSizeExceededLoop(txSize, keySize);
|
|
47768
|
-
} else {
|
|
47769
|
-
continue;
|
|
48573
|
+
case 4 /* DRIFT */: {
|
|
48574
|
+
const driftState = bankMetadataMap[depositBank.address.toBase58()]?.driftStates;
|
|
48575
|
+
if (!driftState) {
|
|
48576
|
+
throw TransactionBuildingError.driftStateNotFound(
|
|
48577
|
+
depositBank.address.toBase58(),
|
|
48578
|
+
depositBank.mint.toBase58(),
|
|
48579
|
+
depositBank.tokenSymbol
|
|
48580
|
+
);
|
|
47770
48581
|
}
|
|
47771
|
-
|
|
47772
|
-
|
|
47773
|
-
|
|
47774
|
-
|
|
47775
|
-
|
|
47776
|
-
|
|
47777
|
-
|
|
47778
|
-
|
|
48582
|
+
const driftMarketIndex = driftState.spotMarketState.marketIndex;
|
|
48583
|
+
const driftOracle = driftState.spotMarketState.oracle;
|
|
48584
|
+
depositIxs = await makeDriftDepositIx3({
|
|
48585
|
+
program,
|
|
48586
|
+
bank: depositBank,
|
|
48587
|
+
tokenProgram: depositTokenProgram,
|
|
48588
|
+
amount: amountToDeposit,
|
|
48589
|
+
accountAddress: marginfiAccount.address,
|
|
48590
|
+
authority: marginfiAccount.authority,
|
|
48591
|
+
group: marginfiAccount.group,
|
|
48592
|
+
driftMarketIndex,
|
|
48593
|
+
driftOracle,
|
|
48594
|
+
opts: {
|
|
48595
|
+
wrapAndUnwrapSol: false,
|
|
48596
|
+
overrideInferAccounts
|
|
48597
|
+
}
|
|
48598
|
+
});
|
|
48599
|
+
break;
|
|
48600
|
+
}
|
|
48601
|
+
case 6 /* JUPLEND */: {
|
|
48602
|
+
depositIxs = await makeJuplendDepositIx2({
|
|
48603
|
+
program,
|
|
48604
|
+
bank: depositBank,
|
|
48605
|
+
tokenProgram: depositTokenProgram,
|
|
48606
|
+
amount: amountToDeposit,
|
|
48607
|
+
accountAddress: marginfiAccount.address,
|
|
48608
|
+
authority: marginfiAccount.authority,
|
|
48609
|
+
group: marginfiAccount.group,
|
|
48610
|
+
opts: {
|
|
48611
|
+
wrapAndUnwrapSol: false,
|
|
48612
|
+
overrideInferAccounts
|
|
48613
|
+
}
|
|
48614
|
+
});
|
|
48615
|
+
break;
|
|
48616
|
+
}
|
|
48617
|
+
default: {
|
|
48618
|
+
depositIxs = await makeDepositIx3({
|
|
48619
|
+
program,
|
|
48620
|
+
bank: depositBank,
|
|
48621
|
+
tokenProgram: depositTokenProgram,
|
|
48622
|
+
amount: amountToDeposit,
|
|
48623
|
+
accountAddress: marginfiAccount.address,
|
|
48624
|
+
authority: marginfiAccount.authority,
|
|
48625
|
+
group: marginfiAccount.group,
|
|
48626
|
+
opts: {
|
|
48627
|
+
wrapAndUnwrapSol: false,
|
|
48628
|
+
overrideInferAccounts
|
|
48629
|
+
}
|
|
48630
|
+
});
|
|
48631
|
+
break;
|
|
47779
48632
|
}
|
|
47780
48633
|
}
|
|
47781
|
-
|
|
48634
|
+
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
48635
|
+
const allNonFlIxs = [
|
|
48636
|
+
...cuRequestIxs,
|
|
48637
|
+
...withdrawIxs.instructions,
|
|
48638
|
+
...swapInstructions,
|
|
48639
|
+
...depositIxs.instructions
|
|
48640
|
+
];
|
|
48641
|
+
if (swapInstructions.length > 0) {
|
|
48642
|
+
compileFlashloanPrecheck({
|
|
48643
|
+
allIxs: allNonFlIxs,
|
|
48644
|
+
payer: marginfiAccount.authority,
|
|
48645
|
+
luts,
|
|
48646
|
+
sizeConstraint: sizeConstraintUsed,
|
|
48647
|
+
swapIxCount: swapInstructions.length,
|
|
48648
|
+
swapLutCount: swapLookupTables.length
|
|
48649
|
+
});
|
|
48650
|
+
}
|
|
48651
|
+
const flashloanTx = await makeFlashLoanTx({
|
|
48652
|
+
program,
|
|
48653
|
+
marginfiAccount,
|
|
48654
|
+
bankMap,
|
|
48655
|
+
addressLookupTableAccounts: luts,
|
|
48656
|
+
blockhash,
|
|
48657
|
+
ixs: allNonFlIxs,
|
|
48658
|
+
isSync: true
|
|
48659
|
+
});
|
|
48660
|
+
const txSize = getTxSize(flashloanTx);
|
|
48661
|
+
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
48662
|
+
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
48663
|
+
throw TransactionBuildingError.swapSizeExceededLoop(
|
|
48664
|
+
txSize,
|
|
48665
|
+
totalKeys,
|
|
48666
|
+
swapOpts.swapConfig?.provider
|
|
48667
|
+
);
|
|
48668
|
+
}
|
|
48669
|
+
return {
|
|
48670
|
+
flashloanTx,
|
|
48671
|
+
setupInstructions,
|
|
48672
|
+
swapQuote,
|
|
48673
|
+
withdrawIxs,
|
|
48674
|
+
depositIxs
|
|
48675
|
+
};
|
|
47782
48676
|
}
|
|
47783
48677
|
async function makeSwapDebtTx(params) {
|
|
47784
48678
|
const {
|
|
@@ -47916,7 +48810,6 @@ async function buildSwapDebtFlashloanTx({
|
|
|
47916
48810
|
throw new Error("repayAmount must be greater than 0");
|
|
47917
48811
|
}
|
|
47918
48812
|
const actualRepayAmount = Math.min(repayAmount ?? totalPositionAmount, totalPositionAmount);
|
|
47919
|
-
const swapResult = [];
|
|
47920
48813
|
const cuRequestIxs = [
|
|
47921
48814
|
ComputeBudgetProgram.setComputeUnitLimit({ units: 12e5 }),
|
|
47922
48815
|
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 })
|
|
@@ -47927,140 +48820,120 @@ async function buildSwapDebtFlashloanTx({
|
|
|
47927
48820
|
true,
|
|
47928
48821
|
repayTokenProgram.equals(TOKEN_2022_PROGRAM_ID) ? TOKEN_2022_PROGRAM_ID : void 0
|
|
47929
48822
|
);
|
|
47930
|
-
const
|
|
47931
|
-
const estimateQuote = await jupiterApiClient.quoteGet({
|
|
48823
|
+
const { otherAmountThreshold } = await getExactOutEstimate({
|
|
47932
48824
|
inputMint: borrowBank.mint.toBase58(),
|
|
47933
48825
|
outputMint: repayBank.mint.toBase58(),
|
|
47934
48826
|
amount: uiToNative(actualRepayAmount, repayBank.mintDecimals).toNumber(),
|
|
47935
|
-
|
|
47936
|
-
|
|
47937
|
-
slippageBps: swapOpts.jupiterOptions?.slippageBps
|
|
48827
|
+
swapOpts,
|
|
48828
|
+
connection
|
|
47938
48829
|
});
|
|
47939
|
-
const estimatedBorrowAmount = nativeToUi(
|
|
47940
|
-
|
|
47941
|
-
|
|
47942
|
-
|
|
47943
|
-
|
|
47944
|
-
|
|
47945
|
-
|
|
47946
|
-
|
|
47947
|
-
|
|
47948
|
-
|
|
47949
|
-
|
|
47950
|
-
|
|
47951
|
-
|
|
47952
|
-
|
|
47953
|
-
|
|
48830
|
+
const estimatedBorrowAmount = nativeToUi(otherAmountThreshold, borrowBank.mintDecimals);
|
|
48831
|
+
const swapConstraints = await computeFlashloanSwapConstraints({
|
|
48832
|
+
program,
|
|
48833
|
+
marginfiAccount,
|
|
48834
|
+
bankMap,
|
|
48835
|
+
bankMetadataMap,
|
|
48836
|
+
addressLookupTableAccounts: addressLookupTableAccounts ?? [],
|
|
48837
|
+
primaryIx: { type: "borrow", bank: borrowBank, tokenProgram: borrowTokenProgram },
|
|
48838
|
+
secondaryIx: { type: "repay", bank: repayBank, tokenProgram: repayTokenProgram },
|
|
48839
|
+
overrideInferAccounts
|
|
48840
|
+
});
|
|
48841
|
+
const swapResponses = await getSwapIxsForFlashloan({
|
|
48842
|
+
inputMint: borrowBank.mint.toBase58(),
|
|
48843
|
+
outputMint: repayBank.mint.toBase58(),
|
|
48844
|
+
amount: uiToNative(estimatedBorrowAmount, borrowBank.mintDecimals).toNumber(),
|
|
48845
|
+
swapMode: "ExactIn",
|
|
47954
48846
|
authority: marginfiAccount.authority,
|
|
47955
48847
|
connection,
|
|
47956
48848
|
destinationTokenAccount,
|
|
47957
|
-
|
|
48849
|
+
swapOpts,
|
|
48850
|
+
sizeConstraint: swapConstraints.sizeConstraint,
|
|
48851
|
+
maxSwapTotalAccounts: swapConstraints.maxSwapTotalAccounts
|
|
47958
48852
|
});
|
|
47959
|
-
|
|
47960
|
-
|
|
47961
|
-
|
|
47962
|
-
|
|
47963
|
-
|
|
47964
|
-
|
|
47965
|
-
|
|
47966
|
-
|
|
47967
|
-
|
|
47968
|
-
|
|
47969
|
-
|
|
47970
|
-
|
|
47971
|
-
|
|
47972
|
-
|
|
47973
|
-
|
|
47974
|
-
|
|
48853
|
+
const { quoteResponse } = swapResponses;
|
|
48854
|
+
const outAmount = nativeToUi(quoteResponse.outAmount, repayBank.mintDecimals);
|
|
48855
|
+
const outAmountThreshold = nativeToUi(quoteResponse.otherAmountThreshold, repayBank.mintDecimals);
|
|
48856
|
+
const amountToRepay = outAmount > totalPositionAmount ? totalPositionAmount : outAmountThreshold;
|
|
48857
|
+
const borrowAmount = nativeToUi(quoteResponse.inAmount, borrowBank.mintDecimals);
|
|
48858
|
+
const borrowIxs = await makeBorrowIx3({
|
|
48859
|
+
program,
|
|
48860
|
+
bank: borrowBank,
|
|
48861
|
+
bankMap,
|
|
48862
|
+
tokenProgram: borrowTokenProgram,
|
|
48863
|
+
amount: borrowAmount,
|
|
48864
|
+
marginfiAccount,
|
|
48865
|
+
authority: marginfiAccount.authority,
|
|
48866
|
+
isSync: true,
|
|
48867
|
+
opts: {
|
|
48868
|
+
createAtas: false,
|
|
48869
|
+
wrapAndUnwrapSol: false,
|
|
48870
|
+
overrideInferAccounts
|
|
48871
|
+
}
|
|
47975
48872
|
});
|
|
47976
|
-
|
|
47977
|
-
|
|
47978
|
-
|
|
47979
|
-
|
|
47980
|
-
|
|
47981
|
-
|
|
47982
|
-
|
|
48873
|
+
const repayIxs = await makeRepayIx3({
|
|
48874
|
+
program,
|
|
48875
|
+
bank: repayBank,
|
|
48876
|
+
tokenProgram: repayTokenProgram,
|
|
48877
|
+
amount: amountToRepay,
|
|
48878
|
+
accountAddress: marginfiAccount.address,
|
|
48879
|
+
authority: marginfiAccount.authority,
|
|
48880
|
+
repayAll: isWholePosition(
|
|
48881
|
+
{
|
|
48882
|
+
amount: totalPositionAmount,
|
|
48883
|
+
isLending: false
|
|
48884
|
+
},
|
|
47983
48885
|
amountToRepay,
|
|
47984
|
-
|
|
47985
|
-
|
|
47986
|
-
|
|
47987
|
-
|
|
47988
|
-
|
|
47989
|
-
|
|
47990
|
-
const borrowIxs = await makeBorrowIx3({
|
|
47991
|
-
program,
|
|
47992
|
-
bank: borrowBank,
|
|
47993
|
-
bankMap,
|
|
47994
|
-
tokenProgram: borrowTokenProgram,
|
|
47995
|
-
amount: borrowAmount,
|
|
47996
|
-
marginfiAccount,
|
|
47997
|
-
authority: marginfiAccount.authority,
|
|
47998
|
-
isSync: true,
|
|
47999
|
-
opts: {
|
|
48000
|
-
createAtas: false,
|
|
48001
|
-
wrapAndUnwrapSol: false,
|
|
48002
|
-
overrideInferAccounts
|
|
48003
|
-
}
|
|
48004
|
-
});
|
|
48005
|
-
const repayIxs = await makeRepayIx3({
|
|
48006
|
-
program,
|
|
48007
|
-
bank: repayBank,
|
|
48008
|
-
tokenProgram: repayTokenProgram,
|
|
48009
|
-
amount: amountToRepay,
|
|
48010
|
-
accountAddress: marginfiAccount.address,
|
|
48011
|
-
authority: marginfiAccount.authority,
|
|
48012
|
-
repayAll: isWholePosition(
|
|
48013
|
-
{
|
|
48014
|
-
amount: totalPositionAmount,
|
|
48015
|
-
isLending: false
|
|
48016
|
-
},
|
|
48017
|
-
amountToRepay,
|
|
48018
|
-
repayBank.mintDecimals
|
|
48019
|
-
),
|
|
48020
|
-
isSync: true,
|
|
48021
|
-
opts: {
|
|
48022
|
-
wrapAndUnwrapSol: false,
|
|
48023
|
-
overrideInferAccounts
|
|
48024
|
-
}
|
|
48025
|
-
});
|
|
48026
|
-
const luts = [...addressLookupTableAccounts ?? [], ...swapLookupTables];
|
|
48027
|
-
const flashloanParams = {
|
|
48028
|
-
program,
|
|
48029
|
-
marginfiAccount,
|
|
48030
|
-
bankMap,
|
|
48031
|
-
addressLookupTableAccounts: luts,
|
|
48032
|
-
blockhash
|
|
48033
|
-
};
|
|
48034
|
-
const flashloanTx = await makeFlashLoanTx({
|
|
48035
|
-
...flashloanParams,
|
|
48036
|
-
ixs: [
|
|
48037
|
-
...cuRequestIxs,
|
|
48038
|
-
...borrowIxs.instructions,
|
|
48039
|
-
...swapInstructions,
|
|
48040
|
-
...repayIxs.instructions
|
|
48041
|
-
],
|
|
48042
|
-
isSync: true
|
|
48043
|
-
});
|
|
48044
|
-
const txSize = getTxSize(flashloanTx);
|
|
48045
|
-
const keySize = getAccountKeys(flashloanTx, luts);
|
|
48046
|
-
const isLast = index === swapResult.length - 1;
|
|
48047
|
-
if (txSize > MAX_TX_SIZE || keySize > 64) {
|
|
48048
|
-
if (isLast) {
|
|
48049
|
-
throw TransactionBuildingError.jupiterSwapSizeExceededLoop(txSize, keySize);
|
|
48050
|
-
} else {
|
|
48051
|
-
continue;
|
|
48052
|
-
}
|
|
48053
|
-
} else {
|
|
48054
|
-
return {
|
|
48055
|
-
flashloanTx,
|
|
48056
|
-
setupInstructions,
|
|
48057
|
-
swapQuote: quoteResponse,
|
|
48058
|
-
borrowIxs,
|
|
48059
|
-
repayIxs
|
|
48060
|
-
};
|
|
48886
|
+
repayBank.mintDecimals
|
|
48887
|
+
),
|
|
48888
|
+
isSync: true,
|
|
48889
|
+
opts: {
|
|
48890
|
+
wrapAndUnwrapSol: false,
|
|
48891
|
+
overrideInferAccounts
|
|
48061
48892
|
}
|
|
48893
|
+
});
|
|
48894
|
+
const luts = [
|
|
48895
|
+
...addressLookupTableAccounts ?? [],
|
|
48896
|
+
...swapResponses.addressLookupTableAddresses
|
|
48897
|
+
];
|
|
48898
|
+
const allNonFlIxs = [
|
|
48899
|
+
...cuRequestIxs,
|
|
48900
|
+
...borrowIxs.instructions,
|
|
48901
|
+
...swapResponses.swapInstructions,
|
|
48902
|
+
...repayIxs.instructions
|
|
48903
|
+
];
|
|
48904
|
+
compileFlashloanPrecheck({
|
|
48905
|
+
allIxs: allNonFlIxs,
|
|
48906
|
+
payer: marginfiAccount.authority,
|
|
48907
|
+
luts,
|
|
48908
|
+
sizeConstraint: swapConstraints.sizeConstraint,
|
|
48909
|
+
swapIxCount: swapResponses.swapInstructions.length,
|
|
48910
|
+
swapLutCount: swapResponses.addressLookupTableAddresses.length
|
|
48911
|
+
});
|
|
48912
|
+
const flashloanTx = await makeFlashLoanTx({
|
|
48913
|
+
program,
|
|
48914
|
+
marginfiAccount,
|
|
48915
|
+
bankMap,
|
|
48916
|
+
addressLookupTableAccounts: luts,
|
|
48917
|
+
blockhash,
|
|
48918
|
+
ixs: allNonFlIxs,
|
|
48919
|
+
isSync: true
|
|
48920
|
+
});
|
|
48921
|
+
const txSize = getTxSize(flashloanTx);
|
|
48922
|
+
const totalKeys = getTotalAccountKeys(flashloanTx);
|
|
48923
|
+
if (txSize > MAX_TX_SIZE || totalKeys > MAX_ACCOUNT_LOCKS) {
|
|
48924
|
+
throw TransactionBuildingError.swapSizeExceededLoop(
|
|
48925
|
+
txSize,
|
|
48926
|
+
totalKeys,
|
|
48927
|
+
swapOpts.swapConfig?.provider
|
|
48928
|
+
);
|
|
48062
48929
|
}
|
|
48063
|
-
|
|
48930
|
+
return {
|
|
48931
|
+
flashloanTx,
|
|
48932
|
+
setupInstructions: swapResponses.setupInstructions,
|
|
48933
|
+
swapQuote: quoteResponse,
|
|
48934
|
+
borrowIxs,
|
|
48935
|
+
repayIxs
|
|
48936
|
+
};
|
|
48064
48937
|
}
|
|
48065
48938
|
var SYSVAR_CLOCK_ID2 = new PublicKey("SysvarC1ock11111111111111111111111111111111");
|
|
48066
48939
|
async function makeMintStakedLstIx(params) {
|
|
@@ -48859,17 +49732,528 @@ function computeMaxWithdrawForBank(params) {
|
|
|
48859
49732
|
const maxWithdraw = initUntiedCollateralForBank.div(initWeightedPrice);
|
|
48860
49733
|
return maxWithdraw;
|
|
48861
49734
|
}
|
|
49735
|
+
var TITAN_FEE_WALLET = new PublicKey("6ryqDDCwKFZfSiHQrYRkjTEarbsLjg9TmuFg1RJorBk3");
|
|
49736
|
+
var getTitanFeeAccount = (mint) => {
|
|
49737
|
+
return getAssociatedTokenAddressSync(mint, TITAN_FEE_WALLET, true);
|
|
49738
|
+
};
|
|
49739
|
+
var checkTitanFeeAccount = async (connection, mint) => {
|
|
49740
|
+
const feeAccount = getTitanFeeAccount(mint);
|
|
49741
|
+
const hasFeeAccount = !!await connection.getAccountInfo(feeAccount);
|
|
49742
|
+
return { feeAccount, hasFeeAccount, feeWallet: TITAN_FEE_WALLET };
|
|
49743
|
+
};
|
|
49744
|
+
function deserializeTitanInstruction(ix) {
|
|
49745
|
+
return new TransactionInstruction({
|
|
49746
|
+
programId: new PublicKey(ix.p),
|
|
49747
|
+
keys: ix.a.map((account) => ({
|
|
49748
|
+
pubkey: new PublicKey(account.p),
|
|
49749
|
+
isSigner: account.s,
|
|
49750
|
+
isWritable: account.w
|
|
49751
|
+
})),
|
|
49752
|
+
data: Buffer.from(ix.d)
|
|
49753
|
+
});
|
|
49754
|
+
}
|
|
49755
|
+
var getTitanSwapIxsForFlashloan = async ({
|
|
49756
|
+
quoteParams,
|
|
49757
|
+
authority,
|
|
49758
|
+
connection,
|
|
49759
|
+
destinationTokenAccount,
|
|
49760
|
+
apiConfig
|
|
49761
|
+
}) => {
|
|
49762
|
+
const basePath = apiConfig?.basePath ?? "";
|
|
49763
|
+
const feeMint = new PublicKey(
|
|
49764
|
+
quoteParams.swapMode === "ExactIn" ? quoteParams.outputMint : quoteParams.inputMint
|
|
49765
|
+
);
|
|
49766
|
+
const { feeAccount, hasFeeAccount } = await checkTitanFeeAccount(connection, feeMint);
|
|
49767
|
+
let finalQuoteParams = quoteParams;
|
|
49768
|
+
if (!hasFeeAccount) {
|
|
49769
|
+
console.warn("Warning: Titan fee account ATA does not exist, disabling platform fee");
|
|
49770
|
+
finalQuoteParams = {
|
|
49771
|
+
...quoteParams,
|
|
49772
|
+
platformFeeBps: void 0
|
|
49773
|
+
};
|
|
49774
|
+
}
|
|
49775
|
+
if (basePath.startsWith("wss://") || basePath.startsWith("ws://")) {
|
|
49776
|
+
return getTitanSwapIxsViaWebSocket(
|
|
49777
|
+
{ quoteParams: finalQuoteParams, authority, connection, destinationTokenAccount, apiConfig },
|
|
49778
|
+
hasFeeAccount ? feeAccount : void 0
|
|
49779
|
+
);
|
|
49780
|
+
} else {
|
|
49781
|
+
return getTitanSwapIxsViaHttpProxy(
|
|
49782
|
+
{ quoteParams: finalQuoteParams, authority, connection, destinationTokenAccount, apiConfig },
|
|
49783
|
+
hasFeeAccount ? feeAccount : void 0
|
|
49784
|
+
);
|
|
49785
|
+
}
|
|
49786
|
+
};
|
|
49787
|
+
async function getTitanSwapIxsViaWebSocket(params, feeAccount) {
|
|
49788
|
+
const { quoteParams, authority, connection, destinationTokenAccount, apiConfig } = params;
|
|
49789
|
+
const {
|
|
49790
|
+
inputMint,
|
|
49791
|
+
outputMint,
|
|
49792
|
+
amount,
|
|
49793
|
+
swapMode,
|
|
49794
|
+
slippageBps,
|
|
49795
|
+
platformFeeBps,
|
|
49796
|
+
directRoutesOnly,
|
|
49797
|
+
sizeConstraint,
|
|
49798
|
+
maxSwapAccounts,
|
|
49799
|
+
maxSwapTotalAccounts
|
|
49800
|
+
} = quoteParams;
|
|
49801
|
+
const wsUrl = apiConfig?.basePath;
|
|
49802
|
+
if (!wsUrl) {
|
|
49803
|
+
throw new Error("Titan WebSocket URL is required (apiConfig.basePath)");
|
|
49804
|
+
}
|
|
49805
|
+
const txParams = {
|
|
49806
|
+
userPublicKey: authority.toBytes(),
|
|
49807
|
+
outputAccount: destinationTokenAccount.toBytes()
|
|
49808
|
+
};
|
|
49809
|
+
if (feeAccount && platformFeeBps) {
|
|
49810
|
+
txParams.feeBps = platformFeeBps;
|
|
49811
|
+
txParams.feeAccount = feeAccount.toBytes();
|
|
49812
|
+
}
|
|
49813
|
+
const client = await V1Client.connect(wsUrl);
|
|
49814
|
+
try {
|
|
49815
|
+
const { stream } = await client.newSwapQuoteStream({
|
|
49816
|
+
swap: {
|
|
49817
|
+
inputMint: new PublicKey(inputMint).toBytes(),
|
|
49818
|
+
outputMint: new PublicKey(outputMint).toBytes(),
|
|
49819
|
+
amount,
|
|
49820
|
+
swapMode,
|
|
49821
|
+
slippageBps,
|
|
49822
|
+
onlyDirectRoutes: directRoutesOnly,
|
|
49823
|
+
addSizeConstraint: sizeConstraint !== void 0,
|
|
49824
|
+
sizeConstraint,
|
|
49825
|
+
accountsLimitWritable: maxSwapAccounts,
|
|
49826
|
+
accountsLimitTotal: maxSwapTotalAccounts
|
|
49827
|
+
},
|
|
49828
|
+
transaction: txParams,
|
|
49829
|
+
update: {
|
|
49830
|
+
num_quotes: 3
|
|
49831
|
+
}
|
|
49832
|
+
});
|
|
49833
|
+
const reader = stream.getReader();
|
|
49834
|
+
const { value: swapQuotes, done } = await reader.read();
|
|
49835
|
+
reader.releaseLock();
|
|
49836
|
+
if (done || !swapQuotes) {
|
|
49837
|
+
throw new Error("Titan swap quote stream ended without data");
|
|
49838
|
+
}
|
|
49839
|
+
const quotes = swapQuotes;
|
|
49840
|
+
const bestRoute = selectBestRoute(quotes.quotes, swapMode);
|
|
49841
|
+
if (!bestRoute) {
|
|
49842
|
+
throw new Error(`No Titan swap routes found for ${inputMint} -> ${outputMint}`);
|
|
49843
|
+
}
|
|
49844
|
+
const swapInstructions = bestRoute.instructions.map(deserializeTitanInstruction);
|
|
49845
|
+
const lutPubkeys = bestRoute.addressLookupTables.map((lutBytes) => new PublicKey(lutBytes));
|
|
49846
|
+
const addressLookupTableAddresses = await resolveLookupTables(connection, lutPubkeys);
|
|
49847
|
+
const quoteResponse = {
|
|
49848
|
+
...buildSwapQuoteResult(bestRoute, swapMode),
|
|
49849
|
+
provider: "TITAN" /* TITAN */
|
|
49850
|
+
};
|
|
49851
|
+
return {
|
|
49852
|
+
swapInstructions,
|
|
49853
|
+
setupInstructions: [],
|
|
49854
|
+
addressLookupTableAddresses,
|
|
49855
|
+
quoteResponse
|
|
49856
|
+
};
|
|
49857
|
+
} finally {
|
|
49858
|
+
if (!client.closed) {
|
|
49859
|
+
await client.close();
|
|
49860
|
+
}
|
|
49861
|
+
}
|
|
49862
|
+
}
|
|
49863
|
+
async function getTitanSwapIxsViaHttpProxy(params, feeAccount) {
|
|
49864
|
+
const { quoteParams, authority, connection, destinationTokenAccount, apiConfig } = params;
|
|
49865
|
+
const {
|
|
49866
|
+
inputMint,
|
|
49867
|
+
outputMint,
|
|
49868
|
+
amount,
|
|
49869
|
+
swapMode,
|
|
49870
|
+
slippageBps,
|
|
49871
|
+
platformFeeBps,
|
|
49872
|
+
directRoutesOnly,
|
|
49873
|
+
sizeConstraint,
|
|
49874
|
+
maxSwapAccounts,
|
|
49875
|
+
maxSwapTotalAccounts
|
|
49876
|
+
} = quoteParams;
|
|
49877
|
+
const basePath = apiConfig?.basePath;
|
|
49878
|
+
if (!basePath) {
|
|
49879
|
+
throw new Error("Titan proxy URL is required (apiConfig.basePath)");
|
|
49880
|
+
}
|
|
49881
|
+
const txBody = {
|
|
49882
|
+
userPublicKey: authority.toBase58(),
|
|
49883
|
+
outputAccount: destinationTokenAccount.toBase58()
|
|
49884
|
+
};
|
|
49885
|
+
if (feeAccount && platformFeeBps) {
|
|
49886
|
+
txBody.feeBps = platformFeeBps;
|
|
49887
|
+
txBody.feeAccount = feeAccount.toBase58();
|
|
49888
|
+
}
|
|
49889
|
+
const response = await fetch(`${basePath}/swap-quote`, {
|
|
49890
|
+
method: "POST",
|
|
49891
|
+
headers: {
|
|
49892
|
+
"Content-Type": "application/json",
|
|
49893
|
+
...apiConfig?.headers ?? {}
|
|
49894
|
+
},
|
|
49895
|
+
body: JSON.stringify({
|
|
49896
|
+
swap: {
|
|
49897
|
+
inputMint,
|
|
49898
|
+
outputMint,
|
|
49899
|
+
amount,
|
|
49900
|
+
swapMode,
|
|
49901
|
+
slippageBps,
|
|
49902
|
+
onlyDirectRoutes: directRoutesOnly,
|
|
49903
|
+
addSizeConstraint: sizeConstraint !== void 0,
|
|
49904
|
+
sizeConstraint,
|
|
49905
|
+
accountsLimitWritable: maxSwapAccounts,
|
|
49906
|
+
accountsLimitTotal: maxSwapTotalAccounts
|
|
49907
|
+
},
|
|
49908
|
+
transaction: txBody
|
|
49909
|
+
})
|
|
49910
|
+
});
|
|
49911
|
+
if (!response.ok) {
|
|
49912
|
+
const errorData = await response.json().catch(() => ({}));
|
|
49913
|
+
throw new Error(
|
|
49914
|
+
`Titan proxy error (${response.status}): ${errorData.message ?? response.statusText}`
|
|
49915
|
+
);
|
|
49916
|
+
}
|
|
49917
|
+
const data = await response.json();
|
|
49918
|
+
const bestRoute = selectBestRoute(data.quotes, swapMode);
|
|
49919
|
+
if (!bestRoute) {
|
|
49920
|
+
throw new Error(`No Titan swap routes found for ${inputMint} -> ${outputMint}`);
|
|
49921
|
+
}
|
|
49922
|
+
const swapInstructions = bestRoute.instructions.map(deserializeSerializedInstruction);
|
|
49923
|
+
const lutPubkeys = bestRoute.addressLookupTables.map(
|
|
49924
|
+
(b64) => new PublicKey(Buffer.from(b64, "base64"))
|
|
49925
|
+
);
|
|
49926
|
+
const addressLookupTableAddresses = await resolveLookupTables(connection, lutPubkeys);
|
|
49927
|
+
const quoteResponse = {
|
|
49928
|
+
...buildSwapQuoteResult(bestRoute, swapMode),
|
|
49929
|
+
provider: "TITAN" /* TITAN */
|
|
49930
|
+
};
|
|
49931
|
+
return {
|
|
49932
|
+
swapInstructions,
|
|
49933
|
+
setupInstructions: [],
|
|
49934
|
+
addressLookupTableAddresses,
|
|
49935
|
+
quoteResponse
|
|
49936
|
+
};
|
|
49937
|
+
}
|
|
49938
|
+
var getTitanExactOutEstimate = async (params) => {
|
|
49939
|
+
const basePath = params.apiConfig?.basePath ?? "";
|
|
49940
|
+
if (basePath.startsWith("wss://") || basePath.startsWith("ws://")) {
|
|
49941
|
+
return getTitanExactOutViaWebSocket(params);
|
|
49942
|
+
} else {
|
|
49943
|
+
return getTitanExactOutViaHttpProxy(params);
|
|
49944
|
+
}
|
|
49945
|
+
};
|
|
49946
|
+
async function getTitanExactOutViaWebSocket(params) {
|
|
49947
|
+
const { inputMint, outputMint, amount, slippageBps, apiConfig } = params;
|
|
49948
|
+
const wsUrl = apiConfig?.basePath;
|
|
49949
|
+
if (!wsUrl) {
|
|
49950
|
+
throw new Error("Titan WebSocket URL is required (apiConfig.basePath)");
|
|
49951
|
+
}
|
|
49952
|
+
const client = await V1Client.connect(wsUrl);
|
|
49953
|
+
try {
|
|
49954
|
+
const { stream } = await client.newSwapQuoteStream({
|
|
49955
|
+
swap: {
|
|
49956
|
+
inputMint: new PublicKey(inputMint).toBytes(),
|
|
49957
|
+
outputMint: new PublicKey(outputMint).toBytes(),
|
|
49958
|
+
amount,
|
|
49959
|
+
swapMode: "ExactOut",
|
|
49960
|
+
slippageBps
|
|
49961
|
+
},
|
|
49962
|
+
transaction: {
|
|
49963
|
+
userPublicKey: new Uint8Array(32)
|
|
49964
|
+
// placeholder, not executing
|
|
49965
|
+
},
|
|
49966
|
+
update: {
|
|
49967
|
+
num_quotes: 1
|
|
49968
|
+
}
|
|
49969
|
+
});
|
|
49970
|
+
const reader = stream.getReader();
|
|
49971
|
+
const { value: swapQuotes, done } = await reader.read();
|
|
49972
|
+
reader.releaseLock();
|
|
49973
|
+
if (done || !swapQuotes) {
|
|
49974
|
+
throw new Error("Titan ExactOut estimate stream ended without data");
|
|
49975
|
+
}
|
|
49976
|
+
const quotes = swapQuotes;
|
|
49977
|
+
const bestRoute = selectBestRoute(quotes.quotes, "ExactOut");
|
|
49978
|
+
if (!bestRoute) {
|
|
49979
|
+
throw new Error(`No Titan ExactOut routes found for ${inputMint} -> ${outputMint}`);
|
|
49980
|
+
}
|
|
49981
|
+
const quoteResult = {
|
|
49982
|
+
...buildSwapQuoteResult(bestRoute, "ExactOut"),
|
|
49983
|
+
provider: "TITAN" /* TITAN */
|
|
49984
|
+
};
|
|
49985
|
+
return {
|
|
49986
|
+
otherAmountThreshold: quoteResult.otherAmountThreshold,
|
|
49987
|
+
quoteResult
|
|
49988
|
+
};
|
|
49989
|
+
} finally {
|
|
49990
|
+
if (!client.closed) {
|
|
49991
|
+
await client.close();
|
|
49992
|
+
}
|
|
49993
|
+
}
|
|
49994
|
+
}
|
|
49995
|
+
async function getTitanExactOutViaHttpProxy(params) {
|
|
49996
|
+
const { inputMint, outputMint, amount, slippageBps, apiConfig } = params;
|
|
49997
|
+
const basePath = apiConfig?.basePath;
|
|
49998
|
+
if (!basePath) {
|
|
49999
|
+
throw new Error("Titan proxy URL is required (apiConfig.basePath)");
|
|
50000
|
+
}
|
|
50001
|
+
const response = await fetch(`${basePath}/exact-out-estimate`, {
|
|
50002
|
+
method: "POST",
|
|
50003
|
+
headers: {
|
|
50004
|
+
"Content-Type": "application/json",
|
|
50005
|
+
...apiConfig?.headers ?? {}
|
|
50006
|
+
},
|
|
50007
|
+
body: JSON.stringify({
|
|
50008
|
+
inputMint,
|
|
50009
|
+
outputMint,
|
|
50010
|
+
amount,
|
|
50011
|
+
slippageBps
|
|
50012
|
+
})
|
|
50013
|
+
});
|
|
50014
|
+
if (!response.ok) {
|
|
50015
|
+
const errorData = await response.json().catch(() => ({}));
|
|
50016
|
+
throw new Error(
|
|
50017
|
+
`Titan proxy error (${response.status}): ${errorData.message ?? response.statusText}`
|
|
50018
|
+
);
|
|
50019
|
+
}
|
|
50020
|
+
const data = await response.json();
|
|
50021
|
+
const quoteResult = {
|
|
50022
|
+
inAmount: String(data.inAmount),
|
|
50023
|
+
outAmount: String(data.outAmount),
|
|
50024
|
+
otherAmountThreshold: data.otherAmountThreshold,
|
|
50025
|
+
slippageBps: data.slippageBps,
|
|
50026
|
+
provider: "TITAN" /* TITAN */
|
|
50027
|
+
};
|
|
50028
|
+
return {
|
|
50029
|
+
otherAmountThreshold: data.otherAmountThreshold,
|
|
50030
|
+
quoteResult
|
|
50031
|
+
};
|
|
50032
|
+
}
|
|
50033
|
+
|
|
50034
|
+
// src/services/account/utils/swap.utils.ts
|
|
50035
|
+
function getSwapProviderFn({
|
|
50036
|
+
attemptProvider,
|
|
50037
|
+
maxSwapTotalAccounts,
|
|
50038
|
+
inputMint,
|
|
50039
|
+
outputMint,
|
|
50040
|
+
amount,
|
|
50041
|
+
swapMode,
|
|
50042
|
+
authority,
|
|
50043
|
+
connection,
|
|
50044
|
+
destinationTokenAccount,
|
|
50045
|
+
swapOpts,
|
|
50046
|
+
sizeConstraint
|
|
50047
|
+
}) {
|
|
50048
|
+
switch (attemptProvider) {
|
|
50049
|
+
case "TITAN" /* TITAN */:
|
|
50050
|
+
return (apiConfig) => getTitanSwapIxsForFlashloan({
|
|
50051
|
+
quoteParams: {
|
|
50052
|
+
inputMint,
|
|
50053
|
+
outputMint,
|
|
50054
|
+
amount,
|
|
50055
|
+
swapMode,
|
|
50056
|
+
slippageBps: swapOpts.swapConfig?.slippageBps,
|
|
50057
|
+
platformFeeBps: swapOpts.swapConfig?.platformFeeBps,
|
|
50058
|
+
directRoutesOnly: swapOpts.swapConfig?.directRoutesOnly,
|
|
50059
|
+
sizeConstraint,
|
|
50060
|
+
maxSwapTotalAccounts
|
|
50061
|
+
},
|
|
50062
|
+
authority,
|
|
50063
|
+
connection,
|
|
50064
|
+
destinationTokenAccount,
|
|
50065
|
+
apiConfig
|
|
50066
|
+
});
|
|
50067
|
+
case "JUPITER" /* JUPITER */:
|
|
50068
|
+
return (apiConfig) => getJupiterSwapIxsForFlashloan({
|
|
50069
|
+
quoteParams: {
|
|
50070
|
+
inputMint,
|
|
50071
|
+
outputMint,
|
|
50072
|
+
amount,
|
|
50073
|
+
swapMode,
|
|
50074
|
+
dynamicSlippage: swapOpts.swapConfig ? swapOpts.swapConfig.slippageMode === "DYNAMIC" : true,
|
|
50075
|
+
slippageBps: swapOpts.swapConfig?.slippageBps,
|
|
50076
|
+
platformFeeBps: swapOpts.swapConfig?.platformFeeBps,
|
|
50077
|
+
onlyDirectRoutes: swapOpts.swapConfig?.directRoutesOnly ?? false
|
|
50078
|
+
},
|
|
50079
|
+
authority,
|
|
50080
|
+
connection,
|
|
50081
|
+
destinationTokenAccount,
|
|
50082
|
+
apiConfig,
|
|
50083
|
+
maxSwapAccounts: maxSwapTotalAccounts
|
|
50084
|
+
});
|
|
50085
|
+
default:
|
|
50086
|
+
return void 0;
|
|
50087
|
+
}
|
|
50088
|
+
}
|
|
50089
|
+
function getExactOutProviderFn({
|
|
50090
|
+
attemptProvider,
|
|
50091
|
+
inputMint,
|
|
50092
|
+
outputMint,
|
|
50093
|
+
amount,
|
|
50094
|
+
swapOpts,
|
|
50095
|
+
apiConfig
|
|
50096
|
+
}) {
|
|
50097
|
+
switch (attemptProvider) {
|
|
50098
|
+
case "TITAN" /* TITAN */:
|
|
50099
|
+
return () => getTitanExactOutEstimate({
|
|
50100
|
+
inputMint,
|
|
50101
|
+
outputMint,
|
|
50102
|
+
amount,
|
|
50103
|
+
slippageBps: swapOpts.swapConfig?.slippageBps,
|
|
50104
|
+
apiConfig
|
|
50105
|
+
});
|
|
50106
|
+
case "JUPITER" /* JUPITER */:
|
|
50107
|
+
return async () => {
|
|
50108
|
+
const configParams = toJupiterConfig(apiConfig);
|
|
50109
|
+
const jupiterApiClient = configParams?.basePath ? new SwapApi(new Configuration(configParams)) : createJupiterApiClient(configParams);
|
|
50110
|
+
const estimateQuote = await jupiterApiClient.quoteGet({
|
|
50111
|
+
inputMint,
|
|
50112
|
+
outputMint,
|
|
50113
|
+
amount,
|
|
50114
|
+
swapMode: "ExactOut",
|
|
50115
|
+
dynamicSlippage: swapOpts.swapConfig ? swapOpts.swapConfig.slippageMode === "DYNAMIC" : true,
|
|
50116
|
+
slippageBps: swapOpts.swapConfig?.slippageBps
|
|
50117
|
+
});
|
|
50118
|
+
const quoteResult = mapJupiterQuoteToSwapQuoteResult(estimateQuote);
|
|
50119
|
+
return { otherAmountThreshold: quoteResult.otherAmountThreshold, quoteResult };
|
|
50120
|
+
};
|
|
50121
|
+
default:
|
|
50122
|
+
return void 0;
|
|
50123
|
+
}
|
|
50124
|
+
}
|
|
50125
|
+
var getSwapIxsForFlashloan = async (params) => {
|
|
50126
|
+
const {
|
|
50127
|
+
inputMint,
|
|
50128
|
+
outputMint,
|
|
50129
|
+
amount,
|
|
50130
|
+
swapMode,
|
|
50131
|
+
authority,
|
|
50132
|
+
connection,
|
|
50133
|
+
destinationTokenAccount,
|
|
50134
|
+
swapOpts,
|
|
50135
|
+
sizeConstraint,
|
|
50136
|
+
maxSwapTotalAccounts
|
|
50137
|
+
} = params;
|
|
50138
|
+
if (swapOpts.swapIxs) {
|
|
50139
|
+
return {
|
|
50140
|
+
swapInstructions: swapOpts.swapIxs.instructions,
|
|
50141
|
+
setupInstructions: [],
|
|
50142
|
+
addressLookupTableAddresses: swapOpts.swapIxs.lookupTables,
|
|
50143
|
+
quoteResponse: {
|
|
50144
|
+
inAmount: String(amount),
|
|
50145
|
+
outAmount: "0",
|
|
50146
|
+
otherAmountThreshold: "0",
|
|
50147
|
+
slippageBps: 0
|
|
50148
|
+
}
|
|
50149
|
+
};
|
|
50150
|
+
}
|
|
50151
|
+
const provider = swapOpts.swapConfig?.provider ?? "JUPITER" /* JUPITER */;
|
|
50152
|
+
const attempts = [
|
|
50153
|
+
{ provider, apiConfig: swapOpts.swapConfig?.apiConfig },
|
|
50154
|
+
...swapOpts.swapConfig?.fallbackProviders ?? []
|
|
50155
|
+
];
|
|
50156
|
+
let lastError;
|
|
50157
|
+
for (const { provider: attemptProvider, apiConfig } of attempts) {
|
|
50158
|
+
const fn = getSwapProviderFn({
|
|
50159
|
+
attemptProvider,
|
|
50160
|
+
maxSwapTotalAccounts: params.maxSwapTotalAccounts,
|
|
50161
|
+
inputMint,
|
|
50162
|
+
outputMint,
|
|
50163
|
+
amount,
|
|
50164
|
+
swapMode,
|
|
50165
|
+
authority,
|
|
50166
|
+
connection,
|
|
50167
|
+
destinationTokenAccount,
|
|
50168
|
+
swapOpts,
|
|
50169
|
+
sizeConstraint
|
|
50170
|
+
});
|
|
50171
|
+
if (!fn) continue;
|
|
50172
|
+
try {
|
|
50173
|
+
return await fn(apiConfig);
|
|
50174
|
+
} catch (err) {
|
|
50175
|
+
if (err instanceof TransactionBuildingError) throw err;
|
|
50176
|
+
lastError = err;
|
|
50177
|
+
console.warn(`[swap] ${attemptProvider} failed:`, err instanceof Error ? err.message : err);
|
|
50178
|
+
}
|
|
50179
|
+
}
|
|
50180
|
+
const firstProvider = attempts[0]?.provider ?? "Swap";
|
|
50181
|
+
throw TransactionBuildingError.swapQuoteFailed(
|
|
50182
|
+
firstProvider,
|
|
50183
|
+
inputMint,
|
|
50184
|
+
outputMint,
|
|
50185
|
+
lastError?.message ?? "No swap route available"
|
|
50186
|
+
);
|
|
50187
|
+
};
|
|
50188
|
+
var getExactOutEstimate = async (params) => {
|
|
50189
|
+
const { inputMint, outputMint, amount, swapOpts, connection } = params;
|
|
50190
|
+
const provider = swapOpts.swapConfig?.provider ?? "JUPITER" /* JUPITER */;
|
|
50191
|
+
const attempts = [
|
|
50192
|
+
{ provider, apiConfig: swapOpts.swapConfig?.apiConfig },
|
|
50193
|
+
...swapOpts.swapConfig?.fallbackProviders ?? []
|
|
50194
|
+
];
|
|
50195
|
+
let lastError;
|
|
50196
|
+
for (const { provider: attemptProvider, apiConfig } of attempts) {
|
|
50197
|
+
const fn = getExactOutProviderFn({
|
|
50198
|
+
attemptProvider,
|
|
50199
|
+
inputMint,
|
|
50200
|
+
outputMint,
|
|
50201
|
+
amount,
|
|
50202
|
+
swapOpts,
|
|
50203
|
+
apiConfig
|
|
50204
|
+
});
|
|
50205
|
+
if (!fn) continue;
|
|
50206
|
+
try {
|
|
50207
|
+
return await fn(apiConfig);
|
|
50208
|
+
} catch (err) {
|
|
50209
|
+
if (err instanceof TransactionBuildingError) throw err;
|
|
50210
|
+
lastError = err;
|
|
50211
|
+
console.warn(
|
|
50212
|
+
`[exactout] ${attemptProvider} failed:`,
|
|
50213
|
+
err instanceof Error ? err.message : err
|
|
50214
|
+
);
|
|
50215
|
+
}
|
|
50216
|
+
}
|
|
50217
|
+
const firstProvider = attempts[0]?.provider ?? "Swap";
|
|
50218
|
+
throw TransactionBuildingError.swapQuoteFailed(
|
|
50219
|
+
firstProvider,
|
|
50220
|
+
inputMint,
|
|
50221
|
+
outputMint,
|
|
50222
|
+
lastError?.message ?? "No swap route available"
|
|
50223
|
+
);
|
|
50224
|
+
};
|
|
50225
|
+
function mapJupiterQuoteToSwapQuoteResult(quote) {
|
|
50226
|
+
return {
|
|
50227
|
+
inAmount: quote.inAmount,
|
|
50228
|
+
outAmount: quote.outAmount,
|
|
50229
|
+
otherAmountThreshold: quote.otherAmountThreshold,
|
|
50230
|
+
slippageBps: quote.slippageBps,
|
|
50231
|
+
platformFee: quote.platformFee ? {
|
|
50232
|
+
amount: quote.platformFee.amount ?? "0",
|
|
50233
|
+
feeBps: quote.platformFee.feeBps ?? 0
|
|
50234
|
+
} : void 0,
|
|
50235
|
+
priceImpactPct: quote.priceImpactPct,
|
|
50236
|
+
contextSlot: quote.contextSlot,
|
|
50237
|
+
timeTaken: quote.timeTaken,
|
|
50238
|
+
provider: "JUPITER" /* JUPITER */
|
|
50239
|
+
};
|
|
50240
|
+
}
|
|
50241
|
+
|
|
50242
|
+
// src/services/account/utils/jupiter.utils.ts
|
|
48862
50243
|
var REFERRAL_PROGRAM_ID = new PublicKey("REFER4ZgmyYx9c6He5XfaTMiGfdLwRnkV4RPp9t9iF3");
|
|
48863
50244
|
var REFERRAL_ACCOUNT_PUBKEY = new PublicKey("Mm7HcujSK2JzPW4eX7g4oqTXbWYDuFxapNMHXe8yp1B");
|
|
48864
50245
|
var getFeeAccount = (mint) => {
|
|
48865
|
-
const referralProgramPubkey = REFERRAL_PROGRAM_ID;
|
|
48866
|
-
const referralAccountPubkey = REFERRAL_ACCOUNT_PUBKEY;
|
|
48867
50246
|
const [feeAccount] = PublicKey.findProgramAddressSync(
|
|
48868
|
-
[Buffer.from("referral_ata"),
|
|
48869
|
-
|
|
50247
|
+
[Buffer.from("referral_ata"), REFERRAL_ACCOUNT_PUBKEY.toBuffer(), mint.toBuffer()],
|
|
50248
|
+
REFERRAL_PROGRAM_ID
|
|
48870
50249
|
);
|
|
48871
50250
|
return feeAccount.toBase58();
|
|
48872
50251
|
};
|
|
50252
|
+
var checkFeeAccount = async (connection, mint) => {
|
|
50253
|
+
const feeAccount = getFeeAccount(mint);
|
|
50254
|
+
const hasFeeAccount = !!await connection.getAccountInfo(new PublicKey(feeAccount));
|
|
50255
|
+
return { feeAccount, hasFeeAccount };
|
|
50256
|
+
};
|
|
48873
50257
|
function deserializeJupiterInstruction(instruction) {
|
|
48874
50258
|
return new TransactionInstruction({
|
|
48875
50259
|
programId: new PublicKey(instruction.programId),
|
|
@@ -48881,17 +50265,26 @@ function deserializeJupiterInstruction(instruction) {
|
|
|
48881
50265
|
data: Buffer.from(instruction.data, "base64")
|
|
48882
50266
|
});
|
|
48883
50267
|
}
|
|
50268
|
+
function toJupiterConfig(apiConfig) {
|
|
50269
|
+
if (!apiConfig) return void 0;
|
|
50270
|
+
return {
|
|
50271
|
+
basePath: apiConfig.basePath,
|
|
50272
|
+
apiKey: apiConfig.apiKey ? () => apiConfig.apiKey : void 0,
|
|
50273
|
+
headers: apiConfig.headers
|
|
50274
|
+
};
|
|
50275
|
+
}
|
|
48884
50276
|
var getJupiterSwapIxsForFlashloan = async ({
|
|
48885
50277
|
quoteParams,
|
|
48886
50278
|
authority,
|
|
48887
50279
|
connection,
|
|
48888
50280
|
destinationTokenAccount,
|
|
48889
|
-
|
|
50281
|
+
apiConfig,
|
|
50282
|
+
maxSwapAccounts
|
|
48890
50283
|
}) => {
|
|
50284
|
+
const configParams = toJupiterConfig(apiConfig);
|
|
48891
50285
|
const jupiterApiClient = configParams?.basePath ? new SwapApi(new Configuration(configParams)) : createJupiterApiClient(configParams);
|
|
48892
50286
|
const feeMint = quoteParams.swapMode === "ExactIn" ? quoteParams.outputMint : quoteParams.inputMint;
|
|
48893
|
-
const feeAccount =
|
|
48894
|
-
const hasFeeAccount = !!await connection.getAccountInfo(new PublicKey(feeAccount));
|
|
50287
|
+
const { feeAccount, hasFeeAccount } = await checkFeeAccount(connection, new PublicKey(feeMint));
|
|
48895
50288
|
const project0JupiterLut = (await connection.getAddressLookupTable(ADDRESS_LOOKUP_TABLE_FOR_SWAP))?.value;
|
|
48896
50289
|
let finalQuoteParams = quoteParams;
|
|
48897
50290
|
if (!hasFeeAccount) {
|
|
@@ -48901,67 +50294,44 @@ var getJupiterSwapIxsForFlashloan = async ({
|
|
|
48901
50294
|
platformFeeBps: void 0
|
|
48902
50295
|
};
|
|
48903
50296
|
}
|
|
48904
|
-
const
|
|
48905
|
-
const
|
|
48906
|
-
|
|
48907
|
-
|
|
48908
|
-
|
|
48909
|
-
|
|
48910
|
-
|
|
48911
|
-
|
|
48912
|
-
|
|
48913
|
-
|
|
48914
|
-
|
|
48915
|
-
|
|
48916
|
-
|
|
48917
|
-
|
|
48918
|
-
|
|
48919
|
-
userPublicKey: authority.toBase58(),
|
|
48920
|
-
feeAccount: hasFeeAccount ? feeAccount : void 0,
|
|
48921
|
-
wrapAndUnwrapSol: false,
|
|
48922
|
-
destinationTokenAccount: destinationTokenAccount.toBase58()
|
|
48923
|
-
}
|
|
48924
|
-
})
|
|
48925
|
-
)
|
|
48926
|
-
);
|
|
48927
|
-
const lutAddresses = swapInstructionResponses.map(
|
|
48928
|
-
(swapInstructionResponse) => swapInstructionResponse.addressLookupTableAddresses
|
|
48929
|
-
);
|
|
50297
|
+
const maxAccounts = maxSwapAccounts ?? 40;
|
|
50298
|
+
const swapQuote = await jupiterApiClient.quoteGet({
|
|
50299
|
+
...finalQuoteParams,
|
|
50300
|
+
maxAccounts
|
|
50301
|
+
});
|
|
50302
|
+
const swapInstructionResponse = await jupiterApiClient.swapInstructionsPost({
|
|
50303
|
+
swapRequest: {
|
|
50304
|
+
quoteResponse: swapQuote,
|
|
50305
|
+
userPublicKey: authority.toBase58(),
|
|
50306
|
+
feeAccount: hasFeeAccount ? feeAccount : void 0,
|
|
50307
|
+
wrapAndUnwrapSol: false,
|
|
50308
|
+
destinationTokenAccount: destinationTokenAccount.toBase58()
|
|
50309
|
+
}
|
|
50310
|
+
});
|
|
50311
|
+
const lutAddresses = swapInstructionResponse.addressLookupTableAddresses;
|
|
48930
50312
|
const lutAccountsRaw = await connection.getMultipleAccountsInfo(
|
|
48931
|
-
lutAddresses.
|
|
50313
|
+
lutAddresses.map((address) => new PublicKey(address))
|
|
48932
50314
|
);
|
|
48933
|
-
|
|
48934
|
-
|
|
48935
|
-
|
|
48936
|
-
|
|
48937
|
-
|
|
48938
|
-
|
|
48939
|
-
|
|
48940
|
-
|
|
48941
|
-
const addressesStartIndex = currentIndex;
|
|
48942
|
-
const addressesEndIndex = addressesStartIndex + addressesLength;
|
|
48943
|
-
currentIndex = addressesEndIndex;
|
|
48944
|
-
const lutAccounts = lutAccountsRaw.slice(addressesStartIndex, addressesEndIndex);
|
|
48945
|
-
const addressLookupTableAccounts = lutAccounts.map((accountInfo, index) => {
|
|
48946
|
-
const addressLookupTableAddress = address[index];
|
|
48947
|
-
if (!accountInfo || !addressLookupTableAddress) {
|
|
48948
|
-
return null;
|
|
48949
|
-
}
|
|
48950
|
-
return new AddressLookupTableAccount({
|
|
48951
|
-
key: new PublicKey(addressLookupTableAddress),
|
|
48952
|
-
state: AddressLookupTableAccount.deserialize(accountInfo.data)
|
|
48953
|
-
});
|
|
48954
|
-
}).filter((account) => account !== null).concat(project0JupiterLut ? [project0JupiterLut] : []);
|
|
48955
|
-
const instruction = deserializeJupiterInstruction(response.swapInstruction);
|
|
48956
|
-
const setupInstructions = response.setupInstructions.map(deserializeJupiterInstruction);
|
|
48957
|
-
jupiterSwapIxs.push({
|
|
48958
|
-
swapInstruction: instruction,
|
|
48959
|
-
setupInstructions,
|
|
48960
|
-
addressLookupTableAddresses: addressLookupTableAccounts,
|
|
48961
|
-
quoteResponse: quote
|
|
50315
|
+
const addressLookupTableAccounts = lutAccountsRaw.map((accountInfo, index) => {
|
|
50316
|
+
const addressLookupTableAddress = lutAddresses[index];
|
|
50317
|
+
if (!accountInfo || !addressLookupTableAddress) {
|
|
50318
|
+
return null;
|
|
50319
|
+
}
|
|
50320
|
+
return new AddressLookupTableAccount({
|
|
50321
|
+
key: new PublicKey(addressLookupTableAddress),
|
|
50322
|
+
state: AddressLookupTableAccount.deserialize(accountInfo.data)
|
|
48962
50323
|
});
|
|
48963
|
-
}
|
|
48964
|
-
|
|
50324
|
+
}).filter((account) => account !== null).concat(project0JupiterLut ? [project0JupiterLut] : []);
|
|
50325
|
+
const instruction = deserializeJupiterInstruction(swapInstructionResponse.swapInstruction);
|
|
50326
|
+
const setupInstructions = swapInstructionResponse.setupInstructions.map(
|
|
50327
|
+
deserializeJupiterInstruction
|
|
50328
|
+
);
|
|
50329
|
+
return {
|
|
50330
|
+
swapInstructions: [instruction],
|
|
50331
|
+
setupInstructions,
|
|
50332
|
+
addressLookupTableAddresses: addressLookupTableAccounts,
|
|
50333
|
+
quoteResponse: mapJupiterQuoteToSwapQuoteResult(swapQuote)
|
|
50334
|
+
};
|
|
48965
50335
|
};
|
|
48966
50336
|
|
|
48967
50337
|
// src/services/account/utils/misc.utils.ts
|
|
@@ -50182,7 +51552,7 @@ function computeMaxLeverage(depositBank, borrowBank, opts) {
|
|
|
50182
51552
|
ltv
|
|
50183
51553
|
};
|
|
50184
51554
|
}
|
|
50185
|
-
function computeLoopingParams(principal, targetLeverage, depositBank, borrowBank,
|
|
51555
|
+
function computeLoopingParams(principal, targetLeverage, depositBank, borrowBank, depositPriceUsd, borrowPriceUsd, opts) {
|
|
50186
51556
|
const initialCollateral = toBigNumber(principal);
|
|
50187
51557
|
const { maxLeverage } = computeMaxLeverage(depositBank, borrowBank, opts);
|
|
50188
51558
|
let clampedLeverage = targetLeverage;
|
|
@@ -50197,7 +51567,7 @@ function computeLoopingParams(principal, targetLeverage, depositBank, borrowBank
|
|
|
50197
51567
|
}
|
|
50198
51568
|
const totalDepositAmount = initialCollateral.times(new BigNumber3(clampedLeverage));
|
|
50199
51569
|
const additionalDepositAmount = totalDepositAmount.minus(initialCollateral);
|
|
50200
|
-
const totalBorrowAmount = additionalDepositAmount.times(
|
|
51570
|
+
const totalBorrowAmount = additionalDepositAmount.times(new BigNumber3(depositPriceUsd)).div(new BigNumber3(borrowPriceUsd));
|
|
50201
51571
|
return {
|
|
50202
51572
|
totalBorrowAmount: totalBorrowAmount.decimalPlaces(
|
|
50203
51573
|
borrowBank.mintDecimals,
|
|
@@ -52664,7 +54034,7 @@ var MarginfiAccount = class _MarginfiAccount {
|
|
|
52664
54034
|
* @param params.oraclePrices - Map of current oracle prices
|
|
52665
54035
|
* @param params.depositOpts - Deposit configuration (bank, amount, mode)
|
|
52666
54036
|
* @param params.borrowOpts - Borrow configuration (bank, amount)
|
|
52667
|
-
* @param params.swapOpts -
|
|
54037
|
+
* @param params.swapOpts - Swap configuration (venue, slippage, fees)
|
|
52668
54038
|
* @param params.addressLookupTableAccounts - Address lookup tables
|
|
52669
54039
|
* @param params.overrideInferAccounts - Optional account overrides
|
|
52670
54040
|
* @param params.additionalIxs - Additional instructions to include
|
|
@@ -52702,7 +54072,7 @@ var MarginfiAccount = class _MarginfiAccount {
|
|
|
52702
54072
|
* @param params.oraclePrices - Map of current oracle prices
|
|
52703
54073
|
* @param params.withdrawOpts - Withdraw configuration (bank, amount)
|
|
52704
54074
|
* @param params.repayOpts - Repay configuration (bank, optional amount)
|
|
52705
|
-
* @param params.swapOpts -
|
|
54075
|
+
* @param params.swapOpts - Swap configuration (venue, slippage, fees)
|
|
52706
54076
|
* @param params.addressLookupTableAccounts - Address lookup tables
|
|
52707
54077
|
* @param params.overrideInferAccounts - Optional account overrides
|
|
52708
54078
|
* @param params.additionalIxs - Additional instructions to include
|
|
@@ -52742,7 +54112,7 @@ var MarginfiAccount = class _MarginfiAccount {
|
|
|
52742
54112
|
* @param params.oraclePrices - Map of current oracle prices
|
|
52743
54113
|
* @param params.withdrawOpts - Withdraw configuration (bank, amount, tokenProgram)
|
|
52744
54114
|
* @param params.depositOpts - Deposit configuration (bank, tokenProgram)
|
|
52745
|
-
* @param params.swapOpts -
|
|
54115
|
+
* @param params.swapOpts - Swap configuration (venue, slippage, fees)
|
|
52746
54116
|
* @param params.addressLookupTableAccounts - Address lookup tables
|
|
52747
54117
|
* @param params.overrideInferAccounts - Optional account overrides
|
|
52748
54118
|
* @param params.additionalIxs - Additional instructions to include
|
|
@@ -52782,7 +54152,7 @@ var MarginfiAccount = class _MarginfiAccount {
|
|
|
52782
54152
|
* @param params.oraclePrices - Map of current oracle prices
|
|
52783
54153
|
* @param params.repayOpts - Repay configuration (bank, amount, tokenProgram)
|
|
52784
54154
|
* @param params.borrowOpts - Borrow configuration (bank, tokenProgram)
|
|
52785
|
-
* @param params.swapOpts -
|
|
54155
|
+
* @param params.swapOpts - Swap configuration (venue, slippage, fees)
|
|
52786
54156
|
* @param params.addressLookupTableAccounts - Address lookup tables
|
|
52787
54157
|
* @param params.overrideInferAccounts - Optional account overrides
|
|
52788
54158
|
* @param params.additionalIxs - Additional instructions to include
|
|
@@ -54097,6 +55467,6 @@ var EmodeSettings = class _EmodeSettings {
|
|
|
54097
55467
|
}
|
|
54098
55468
|
};
|
|
54099
55469
|
|
|
54100
|
-
export { ADDRESS_LOOKUP_TABLE_FOR_GROUP, ADDRESS_LOOKUP_TABLE_FOR_SWAP, AccountFlags, AccountType, AssetTag, BUNDLE_TX_SIZE, Balance, Bank, BankConfig, BankConfigFlag, BankVaultType, DEFAULT_ORACLE_MAX_AGE, DISABLED_FLAG, EMPTY_HEALTH_CACHE, EmodeEntryFlags, EmodeFlags, EmodeImpactStatus, EmodeSettings, EmodeTag, FLASHLOAN_ENABLED_FLAG, HOURS_PER_YEAR, HealthCache, HealthCacheFlags, HealthCacheSimulationError, HealthCacheStatus, JUPITER_V6_PROGRAM, JUP_SWAP_LUT_PROGRAM_AUTHORITY_INDEX, LST_MINT, MARGINFI_IDL, MARGINFI_PROGRAM, MARGINFI_PROGRAM_STAGING, MARGINFI_PROGRAM_STAGING_ALT, MARGINFI_SPONSORED_SHARD_ID, MAX_CONFIDENCE_INTERVAL_RATIO, MAX_TX_SIZE, MAX_U64, MPL_METADATA_PROGRAM_ID, MarginRequirementType, MarginfiAccount, MarginfiAccountWrapper, MarginfiGroup, OperationalState, OracleSetup, PDA_BANK_EMISSIONS_AUTH_SEED, PDA_BANK_EMISSIONS_VAULT_SEED, PDA_BANK_FEE_STATE_SEED, PDA_BANK_FEE_VAULT_AUTH_SEED, PDA_BANK_FEE_VAULT_SEED, PDA_BANK_INSURANCE_VAULT_AUTH_SEED, PDA_BANK_INSURANCE_VAULT_SEED, PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED, PDA_BANK_LIQUIDITY_VAULT_SEED, PDA_MARGINFI_ACCOUNT_SEED, PRIORITY_TX_SIZE, PYTH_PRICE_CONF_INTERVALS, PYTH_PUSH_ORACLE_ID, PYTH_SPONSORED_SHARD_ID, PriceBias, Project0Client, RiskTier, SINGLE_POOL_PROGRAM_ID, STAKE_CONFIG_ID, STAKE_PROGRAM_ID, SWB_PRICE_CONF_INTERVALS, SYSTEM_PROGRAM_ID, SYSVAR_CLOCK_ID, SYSVAR_RENT_ID, SYSVAR_STAKE_HISTORY_ID, TRANSFER_ACCOUNT_AUTHORITY_FLAG, TransactionArenaKeyMap, TransactionBuildingError, TransactionBuildingErrorCode, TransactionConfigMap, TransactionType, USDC_DECIMALS, USDC_MINT, WSOL_MINT, ZERO_ORACLE_KEY, accountFlagToBN, addOracleToBanksIx, addTransactionMetadata, adjustPriceComponent, aprToApy, apyToApr, balanceToDto, bankConfigRawToDto, bankConfigToBankConfigRaw, bankMetadataMapToDto, bankMetadataToDto, bankRawToDto, bigNumberToWrappedI80F48, bpsToPercentile, calculateApyFromInterest, calculateInterestFromApy, capConfidenceInterval, categorizePythBanks, checkBatchOracleCrankability, checkMultipleOraclesCrankability, chunkedGetRawMultipleAccountInfoOrdered, chunkedGetRawMultipleAccountInfoOrderedWithNulls, chunkedGetRawMultipleAccountInfos, composeRemainingAccounts, computeAccountValue, computeActiveEmodePairs, computeAssetHealthComponent, computeAssetUsdValue, computeBalanceUsdValue, computeBaseInterestRate, computeClaimedEmissions, computeClosePositionTokenAmount, computeEmodeImpacts, computeFreeCollateralFromBalances, computeFreeCollateralFromCache, computeHealthAccountMetas, computeHealthCacheStatus, computeHealthCheckAccounts, computeHealthComponentsFromBalances, computeHealthComponentsFromCache, computeHealthComponentsWithoutBiasFromBalances, computeInterestRates, computeLiabilityHealthComponent, computeLiabilityUsdValue, computeLiquidationPriceForBank, computeLoopingParams, computeLowestEmodeWeights, computeMaxBorrowForBank, computeMaxLeverage, computeMaxWithdrawForBank, computeNetApy, computeProjectedActiveBalancesNoCpi, computeProjectedActiveBanksNoCpi, computeQuantity, computeQuantityUi, computeRemainingCapacity, computeSmartCrank, computeTotalOutstandingEmissions, computeTvl, computeUsdValue, computeUtilizationRate, convertVoteAccCoeffsToBankCoeffs, createActiveEmodePairFromPairs, createEmptyBalance, decodeAccountRaw, decodeBankRaw, decodeInstruction, decompileV0Transaction, deriveBankEmissionsAuth, deriveBankEmissionsVault, deriveBankFeeVault, deriveBankFeeVaultAuthority, deriveBankInsuranceVault, deriveBankInsuranceVaultAuthority, deriveBankLiquidityVault, deriveBankLiquidityVaultAuthority, deriveFeeState, deriveMarginfiAccount, dtoToBalance, dtoToBank, dtoToBankConfig, dtoToBankConfigRaw, dtoToBankMetadata, dtoToBankMetadataMap, dtoToBankRaw, dtoToEmodeSettings, dtoToEmodeSettingsRaw, dtoToGroup, dtoToHealthCache, dtoToInterestRateConfig, dtoToMarginfiAccount, dtoToOraclePrice, dtoToValidatorStakeGroup, emodeSettingsRawToDto, extractPythOracleKeys, fetchBank, fetchBankIntegrationMetadata, fetchMarginfiAccountAddresses, fetchMarginfiAccountData, fetchMultipleBanks, fetchNativeStakeAccounts, fetchOracleData, fetchProgramForMints, fetchPythOracleData, fetchPythOraclePricesFromAPI, fetchPythOraclePricesFromChain, fetchStakeAccount, fetchStakePoolActiveStates, fetchStakePoolMev, fetchSwbOracleAccountsFromAPI, fetchSwbOracleAccountsFromChain, fetchSwbOracleData, fetchSwbOraclePricesFromAPI, fetchSwbOraclePricesFromCrossbar, findRandomAvailableAccountIndex, freezeBankConfigIx, getAccountKeys, getActiveAccountFlags, getActiveBalances, getActiveEmodeEntryFlags, getActiveEmodeFlags, getActiveHealthCacheFlags, getAssetQuantity, getAssetShares, getAssetWeight, getBalance, getBalanceUsdValueWithPriceBias, getBankVaultAuthority, getBankVaultSeeds, getBirdeyeFallbackPricesByFeedId, getBirdeyePricesForMints, getConfig, getDriftCTokenMultiplier, getDriftMetadata, getDriftStatesDto, getEmodePairs, getHealthCacheStatusDescription, getHealthSimulationTransactions, getJupLendFTokenMultiplier, getJupLendMetadata, getJupLendStatesDto, getJupiterSwapIxsForFlashloan, getKaminoCTokenMultiplier, getKaminoMetadata, getKaminoStatesDto, getLiabilityQuantity, getLiabilityShares, getLiabilityWeight, getOracleSourceFromBank, getOracleSourceFromOracleSetup, getOracleSourceNameFromKey, getPrice, getPriceWithConfidence, getStakedBankMetadataMap, getTotalAssetQuantity, getTotalLiabilityQuantity, getTxSize, getValidatorVoteAccountByBank, groupToDto, hasAccountFlag, hasEmodeEntryFlag, hasEmodeFlag, hasHealthCacheFlag, healthCacheToDto, isFlashloan, isV0Tx, isWeightedPrice, isWholePosition, makeAddPermissionlessStakedBankIx, makeBeginFlashLoanIx3 as makeBeginFlashLoanIx, makeBorrowIx3 as makeBorrowIx, makeBorrowTx, makeBundleTipIx, makeClearEmissionsIx, makeCloseMarginfiAccountIx, makeCloseMarginfiAccountTx, makeCrankSwbFeedIx, makeCreateAccountIxWithProjection, makeCreateAccountTxWithProjection, makeCreateMarginfiAccountIx, makeCreateMarginfiAccountTx, makeDepositIx3 as makeDepositIx, makeDepositTx, makeDriftDepositIx3 as makeDriftDepositIx, makeDriftDepositTx, makeDriftWithdrawIx3 as makeDriftWithdrawIx, makeDriftWithdrawTx, makeEndFlashLoanIx3 as makeEndFlashLoanIx, makeFlashLoanTx, makeJuplendDepositIx2 as makeJuplendDepositIx, makeJuplendDepositTx, makeJuplendWithdrawIx2 as makeJuplendWithdrawIx, makeJuplendWithdrawTx, makeKaminoDepositIx3 as makeKaminoDepositIx, makeKaminoDepositTx, makeKaminoWithdrawIx3 as makeKaminoWithdrawIx, makeKaminoWithdrawTx, makeLoopTx, makeMergeStakeAccountsTx, makeMintStakedLstIx, makeMintStakedLstTx, makePoolAddBankIx3 as makePoolAddBankIx, makePoolConfigureBankIx3 as makePoolConfigureBankIx, makePriorityFeeIx, makePriorityFeeMicroIx, makePulseHealthIx2 as makePulseHealthIx, makeRedeemStakedLstIx, makeRedeemStakedLstTx, makeRefreshKaminoBanksIxs, makeRepayIx3 as makeRepayIx, makeRepayTx, makeRepayWithCollatTx, makeSetupIx, makeSmartCrankSwbFeedIx, makeSwapCollateralTx, makeSwapDebtTx, makeTxPriorityIx, makeUnwrapSolIx, makeUpdateDriftMarketIxs, makeUpdateJupLendRateIxs, makeUpdateSwbFeedIx, makeVersionedTransaction, makeWithdrawIx3 as makeWithdrawIx, makeWithdrawTx, makeWrapSolIxs, mapBrokenFeedsToOraclePrices, mapPythBanksToOraclePrices, mapSwbBanksToOraclePrices, marginfiAccountToDto, nativeToUi, oraclePriceToDto, parseBalanceRaw, parseBankConfigRaw, parseBankRaw, parseEmodeSettingsRaw, parseEmodeTag, parseHealthCacheRaw, parseMarginfiAccountRaw, parseOperationalState, parseOracleSetup, parseOraclePriceData as parsePriceInfo, parseRiskTier, parseRpcPythPriceData, parseSwbOraclePriceData, partitionBanksByCrankability, resolveAmount, serializeBankConfigOpt, serializeInterestRateConfig, serializeOperationalState, serializeOracleSetup, serializeOracleSetupToIndex, serializeRiskTier, shortenAddress, simulateAccountHealthCache, simulateAccountHealthCacheWithFallback, simulateBundle, splitInstructionsToFitTransactions, toBankConfigDto, toBankDto, toBigNumber, toEmodeSettingsDto, toInterestRateConfigDto, toNumber, uiToNative, uiToNativeBigNumber, validatorStakeGroupToDto, wrappedI80F48toBigNumber };
|
|
55470
|
+
export { ADDRESS_LOOKUP_TABLE_FOR_GROUP, ADDRESS_LOOKUP_TABLE_FOR_SWAP, AccountFlags, AccountType, AssetTag, BUNDLE_TX_SIZE, Balance, Bank, BankConfig, BankConfigFlag, BankVaultType, DEFAULT_ORACLE_MAX_AGE, DISABLED_FLAG, EMPTY_HEALTH_CACHE, EmodeEntryFlags, EmodeFlags, EmodeImpactStatus, EmodeSettings, EmodeTag, FLASHLOAN_ENABLED_FLAG, HOURS_PER_YEAR, HealthCache, HealthCacheFlags, HealthCacheSimulationError, HealthCacheStatus, JUPITER_V6_PROGRAM, JUP_SWAP_LUT_PROGRAM_AUTHORITY_INDEX, LST_MINT, MARGINFI_IDL, MARGINFI_PROGRAM, MARGINFI_PROGRAM_STAGING, MARGINFI_PROGRAM_STAGING_ALT, MARGINFI_SPONSORED_SHARD_ID, MAX_ACCOUNT_LOCKS, MAX_CONFIDENCE_INTERVAL_RATIO, MAX_TX_SIZE, MAX_U64, MPL_METADATA_PROGRAM_ID, MarginRequirementType, MarginfiAccount, MarginfiAccountWrapper, MarginfiGroup, OperationalState, OracleSetup, PDA_BANK_EMISSIONS_AUTH_SEED, PDA_BANK_EMISSIONS_VAULT_SEED, PDA_BANK_FEE_STATE_SEED, PDA_BANK_FEE_VAULT_AUTH_SEED, PDA_BANK_FEE_VAULT_SEED, PDA_BANK_INSURANCE_VAULT_AUTH_SEED, PDA_BANK_INSURANCE_VAULT_SEED, PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED, PDA_BANK_LIQUIDITY_VAULT_SEED, PDA_MARGINFI_ACCOUNT_SEED, PRIORITY_TX_SIZE, PYTH_PRICE_CONF_INTERVALS, PYTH_PUSH_ORACLE_ID, PYTH_SPONSORED_SHARD_ID, PriceBias, Project0Client, RiskTier, SINGLE_POOL_PROGRAM_ID, STAKE_CONFIG_ID, STAKE_PROGRAM_ID, SWB_PRICE_CONF_INTERVALS, SYSTEM_PROGRAM_ID, SYSVAR_CLOCK_ID, SYSVAR_RENT_ID, SYSVAR_STAKE_HISTORY_ID, SwapProvider, TRANSFER_ACCOUNT_AUTHORITY_FLAG, TransactionArenaKeyMap, TransactionBuildingError, TransactionBuildingErrorCode, TransactionConfigMap, TransactionType, USDC_DECIMALS, USDC_MINT, WSOL_MINT, ZERO_ORACLE_KEY, accountFlagToBN, addOracleToBanksIx, addTransactionMetadata, adjustPriceComponent, aprToApy, apyToApr, balanceToDto, bankConfigRawToDto, bankConfigToBankConfigRaw, bankMetadataMapToDto, bankMetadataToDto, bankRawToDto, bigNumberToWrappedI80F48, bpsToPercentile, calculateApyFromInterest, calculateInterestFromApy, capConfidenceInterval, categorizePythBanks, checkBatchOracleCrankability, checkMultipleOraclesCrankability, chunkedGetRawMultipleAccountInfoOrdered, chunkedGetRawMultipleAccountInfoOrderedWithNulls, chunkedGetRawMultipleAccountInfos, compileFlashloanPrecheck, composeRemainingAccounts, computeAccountValue, computeActiveEmodePairs, computeAssetHealthComponent, computeAssetUsdValue, computeBalanceUsdValue, computeBaseInterestRate, computeClaimedEmissions, computeClosePositionTokenAmount, computeEmodeImpacts, computeFlashLoanNonSwapBudget, computeFlashloanSwapConstraints, computeFreeCollateralFromBalances, computeFreeCollateralFromCache, computeHealthAccountMetas, computeHealthCacheStatus, computeHealthCheckAccounts, computeHealthComponentsFromBalances, computeHealthComponentsFromCache, computeHealthComponentsWithoutBiasFromBalances, computeInterestRates, computeLiabilityHealthComponent, computeLiabilityUsdValue, computeLiquidationPriceForBank, computeLoopingParams, computeLowestEmodeWeights, computeMaxBorrowForBank, computeMaxLeverage, computeMaxWithdrawForBank, computeNetApy, computeProjectedActiveBalancesNoCpi, computeProjectedActiveBanksNoCpi, computeQuantity, computeQuantityUi, computeRemainingCapacity, computeSmartCrank, computeTotalOutstandingEmissions, computeTvl, computeUsdValue, computeUtilizationRate, computeV0TxSize, convertVoteAccCoeffsToBankCoeffs, createActiveEmodePairFromPairs, createEmptyBalance, decodeAccountRaw, decodeBankRaw, decodeInstruction, decompileV0Transaction, deriveBankEmissionsAuth, deriveBankEmissionsVault, deriveBankFeeVault, deriveBankFeeVaultAuthority, deriveBankInsuranceVault, deriveBankInsuranceVaultAuthority, deriveBankLiquidityVault, deriveBankLiquidityVaultAuthority, deriveFeeState, deriveMarginfiAccount, dtoToBalance, dtoToBank, dtoToBankConfig, dtoToBankConfigRaw, dtoToBankMetadata, dtoToBankMetadataMap, dtoToBankRaw, dtoToEmodeSettings, dtoToEmodeSettingsRaw, dtoToGroup, dtoToHealthCache, dtoToInterestRateConfig, dtoToMarginfiAccount, dtoToOraclePrice, dtoToValidatorStakeGroup, emodeSettingsRawToDto, extractPythOracleKeys, fetchBank, fetchBankIntegrationMetadata, fetchMarginfiAccountAddresses, fetchMarginfiAccountData, fetchMultipleBanks, fetchNativeStakeAccounts, fetchOracleData, fetchProgramForMints, fetchPythOracleData, fetchPythOraclePricesFromAPI, fetchPythOraclePricesFromChain, fetchStakeAccount, fetchStakePoolActiveStates, fetchStakePoolMev, fetchSwbOracleAccountsFromAPI, fetchSwbOracleAccountsFromChain, fetchSwbOracleData, fetchSwbOraclePricesFromAPI, fetchSwbOraclePricesFromCrossbar, findRandomAvailableAccountIndex, freezeBankConfigIx, getAccountKeys, getActiveAccountFlags, getActiveBalances, getActiveEmodeEntryFlags, getActiveEmodeFlags, getActiveHealthCacheFlags, getAssetQuantity, getAssetShares, getAssetWeight, getBalance, getBalanceUsdValueWithPriceBias, getBankVaultAuthority, getBankVaultSeeds, getBirdeyeFallbackPricesByFeedId, getBirdeyePricesForMints, getConfig, getDriftCTokenMultiplier, getDriftMetadata, getDriftStatesDto, getEmodePairs, getExactOutEstimate, getHealthCacheStatusDescription, getHealthSimulationTransactions, getJupLendFTokenMultiplier, getJupLendMetadata, getJupLendStatesDto, getJupiterSwapIxsForFlashloan, getKaminoCTokenMultiplier, getKaminoMetadata, getKaminoStatesDto, getLiabilityQuantity, getLiabilityShares, getLiabilityWeight, getOracleSourceFromBank, getOracleSourceFromOracleSetup, getOracleSourceNameFromKey, getPrice, getPriceWithConfidence, getStakedBankMetadataMap, getSwapIxsForFlashloan, getTitanExactOutEstimate, getTitanSwapIxsForFlashloan, getTotalAccountKeys, getTotalAssetQuantity, getTotalLiabilityQuantity, getTxSize, getValidatorVoteAccountByBank, getWritableAccountKeys, groupToDto, hasAccountFlag, hasEmodeEntryFlag, hasEmodeFlag, hasHealthCacheFlag, healthCacheToDto, isFlashloan, isV0Tx, isWeightedPrice, isWholePosition, makeAddPermissionlessStakedBankIx, makeBeginFlashLoanIx3 as makeBeginFlashLoanIx, makeBorrowIx3 as makeBorrowIx, makeBorrowTx, makeBundleTipIx, makeClearEmissionsIx, makeCloseMarginfiAccountIx, makeCloseMarginfiAccountTx, makeCrankSwbFeedIx, makeCreateAccountIxWithProjection, makeCreateAccountTxWithProjection, makeCreateMarginfiAccountIx, makeCreateMarginfiAccountTx, makeDepositIx3 as makeDepositIx, makeDepositTx, makeDriftDepositIx3 as makeDriftDepositIx, makeDriftDepositTx, makeDriftWithdrawIx3 as makeDriftWithdrawIx, makeDriftWithdrawTx, makeEndFlashLoanIx3 as makeEndFlashLoanIx, makeFlashLoanTx, makeJuplendDepositIx2 as makeJuplendDepositIx, makeJuplendDepositTx, makeJuplendWithdrawIx2 as makeJuplendWithdrawIx, makeJuplendWithdrawTx, makeKaminoDepositIx3 as makeKaminoDepositIx, makeKaminoDepositTx, makeKaminoWithdrawIx3 as makeKaminoWithdrawIx, makeKaminoWithdrawTx, makeLoopTx, makeMergeStakeAccountsTx, makeMintStakedLstIx, makeMintStakedLstTx, makePoolAddBankIx3 as makePoolAddBankIx, makePoolConfigureBankIx3 as makePoolConfigureBankIx, makePriorityFeeIx, makePriorityFeeMicroIx, makePulseHealthIx2 as makePulseHealthIx, makeRedeemStakedLstIx, makeRedeemStakedLstTx, makeRefreshKaminoBanksIxs, makeRepayIx3 as makeRepayIx, makeRepayTx, makeRepayWithCollatTx, makeSetupIx, makeSmartCrankSwbFeedIx, makeSwapCollateralTx, makeSwapDebtTx, makeTxPriorityIx, makeUnwrapSolIx, makeUpdateDriftMarketIxs, makeUpdateJupLendRateIxs, makeUpdateSwbFeedIx, makeVersionedTransaction, makeWithdrawIx3 as makeWithdrawIx, makeWithdrawTx, makeWrapSolIxs, mapBrokenFeedsToOraclePrices, mapJupiterQuoteToSwapQuoteResult, mapPythBanksToOraclePrices, mapSwbBanksToOraclePrices, marginfiAccountToDto, nativeToUi, oraclePriceToDto, parseBalanceRaw, parseBankConfigRaw, parseBankRaw, parseEmodeSettingsRaw, parseEmodeTag, parseHealthCacheRaw, parseMarginfiAccountRaw, parseOperationalState, parseOracleSetup, parseOraclePriceData as parsePriceInfo, parseRiskTier, parseRpcPythPriceData, parseSwbOraclePriceData, partitionBanksByCrankability, resolveAmount, serializeBankConfigOpt, serializeInterestRateConfig, serializeOperationalState, serializeOracleSetup, serializeOracleSetupToIndex, serializeRiskTier, shortenAddress, simulateAccountHealthCache, simulateAccountHealthCacheWithFallback, simulateBundle, splitInstructionsToFitTransactions, toBankConfigDto, toBankDto, toBigNumber, toEmodeSettingsDto, toInterestRateConfigDto, toJupiterConfig, toNumber, uiToNative, uiToNativeBigNumber, validatorStakeGroupToDto, wrappedI80F48toBigNumber };
|
|
54101
55471
|
//# sourceMappingURL=index.js.map
|
|
54102
55472
|
//# sourceMappingURL=index.js.map
|