Skip to content

Commit

Permalink
Refactor and optimize route and swap SecretSwap functions
Browse files Browse the repository at this point in the history
  • Loading branch information
dredshep committed Jun 25, 2024
1 parent 40adf51 commit 53e8b47
Show file tree
Hide file tree
Showing 19 changed files with 681 additions and 247 deletions.
2 changes: 1 addition & 1 deletion types/api/azure/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export * from "./secretswap_pairs";
export * from "./rewards";
export * from "./secretswap_pools";
export * from "./secret_tokens_legacy";
// export * from "./secret_tokens_legacy";
export * from "./tokens";

// Note: Types below are untested and may be incorrect
Expand Down
40 changes: 20 additions & 20 deletions utils/dummyData/usages2test.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
// Define a type for Usage which can be one of these three strings
export type Usage = "BRIDGE" | "LPSTAKING" | "SWAP";

// This utility type checks if any element is present more than once in a tuple
export type HasDuplicates<T extends readonly any[]> = T extends readonly [
infer X,
...infer Rest
]
? X extends Rest[number]
? true
: HasDuplicates<Rest>
: false;
// // This utility type checks if any element is present more than once in a tuple
// export type HasDuplicates<T extends readonly any[]> = T extends readonly [
// infer X,
// ...infer Rest
// ]
// ? X extends Rest[number]
// ? true
// : HasDuplicates<Rest>
// : false;

// Define a type that is either the array or never if there are duplicates
export type UniqueArray<T extends readonly any[]> =
HasDuplicates<T> extends true ? never : T;
// // Define a type that is either the array or never if there are duplicates
// export type UniqueArray<T extends readonly any[]> =
// HasDuplicates<T> extends true ? never : T;

// Usage of UniqueArray type
export type Usages = UniqueArray<[Usage, Usage, Usage]>;
// export type Usages = UniqueArray<[Usage, Usage, Usage]>;

// Example usages
const validUsages: Usages = ["BRIDGE", "LPSTAKING", "SWAP"] as const; // This will be of type Usages if unique
// const validUsages: Usages = ["BRIDGE", "LPSTAKING", "SWAP"] as const; // This will be of type Usages if unique
// const invalidUsages: Usages = ["BRIDGE", "BRIDGE", "SWAP"] as const; // This will raise a type error as it should be never

// Helper function to construct a UniqueArray, ensuring type checking
function createUniqueArray<T extends Usage[]>(
...elements: UniqueArray<T>
): UniqueArray<T> {
return elements as UniqueArray<T>;
}
// function createUniqueArray<T extends Usage[]>(
// ...elements: UniqueArray<T>
// ): UniqueArray<T> {
// return elements as UniqueArray<T>;
// }

// Proper usage
const uniqueUsages = createUniqueArray("BRIDGE", "LPSTAKING", "SWAP"); // OK
// const uniqueUsages = createUniqueArray("BRIDGE", "LPSTAKING", "SWAP"); // OK
// const invalidUsages = createUniqueArray("BRIDGE", "BRIDGE", "SWAP"); // Error at compile time
16 changes: 8 additions & 8 deletions utils/secretjs/SecretSwapSite/SwapFunctions/getBestRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import BigNumber from "bignumber.js";
import {
compute_offer_amount,
compute_swap,
} from "../blockchain-bridge/scrt/swap";
} from "../blockchain-bridge/scrt/swap/swap";
import { SwapPair } from "../types/SwapPair";
import { getOfferAndAskPools } from "./getOfferAndAskPools";
import { SwapTokenMap } from "../types/SwapToken";
Expand Down Expand Up @@ -52,7 +52,7 @@ export function getBestRoute({
const fromToken = route[i];
const toToken = route[i + 1];
const pair: SwapPair | undefined = pairs.get(
`${fromToken}${SwapPair.id_delimiter}${toToken}`
`${fromToken}${SwapPair.id_delimiter}${toToken}`,
);
if (!pair) {
break;
Expand All @@ -63,7 +63,7 @@ export function getBestRoute({
toToken,
pair,
tokens,
balances
balances,
);

const offer_amount = from;
Expand All @@ -80,7 +80,7 @@ export function getBestRoute({
const { return_amount } = compute_swap(
offer_pool,
ask_pool,
offer_amount
offer_amount,
);

if (return_amount.isNaN() || return_amount.isLessThanOrEqualTo(0)) {
Expand Down Expand Up @@ -115,7 +115,7 @@ export function getBestRoute({
const fromToken = route[i - 1];
const toToken = route[i];
const pair: SwapPair | undefined = pairs.get(
`${fromToken}${SwapPair.id_delimiter}${toToken}`
`${fromToken}${SwapPair.id_delimiter}${toToken}`,
);
if (!pair) {
break;
Expand All @@ -125,7 +125,7 @@ export function getBestRoute({
toToken,
pair,
tokens,
balances
balances,
);

const ask_amount = to;
Expand All @@ -143,7 +143,7 @@ export function getBestRoute({
const { offer_amount } = compute_offer_amount(
offer_pool,
ask_pool,
ask_amount
ask_amount,
);

if (offer_amount.isNaN() || offer_amount.isLessThanOrEqualTo(0)) {
Expand All @@ -160,7 +160,7 @@ export function getBestRoute({
}

const fromWithGas = from.plus(
cachedGasFeesUnfilledCoin[route.length - 1]
cachedGasFeesUnfilledCoin[route.length - 1],
);

allRoutesOutputs.push({ route, fromOutput: from, fromWithGas });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Asset, NativeToken, Token } from './trade';
import { getSymbolsFromPair, Pair } from '../../../blockchain-bridge/scrt/swap';
import { SwapTokenMap } from './SwapToken';
import { CosmWasmClient } from 'secretjs';

export class SwapPair {
pair_identifier: string;
asset_infos: Asset[];
contract_addr: string;
liquidity_token: string;
static id_delimiter = '/';

constructor(
symbol0: string,
asset0: NativeToken | Token,
symbol1: string,
asset1: NativeToken | Token,
contract_addr: string,
liquidity_token: string,
pair_identifier: string,
) {
this.asset_infos = [];
this.asset_infos.push(new Asset(symbol0, asset0));
this.asset_infos.push(new Asset(symbol1, asset1));
this.contract_addr = contract_addr;
this.liquidity_token = liquidity_token;
this.pair_identifier = pair_identifier;
}

lpTokenSymbol(): string {
return `LP-${this.identifier()}`;
}

identifier(): string {
return this.pair_identifier;
}

assetIds(): string[] {
return this.pair_identifier.split(SwapPair.id_delimiter);
}

isSymbolInPair(symbol: string): boolean {
return symbol.toUpperCase() === this.asset_infos[0].symbol || symbol.toUpperCase() === this.asset_infos[1].symbol;
}

humanizedSymbol(): string {
return `${this.asset_infos[0].symbol}-${this.asset_infos[1].symbol}`;
}

isIdInPair(id: string): boolean {
const pairIdentifiers = this.pair_identifier.split(SwapPair.id_delimiter);

for (const pId of pairIdentifiers) {
if (pId.toLowerCase() === id) {
return true;
}
}

return false;
}

static fromPair(pair: Pair, tokenMap: SwapTokenMap) {
const identifiers = getSymbolsFromPair(pair);

const symbol0 = tokenMap.get(identifiers[0]).symbol;
const symbol1 = tokenMap.get(identifiers[1]).symbol;

const pair_identifier = pairIdFromTokenIds(identifiers[0], identifiers[1]);

//const symbol0 = asset0.type === 'native_token' ? asset0.native_token.denom : asset0.token.contract_addr;
return new SwapPair(
symbol0,
pair.asset_infos[0],
symbol1,
pair.asset_infos[1],
pair.contract_addr,
pair.liquidity_token,
pair_identifier,
);
}

private static code_hash: string;
static getPairCodeHash(pair_address: string, secretjs: CosmWasmClient): Promise<string> {
// TODO fix this if we ever have a factory with multiple pair_code_id
// For now this is the best way to avoid a lot of secretjs requests
return new Promise(async (accept, reject) => {
try {
if (!SwapPair.code_hash) {
SwapPair.code_hash = await secretjs.getCodeHashByContractAddr(pair_address);
}
accept(SwapPair.code_hash);
} catch (e) {
reject(e);
}
});
}
}

export const pairIdFromTokenIds = (id0: string, id1: string): string => {
return id0.localeCompare(id1) === -1
? `${id0}${SwapPair.id_delimiter}${id1}`
: `${id1}${SwapPair.id_delimiter}${id0}`;
};
export type PairMap = Map<string, SwapPair>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { ITokenInfo } from '../../../stores/interfaces';
import { Snip20TokenInfo, validateBech32Address } from '../../../blockchain-bridge';
import { tokenImages } from '../../../components/Earn/EarnRow';
import { sleep } from 'utils';

export type SwapTokenMap = Map<string, SwapToken>;

export type SwapToken = {
symbol: string;
logo?: string;
identifier?: string;
decimals?: number;
address?: string;
name?: string;
balance?: string;
price?: Number;
};

export const getPricesForJSONTokens = async () => {
for (let i = 0; i < 4; i++) {
if (globalThis.config['PRICE_DATA']['SEFI/USDT'].price) {
break
}
await sleep(1000)
}
return {
'secret15l9cqgz5uezgydrglaak5ahfac69kmx2qpd6xt': globalThis.config['PRICE_DATA']['SEFI/USDT'].price,
'uscrt': globalThis.config['PRICE_DATA']['SCRT/USD'].price,
'secret1yxcexylwyxlq58umhgsjgstgcg2a0ytfy4d9lt': globalThis.config['PRICE_DATA']['BUTT/USD'].price,
'secret14mzwd0ps5q277l20ly2q3aetqe3ev4m4260gf4': globalThis.config['PRICE_DATA']['ATOM/USD'].price,
'secret1zwwealwm0pcl9cul4nt6f38dsy6vzplw8lp3qg': globalThis.config['PRICE_DATA']['OSMO/USD'].price,
'secret1k8cge73c3nh32d4u0dsd5dgtmk63shtlrfscj5': globalThis.config['PRICE_DATA']['DVPN/USD'].price,
'secret19ungtd2c7srftqdwgq0dspwvrw63dhu79qxv88': globalThis.config['PRICE_DATA']['XMR/USD'].price,
}
}

export const SwapTokenFromSnip20Params = (address: string, token: Snip20TokenInfo) => {

const customTokenInfo: SwapToken = {
symbol: token.symbol,
address: address,
decimals: token.decimals,
logo: '/static/unknown.png',
identifier: address,
name: token.name,
};

return customTokenInfo;
};

export const TokenMapfromITokenInfo = async (tokens: ITokenInfo[]): Promise<SwapTokenMap> => {
let swapTokens: SwapTokenMap = new Map<string, SwapToken>();

const tokenPrices = await getPricesForJSONTokens()

for (const t of tokens) {
const secretAddress = validateBech32Address(t.dst_address)
? t.dst_address
: validateBech32Address(t.src_address)
? t.src_address
: '';
let symbol;
if (t.display_props.symbol === 'SCRT') {
symbol = 'SCRT';
} else if (t.display_props.symbol.toLowerCase() === 'sscrt') {
symbol = 'sSCRT';
} else if (t.display_props.symbol.toLowerCase() === 'sefi') {
symbol = 'SEFI';
} else if (t.display_props.symbol.toLowerCase() === 'sienna') {
symbol = t.display_props.symbol.toUpperCase();
} else if (t.display_props.symbol.toLowerCase() === 'alter') {
symbol = t.display_props.symbol.toUpperCase();
} else if (t.display_props.symbol.toLowerCase() === 'shd') {
symbol = t.display_props.symbol.toUpperCase();
} else {
symbol = 's' + t.display_props.symbol;
}

const swapToken: SwapToken = {
identifier: secretAddress,
symbol: symbol,
logo: t.display_props.symbol.startsWith("lp-") ? t.display_props.image : tokenImages[t.display_props.symbol.toUpperCase()],
decimals: Number(t.decimals),
name: t.name,
address: secretAddress,
price: secretAddress === 'secret15l9cqgz5uezgydrglaak5ahfac69kmx2qpd6xt' ? tokenPrices[secretAddress] : (Number(t.price) ? Number(t.price) : 0),
};

swapTokens.set(swapToken.identifier, swapToken);
}

return swapTokens;
};
Loading

0 comments on commit 53e8b47

Please sign in to comment.