goosefx-ssl-sdk-prism
Version:
SDK for interacting with GooseFX Single-sided Liquidity pools
291 lines • 14.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Swap = exports.deserializeAccount = void 0;
const layouts_1 = require("../layouts");
const web3_js_1 = require("@solana/web3.js");
const buffer_1 = require("buffer");
const constants_1 = require("../constants");
const utils_1 = require("./utils");
const gfx_ssl_wasm_data_1 = __importDefault(require("../wasm/gfx_ssl_wasm_data"));
const gfx_ssl_wasm_1 = __importStar(require("../wasm/gfx_ssl_wasm")), wasm = gfx_ssl_wasm_1;
const ssl_1 = require("./ssl");
const borsh_1 = require("@project-serum/borsh");
let wasmInited = false;
function deserializeAccount(account) {
const TOKEN_ACCOUNT_LAYOUT = (0, borsh_1.struct)([
(0, borsh_1.publicKey)("mint"),
(0, borsh_1.publicKey)("authority"),
(0, borsh_1.u64)("amount"),
(0, borsh_1.publicKey)("delegate"),
(0, borsh_1.u8)("state"),
(0, borsh_1.u64)("isNative"),
(0, borsh_1.u64)("delegatedAmount"),
(0, borsh_1.publicKey)("closeAuthority"),
]);
return TOKEN_ACCOUNT_LAYOUT.decode(account);
}
exports.deserializeAccount = deserializeAccount;
class Swap {
constructor(connection, controller = constants_1.ADDRESSES["MAINNET"].GFX_CONTROLLER, programId = constants_1.ADDRESSES["MAINNET"].SSL_PROGRAM_ID) {
this.connection = connection;
this.controller = controller;
this.programId = programId;
this.getPairAddress = (tokenA, tokenB) => {
const addresses = [tokenA.toBuffer(), tokenB.toBuffer()].sort(buffer_1.Buffer.compare);
const pairArr = web3_js_1.PublicKey.findProgramAddressSync([
buffer_1.Buffer.from("GFX-SSL-Pair", "utf-8"),
this.controller.toBuffer(),
addresses[0],
addresses[1],
], this.programId);
return pairArr[0];
};
this.getQuoterSync = (tokenIn, tokenOut) => {
let wasm = this.getWasm();
return new Quoter(this.connection, this.programId, this.controller, tokenIn, tokenOut, wasm);
};
this.getQuoter = (tokenIn, tokenOut) => __awaiter(this, void 0, void 0, function* () {
let wasm = yield this.getWasm();
return new Quoter(this.connection, this.programId, this.controller, tokenIn, tokenOut, wasm);
});
this.getQuote = (tokenIn, tokenOut, inTokenAmount) => __awaiter(this, void 0, void 0, function* () {
const quoter = yield this.getQuoter(tokenIn, tokenOut);
yield quoter.prepare();
return quoter.quote(inTokenAmount);
});
this.getMinimumQuote = (tokenA, tokenB, inTokenAmount, slippage) => __awaiter(this, void 0, void 0, function* () {
const result = yield this.getQuote(tokenA, tokenB, inTokenAmount);
const minAmountOut = (result.out * (10000n - BigInt(slippage * 10000))) / 10000n;
return minAmountOut;
});
}
getWasm() {
return __awaiter(this, void 0, void 0, function* () {
if (!wasmInited) {
yield (0, gfx_ssl_wasm_1.default)(buffer_1.Buffer.from(gfx_ssl_wasm_data_1.default, "base64"));
wasmInited = true;
}
return wasm;
});
}
getWasmSync() {
return wasm;
}
}
exports.Swap = Swap;
class Quoter {
constructor(connection, programId, controller, tokenIn, tokenOut, wasm) {
this.connection = connection;
this.programId = programId;
this.controller = controller;
this.tokenIn = tokenIn;
this.tokenOut = tokenOut;
this.wasm = wasm;
this.prepared = undefined;
this.getPairAddress = (tokenA, tokenB) => {
const addresses = [tokenA.toBuffer(), tokenB.toBuffer()].sort(buffer_1.Buffer.compare);
const pairArr = web3_js_1.PublicKey.findProgramAddressSync([
buffer_1.Buffer.from("GFX-SSL-Pair", "utf-8"),
this.controller.toBuffer(),
addresses[0],
addresses[1],
], this.programId);
return pairArr[0];
};
}
getAccountsForUpdate(pairData) {
let accounts = [];
const pair = this.getPairAddress(this.tokenIn, this.tokenOut);
accounts.push(pair);
const sslIn = ssl_1.SSL.findAddress(this.controller, this.tokenIn, this.programId);
accounts.push(sslIn);
const sslOut = ssl_1.SSL.findAddress(this.controller, this.tokenOut, this.programId);
accounts.push(sslOut);
accounts.push((0, utils_1.findAssociatedTokenAddress)(sslIn, this.tokenIn));
accounts.push((0, utils_1.findAssociatedTokenAddress)(sslIn, this.tokenOut));
accounts.push((0, utils_1.findAssociatedTokenAddress)(sslOut, this.tokenOut));
accounts.push((0, utils_1.findAssociatedTokenAddress)(sslOut, this.tokenIn));
const decoded = layouts_1.PAIR_LAYOUT.decode(pairData.data);
let oracles = decoded.oracles;
let nOracle = decoded.nOracle;
const n = Number(nOracle.toString());
for (const oracle of oracles.slice(0, n)) {
const n = Number(oracle.n);
for (const elem of oracle.elements.slice(0, n)) {
accounts.push(elem.address);
}
}
return accounts;
}
prepareSync(parsedAccounts) {
var _a, _b, _c, _d;
const pairData = parsedAccounts[0];
const sslInData = parsedAccounts[1];
const sslOutData = parsedAccounts[2];
const liabilityVaultIn = parsedAccounts[3];
const swappedLiabilityVaultIn = parsedAccounts[4];
const liabilityVaultOut = parsedAccounts[5];
const swappedLiabilityVaultOut = parsedAccounts[6];
const OracleRegistry = wasm.OracleRegistry;
const decoded = layouts_1.PAIR_LAYOUT.decode(pairData.data);
let oracles = decoded.oracles;
let nOracle = decoded.nOracle;
const n = Number(nOracle.toString());
const registry = new OracleRegistry();
let count = 7;
for (const oracle of oracles.slice(0, n)) {
const n = Number(oracle.n);
for (const elem of oracle.elements.slice(0, n)) {
const acctInfo = parsedAccounts[count];
count++;
if (acctInfo === null || acctInfo === void 0 ? void 0 : acctInfo.data) {
registry.add_oracle(elem.address.toBuffer(), acctInfo.data);
}
}
}
this.prepared = {
pairData: pairData.data,
sslInData: sslInData.data,
sslOutData: sslOutData.data,
liabilityIn: BigInt((_a = deserializeAccount(liabilityVaultIn.data)) === null || _a === void 0 ? void 0 : _a.amount.toString()),
swappedLiabilityIn: BigInt((_b = deserializeAccount(swappedLiabilityVaultIn.data)) === null || _b === void 0 ? void 0 : _b.amount.toString()),
liabilityOut: BigInt((_c = deserializeAccount(liabilityVaultOut.data)) === null || _c === void 0 ? void 0 : _c.amount.toString()),
swappedLiabilityOut: BigInt((_d = deserializeAccount(swappedLiabilityVaultOut.data)) === null || _d === void 0 ? void 0 : _d.amount.toString()),
registry: registry,
suspended: (new ssl_1.SSL(sslInData)).isSuspended() || (new ssl_1.SSL(sslOutData)).isSuspended(),
};
}
prepare() {
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function* () {
const pair = this.getPairAddress(this.tokenIn, this.tokenOut);
const pairData = yield this.connection.getAccountInfo(pair);
if (!pairData)
throw "Cannot get Pair";
const sslIn = ssl_1.SSL.findAddress(this.controller, this.tokenIn, this.programId);
const sslInData = yield this.connection.getAccountInfo(sslIn);
if (!sslInData)
throw "Cannot get SSL for tokenIn";
const sslOut = ssl_1.SSL.findAddress(this.controller, this.tokenOut, this.programId);
const sslOutData = yield this.connection.getAccountInfo(sslOut);
if (!sslOutData)
throw "Cannot get SSL for tokenOut";
const liabilityVaultIn = yield this.connection.getAccountInfo((0, utils_1.findAssociatedTokenAddress)(sslIn, this.tokenIn));
const swappedLiabilityVaultIn = yield this.connection.getAccountInfo((0, utils_1.findAssociatedTokenAddress)(sslIn, this.tokenOut));
const liabilityVaultOut = yield this.connection.getAccountInfo((0, utils_1.findAssociatedTokenAddress)(sslOut, this.tokenOut));
const swappedLiabilityVaultOut = yield this.connection.getAccountInfo((0, utils_1.findAssociatedTokenAddress)(sslOut, this.tokenIn));
const OracleRegistry = wasm.OracleRegistry;
const decoded = layouts_1.PAIR_LAYOUT.decode(pairData.data);
let oracles = decoded.oracles;
let nOracle = decoded.nOracle;
const n = Number(nOracle.toString());
const registry = new OracleRegistry();
for (const oracle of oracles.slice(0, n)) {
const n = Number(oracle.n);
for (const elem of oracle.elements.slice(0, n)) {
const acctInfo = yield this.connection.getAccountInfo(elem.address);
if (acctInfo === null || acctInfo === void 0 ? void 0 : acctInfo.data) {
registry.add_oracle(elem.address.toBuffer(), acctInfo.data);
}
}
}
this.prepared = {
pairData: pairData.data,
sslInData: sslInData.data,
sslOutData: sslOutData.data,
liabilityIn: BigInt((_a = deserializeAccount(liabilityVaultIn.data)) === null || _a === void 0 ? void 0 : _a.amount.toString()),
swappedLiabilityIn: BigInt((_b = deserializeAccount(swappedLiabilityVaultIn.data)) === null || _b === void 0 ? void 0 : _b.amount.toString()),
liabilityOut: BigInt((_c = deserializeAccount(liabilityVaultOut.data)) === null || _c === void 0 ? void 0 : _c.amount.toString()),
swappedLiabilityOut: BigInt((_d = deserializeAccount(swappedLiabilityVaultOut.data)) === null || _d === void 0 ? void 0 : _d.amount.toString()),
registry: registry,
suspended: (new ssl_1.SSL(sslInData)).isSuspended() || (new ssl_1.SSL(sslOutData)).isSuspended(),
};
});
}
isSuspended() {
if (this.prepared === undefined)
throw "Run prepare first";
return this.prepared.suspended;
}
quote(inTokenAmount, silent = true) {
const swapWASM = wasm.swap;
if (inTokenAmount === BigInt(0))
return {
amountIn: BigInt(0),
fee: BigInt(0),
amountOut: BigInt(0),
impact: 0,
swapPrice: 0,
instantPrice: 0,
oraclePrice: 0,
};
if (this.prepared === undefined)
throw "Run prepare first";
const prepared = this.prepared;
let out;
try {
out = swapWASM(prepared.sslInData.slice(), prepared.sslOutData.slice(), prepared.pairData.slice(), prepared.liabilityIn, prepared.liabilityOut, prepared.swappedLiabilityIn, prepared.swappedLiabilityOut, prepared.registry, inTokenAmount);
}
catch (e) {
if (silent) {
return {
amountIn: inTokenAmount,
fee: BigInt(0),
amountOut: BigInt(0),
impact: 1,
swapPrice: 0,
instantPrice: 0,
oraclePrice: 0,
};
}
else {
throw e;
}
}
return {
amountIn: out.amount_in,
fee: out.fee_paid,
amountOut: out.amount_out,
impact: out.price_impact,
swapPrice: out.swap_price,
instantPrice: out.insta_price,
oraclePrice: out.oracle_price,
};
}
}
//# sourceMappingURL=swap.js.map