Skip to content

Commit

Permalink
🚚Moved horizon helpers to his own file
Browse files Browse the repository at this point in the history
  • Loading branch information
MattPoblete committed Jun 19, 2024
1 parent dfad3d2 commit 54d4a2c
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 177 deletions.
128 changes: 128 additions & 0 deletions src/helpers/horizon/getHorizonPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { ServerApi } from '@stellar/stellar-sdk/lib/horizon';
import { Asset } from '@stellar/stellar-sdk'
import { SorobanContextType } from '@soroban-react/core';
import BigNumber from 'bignumber.js';
import { CurrencyAmount, TokenType } from 'interfaces';
import { InterfaceTrade, PlatformType, QuoteState, TradeState, TradeType } from 'state/routing/types';

const getClassicAsset = (currency: TokenType) => {
if (!currency) return
if (currency?.code === 'XLM') {
const nativeAsset = Asset.native()
return nativeAsset
}
if (!currency.issuer) {
throw new Error(`Can't convert ${currency.code} to stellar classic asset`)
}
const asset = new Asset(currency.code, currency.issuer)
return asset
}

const getAmount = (amount: string) => {
return new BigNumber(amount).dividedBy(10000000).toString()
}

const parseHorizonResult = (payload: ServerApi.PaymentPathRecord, tradeType: TradeType) =>{
const currecnyIn: TokenType = payload.source_asset_type == 'native' ? {
code: 'XLM',
contract: '',
} : {
code: payload.source_asset_code,
issuer: payload.source_asset_issuer,
contract: `${payload.source_asset_code}:${payload.source_asset_issuer}`
}
const currencyOut: TokenType = payload.destination_asset_type == 'native' ? {
code: 'XLM',
contract: '',
} : {
code: payload.destination_asset_code,
issuer: payload.destination_asset_issuer,
contract: `${payload.destination_asset_code}:${payload.destination_asset_issuer}`
}
const inputAmount: CurrencyAmount = {
currency: currecnyIn,
value: new BigNumber(payload.source_amount).multipliedBy(10000000).toString()
}
const outputAmount: CurrencyAmount = {
currency: currencyOut,
value: new BigNumber(payload.destination_amount).multipliedBy(10000000).toString()
}
const path = [currecnyIn, ...payload.path, currencyOut]
const parsedResult = {
inputAmount: inputAmount,
outputAmount: outputAmount,
tradeType: tradeType,
path: path,
priceImpact: undefined,
platform: PlatformType.STELLAR_CLASSIC,
}
return parsedResult
}

function getHorizonBestPath(
payload: any,
sorobanContext: SorobanContextType
) {
if (!payload.assetFrom || !payload.assetTo || !payload.amount || !sorobanContext) {
return;
}

const { serverHorizon, activeChain } = sorobanContext;
if (!serverHorizon || !activeChain) {
console.log('no serverHorizon or activeChain');
}

const args = {
assetFrom: getClassicAsset(payload.assetFrom),
assetTo: getClassicAsset(payload.assetTo),
amount: getAmount(payload.amount)
};

if (payload.tradeType === TradeType.EXACT_INPUT) {
try {
const send = serverHorizon?.strictSendPaths(
args.assetFrom!,
args?.amount,
[args.assetTo!]
).call().then((res) => {
return res.records;
});
return send?.then(res => {
return res.reduce((maxObj, obj) => {
console.log(maxObj)
if (obj.destination_amount > maxObj.destination_amount) {
return obj;
} else {
return maxObj;
}
});
});
} catch (error) {
console.log(error);
}
}

if (payload.tradeType === TradeType.EXACT_OUTPUT) {
try {
const receive = serverHorizon?.strictReceivePaths(
[args.assetFrom!],
args.assetTo!,
args?.amount,
).call().then((res) => {
return res.records;
});

return receive?.then(res => {
return res.reduce((maxObj, obj) => {
if (obj.destination_amount > maxObj.destination_amount) {
return obj;
} else {
return maxObj;
}
});
});
} catch (error) {
console.log(error);
}
}
}
179 changes: 2 additions & 177 deletions src/hooks/useBestTrade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,142 +2,16 @@ import { useRouterSDK } from 'functions/generateRoute';
import { CurrencyAmount, TokenType } from 'interfaces';
import { useEffect, useMemo, useState } from 'react';
import { TradeType as SdkTradeType } from 'soroswap-router-sdk';
import { InterfaceTrade, QuoteState, TradeState, TradeType, TransactionType } from 'state/routing/types';
import { InterfaceTrade, PlatformType, QuoteState, TradeState, TradeType } from 'state/routing/types';
import useSWR from 'swr';
import {Asset} from '@stellar/stellar-sdk'
import { SorobanContextType } from '@soroban-react/core';
import BigNumber from 'bignumber.js';
import { ServerApi } from '@stellar/stellar-sdk/lib/horizon';

const TRADE_NOT_FOUND = {
state: TradeState.NO_ROUTE_FOUND,
trade: undefined,
} as const;
const TRADE_LOADING = { state: TradeState.LOADING, trade: undefined } as const;

const getClassicAsset = (currency: TokenType) => {
if (!currency) return
if (currency?.code === 'XLM') {
const nativeAsset = Asset.native()
return nativeAsset
}
if (!currency.issuer) {
throw new Error(`Can't convert ${currency.code} to stellar classic asset`)
}
const asset = new Asset(currency.code, currency.issuer)
return asset
}

const getAmount = (amount: string) => {
return new BigNumber(amount).dividedBy(10000000).toString()
}

const parseHorizonResult = (payload: ServerApi.PaymentPathRecord, tradeType: TradeType) =>{
console.log('🔴🔴Object', payload)
const currecnyIn: TokenType = payload.source_asset_type == 'native' ? {
code: 'XLM',
contract: '',
} : {
code: payload.source_asset_code,
issuer: payload.source_asset_issuer,
contract: `${payload.source_asset_code}:${payload.source_asset_issuer}`
}
const currencyOut: TokenType = payload.destination_asset_type == 'native' ? {
code: 'XLM',
contract: '',
} : {
code: payload.destination_asset_code,
issuer: payload.destination_asset_issuer,
contract: `${payload.destination_asset_code}:${payload.destination_asset_issuer}`
}
const inputAmount: CurrencyAmount = {
currency: currecnyIn,
value: new BigNumber(payload.source_amount).multipliedBy(10000000).toString()
}
const outputAmount: CurrencyAmount = {
currency: currencyOut,
value: new BigNumber(payload.destination_amount).multipliedBy(10000000).toString()
}
const path = [currecnyIn, ...payload.path, currencyOut]
const parsedResult = {
inputAmount: inputAmount,
outputAmount: outputAmount,
tradeType: tradeType,
path: path,
priceImpact: undefined,
transctionType: TransactionType.STELLAR_CLASSIC,
}
return parsedResult
}

function getHorizonBestPath(
payload: any,
sorobanContext: SorobanContextType
) {
if (!payload.assetFrom || !payload.assetTo || !payload.amount || !sorobanContext) {
return;
}

const { serverHorizon, activeChain } = sorobanContext;
if (!serverHorizon || !activeChain) {
console.log('no serverHorizon or activeChain');
}

const args = {
assetFrom: getClassicAsset(payload.assetFrom),
assetTo: getClassicAsset(payload.assetTo),
amount: getAmount(payload.amount)
};

if (payload.tradeType === TradeType.EXACT_INPUT) {
try {
const send = serverHorizon?.strictSendPaths(
args.assetFrom!,
args?.amount,
[args.assetTo!]
).call().then((res) => {
return res.records;
});
return send?.then(res => {
return res.reduce((maxObj, obj) => {
console.log(maxObj)
if (obj.destination_amount > maxObj.destination_amount) {
return obj;
} else {
return maxObj;
}
});
});
} catch (error) {
console.log(error);
}
}

if (payload.tradeType === TradeType.EXACT_OUTPUT) {
try {
const receive = serverHorizon?.strictReceivePaths(
[args.assetFrom!],
args.assetTo!,
args?.amount,
).call().then((res) => {
return res.records;
});

return receive?.then(res => {
return res.reduce((maxObj, obj) => {
if (obj.destination_amount > maxObj.destination_amount) {
return obj;
} else {
return maxObj;
}
});
});
} catch (error) {
console.log(error);
}
}
}

/**
* Returns the best v2+v3 trade for a desired swap.
* @param tradeType whether the swap is an exact in/out
Expand All @@ -164,55 +38,6 @@ export function useBestTrade(
* @param {number} maxHops - The maximum number of hops allowed for the trade.
* @returns {object} - The data, isLoading, and isValidating values from the SWR hook.
*/
const payload = {
assetFrom: amountSpecified?.currency,
assetTo: otherCurrency,
amount: amountSpecified?.value,
tradeType: tradeType,
}
const [horizonPath, setHorizonPath] = useState<any>('')
const [soroswapPath, setSoroswapPath] = useState<any>('')

const calculatePaths = async () => {
if(!amountSpecified || !otherCurrency) return;
await getHorizonBestPath(payload, sorobanContext)?.then(res=>{
const parsedResult = parseHorizonResult(res, tradeType)
setHorizonPath(parsedResult);
})
await generateRoute({
amountTokenAddress: amountSpecified?.currency?.contract!,
quoteTokenAddress: otherCurrency?.contract!,
amount: amountSpecified?.value!,
tradeType: tradeType === TradeType.EXACT_INPUT ? SdkTradeType.EXACT_INPUT : SdkTradeType.EXACT_OUTPUT })?.then(res=>{
const updatedResult = {
...res,
transactionType: TransactionType.SOROBAN
};
setSoroswapPath(updatedResult);
})
}

const chooseBestPath = () => {
if(!horizonPath || !soroswapPath) return;
if(horizonPath.destination_amount > soroswapPath.trade.amountOutMin) {
return horizonPath
} else {
return soroswapPath
}
}

useEffect(() => {
calculatePaths()
}, [amountSpecified, otherCurrency, tradeType])

useEffect(() => {
if(!amountSpecified || !otherCurrency) return;
const bestPath = chooseBestPath()
console.log(bestPath)
console.log('🔵', horizonPath)
}, [horizonPath, soroswapPath])


// Fetch or save the route in cache
const {
data,
Expand Down Expand Up @@ -313,7 +138,7 @@ export function useBestTrade(
tradeType: tradeType,
rawRoute: data,
priceImpact: data?.priceImpact,
transctionType: TransactionType.SOROBAN,
platform: PlatformType.SOROBAN,
};
}, [expectedAmount, inputAmount, outputAmount, tradeType, data]);

Expand Down

0 comments on commit 54d4a2c

Please sign in to comment.