@pontem/liquidswap-sdk
Advanced tools
Comparing version 0.0.1 to 0.1.0
import { SDK, SdkOptions } from "./sdk"; | ||
import { SwapModule, CalculateRatesParams, CreateTXPayloadParams } from "./modules/SwapModule"; | ||
import { ResourcesModule } from "./modules/ResourcesModule"; | ||
export { SDK, SwapModule, ResourcesModule, SdkOptions, CalculateRatesParams, CreateTXPayloadParams }; | ||
import { getCoinsInWithFeesStable, getCoinsOutWithFeesStable, getCoinOutWithFees, getCoinInWithFees } from './utils'; | ||
export { SDK, SwapModule, ResourcesModule, SdkOptions, CalculateRatesParams, CreateTXPayloadParams, getCoinInWithFees, getCoinOutWithFees, getCoinsOutWithFeesStable, getCoinsInWithFeesStable }; | ||
export default SDK; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ResourcesModule = exports.SwapModule = exports.SDK = void 0; | ||
exports.getCoinsInWithFeesStable = exports.getCoinsOutWithFeesStable = exports.getCoinOutWithFees = exports.getCoinInWithFees = exports.ResourcesModule = exports.SwapModule = exports.SDK = void 0; | ||
const sdk_1 = require("./sdk"); | ||
@@ -10,3 +10,8 @@ Object.defineProperty(exports, "SDK", { enumerable: true, get: function () { return sdk_1.SDK; } }); | ||
Object.defineProperty(exports, "ResourcesModule", { enumerable: true, get: function () { return ResourcesModule_1.ResourcesModule; } }); | ||
const utils_1 = require("./utils"); | ||
Object.defineProperty(exports, "getCoinsInWithFeesStable", { enumerable: true, get: function () { return utils_1.getCoinsInWithFeesStable; } }); | ||
Object.defineProperty(exports, "getCoinsOutWithFeesStable", { enumerable: true, get: function () { return utils_1.getCoinsOutWithFeesStable; } }); | ||
Object.defineProperty(exports, "getCoinOutWithFees", { enumerable: true, get: function () { return utils_1.getCoinOutWithFees; } }); | ||
Object.defineProperty(exports, "getCoinInWithFees", { enumerable: true, get: function () { return utils_1.getCoinInWithFees; } }); | ||
exports.default = sdk_1.SDK; | ||
//# sourceMappingURL=main.js.map |
import { SDK } from "../sdk"; | ||
import { IModule } from "../interfaces/IModule"; | ||
import { AptosResource, AptosResourceType } from "../types/aptos"; | ||
import { BigNumber } from "../types"; | ||
export declare type CalculateRatesParams = { | ||
fromToken: AptosResourceType; | ||
toToken: AptosResourceType; | ||
fromAmount: BigNumber; | ||
toAmount: BigNumber; | ||
}; | ||
export declare class ResourcesModule implements IModule { | ||
@@ -12,0 +5,0 @@ protected _sdk: SDK; |
@@ -0,16 +1,11 @@ | ||
import Decimal from 'decimal.js'; | ||
import { SDK } from "../sdk"; | ||
import { IModule } from "../interfaces/IModule"; | ||
import { AptosResourceType, TxPayloadCallFunction } from "../types/aptos"; | ||
import { BigNumber } from "../types"; | ||
import Decimal from "decimal.js"; | ||
import { AptosPoolResource, AptosResourceType, TAptosTxPayload, CurveType } from "../types/aptos"; | ||
export declare type CalculateRatesParams = { | ||
fromToken: AptosResourceType; | ||
toToken: AptosResourceType; | ||
amount: BigNumber; | ||
amount: Decimal; | ||
interactiveToken: 'from' | 'to'; | ||
pool: { | ||
lpToken: AptosResourceType; | ||
moduleAddress: string; | ||
address: string; | ||
}; | ||
curveType: CurveType; | ||
}; | ||
@@ -20,11 +15,8 @@ export declare type CreateTXPayloadParams = { | ||
toToken: AptosResourceType; | ||
fromAmount: BigNumber; | ||
toAmount: BigNumber; | ||
fromAmount: Decimal; | ||
toAmount: Decimal; | ||
interactiveToken: 'from' | 'to'; | ||
slippage: number; | ||
pool: { | ||
lpToken: AptosResourceType; | ||
moduleAddress: string; | ||
address: string; | ||
}; | ||
slippage: Decimal; | ||
stableSwapType: 'high' | 'normal'; | ||
curveType: CurveType; | ||
}; | ||
@@ -36,4 +28,7 @@ export declare class SwapModule implements IModule { | ||
calculateRates(params: CalculateRatesParams): Promise<string>; | ||
createSwapTransactionPayload(params: CreateTXPayloadParams): TxPayloadCallFunction; | ||
createSwapTransactionPayload(params: CreateTXPayloadParams): TAptosTxPayload; | ||
getLiquidityPoolResource(params: CalculateRatesParams): Promise<{ | ||
liquidityPoolType: string; | ||
liquidityPoolResource: import("../types/aptos").AptosResource<AptosPoolResource> | undefined; | ||
}>; | ||
} | ||
export declare function withSlippage(value: Decimal.Instance, slippage: Decimal.Instance, mode: 'plus' | 'minus'): Decimal; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.withSlippage = exports.SwapModule = void 0; | ||
exports.SwapModule = void 0; | ||
const tslib_1 = require("tslib"); | ||
const contracts_1 = require("../utils/contracts"); | ||
const numbers_1 = require("../utils/numbers"); | ||
const utils_1 = require("../utils"); | ||
const constants_1 = require("../constants"); | ||
class SwapModule { | ||
@@ -17,6 +17,6 @@ constructor(sdk) { | ||
const { modules } = this.sdk.networkOptions; | ||
const fromCoinInfo = yield this.sdk.Resources.fetchAccountResource((0, contracts_1.extractAddressFromType)(params.fromToken), (0, contracts_1.composeType)(modules.CoinInfo, [params.fromToken])); | ||
const toCoinInfo = yield this.sdk.Resources.fetchAccountResource((0, contracts_1.extractAddressFromType)(params.toToken), (0, contracts_1.composeType)(modules.CoinInfo, [params.toToken])); | ||
const fromCoinInfo = yield this.sdk.Resources.fetchAccountResource((0, utils_1.extractAddressFromType)(params.fromToken), (0, utils_1.composeType)(modules.CoinInfo, [params.fromToken])); | ||
const toCoinInfo = yield this.sdk.Resources.fetchAccountResource((0, utils_1.extractAddressFromType)(params.toToken), (0, utils_1.composeType)(modules.CoinInfo, [params.toToken])); | ||
if (!fromCoinInfo) { | ||
throw new Error('To Coin not exists'); | ||
throw new Error('From Coin not exists'); | ||
} | ||
@@ -26,50 +26,60 @@ if (!toCoinInfo) { | ||
} | ||
const isSorted = (0, contracts_1.isSortedSymbols)(fromCoinInfo.data.symbol, toCoinInfo.data.symbol); | ||
const [fromToken, toToken] = isSorted | ||
? [params.fromToken, params.toToken] | ||
: [params.toToken, params.fromToken]; | ||
const liquidityPoolType = (0, contracts_1.composeType)(params.pool.moduleAddress, 'liquidity_pool', 'LiquidityPool', [ | ||
fromToken, | ||
toToken, | ||
params.pool.lpToken, | ||
]); | ||
const liquidityPoolResource = yield this.sdk.Resources.fetchAccountResource(params.pool.address, liquidityPoolType); | ||
const { liquidityPoolType, liquidityPoolResource } = yield this.getLiquidityPoolResource(params); | ||
if (!liquidityPoolResource) { | ||
throw new Error(`LiquidityPool (${liquidityPoolType}) not found`); | ||
} | ||
const coinXReserve = liquidityPoolResource.data.coin_x_reserve.value; | ||
const coinYReserve = liquidityPoolResource.data.coin_y_reserve.value; | ||
const [reserveX, reserveY] = isSorted | ||
? params.interactiveToken === 'from' | ||
? [(0, numbers_1.d)(coinXReserve), (0, numbers_1.d)(coinYReserve)] | ||
: [(0, numbers_1.d)(coinYReserve), (0, numbers_1.d)(coinXReserve)] | ||
: params.interactiveToken === 'from' | ||
? [(0, numbers_1.d)(coinYReserve), (0, numbers_1.d)(coinXReserve)] | ||
: [(0, numbers_1.d)(coinXReserve), (0, numbers_1.d)(coinYReserve)]; | ||
const outputTokens = params.interactiveToken === 'from' | ||
? getCoinOutWithFees((0, numbers_1.d)(params.amount), reserveX, reserveY) | ||
: getCoinInWithFees((0, numbers_1.d)(params.amount), reserveX, reserveY); | ||
return outputTokens.toString(); | ||
const isSorted = (0, utils_1.is_sorted)(params.fromToken, params.toToken); | ||
const [sortedFromCoinInfo, sortedToCoinInfo] = isSorted | ||
? [fromCoinInfo, toCoinInfo] | ||
: [toCoinInfo, fromCoinInfo]; | ||
const coinXReserve = (0, utils_1.d)(liquidityPoolResource.data.coin_x_reserve.value); | ||
const coinYReserve = (0, utils_1.d)(liquidityPoolResource.data.coin_y_reserve.value); | ||
const fee = (0, utils_1.d)(liquidityPoolResource.data.fee); | ||
const coinFromDecimals = +sortedFromCoinInfo.data.decimals; | ||
const coinToDecimals = +sortedToCoinInfo.data.decimals; | ||
const [fromReserve, toReserve] = isSorted | ||
? [coinXReserve, coinYReserve] | ||
: [coinYReserve, coinXReserve]; | ||
let rate; | ||
if (!params.amount) { | ||
throw new Error(`Amount equals zero or undefined`); | ||
} | ||
if (params.curveType === 'stable') { | ||
rate = params.interactiveToken === 'from' | ||
? (0, utils_1.getCoinOutWithFees)(params.amount, fromReserve, toReserve, fee) | ||
: (0, utils_1.getCoinInWithFees)(params.amount, toReserve, fromReserve, fee); | ||
return rate.toString(); | ||
} | ||
else { | ||
rate = params.interactiveToken === 'from' | ||
? (0, utils_1.getCoinsOutWithFeesStable)(params.amount, toReserve, fromReserve, (0, utils_1.d)(Math.pow(10, coinToDecimals)), (0, utils_1.d)(Math.pow(10, coinFromDecimals)), fee) | ||
: (0, utils_1.getCoinsInWithFeesStable)(params.amount, fromReserve, toReserve, (0, utils_1.d)(Math.pow(10, coinFromDecimals)), (0, utils_1.d)(Math.pow(10, coinToDecimals)), fee); | ||
return rate; | ||
} | ||
}); | ||
} | ||
createSwapTransactionPayload(params) { | ||
if (params.slippage >= 1 || params.slippage <= 0) { | ||
if (params.slippage.gte(1) || params.slippage.lte(0)) { | ||
throw new Error(`Invalid slippage (${params.slippage}) value`); | ||
} | ||
const { modules } = this.sdk.networkOptions; | ||
const functionName = (0, contracts_1.composeType)(modules.Scripts, params.interactiveToken === 'from' ? 'swap' : 'swap_into'); | ||
const isUnchecked = params.curveType === 'stable' && params.stableSwapType === 'normal'; | ||
const functionName = (0, utils_1.composeType)(modules.Scripts, isUnchecked | ||
? 'swap_unchecked' | ||
: params.interactiveToken === 'from' ? 'swap' : 'swap_into'); | ||
const curve = params.curveType === 'stable' ? constants_1.CURVE_STABLE : constants_1.CURVE_UNCORRELATED; | ||
const typeArguments = [ | ||
params.fromToken, | ||
params.toToken, | ||
params.pool.lpToken, | ||
curve | ||
]; | ||
const fromAmount = params.interactiveToken === 'from' | ||
? params.fromAmount | ||
: withSlippage((0, numbers_1.d)(params.fromAmount), (0, numbers_1.d)(params.slippage), 'minus'); | ||
: (0, utils_1.withSlippage)(params.slippage, params.fromAmount).toFixed(0); | ||
const toAmount = params.interactiveToken === 'to' | ||
? params.toAmount | ||
: withSlippage((0, numbers_1.d)(params.toAmount), (0, numbers_1.d)(params.slippage), 'plus'); | ||
const args = [params.pool.address, (0, numbers_1.d)(fromAmount).toString(), (0, numbers_1.d)(toAmount).toString()]; | ||
: (0, utils_1.withSlippage)(params.slippage, params.toAmount).toFixed(0); | ||
const args = [fromAmount.toString(), toAmount.toString()]; | ||
return { | ||
type: 'script_function_payload', | ||
type: 'entry_function_payload', | ||
function: functionName, | ||
@@ -80,21 +90,25 @@ typeArguments: typeArguments, | ||
} | ||
getLiquidityPoolResource(params) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function* () { | ||
const modulesLiquidityPool = (0, utils_1.composeType)(constants_1.MODULES_ACCOUNT, 'liquidity_pool', 'LiquidityPool'); | ||
function getPoolStr(coinX, coinY, curve) { | ||
const [sortedX, sortedY] = (0, utils_1.is_sorted)(coinX, coinY) | ||
? [coinX, coinY] | ||
: [coinY, coinX]; | ||
return (0, utils_1.composeType)(modulesLiquidityPool, [sortedX, sortedY, curve]); | ||
} | ||
const curve = params.curveType === 'stable' ? constants_1.CURVE_STABLE : constants_1.CURVE_UNCORRELATED; | ||
const liquidityPoolType = getPoolStr(params.fromToken, params.toToken, curve); | ||
let liquidityPoolResource; | ||
try { | ||
liquidityPoolResource = yield this.sdk.Resources.fetchAccountResource(constants_1.RESOURCES_ACCOUNT, liquidityPoolType); | ||
} | ||
catch (e) { | ||
console.log(e); | ||
} | ||
return { liquidityPoolType, liquidityPoolResource }; | ||
}); | ||
} | ||
} | ||
exports.SwapModule = SwapModule; | ||
function getCoinOutWithFees(coinInVal, reserveInSize, reserveOutSize) { | ||
const { feePct, feeScale } = { feePct: (0, numbers_1.d)(3), feeScale: (0, numbers_1.d)(1000) }; | ||
const feeMultiplier = feeScale.sub(feePct); | ||
const coinInAfterFees = coinInVal.mul(feeMultiplier); | ||
const newReservesInSize = reserveInSize.mul(feeScale).plus(coinInAfterFees); | ||
return coinInAfterFees.mul(reserveOutSize).div(newReservesInSize).toDP(0); | ||
} | ||
function getCoinInWithFees(coinOutVal, reserveOutSize, reserveInSize) { | ||
const { feePct, feeScale } = { feePct: (0, numbers_1.d)(3), feeScale: (0, numbers_1.d)(1000) }; | ||
const feeMultiplier = feeScale.sub(feePct); | ||
const newReservesOutSize = reserveOutSize.sub(coinOutVal).mul(feeMultiplier); | ||
return coinOutVal.mul(feeScale).mul(reserveInSize).div(newReservesOutSize).plus(1).toDP(0); | ||
} | ||
function withSlippage(value, slippage, mode) { | ||
return (0, numbers_1.d)(value)[mode]((0, numbers_1.d)(value).mul(slippage)).toDP(0); | ||
} | ||
exports.withSlippage = withSlippage; | ||
//# sourceMappingURL=SwapModule.js.map |
@@ -30,5 +30,6 @@ export declare type AptosResourceType = string; | ||
}; | ||
fee: number; | ||
}; | ||
export declare type TxPayloadCallFunction = { | ||
type: 'script_function_payload'; | ||
type: 'entry_function_payload'; | ||
function: string; | ||
@@ -38,3 +39,3 @@ typeArguments: string[]; | ||
}; | ||
export declare type TxPayloadInstallModule = { | ||
declare type TxPayloadInstallModule = { | ||
type: 'module_bundle_payload'; | ||
@@ -45,3 +46,3 @@ modules: { | ||
}; | ||
export declare type AptosTxPayload = TxPayloadCallFunction | TxPayloadInstallModule; | ||
export declare type TAptosTxPayload = TxPayloadCallFunction | TxPayloadInstallModule; | ||
export declare type AptosCreateTx = { | ||
@@ -53,3 +54,5 @@ sender: string; | ||
expiration: string; | ||
payload: AptosTxPayload; | ||
payload: TAptosTxPayload; | ||
}; | ||
export declare type CurveType = 'uncorrelated' | 'stable'; | ||
export {}; |
@@ -1,6 +0,20 @@ | ||
import { AptosResourceType } from "../types/aptos"; | ||
export declare function isSortedSymbols(symbolX: string, symbolY: string): boolean; | ||
export declare function composeType(address: string, generics: AptosResourceType[]): AptosResourceType; | ||
export declare function composeType(address: string, struct: string, generics?: AptosResourceType[]): AptosResourceType; | ||
export declare function composeType(address: string, module: string, struct: string, generics?: AptosResourceType[]): AptosResourceType; | ||
import Decimal from 'decimal.js'; | ||
/** | ||
* Compare sorting between two coin types | ||
* | ||
* @param coin_x string with full address of coin | ||
* @param coin_y string with full address of coin | ||
* @returns boolean | ||
*/ | ||
export declare function is_sorted(coin_x: string, coin_y: string): boolean; | ||
export declare function composeType(address: string, generics: string[]): string; | ||
export declare function composeType(address: string, struct: string, generics?: string[]): string; | ||
export declare function composeType(address: string, module: string, struct: string, generics?: string[]): string; | ||
/** | ||
* Calculate value with slippage. | ||
* @param {Decimal} slippage - slippage refers to the difference between the expected price of a trade | ||
* and the price at which the trade is executed. | ||
* @param {Decimal} value - value to calculate slippage | ||
*/ | ||
export declare function withSlippage(slippage: Decimal, value: Decimal): number; | ||
export declare function extractAddressFromType(type: string): string; | ||
@@ -7,0 +21,0 @@ export declare function checkAptosType(type: any, options?: { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.checkAptosType = exports.extractAddressFromType = exports.composeType = exports.isSortedSymbols = void 0; | ||
exports.checkAptosType = exports.extractAddressFromType = exports.withSlippage = exports.composeType = exports.is_sorted = void 0; | ||
const tslib_1 = require("tslib"); | ||
const buffer_1 = require("buffer"); | ||
const decimal_js_1 = tslib_1.__importDefault(require("decimal.js")); | ||
const hex_1 = require("./hex"); | ||
@@ -20,19 +23,68 @@ const EQUAL = 0; | ||
function compare(symbolX, symbolY) { | ||
let iX = symbolX.length; | ||
let iY = symbolY.length; | ||
const lenCmp = cmp(iX, iY); | ||
while (iX > 0 && iY > 0) { | ||
iX -= 1; | ||
iY -= 1; | ||
const elemCmp = cmp(symbolX.charCodeAt(iX), symbolY.charCodeAt(iY)); | ||
if (elemCmp !== 0) { | ||
return elemCmp; | ||
const lenCmp = cmp(symbolX.length, symbolY.length); | ||
if (lenCmp != EQUAL) { | ||
return lenCmp; | ||
} | ||
let i = 0; | ||
while (i < symbolX.length && i < symbolY.length) { | ||
const elem_cmp = cmp(symbolX.charCodeAt(i), symbolY.charCodeAt(i)); | ||
if (elem_cmp != EQUAL) | ||
return elem_cmp; | ||
i++; | ||
} | ||
return EQUAL; | ||
} | ||
function cmp_addresses(a, b) { | ||
if (a.startsWith('0x')) { | ||
a = a.substring(2); | ||
} | ||
if (a.length != 64) { | ||
while (a.length < 64) { | ||
a = '0' + a; | ||
} | ||
} | ||
return lenCmp; | ||
if (b.startsWith('0x')) { | ||
b = b.substring(2); | ||
} | ||
if (b.length != 64) { | ||
while (b.length < 64) { | ||
b = '0' + b; | ||
} | ||
} | ||
const a_buf = buffer_1.Buffer.from(a, 'hex'); | ||
const b_buf = buffer_1.Buffer.from(b, 'hex'); | ||
for (let i = 0; i < 32; i++) { | ||
if (a_buf[i] < b_buf[i]) { | ||
return LESS_THAN; | ||
} | ||
else if (a_buf[i] > b_buf[i]) { | ||
return GREATER_THAN; | ||
} | ||
} | ||
return EQUAL; | ||
} | ||
function isSortedSymbols(symbolX, symbolY) { | ||
return compare(symbolX, symbolY) === LESS_THAN; | ||
function compare_types(coin_x, coin_y) { | ||
const coin_x_parts = coin_x.split('::').reverse(); | ||
const coin_y_parts = coin_y.split('::').reverse(); | ||
const coin_x_address = coin_x_parts.pop(); | ||
const coin_y_address = coin_y_parts.pop(); | ||
for (let i = 0; i < 2; i++) { | ||
const c = compare(coin_x_parts[i], coin_y_parts[i]); | ||
if (c != EQUAL) { | ||
return c; | ||
} | ||
} | ||
return cmp_addresses(coin_x_address, coin_y_address); | ||
} | ||
exports.isSortedSymbols = isSortedSymbols; | ||
/** | ||
* Compare sorting between two coin types | ||
* | ||
* @param coin_x string with full address of coin | ||
* @param coin_y string with full address of coin | ||
* @returns boolean | ||
*/ | ||
function is_sorted(coin_x, coin_y) { | ||
return compare_types(coin_x, coin_y) == LESS_THAN; | ||
} | ||
exports.is_sorted = is_sorted; | ||
function composeType(address, ...args) { | ||
@@ -50,2 +102,14 @@ const generics = Array.isArray(args[args.length - 1]) | ||
exports.composeType = composeType; | ||
/** | ||
* Calculate value with slippage. | ||
* @param {Decimal} slippage - slippage refers to the difference between the expected price of a trade | ||
* and the price at which the trade is executed. | ||
* @param {Decimal} value - value to calculate slippage | ||
*/ | ||
function withSlippage(slippage, value) { | ||
const multiply = new decimal_js_1.default(10000); | ||
const slippagePercent = slippage.mul(multiply); | ||
return value.minus(value.mul(slippagePercent).div(multiply)).toNumber(); | ||
} | ||
exports.withSlippage = withSlippage; | ||
function extractAddressFromType(type) { | ||
@@ -52,0 +116,0 @@ return type.split('::')[0]; |
@@ -9,6 +9,9 @@ /// <reference types="node" /> | ||
/** | ||
* Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method. | ||
* Attempts to turn a value into a `Buffer`. | ||
* As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method. | ||
* @param v the value | ||
*/ | ||
export declare function toBuffer(v: any): Buffer; | ||
export declare function bufferToHex(buffer: Buffer): string; | ||
export declare function checkAptosType(type: any, options?: { | ||
leadingZero: boolean; | ||
}): boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.bufferToHex = exports.toBuffer = exports.checkAddress = exports.shortAddress = exports.shortString = exports.addHexPrefix = void 0; | ||
exports.checkAptosType = exports.toBuffer = exports.checkAddress = exports.shortAddress = exports.shortString = exports.addHexPrefix = void 0; | ||
const HEX_REGEXP = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/; | ||
@@ -36,3 +36,4 @@ function addHexPrefix(hex) { | ||
/** | ||
* Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method. | ||
* Attempts to turn a value into a `Buffer`. | ||
* As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method. | ||
* @param v the value | ||
@@ -70,6 +71,40 @@ */ | ||
exports.toBuffer = toBuffer; | ||
function bufferToHex(buffer) { | ||
return addHexPrefix(toBuffer(buffer).toString('hex')); | ||
function checkAptosType(type, options = { leadingZero: true }) { | ||
var _a, _b, _c, _d, _e; | ||
if (typeof type !== 'string') { | ||
return false; | ||
} | ||
let _type = type.replace(/\s/g, ''); | ||
const openBracketsCount = (_b = (_a = _type.match(/</g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; | ||
const closeBracketsCount = (_d = (_c = _type.match(/>/g)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0; | ||
if (openBracketsCount !== closeBracketsCount) { | ||
return false; | ||
} | ||
const genericsString = _type.match(/(<.+>)$/); | ||
const generics = (_e = genericsString === null || genericsString === void 0 ? void 0 : genericsString[1]) === null || _e === void 0 ? void 0 : _e.match(/(\w+::\w+::\w+)(?:<.*?>(?!>))?/g); | ||
if (generics) { | ||
_type = _type.slice(0, _type.indexOf('<')); | ||
const validGenerics = generics.every((g) => { | ||
var _a, _b, _c, _d; | ||
const gOpenCount = (_b = (_a = g.match(/</g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; | ||
const gCloseCount = (_d = (_c = g.match(/>/g)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0; | ||
let t = g; | ||
if (gOpenCount !== gCloseCount) { | ||
t = t.slice(0, -(gCloseCount - gOpenCount)); | ||
} | ||
return checkAptosType(t, options); | ||
}); | ||
if (!validGenerics) { | ||
return false; | ||
} | ||
} | ||
const parts = _type.split('::'); | ||
if (parts.length !== 3) { | ||
return false; | ||
} | ||
return (checkAddress(parts[0], options) && | ||
parts[1].length >= 1 && | ||
parts[2].length >= 1); | ||
} | ||
exports.bufferToHex = bufferToHex; | ||
exports.checkAptosType = checkAptosType; | ||
//# sourceMappingURL=hex.js.map |
{ | ||
"name": "@pontem/liquidswap-sdk", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"description": "SDK for use any functions of LiquidSwap", | ||
"author": "Igor Demko <igor@pontem.network>", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/pontem-network/liquidswap-sdk.git" | ||
}, | ||
"repository": "https://github.com/pontem-network/liquidswap-sdk", | ||
"license": "MIT", | ||
@@ -27,2 +24,3 @@ "keywords": [ | ||
"devDependencies": { | ||
"@types/axios": "^0.14.0", | ||
"@types/jest": "^27.4.1", | ||
@@ -41,14 +39,6 @@ "@types/node": "^17.0.26", | ||
"dependencies": { | ||
"aptos": "^1.2.0", | ||
"aptos": "^1.3.17", | ||
"axios": "^0.27.2", | ||
"decimal.js": "^10.3.1" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/pontem-network/liquidswap-sdk/issues" | ||
}, | ||
"homepage": "https://github.com/pontem-network/liquidswap-sdk#readme", | ||
"directories": { | ||
"doc": "docs", | ||
"example": "examples" | ||
"decimal.js": "^10.4.1" | ||
} | ||
} |
105
README.md
@@ -5,16 +5,24 @@ # LiquidSwap SDK | ||
# Installation | ||
npm i @pontem/liquidswap-sdk | ||
# Usage | ||
### Init SDK | ||
```typescript | ||
import { SDK } from '@pontem/liquidswap-sdk'; | ||
import Decimal from 'decimal.js'; | ||
const sdk = new SDK({ | ||
nodeUrl: 'https://fullnode.devnet.aptoslabs.com', // Node URL | ||
nodeUrl: 'https://fullnode.testnet.aptoslabs.com/v1', // Node URL | ||
networkOptions: { | ||
nativeToken: '0x1::test_coin::TestCoin', // Type of Native network token | ||
nativeToken: '0x1::aptos_coin::AptosCoin'', // Type of Native network token | ||
modules: { | ||
Scripts: | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::scripts', // This module is used for Swap | ||
'0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12::scripts_v2', // This module is used for Swap | ||
CoinInfo: '0x1::coin::CoinInfo', // Type of base CoinInfo module | ||
CoinStore: '0x1::coin::CoinStore', // Type of base CoinStore module | ||
LiquidityPool: '0x05a97986a9d031c4567e15b797be516910cfcb4156312482efc6a19c0a30c948::liquidity_pool' // Liquidity pool module | ||
}, | ||
@@ -25,3 +33,4 @@ } | ||
### You want swap EXACTLY 1 APTOS to SLIPPAGED BTC amount | ||
### You want swap EXACTLY 1 APTOS to SLIPPAGED USDT amount | ||
```typescript | ||
@@ -31,13 +40,9 @@ (async () => { | ||
const amount = await sdk.Swap.calculateRates({ | ||
fromToken: '0x1::test_coin::TestCoin', | ||
toToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
amount: 1000000, // 1 APTOS | ||
fromToken: '0x1::aptos_coin::AptosCoin', // APTOS | ||
toToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::USDT', // USDT | ||
amount: new Decimal(1000000), // 1 APTOS (6 decimals) | ||
interactiveToken: 'from', | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>' | ||
} | ||
curveType: 'stable', | ||
}) | ||
console.log(amount) // 1584723 (0.01584723 BTC) | ||
console.log(amount) // '1651.7512324524539471' (0.0016517512324524539471 USDT) | ||
@@ -47,13 +52,10 @@ // Generate TX payload for swap 1 APTOS to maximum 0.01584723 BTC | ||
const txPayload = sdk.Swap.createSwapTransactionPayload({ | ||
fromToken: '0x1::test_coin::TestCoin', | ||
fromToken: '0x1::aptos_coin::AptosCoin', | ||
toToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
fromAmount: 1000000, // 1 APTOS, | ||
toAmount: 1584723, // 0.01584723 BTC, | ||
fromAmount: new Decimal(1000000), // 1 APTOS, | ||
toAmount: new Decimal(1584723), // 0.01584723 BTC, | ||
interactiveToken: 'from', | ||
slippage: 0.05, // 5% (1 - 100%, 0 - 0%) | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>' | ||
} | ||
slippage: new Decimal(0.05), // 5% (1 - 100%, 0 - 0%) | ||
stableSwapType: 'high', | ||
curveType: 'stable', | ||
}) | ||
@@ -64,14 +66,10 @@ console.log(txPayload); | ||
{ | ||
type: 'script_function_payload', | ||
function: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::scripts::swap', | ||
type: 'entry_function_payload', | ||
function: '0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12::scripts_v2::swap', | ||
typeArguments: [ | ||
'0x1::test_coin::TestCoin', | ||
'0x1::aptos_coin::AptosCoin', | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>' | ||
'0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12::curves::Stable' | ||
], | ||
arguments: [ | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
'1000000', | ||
'1505487' | ||
] | ||
arguments: [ '1000000', '1505487' ] | ||
} | ||
@@ -87,28 +85,21 @@ */ | ||
const amount = await sdk.Swap.calculateRates({ | ||
fromToken: '0x1::test_coin::TestCoin', | ||
fromToken: '0x1::aptos_coin::AptosCoin', | ||
toToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
amount: 100000, // 0.001 BTC | ||
interactiveToken: 'to', // from - calculate TO amount, to - calculate FROM amount | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>' | ||
} | ||
amount: new Decimal(100000), // 0.001 BTC | ||
interactiveToken: 'to', // 'from' - calculate TO amount, 'to' - calculate FROM amount | ||
curveType: 'stable', | ||
}) | ||
console.log(amount) // 116831 (0.116831 APTOS) | ||
console.log(amount) // '2741440067.7675726625' (2741.4400677675726625 APTOS) | ||
// Generate TX payload for get EXACTLY 0.001 BTC | ||
// and minimum send 0.116831 + 5% (with slippage 5%) | ||
// and minimum send 2741.440068 + 5% (with slippage 5%) | ||
const txPayload = sdk.Swap.createSwapTransactionPayload({ | ||
fromToken: '0x1::test_coin::TestCoin', | ||
fromToken: '0x1::aptos_coin::AptosCoin', | ||
toToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
fromAmount: 116831, // 0.116831 APTOS, | ||
toAmount: 100000, // 0.001 BTC, | ||
fromAmount: new Decimal(2741440068), // 2741.440068 APTOS, | ||
toAmount: new Decimal(100000), // 0.001 BTC, | ||
interactiveToken: 'to', | ||
slippage: 0.05, // 5% (1 - 100%, 0 - 0%) | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>' | ||
} | ||
slippage: new Decimal(0.05), // 5% (1 - 100%, 0 - 0%) | ||
stableSwapType: 'high', | ||
curveType: 'stable', | ||
}) | ||
@@ -119,14 +110,10 @@ console.log(txPayload); | ||
{ | ||
type: 'script_function_payload', | ||
function: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::scripts::swap_into', | ||
type: 'entry_function_payload', | ||
function: '0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12::scripts_v2::swap_into', | ||
typeArguments: [ | ||
'0x1::test_coin::TestCoin', | ||
'0x1::aptos_coin::AptosCoin', | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>' | ||
'0x190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12::curves::Stable' | ||
], | ||
arguments: [ | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
'110989', | ||
'100000' | ||
] | ||
arguments: [ '2604368065', '100000' ] | ||
} | ||
@@ -133,0 +120,0 @@ */ |
@@ -1,2 +0,2 @@ | ||
import {SDK} from "../sdk"; | ||
import { SDK } from "../sdk"; | ||
@@ -3,0 +3,0 @@ export interface IModule { |
import SDK from './main' | ||
import {d, decimalsMultiplier} from "./utils/numbers"; | ||
import { d, decimalsMultiplier } from "./utils"; | ||
import { NETWORKS_MODULES } from "./constants"; | ||
const TokensMapping: any = { | ||
APTOS: '0x1::test_coin::TestCoin', | ||
const TokensMapping: Record<string, string> = { | ||
APTOS: '0x1::aptos_coin::AptosCoin', | ||
USDT: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::USDT', | ||
BTC: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC', | ||
APTOSBTCLP: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::lp::LP<0x1::test_coin::TestCoin, 0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::coins::BTC>', | ||
} | ||
}; | ||
const CoinInfo: any = { | ||
const CoinInfo: Record<string, { decimals: number }> = { | ||
APTOS: { decimals: 6 }, | ||
BTC: { decimals: 8 }, | ||
APTOSBTCLP: { decimals: 6 }, | ||
USDT: { decimals: 6 }, | ||
BTC: { decimals: 8 } | ||
} | ||
@@ -30,14 +31,11 @@ | ||
const sdk = new SDK({ | ||
nodeUrl: 'https://fullnode.devnet.aptoslabs.com', | ||
nodeUrl: 'https://fullnode.testnet.aptoslabs.com/v1', | ||
networkOptions: { | ||
nativeToken: '0x1::test_coin::TestCoin', | ||
nativeToken: '0x1::aptos_coin::AptosCoin', | ||
modules: { | ||
Scripts: | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::scripts', | ||
Faucet: | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::faucet', | ||
LiquidityPool: | ||
'0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9::liquidity_pool', | ||
CoinInfo: '0x1::coin::CoinInfo', | ||
CoinStore: '0x1::coin::CoinStore', | ||
Scripts: NETWORKS_MODULES.Scripts, | ||
Faucet: NETWORKS_MODULES.Faucet, | ||
LiquidityPool: NETWORKS_MODULES.LiquidityPool, | ||
CoinInfo: NETWORKS_MODULES.CoinInfo, | ||
CoinStore: NETWORKS_MODULES.CoinStore, | ||
}, | ||
@@ -47,12 +45,9 @@ } | ||
test('calculateRates (from mode)', async () => { | ||
console.log({amountIn: convertToDecimals(1, 'APTOS')}); | ||
const output = await sdk.Swap.calculateRates({ | ||
fromToken: TokensMapping.APTOS, | ||
toToken: TokensMapping.BTC, | ||
toToken: TokensMapping.USDT, | ||
amount: convertToDecimals(1, 'APTOS'), | ||
curveType: 'stable', | ||
interactiveToken: 'from', | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: TokensMapping.APTOSBTCLP | ||
} | ||
}) | ||
@@ -62,3 +57,3 @@ | ||
amount: output, | ||
pretty: prettyAmount(output, 'BTC'), | ||
pretty: prettyAmount(output, 'USDT'), | ||
}); | ||
@@ -70,2 +65,4 @@ | ||
test('calculateRates (to mode)', async () => { | ||
console.log({amountInToMode: convertToDecimals('0.001', 'BTC')}); | ||
console.log(convertToDecimals('0.001', 'BTC'),); | ||
@@ -76,8 +73,4 @@ const output = await sdk.Swap.calculateRates({ | ||
amount: convertToDecimals('0.001', 'BTC'), | ||
curveType: 'stable', | ||
interactiveToken: 'to', | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: TokensMapping.APTOSBTCLP | ||
} | ||
}) | ||
@@ -94,15 +87,11 @@ | ||
test('createSwapTransactionPayload (to mode)', async () => { | ||
console.log(convertToDecimals('0.001', 'BTC'),); | ||
const output = sdk.Swap.createSwapTransactionPayload({ | ||
fromToken: TokensMapping.APTOS, | ||
toToken: TokensMapping.BTC, | ||
fromAmount: convertToDecimals('0.116831', 'APTOS'), | ||
toAmount: convertToDecimals('0.001', 'BTC'), | ||
interactiveToken: 'to', | ||
slippage: 0.05, | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: TokensMapping.APTOSBTCLP | ||
} | ||
fromAmount: convertToDecimals('1', 'APTOS'), | ||
toAmount: convertToDecimals('0.01584723', 'BTC'), | ||
interactiveToken: 'from', | ||
slippage: d(0.05), | ||
stableSwapType: 'high', | ||
curveType: 'stable', | ||
}) | ||
@@ -116,15 +105,11 @@ | ||
test('createSwapTransactionPayload (from mode)', async () => { | ||
console.log(convertToDecimals('0.001', 'BTC'),); | ||
const output = sdk.Swap.createSwapTransactionPayload({ | ||
fromToken: TokensMapping.APTOS, | ||
toToken: TokensMapping.BTC, | ||
fromAmount: convertToDecimals('1', 'APTOS'), | ||
toAmount: convertToDecimals('0.01584723', 'BTC'), | ||
interactiveToken: 'from', | ||
slippage: 0.05, | ||
pool: { | ||
address: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
moduleAddress: '0x43417434fd869edee76cca2a4d2301e528a1551b1d719b75c350c3c97d15b8b9', | ||
lpToken: TokensMapping.APTOSBTCLP | ||
} | ||
fromAmount: convertToDecimals('2741.440068', 'APTOS'), | ||
toAmount: convertToDecimals('0.001', 'BTC'), | ||
interactiveToken: 'to', | ||
slippage: d(0.05), | ||
stableSwapType: 'high', | ||
curveType: 'stable', | ||
}) | ||
@@ -131,0 +116,0 @@ |
import { SDK, SdkOptions } from "./sdk"; | ||
import { SwapModule, CalculateRatesParams, CreateTXPayloadParams } from "./modules/SwapModule"; | ||
import { ResourcesModule } from "./modules/ResourcesModule"; | ||
import { getCoinsInWithFeesStable, getCoinsOutWithFeesStable, getCoinOutWithFees, getCoinInWithFees } from './utils' | ||
@@ -11,5 +12,9 @@ export { | ||
CalculateRatesParams, | ||
CreateTXPayloadParams | ||
CreateTXPayloadParams, | ||
getCoinInWithFees, | ||
getCoinOutWithFees, | ||
getCoinsOutWithFeesStable, | ||
getCoinsInWithFeesStable | ||
}; | ||
export default SDK; |
import {SDK} from "../sdk"; | ||
import {IModule} from "../interfaces/IModule"; | ||
import {AptosResource, AptosResourceType} from "../types/aptos"; | ||
import {BigNumber} from "../types"; | ||
import {isAxiosError} from "../utils/is"; | ||
export type CalculateRatesParams = { | ||
fromToken: AptosResourceType; | ||
toToken: AptosResourceType; | ||
fromAmount: BigNumber; | ||
toAmount: BigNumber; | ||
} | ||
@@ -28,3 +21,2 @@ export class ResourcesModule implements IModule { | ||
const response = await this._sdk.client.getAccountResource(accountAddress, resourceType); | ||
return response as unknown as AptosResource<T>; | ||
@@ -31,0 +23,0 @@ } catch (e: unknown) { |
@@ -1,3 +0,5 @@ | ||
import {SDK} from "../sdk"; | ||
import {IModule} from "../interfaces/IModule"; | ||
import Decimal from 'decimal.js' | ||
import { SDK } from "../sdk"; | ||
import { IModule } from "../interfaces/IModule"; | ||
import { | ||
@@ -7,8 +9,22 @@ AptosCoinInfoResource, | ||
AptosResourceType, | ||
TxPayloadCallFunction | ||
TAptosTxPayload, | ||
CurveType, | ||
} from "../types/aptos"; | ||
import {BigNumber} from "../types"; | ||
import {composeType, extractAddressFromType, isSortedSymbols} from "../utils/contracts"; | ||
import {d} from "../utils/numbers"; | ||
import Decimal from "decimal.js"; | ||
import { | ||
withSlippage, | ||
composeType, | ||
extractAddressFromType, | ||
getCoinInWithFees, | ||
getCoinOutWithFees, | ||
getCoinsOutWithFeesStable, | ||
getCoinsInWithFeesStable, | ||
d, | ||
is_sorted, | ||
} from "../utils"; | ||
import { | ||
MODULES_ACCOUNT, | ||
RESOURCES_ACCOUNT, | ||
CURVE_STABLE, | ||
CURVE_UNCORRELATED | ||
} from '../constants'; | ||
@@ -18,9 +34,5 @@ export type CalculateRatesParams = { | ||
toToken: AptosResourceType; | ||
amount: BigNumber; | ||
interactiveToken: 'from' | 'to', | ||
pool: { | ||
lpToken: AptosResourceType, | ||
moduleAddress: string, | ||
address: string | ||
}, | ||
amount: Decimal; | ||
interactiveToken: 'from' | 'to'; | ||
curveType: CurveType; | ||
} | ||
@@ -31,11 +43,8 @@ | ||
toToken: AptosResourceType; | ||
fromAmount: BigNumber; | ||
toAmount: BigNumber; | ||
fromAmount: Decimal; | ||
toAmount: Decimal; | ||
interactiveToken: 'from' | 'to'; | ||
slippage: number, | ||
pool: { | ||
lpToken: AptosResourceType, | ||
moduleAddress: string, | ||
address: string | ||
}, | ||
slippage: Decimal; | ||
stableSwapType: 'high' | 'normal'; | ||
curveType: CurveType; | ||
} | ||
@@ -68,3 +77,3 @@ | ||
if(!fromCoinInfo) { | ||
throw new Error('To Coin not exists'); | ||
throw new Error('From Coin not exists'); | ||
} | ||
@@ -76,18 +85,4 @@ | ||
const isSorted = isSortedSymbols(fromCoinInfo.data.symbol, toCoinInfo.data.symbol); | ||
const [fromToken, toToken] = isSorted | ||
? [params.fromToken, params.toToken] | ||
: [params.toToken, params.fromToken]; | ||
const { liquidityPoolType, liquidityPoolResource } = await this.getLiquidityPoolResource(params); | ||
const liquidityPoolType = composeType(params.pool.moduleAddress,'liquidity_pool', 'LiquidityPool', [ | ||
fromToken, | ||
toToken, | ||
params.pool.lpToken, | ||
]) | ||
const liquidityPoolResource = await this.sdk.Resources.fetchAccountResource<AptosPoolResource>( | ||
params.pool.address, | ||
liquidityPoolType | ||
) | ||
if(!liquidityPoolResource) { | ||
@@ -97,23 +92,56 @@ throw new Error(`LiquidityPool (${liquidityPoolType}) not found`) | ||
const coinXReserve = liquidityPoolResource.data.coin_x_reserve.value | ||
const coinYReserve = liquidityPoolResource.data.coin_y_reserve.value | ||
const isSorted = is_sorted(params.fromToken, params.toToken); | ||
const [reserveX, reserveY] = isSorted | ||
? params.interactiveToken === 'from' | ||
? [d(coinXReserve), d(coinYReserve)] | ||
: [d(coinYReserve), d(coinXReserve)] | ||
: params.interactiveToken === 'from' | ||
? [d(coinYReserve), d(coinXReserve)] | ||
: [d(coinXReserve), d(coinYReserve)]; | ||
const [sortedFromCoinInfo, sortedToCoinInfo] = isSorted | ||
? [fromCoinInfo, toCoinInfo] | ||
: [toCoinInfo, fromCoinInfo]; | ||
const outputTokens = | ||
params.interactiveToken === 'from' | ||
? getCoinOutWithFees(d(params.amount), reserveX, reserveY) | ||
: getCoinInWithFees(d(params.amount), reserveX, reserveY); | ||
const coinXReserve = d(liquidityPoolResource.data.coin_x_reserve.value); | ||
const coinYReserve = d(liquidityPoolResource.data.coin_y_reserve.value); | ||
const fee = d(liquidityPoolResource.data.fee); | ||
return outputTokens.toString(); | ||
const coinFromDecimals = +sortedFromCoinInfo.data.decimals; | ||
const coinToDecimals = +sortedToCoinInfo.data.decimals; | ||
const [fromReserve, toReserve] = isSorted | ||
? [coinXReserve, coinYReserve] | ||
: [coinYReserve, coinXReserve]; | ||
let rate; | ||
if (!params.amount) { | ||
throw new Error(`Amount equals zero or undefined`); | ||
} | ||
if (params.curveType === 'stable') { | ||
rate = params.interactiveToken === 'from' | ||
? getCoinOutWithFees(params.amount, fromReserve, toReserve, fee) | ||
: getCoinInWithFees(params.amount, toReserve, fromReserve, fee); | ||
return rate.toString(); | ||
} else { | ||
rate = params.interactiveToken === 'from' | ||
? getCoinsOutWithFeesStable( | ||
params.amount, | ||
toReserve, | ||
fromReserve, | ||
d(Math.pow(10, coinToDecimals)), | ||
d(Math.pow(10, coinFromDecimals)), | ||
fee | ||
) | ||
: getCoinsInWithFeesStable( | ||
params.amount, | ||
fromReserve, | ||
toReserve, | ||
d(Math.pow(10, coinFromDecimals)), | ||
d(Math.pow(10, coinToDecimals)), | ||
fee | ||
) | ||
return rate; | ||
} | ||
} | ||
createSwapTransactionPayload(params: CreateTXPayloadParams): TxPayloadCallFunction { | ||
if(params.slippage >= 1 || params.slippage <= 0) { | ||
createSwapTransactionPayload(params: CreateTXPayloadParams): TAptosTxPayload { | ||
if(params.slippage.gte(1) || params.slippage.lte(0 )) { | ||
throw new Error(`Invalid slippage (${params.slippage}) value`); | ||
@@ -124,11 +152,17 @@ } | ||
const isUnchecked = params.curveType === 'stable' && params.stableSwapType === 'normal'; | ||
const functionName = composeType( | ||
modules.Scripts, | ||
params.interactiveToken === 'from' ? 'swap' : 'swap_into' | ||
isUnchecked | ||
? 'swap_unchecked' | ||
: params.interactiveToken === 'from' ? 'swap' : 'swap_into' | ||
); | ||
const curve = params.curveType === 'stable' ? CURVE_STABLE : CURVE_UNCORRELATED; | ||
const typeArguments = [ | ||
params.fromToken, | ||
params.toToken, | ||
params.pool.lpToken, | ||
curve | ||
]; | ||
@@ -139,12 +173,12 @@ | ||
? params.fromAmount | ||
: withSlippage(d(params.fromAmount), d(params.slippage), 'minus') | ||
: withSlippage(params.slippage, params.fromAmount).toFixed(0); | ||
const toAmount = | ||
params.interactiveToken === 'to' | ||
? params.toAmount | ||
: withSlippage(d(params.toAmount), d(params.slippage), 'plus') | ||
: withSlippage(params.slippage, params.toAmount).toFixed(0); | ||
const args = [params.pool.address, d(fromAmount).toString(), d(toAmount).toString()]; | ||
const args = [fromAmount.toString(), toAmount.toString()]; | ||
return { | ||
type: 'script_function_payload', | ||
type: 'entry_function_payload', | ||
function: functionName, | ||
@@ -155,31 +189,40 @@ typeArguments: typeArguments, | ||
} | ||
} | ||
function getCoinOutWithFees( | ||
coinInVal: Decimal.Instance, | ||
reserveInSize: Decimal.Instance, | ||
reserveOutSize: Decimal.Instance | ||
) { | ||
const { feePct, feeScale } = { feePct: d(3), feeScale: d(1000) }; | ||
const feeMultiplier = feeScale.sub(feePct); | ||
const coinInAfterFees = coinInVal.mul(feeMultiplier); | ||
const newReservesInSize = reserveInSize.mul(feeScale).plus(coinInAfterFees); | ||
async getLiquidityPoolResource(params: CalculateRatesParams) { | ||
const modulesLiquidityPool = composeType( | ||
MODULES_ACCOUNT, | ||
'liquidity_pool', | ||
'LiquidityPool', | ||
); | ||
return coinInAfterFees.mul(reserveOutSize).div(newReservesInSize).toDP(0); | ||
} | ||
function getPoolStr( | ||
coinX: string, | ||
coinY: string, | ||
curve: string, | ||
): string { | ||
const [sortedX, sortedY] = is_sorted(coinX, coinY) | ||
? [coinX, coinY] | ||
: [coinY, coinX]; | ||
return composeType(modulesLiquidityPool, [sortedX, sortedY, curve]); | ||
} | ||
const curve = params.curveType === 'stable' ? CURVE_STABLE : CURVE_UNCORRELATED; | ||
function getCoinInWithFees( | ||
coinOutVal: Decimal.Instance, | ||
reserveOutSize: Decimal.Instance, | ||
reserveInSize: Decimal.Instance | ||
) { | ||
const { feePct, feeScale } = { feePct: d(3), feeScale: d(1000) }; | ||
const feeMultiplier = feeScale.sub(feePct); | ||
const newReservesOutSize = reserveOutSize.sub(coinOutVal).mul(feeMultiplier); | ||
const liquidityPoolType = getPoolStr(params.fromToken, | ||
params.toToken, | ||
curve); | ||
return coinOutVal.mul(feeScale).mul(reserveInSize).div(newReservesOutSize).plus(1).toDP(0); | ||
let liquidityPoolResource; | ||
try { | ||
liquidityPoolResource = await this.sdk.Resources.fetchAccountResource<AptosPoolResource>( | ||
RESOURCES_ACCOUNT, | ||
liquidityPoolType | ||
) | ||
} catch (e) { | ||
console.log(e) | ||
} | ||
return { liquidityPoolType, liquidityPoolResource } | ||
} | ||
} | ||
export function withSlippage(value: Decimal.Instance, slippage: Decimal.Instance, mode: 'plus' | 'minus') { | ||
return d(value)[mode](d(value).mul(slippage)).toDP(0); | ||
} | ||
@@ -29,6 +29,7 @@ export type AptosResourceType = string; | ||
}; | ||
fee: number; | ||
}; | ||
export type TxPayloadCallFunction = { | ||
type: 'script_function_payload'; | ||
type: 'entry_function_payload'; | ||
function: string; | ||
@@ -39,3 +40,3 @@ typeArguments: string[]; | ||
export type TxPayloadInstallModule = { | ||
type TxPayloadInstallModule = { | ||
type: 'module_bundle_payload'; | ||
@@ -45,3 +46,3 @@ modules: { bytecode: string }[]; | ||
export type AptosTxPayload = TxPayloadCallFunction | TxPayloadInstallModule; | ||
export type TAptosTxPayload = TxPayloadCallFunction | TxPayloadInstallModule; | ||
@@ -54,3 +55,6 @@ export type AptosCreateTx = { | ||
expiration: string; | ||
payload: AptosTxPayload; | ||
payload: TAptosTxPayload; | ||
}; | ||
export type CurveType = 'uncorrelated' | 'stable'; | ||
@@ -1,4 +0,6 @@ | ||
import { AptosResourceType } from "../types/aptos"; | ||
import {checkAddress} from "./hex"; | ||
import { Buffer } from "buffer"; | ||
import Decimal from 'decimal.js'; | ||
import { checkAddress } from "./hex"; | ||
const EQUAL = 0; | ||
@@ -19,29 +21,86 @@ const LESS_THAN = 1; | ||
function compare(symbolX: string, symbolY: string) { | ||
let iX = symbolX.length; | ||
let iY = symbolY.length; | ||
const lenCmp = cmp(symbolX.length, symbolY.length); | ||
if (lenCmp != EQUAL) { | ||
return lenCmp; | ||
} | ||
let i = 0; | ||
while (i < symbolX.length && i < symbolY.length) { | ||
const elem_cmp = cmp(symbolX.charCodeAt(i), symbolY.charCodeAt(i)); | ||
if (elem_cmp != EQUAL) return elem_cmp; | ||
i++; | ||
} | ||
return EQUAL; | ||
} | ||
const lenCmp = cmp(iX, iY); | ||
while (iX > 0 && iY > 0) { | ||
iX -= 1; | ||
iY -= 1; | ||
function cmp_addresses(a: string, b: string) { | ||
if (a.startsWith('0x')) { | ||
a = a.substring(2); | ||
} | ||
const elemCmp = cmp(symbolX.charCodeAt(iX), symbolY.charCodeAt(iY)); | ||
if (elemCmp !== 0) { | ||
return elemCmp; | ||
if (a.length != 64) { | ||
while (a.length < 64) { | ||
a = '0' + a; | ||
} | ||
} | ||
return lenCmp; | ||
if (b.startsWith('0x')) { | ||
b = b.substring(2); | ||
} | ||
if (b.length != 64) { | ||
while (b.length < 64) { | ||
b = '0' + b; | ||
} | ||
} | ||
const a_buf = Buffer.from(a, 'hex'); | ||
const b_buf = Buffer.from(b, 'hex'); | ||
for (let i = 0; i < 32; i++) { | ||
if (a_buf[i] < b_buf[i]) { | ||
return LESS_THAN; | ||
} else if (a_buf[i] > b_buf[i]) { | ||
return GREATER_THAN; | ||
} | ||
} | ||
return EQUAL; | ||
} | ||
export function isSortedSymbols(symbolX: string, symbolY: string) { | ||
return compare(symbolX, symbolY) === LESS_THAN; | ||
function compare_types(coin_x: string, coin_y: string) { | ||
const coin_x_parts = coin_x.split('::').reverse(); | ||
const coin_y_parts = coin_y.split('::').reverse(); | ||
const coin_x_address = coin_x_parts.pop() as string; | ||
const coin_y_address = coin_y_parts.pop() as string; | ||
for (let i = 0; i < 2; i++) { | ||
const c = compare(coin_x_parts[i], coin_y_parts[i]); | ||
if (c != EQUAL) { | ||
return c; | ||
} | ||
} | ||
return cmp_addresses(coin_x_address, coin_y_address); | ||
} | ||
export function composeType(address: string, generics: AptosResourceType[]): AptosResourceType; | ||
/** | ||
* Compare sorting between two coin types | ||
* | ||
* @param coin_x string with full address of coin | ||
* @param coin_y string with full address of coin | ||
* @returns boolean | ||
*/ | ||
export function is_sorted(coin_x: string, coin_y: string) { | ||
return compare_types(coin_x, coin_y) == LESS_THAN; | ||
} | ||
export function composeType(address: string, generics: string[]): string; | ||
export function composeType( | ||
address: string, | ||
struct: string, | ||
generics?: AptosResourceType[] | ||
): AptosResourceType; | ||
generics?: string[] | ||
): string; | ||
export function composeType( | ||
@@ -51,5 +110,6 @@ address: string, | ||
struct: string, | ||
generics?: AptosResourceType[] | ||
): AptosResourceType; | ||
export function composeType(address: string, ...args: unknown[]): AptosResourceType { | ||
generics?: string[] | ||
): string; | ||
export function composeType(address: string, ...args: unknown[]): string { | ||
const generics: string[] = Array.isArray(args[args.length - 1]) | ||
@@ -69,2 +129,15 @@ ? (args.pop() as string[]) | ||
/** | ||
* Calculate value with slippage. | ||
* @param {Decimal} slippage - slippage refers to the difference between the expected price of a trade | ||
* and the price at which the trade is executed. | ||
* @param {Decimal} value - value to calculate slippage | ||
*/ | ||
export function withSlippage(slippage: Decimal, value: Decimal) { | ||
const multiply = new Decimal(10000); | ||
const slippagePercent = slippage.mul(multiply); | ||
return value.minus(value.mul(slippagePercent).div(multiply)).toNumber(); | ||
} | ||
export function extractAddressFromType(type: string) { | ||
@@ -125,1 +198,3 @@ return type.split('::')[0]; | ||
} | ||
@@ -39,3 +39,4 @@ const HEX_REGEXP = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/; | ||
/** | ||
* Attempts to turn a value into a `Buffer`. As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method. | ||
* Attempts to turn a value into a `Buffer`. | ||
* As input it supports `Buffer`, `String`, `Number`, null/undefined, `BN` and other objects with a `toArray()` method. | ||
* @param v the value | ||
@@ -67,4 +68,52 @@ */ | ||
export function bufferToHex(buffer: Buffer): string { | ||
return addHexPrefix(toBuffer(buffer).toString('hex')); | ||
export function checkAptosType( | ||
type: any, | ||
options: { leadingZero: boolean } = { leadingZero: true } | ||
): boolean { | ||
if (typeof type !== 'string') { | ||
return false; | ||
} | ||
let _type = type.replace(/\s/g, ''); | ||
const openBracketsCount = _type.match(/</g)?.length ?? 0; | ||
const closeBracketsCount = _type.match(/>/g)?.length ?? 0; | ||
if (openBracketsCount !== closeBracketsCount) { | ||
return false; | ||
} | ||
const genericsString = _type.match(/(<.+>)$/); | ||
const generics = genericsString?.[1]?.match( | ||
/(\w+::\w+::\w+)(?:<.*?>(?!>))?/g | ||
); | ||
if (generics) { | ||
_type = _type.slice(0, _type.indexOf('<')); | ||
const validGenerics = generics.every((g) => { | ||
const gOpenCount = g.match(/</g)?.length ?? 0; | ||
const gCloseCount = g.match(/>/g)?.length ?? 0; | ||
let t = g; | ||
if (gOpenCount !== gCloseCount) { | ||
t = t.slice(0, -(gCloseCount - gOpenCount)); | ||
} | ||
return checkAptosType(t, options); | ||
}); | ||
if (!validGenerics) { | ||
return false; | ||
} | ||
} | ||
const parts = _type.split('::'); | ||
if (parts.length !== 3) { | ||
return false; | ||
} | ||
return ( | ||
checkAddress(parts[0], options) && | ||
parts[1].length >= 1 && | ||
parts[2].length >= 1 | ||
); | ||
} |
@@ -7,3 +7,2 @@ import Decimal from "decimal.js"; | ||
} | ||
return new Decimal(value === undefined ? 0 : value); | ||
@@ -10,0 +9,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
145037
64
2128
12
1
2
116
1
1
Updatedaptos@^1.3.17
Updateddecimal.js@^10.4.1