-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7ffaaf2
commit bb51763
Showing
4 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
import { | ||
asArray, | ||
asBoolean, | ||
asDate, | ||
asMaybe, | ||
asNumber, | ||
asObject, | ||
asOptional, | ||
asString, | ||
asValue | ||
} from 'cleaners' | ||
|
||
import { | ||
asStandardPluginParams, | ||
PartnerPlugin, | ||
PluginParams, | ||
PluginResult, | ||
StandardTx, | ||
Status | ||
} from '../types' | ||
import { datelog, retryFetch, smartIsoDateFromTimestamp, snooze } from '../util' | ||
|
||
// Define cleaner for individual transactions in onRamps and offRamps | ||
const asTxType = asValue('buy', 'sell') | ||
|
||
const asTransaction = asObject({ | ||
_id: asString, | ||
walletAddress: asString, | ||
createdAt: asDate, | ||
type: asTxType, | ||
walletType: asString, | ||
cryptoCurrency: asString, | ||
network: asString | ||
}) | ||
|
||
const asOnRampTx = asObject({ | ||
...asTransaction.shape, | ||
receiveUnitCount: asNumber, | ||
paidAmountUsd: asNumber, | ||
paymentMethod: asString | ||
}) | ||
|
||
const asOffRampTx = asObject({ | ||
...asTransaction.shape, | ||
depositUnitCount: asNumber, | ||
receiveUsd: asNumber | ||
// disburseMethod: asString | ||
}) | ||
|
||
// Define cleaner for the main data structure | ||
const asResponse = asObject({ | ||
success: asBoolean, | ||
// message: asString, | ||
data: asObject({ | ||
onRamps: asArray(asOnRampTx), | ||
offRamps: asArray(asOffRampTx) | ||
}) | ||
}) | ||
|
||
const MAX_RETRIES = 5 | ||
const QUERY_LOOKBACK = 1000 * 60 * 60 * 24 * 30 // 30 days | ||
const QUERY_TIME_BLOCK_MS = QUERY_LOOKBACK | ||
|
||
export async function queryKado( | ||
pluginParams: PluginParams | ||
): Promise<PluginResult> { | ||
const { settings, apiKeys } = asStandardPluginParams(pluginParams) | ||
const { apiKey } = apiKeys | ||
let { latestIsoDate } = settings | ||
|
||
// API doesn't currently support paging by date but leave this in here | ||
// for when it does | ||
if (latestIsoDate === '2018-01-01T00:00:00.000Z') { | ||
latestIsoDate = new Date('2024-01-01T00:00:00.000Z').toISOString() | ||
} | ||
|
||
const ssFormatTxs: StandardTx[] = [] | ||
let retry = 0 | ||
|
||
const url = `https://api.kado.money/v2/organizations/${apiKey}/orders` | ||
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 = asResponse(jsonObj) | ||
const { onRamps, offRamps } = transferResults.data | ||
for (const tx of onRamps) { | ||
const { | ||
_id, | ||
createdAt, | ||
cryptoCurrency, | ||
paidAmountUsd, | ||
receiveUnitCount, | ||
walletAddress | ||
} = tx | ||
const { isoDate, timestamp } = smartIsoDateFromTimestamp( | ||
createdAt.toISOString() | ||
) | ||
const ssTx: StandardTx = { | ||
status: 'complete', | ||
orderId: _id, | ||
depositTxid: undefined, | ||
depositAddress: undefined, | ||
depositCurrency: 'USD', | ||
depositAmount: paidAmountUsd, | ||
payoutTxid: undefined, | ||
payoutAddress: walletAddress, | ||
payoutCurrency: cryptoCurrency, | ||
payoutAmount: receiveUnitCount, | ||
timestamp, | ||
isoDate, | ||
usdValue: paidAmountUsd, | ||
rawTx: tx | ||
} | ||
ssFormatTxs.push(ssTx) | ||
} | ||
for (const tx of offRamps) { | ||
const { | ||
_id, | ||
createdAt, | ||
cryptoCurrency, | ||
depositUnitCount, | ||
receiveUsd | ||
} = tx | ||
const { isoDate, timestamp } = smartIsoDateFromTimestamp( | ||
createdAt.toISOString() | ||
) | ||
const ssTx: StandardTx = { | ||
status: 'complete', | ||
orderId: _id, | ||
depositTxid: undefined, | ||
depositAddress: undefined, | ||
depositCurrency: cryptoCurrency, | ||
depositAmount: depositUnitCount, | ||
payoutTxid: undefined, | ||
payoutAddress: undefined, | ||
payoutCurrency: 'USD', | ||
payoutAmount: receiveUsd, | ||
timestamp, | ||
isoDate, | ||
usdValue: receiveUsd, | ||
rawTx: tx | ||
} | ||
ssFormatTxs.push(ssTx) | ||
} | ||
datelog(`Kado latestIsoDate:${latestIsoDate}`) | ||
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(61000 * retry) | ||
} else { | ||
// We can safely save our progress since we go from oldest to newest. | ||
// break | ||
} | ||
} | ||
|
||
const out = { | ||
settings: {}, | ||
transactions: ssFormatTxs | ||
} | ||
return out | ||
} | ||
|
||
export const kado: PartnerPlugin = { | ||
queryFunc: queryKado, | ||
pluginName: 'Kado', | ||
pluginId: 'kado' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters