Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paul/add lifi #185

Merged
merged 3 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- added: Add Lifi reporting
- changed: Paginate caching engine to prevent timeouts
- changed: Create caching engine 'initialized' document entry for each app:partner pair

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@types/node": "^14.0.22",
"api-changelly": "git://github.com/changelly/api-changelly.git#8e350f3",
"axios": "^0.21.2",
"biggystring": "^3.0.2",
"biggystring": "^4.1.3",
"body-parser": "^1.19.0",
"cleaner-config": "^0.1.10",
"cleaners": "^0.3.13",
Expand Down
4 changes: 4 additions & 0 deletions src/demo/partners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export default {
type: 'fiat',
color: '#2551E8'
},
lifi: {
type: 'swap',
color: '#EBB8FA'
},
moonpay: {
type: 'fiat',
color: '#7214F5'
Expand Down
3 changes: 2 additions & 1 deletion src/partners/banxa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import crypto from 'crypto'
import { Response } from 'node-fetch'

import {
EDGE_APP_START_DATE,
PartnerPlugin,
PluginParams,
PluginResult,
Expand All @@ -22,7 +23,7 @@ import { datelog, retryFetch, smartIsoDateFromTimestamp, snooze } from '../util'

export const asBanxaParams = asObject({
settings: asObject({
latestIsoDate: asOptional(asString, '2018-01-01T00:00:00.000Z')
latestIsoDate: asOptional(asString, EDGE_APP_START_DATE)
}),
apiKeys: asObject({
apiKey: asString,
Expand Down
10 changes: 5 additions & 5 deletions src/partners/bitrefill.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { bns } from 'biggystring'
import { div } from 'biggystring'
import {
asArray,
asBoolean,
Expand Down Expand Up @@ -36,7 +36,7 @@ const asBitrefillResult = asObject({
orders: asArray(asUnknown)
})

const div: { [key: string]: string } = {
const multipliers: { [key: string]: string } = {
BTC: '100000000',
ETH: '1000000',
LTC: '100000000',
Expand Down Expand Up @@ -93,8 +93,8 @@ export async function queryBitrefill(

let inputAmountStr = tx.satoshiPrice?.toString()
const inputCurrency: string = tx.coinCurrency.toUpperCase()
if (typeof div[inputCurrency] !== 'string') {
datelog(inputCurrency + ' has no div')
if (typeof multipliers[inputCurrency] !== 'string') {
datelog(inputCurrency + ' has no multipliers')
break
}
if (typeof inputCurrency === 'string' && inputCurrency !== 'BTC') {
Expand All @@ -104,7 +104,7 @@ export async function queryBitrefill(
break
}
const inputAmountNum = parseFloat(
bns.div(inputAmountStr, div[inputCurrency], 8)
div(inputAmountStr, multipliers[inputCurrency], 8)
)
const ssTx: StandardTx = {
status: 'complete',
Expand Down
3 changes: 2 additions & 1 deletion src/partners/letsexchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from 'cleaners'

import {
EDGE_APP_START_DATE,
PartnerPlugin,
PluginParams,
PluginResult,
Expand All @@ -19,7 +20,7 @@ import { datelog, retryFetch, smartIsoDateFromTimestamp } from '../util'

export const asLetsExchangePluginParams = asObject({
settings: asObject({
latestIsoDate: asOptional(asString, '2018-01-01T00:00:00.000Z')
latestIsoDate: asOptional(asString, EDGE_APP_START_DATE)
}),
apiKeys: asObject({
affiliateId: asOptional(asString),
Expand Down
188 changes: 188 additions & 0 deletions src/partners/lifi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import {
asArray,
asMaybe,
asNumber,
asObject,
asOptional,
asString,
asValue
} from 'cleaners'

import {
asStandardPluginParams,
EDGE_APP_START_DATE,
PartnerPlugin,
PluginParams,
PluginResult,
StandardTx,
Status
} from '../types'
import { datelog, retryFetch, smartIsoDateFromTimestamp, snooze } from '../util'

const PLUGIN_START_DATE = '2023-01-01T00:00:00.000Z'
const asStatuses = asMaybe(asValue('DONE'), 'other')
const asToken = asObject({
// address: asString,
// chainId: asNumber,
symbol: asString,
decimals: asNumber
// name: asString,
// coinKey: asString,
// logoURI: asString,
// priceUSD: asString
})

const asTransaction = asObject({
txHash: asString,
// txLink: asString,
amount: asString,
token: asToken,
// chainId: asNumber,
// gasPrice: asString,
// gasUsed: asString,
// gasToken: asToken,
// gasAmount: asString,
// gasAmountUSD: asString,
amountUSD: asOptional(asString),
// value: asString,
timestamp: asOptional(asNumber)
})

const asTransfer = asObject({
// transactionId: asString,
sending: asTransaction,
receiving: asTransaction,
// lifiExplorerLink: asString,
// fromAddress: asString,
toAddress: asString,
// tool: asString,
status: asString
// substatus: asString,
// substatusMessage: asString,
// metadata: asObject({
// integrator: asString
// })
})

// Define the cleaner for the whole JSON
const asTransfersResult = asObject({
transfers: asArray(asTransfer)
})

type PartnerStatuses = ReturnType<typeof asStatuses>

const MAX_RETRIES = 5
const QUERY_LOOKBACK = 1000 * 60 * 60 * 24 * 30 // 30 days
const QUERY_TIME_BLOCK_MS = QUERY_LOOKBACK

const statusMap: { [key in PartnerStatuses]: Status } = {
DONE: 'complete',
other: 'other'
}

export async function queryLifi(
pluginParams: PluginParams
): Promise<PluginResult> {
const { settings, apiKeys } = asStandardPluginParams(pluginParams)
const { apiKey } = apiKeys
let { latestIsoDate } = settings

if (latestIsoDate === EDGE_APP_START_DATE) {
latestIsoDate = new Date(PLUGIN_START_DATE).toISOString()
}

let lastCheckedTimestamp = new Date(latestIsoDate).getTime() - QUERY_LOOKBACK
if (lastCheckedTimestamp < 0) lastCheckedTimestamp = 0

const ssFormatTxs: StandardTx[] = []
let retry = 0
let startTime = lastCheckedTimestamp

while (true) {
const endTime = startTime + QUERY_TIME_BLOCK_MS
const now = Date.now()

const startTimeS = startTime / 1000
const endTimeS = endTime / 1000

const url = `https://li.quest/v1/analytics/transfers?integrator=${apiKey}&fromTimestamp=${startTimeS}&toTimestamp=${endTimeS}`
try {
const response = await retryFetch(url)
if (!response.ok) {
const text = await response.text()
throw new Error(text)
}
const jsonObj = await response.json()
const transferResults = asTransfersResult(jsonObj)
for (const tx of transferResults.transfers) {
const txTimestamp = tx.receiving.timestamp ?? tx.sending.timestamp ?? 0
if (txTimestamp === 0) {
throw new Error('No timestamp')
}
const { isoDate, timestamp } = smartIsoDateFromTimestamp(txTimestamp)

const depositAmount =
Number(tx.sending.amount) / 10 ** tx.sending.token.decimals

const payoutAmount =
Number(tx.receiving.amount) / 10 ** tx.receiving.token.decimals

const ssTx: StandardTx = {
status: statusMap[tx.status],
orderId: tx.sending.txHash,
depositTxid: tx.sending.txHash,
depositAddress: undefined,
depositCurrency: tx.sending.token.symbol,
depositAmount,
payoutTxid: undefined,
payoutAddress: tx.toAddress,
payoutCurrency: tx.receiving.token.symbol,
payoutAmount,
timestamp,
isoDate,
usdValue: Number(
tx.receiving.amountUSD ?? tx.sending.amountUSD ?? '-1'
),
rawTx: tx
}
ssFormatTxs.push(ssTx)
if (ssTx.isoDate > latestIsoDate) {
latestIsoDate = ssTx.isoDate
}
}
const endDate = new Date(endTime)
startTime = endTime
datelog(
`Lifi endDate:${endDate.toISOString()} latestIsoDate:${latestIsoDate}`
)
if (endTime > now) {
break
}
retry = 0
} catch (e) {
datelog(e)
// Retry a few times with time delay to prevent throttling
retry++
if (retry <= MAX_RETRIES) {
datelog(`Snoozing ${60 * retry}s`)
await snooze(60000 * retry)
} else {
// We can safely save our progress since we go from oldest to newest.
break
}
}
await snooze(3000)
}

const out = {
settings: { latestIsoDate },
transactions: ssFormatTxs
}
return out
}

export const lifi: PartnerPlugin = {
queryFunc: queryLifi,
pluginName: 'Li.Fi',
pluginId: 'lifi'
}
6 changes: 3 additions & 3 deletions src/partners/totle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { bns } from 'biggystring'
import { div } from 'biggystring'
import { asArray, asNumber, asObject, asString, asUnknown } from 'cleaners'
import fetch from 'node-fetch'
import Web3 from 'web3'
Expand Down Expand Up @@ -394,7 +394,7 @@ export async function queryTotle(
depositAddress: receipt.from,
depositCurrency: sourceToken.symbol,
depositAmount: parseFloat(
bns.div(
div(
sourceAmount.toString(),
(10 ** sourceToken.decimals).toString(),
10,
Expand All @@ -405,7 +405,7 @@ export async function queryTotle(
payoutAddress: receipt.to,
payoutCurrency: destinationToken.symbol,
payoutAmount: parseFloat(
bns.div(
div(
destinationAmount.toString(),
(10 ** destinationToken.decimals).toString(),
10,
Expand Down
2 changes: 2 additions & 0 deletions src/queryEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ioniaGiftCards } from './partners/ioniagiftcard'
import { ioniaVisaRewards } from './partners/ioniavisarewards'
import { letsexchange } from './partners/letsexchange'
import { libertyx } from './partners/libertyx'
import { lifi } from './partners/lifi'
import { moonpay } from './partners/moonpay'
import { paytrie } from './partners/paytrie'
import { safello } from './partners/safello'
Expand Down Expand Up @@ -52,6 +53,7 @@ const plugins = [
ioniaGiftCards,
letsexchange,
libertyx,
lifi,
moonpay,
paytrie,
safello,
Expand Down
5 changes: 4 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
asValue
} from 'cleaners'

/** Earliest date that transactions may show in Edge */
export const EDGE_APP_START_DATE = '2018-01-01T00:00:00.000Z'

export const asPluginParams = asObject({
settings: asMap((raw: any): any => raw),
apiKeys: asMap((raw: any): any => raw)
Expand Down Expand Up @@ -71,7 +74,7 @@ export const asDbCurrencyCodeMappings = asObject({

export const asStandardPluginParams = asObject({
settings: asObject({
latestIsoDate: asOptional(asString, '2018-01-01T00:00:00.000Z')
latestIsoDate: asOptional(asString, EDGE_APP_START_DATE)
}),
apiKeys: asObject({
apiKey: asOptional(asString)
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1553,10 +1553,10 @@ better-assert@~1.0.0:
dependencies:
callsite "1.0.0"

biggystring@^3.0.2:
version "3.0.2"
resolved "https://registry.npmjs.org/biggystring/-/biggystring-3.0.2.tgz"
integrity sha512-Sl1Ek3XwFliCf08nIaypxQtW+XwocfF33h5WC2baU5xVBf/LBctiK28cB3hmhWOBeArtZp0FbNk4hgDFCP3Fag==
biggystring@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/biggystring/-/biggystring-4.1.3.tgz#9a7d6e79e82781ecd1504aac30a1a815f073adcc"
integrity sha512-u2Uq8rFRHyo8AJgNdOMjwUk6CxOd174LBA63BeHU+SuUOIzFsDu8gIL176128Y6nRrAgEc9U4BYbPDD7zJ+O0g==
dependencies:
bn.js "^4.11.7"

Expand Down