Skip to content

Commit

Permalink
Merge pull request #320 from EdgeApp/paul/estDex
Browse files Browse the repository at this point in the history
Paul/est dex
  • Loading branch information
paullinator authored Apr 4, 2024
2 parents e9ba596 + 0db7adc commit 46d3f87
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
/coverage/
/dist/
/lib/
/edge/

# Package managers:
node_modules/
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

- added: Login info to testconfig for testpartners.ts
- changed: Change Lifi and Thorchain DA to use variable quotes
- fixed: LiFi and Thorchain/DA memo handling

## 2.3.1 (2024-03-29)

- fixed: Use proper `EdgeMemo` API on `EdgeSpendInfo`
Expand Down
2 changes: 1 addition & 1 deletion src/swap/defi/defiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export const getEvmApprovalData = async (params: {
gasPrice: '20'
}
)
return approveTx.data
return approveTx.data != null ? approveTx.data.replace('0x', '') : undefined
}

export const getEvmTokenData = async (params: {
Expand Down
16 changes: 11 additions & 5 deletions src/swap/defi/lifi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const asInitOptions = asObject({
integrator: asOptional(asString, 'edgeapp')
})

/** Allow up to 20% slippage even for variable rate quotes */
const MAX_SLIPPAGE = '0.2'
const LIFI_SERVERS_DEFAULT = ['https://li.quest']
const EXPIRATION_MS = 1000 * 60
const EXCHANGE_INFO_UPDATE_FREQ_MS = 60000
Expand Down Expand Up @@ -125,7 +127,7 @@ const asExchangeInfo = asObject({
const asEstimate = asObject({
fromAmount: asNumberString, // "400000",
toAmount: asNumberString, // "237318132569913",
toAmountMin: asNumberString, // "225452225941418",
// toAmountMin: asNumberString, // "225452225941418",
approvalAddress: asString, // "0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE",
executionDuration: asNumber // 1168,
// feeCosts: asArray(asFeeCost)
Expand Down Expand Up @@ -279,6 +281,7 @@ export function makeLifiPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
fromAddress,
toAddress,
integrator,
slippage: MAX_SLIPPAGE,
fee: affiliateFee
})
// Get current pool
Expand All @@ -296,7 +299,7 @@ export function makeLifiPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
const quoteJson = await quoteResponse.json()
const quote = asV1Quote(quoteJson)
const { estimate, includedSteps, transactionRequest } = quote
const { approvalAddress, toAmountMin } = estimate
const { approvalAddress, toAmount } = estimate

const { data, gasLimit, gasPrice } = transactionRequest
const gasPriceDecimal = hexToDecimal(gasPrice)
Expand All @@ -316,11 +319,14 @@ export function makeLifiPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
tokenId: null,
spendTargets: [
{
memo: approvalData,
nativeAmount: '0',
publicAddress: fromContractAddress
}
],
memos:
approvalData != null
? [{ type: 'hex', value: approvalData }]
: undefined,
networkFeeOption: 'custom',
customNetworkFee: {
gasPrice: gasPriceGwei
Expand Down Expand Up @@ -364,11 +370,11 @@ export function makeLifiPlugin(opts: EdgeCorePluginOptions): EdgeSwapPlugin {
savedAction: {
actionType: 'swap',
swapInfo,
isEstimate: false,
isEstimate: true,
toAsset: {
pluginId: toWallet.currencyInfo.pluginId,
tokenId: toTokenId,
nativeAmount: toAmountMin
nativeAmount: toAmount
},
fromAsset: {
pluginId: fromWallet.currencyInfo.pluginId,
Expand Down
7 changes: 3 additions & 4 deletions src/swap/defi/thorchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ export const asInitOptions = asObject({
affiliateFeeBasis: asOptional(asString, AFFILIATE_FEE_BASIS_DEFAULT),
ninerealmsClientId: asOptional(asString, ''),
thorname: asOptional(asString, 'ej'),
thorswapApiKey: asOptional(asString)
thorswapApiKey: asOptional(asString),
thorswapXApiKey: asOptional(asString)
})

export const asInboundAddresses = asArray(
Expand Down Expand Up @@ -633,14 +634,12 @@ export function makeThorchainPlugin(

let preTx: EdgeTransaction | undefined
if (approvalData != null) {
approvalData = approvalData.replace('0x', '')

const spendInfo: EdgeSpendInfo = {
// Token approvals only spend the parent currency
tokenId: null,
memos: [
{
type: memoType,
type: 'hex',
value: approvalData
}
],
Expand Down
41 changes: 20 additions & 21 deletions src/swap/defi/thorchainDa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from 'cleaners'
import {
EdgeCorePluginOptions,
EdgeMemo,
EdgeSpendInfo,
EdgeSwapInfo,
EdgeSwapPlugin,
Expand Down Expand Up @@ -86,17 +87,18 @@ const asThorSwapRoute = asObject({
providers: asArray(asString),
calldata: asUnknown,
expectedOutput: asString,
expectedOutputMaxSlippage: asString,
expectedOutputUSD: asString,
expectedOutputMaxSlippageUSD: asString,
// expectedOutputMaxSlippage: asString,
// expectedOutputUSD: asString,
// expectedOutputMaxSlippageUSD: asString,
deadline: asOptional(asString)
})

const asThorSwapQuoteResponse = asObject({
routes: asArray(asThorSwapRoute)
})

const DA_VOLATILITY_SPREAD_DEFAULT = 0.03
/** Max slippage for 20% for estimated quotes */
const DA_VOLATILITY_SPREAD_DEFAULT = 0.2
const THORSWAP_DEFAULT_SERVERS = ['https://api.thorswap.net/aggregator']

type ExchangeInfo = ReturnType<typeof asExchangeInfo>
Expand All @@ -119,7 +121,8 @@ export function makeThorchainDaPlugin(
affiliateFeeBasis,
ninerealmsClientId,
thorname,
thorswapApiKey
thorswapApiKey,
thorswapXApiKey
} = asInitOptions(opts.initOptions)

const headers = {
Expand All @@ -129,6 +132,7 @@ export function makeThorchainDaPlugin(

const thorswapHeaders = {
'Content-Type': 'application/json',
'x-api-key': thorswapXApiKey,
referer: thorswapApiKey
}

Expand All @@ -153,9 +157,9 @@ export function makeThorchainDaPlugin(
throw new SwapCurrencyError(swapInfo, request)
}
const reverseQuote = quoteFor === 'to'
const isEstimate = false
const isEstimate = true

let daVolatilitySpread: number = DA_VOLATILITY_SPREAD_DEFAULT
const daVolatilitySpread: number = DA_VOLATILITY_SPREAD_DEFAULT
let thornodeServers: string[] = THORNODE_SERVERS_DEFAULT
let thorswapServers: string[] = THORSWAP_DEFAULT_SERVERS

Expand Down Expand Up @@ -201,7 +205,8 @@ export function makeThorchainDaPlugin(

if (exchangeInfo != null) {
const { thorchain } = exchangeInfo.swap.plugins
daVolatilitySpread = thorchain.daVolatilitySpread
// Uncomment line below to re-enable server override of volatility spread
// daVolatilitySpread = thorchain.daVolatilitySpread
thorswapServers = thorchain.thorSwapServers ?? THORSWAP_DEFAULT_SERVERS
thornodeServers = thorchain.thornodeServers ?? thornodeServers
}
Expand Down Expand Up @@ -295,12 +300,7 @@ export function makeThorchainDaPlugin(

if (thorSwap == null) throw new SwapCurrencyError(swapInfo, request)

const {
providers,
path,
contractMethod,
expectedOutputMaxSlippage
} = thorSwap
const { providers, path, contractMethod, expectedOutput } = thorSwap

const calldata = asCalldata(thorSwap.calldata)

Expand All @@ -311,10 +311,7 @@ export function makeThorchainDaPlugin(
const tcDirect = providers[0] === 'THORCHAIN'

const toNativeAmount = toFixed(
await toWallet.denominationToNative(
expectedOutputMaxSlippage,
toCurrencyCode
),
await toWallet.denominationToNative(expectedOutput, toCurrencyCode),
0,
0
)
Expand Down Expand Up @@ -344,6 +341,7 @@ export function makeThorchainDaPlugin(
// throw new SwapCurrencyError(swapInfo, request)
// }

const memoType: EdgeMemo['type'] = 'hex'
let memo = calldata.tcMemo ?? calldata.memo ?? ''

log.warn(memo)
Expand Down Expand Up @@ -396,7 +394,7 @@ export function makeThorchainDaPlugin(
nativeAmount
})
} else {
memo = '0x' + Buffer.from(memo).toString('hex')
memo = Buffer.from(memo).toString('hex')
}
} else {
// Cannot yet do tokens on non-EVM chains
Expand All @@ -413,9 +411,9 @@ export function makeThorchainDaPlugin(
const spendInfo: EdgeSpendInfo = {
// Token approvals only spend the parent currency
tokenId: null,
memos: [{ type: 'hex', value: approvalData }],
spendTargets: [
{
memo: approvalData,
nativeAmount: '0',
publicAddress: sourceTokenContractAddress
}
Expand Down Expand Up @@ -448,7 +446,8 @@ export function makeThorchainDaPlugin(
assetAction: {
assetActionType: 'swap'
},
memos: memo == null ? [] : [{ type: 'text', value: memo }],
memos:
memo == null ? [] : [{ type: memoType, value: memo.replace('0x', '') }],
savedAction: {
actionType: 'swap',
swapInfo,
Expand Down
8 changes: 7 additions & 1 deletion test/testconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,11 @@ export const asTestConfig = asObject({
asObject({
appId: asOptional(asString, 'edge')
}).withRest
)
),
YOLO_PASSWORD: asOptional(asString, null),
YOLO_USERNAME: asOptional(asString, null),
YOLO_PIN: asOptional(asString, null),
YOLO_OTPKEY: asOptional(asString),
YOLO_KEY: asOptional(asString, null),
YOLO_DUMP: asOptional(asBoolean, true)
}).withRest
65 changes: 59 additions & 6 deletions test/testpartner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ import {
} from 'cleaners'
import {
addEdgeCorePlugins,
EdgeAccount,
EdgeContext,
EdgeCurrencyWallet,
EdgeSwapQuote,
EdgeSwapRequest,
lockEdgeCorePlugins,
makeEdgeContext,
makeFakeEdgeWorld
} from 'edge-core-js'
import accountBasedPlugins from 'edge-currency-accountbased'
Expand Down Expand Up @@ -73,9 +76,16 @@ async function main(): Promise<void> {
const loginKey = dump.loginKey
const fakeUsers = [dump.data]

const world = await makeFakeEdgeWorld(fakeUsers, {})
const context = await world.makeEdgeContext({
allowNetworkAccess: true,
const {
YOLO_DUMP,
YOLO_KEY,
YOLO_PIN,
YOLO_PASSWORD,
YOLO_OTPKEY,
YOLO_USERNAME
} = config

const contextOpts = {
apiKey: '',
appId: '',
plugins: {
Expand All @@ -86,16 +96,54 @@ async function main(): Promise<void> {
lifi: config.LIFI_INIT,
polygon: config.POLYGON_INIT,
piratechain: true,
thorchain: config.THORCHAIN_INIT
thorchain: config.THORCHAIN_INIT,
thorchainda: config.THORCHAIN_INIT
}
})
}

let account: EdgeAccount | undefined
let context: EdgeContext
if (YOLO_DUMP) {
const world = await makeFakeEdgeWorld(fakeUsers, {})
context = await world.makeEdgeContext({
...contextOpts,
allowNetworkAccess: true
})
account = await context.loginWithKey('bob', loginKey, {
pauseWallets: true
})
} else {
context = await makeEdgeContext(contextOpts)
if (YOLO_USERNAME == null) {
throw new Error('No username')
}
if (YOLO_KEY != null) {
account = await context.loginWithKey(YOLO_USERNAME, YOLO_KEY, {
pauseWallets: true
})
} else if (YOLO_PIN != null) {
account = await context.loginWithPIN(YOLO_USERNAME, YOLO_PIN, {
pauseWallets: true
})
} else if (YOLO_PASSWORD != null) {
account = await context.loginWithPassword(YOLO_USERNAME, YOLO_PASSWORD, {
otpKey: YOLO_OTPKEY,
pauseWallets: true
})
}
if (account == null) {
throw new Error('No account')
}
}
await context.changeLogSettings({
defaultLogLevel: 'info',
sources: {}
})

const account = await context.loginWithKey('bob', loginKey)
// Uncomment the following lines to get the loginKey for an account. This can be
// used in the testconfig.json to quickly login to a real account.
// const lk = await account.getLoginKey()
// console.log(`Login key: ${lk}`)
const btcInfo = await account.getFirstWalletInfo('wallet:bitcoin')
const bchInfo = await account.getFirstWalletInfo('wallet:bitcoincash')
const ethInfo = await account.getFirstWalletInfo('wallet:ethereum')
Expand All @@ -109,6 +157,8 @@ async function main(): Promise<void> {
const avaxWallet = await account.waitForCurrencyWallet(avaxInfo?.id ?? '')
const arrrWallet = await account.waitForCurrencyWallet(arrrInfo?.id ?? '')
const maticWallet = await account.waitForCurrencyWallet(maticInfo?.id ?? '')
await ethWallet.changePaused(false)
await avaxWallet.changePaused(false)

const fetchQuote = async ({
fromWallet,
Expand Down Expand Up @@ -151,6 +201,9 @@ async function main(): Promise<void> {
nativeAmount,
quoteFor
}
if (account == null) {
throw new Error('No account')
}
const quote = await account.fetchSwapQuote(request).catch(e => {
console.log(e)
console.log(e.message)
Expand Down

0 comments on commit 46d3f87

Please sign in to comment.