Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
122539b
Refactor to use common processTx
paullinator Dec 6, 2025
e6e9b56
fixup! Refactor to use common processTx
paullinator Mar 16, 2026
9d1591c
fixup! Refactor to use common processTx
j0ntz Apr 29, 2026
42dbd65
Include all moonpay txs
paullinator Dec 6, 2025
da2fc88
Add EdgeAsset info for moonpay
paullinator Dec 7, 2025
014ad9e
fixup! Add EdgeAsset info for moonpay
paullinator Mar 16, 2026
65a9d07
Add EdgeAsset info for thorchain/maya
paullinator Dec 7, 2025
7aee8fa
fixup! Add EdgeAsset info for thorchain/maya
j0ntz Apr 20, 2026
f35e902
Add EdgeAsset info for changenow
paullinator Dec 7, 2025
8e53a75
fixup! Add EdgeAsset info for changenow
j0ntz Apr 20, 2026
1c0ead3
Add EdgeAsset info for sideshift
paullinator Dec 9, 2025
3c9c3ee
fixup! Add EdgeAsset info for sideshift
j0ntz Apr 20, 2026
22a0c9a
Add EdgeAsset info for banxa
paullinator Dec 11, 2025
4a3421a
fixup! Add EdgeAsset info for banxa
j0ntz Apr 20, 2026
6c4031d
fixup! Add EdgeAsset info for banxa
j0ntz Apr 29, 2026
a046b6a
Add EdgeAsset info for godex
paullinator Dec 12, 2025
d0126ad
Add EdgeAsset info for changehero
paullinator Dec 12, 2025
1b89c0a
fixup! Add EdgeAsset info for changehero
j0ntz Apr 20, 2026
159fca3
Improve v3 rates logging
paullinator Dec 12, 2025
9a8bf7e
Check pluginId/tokenId for updating transactions
paullinator Dec 12, 2025
8cdf52b
fixup! Check pluginId/tokenId for updating transactions
paullinator Mar 16, 2026
36e3f68
Fix ratesEngine bug
paullinator Dec 12, 2025
896fb0b
Add EdgeAsset info for letsexchange
paullinator Dec 12, 2025
3a52440
fixup! Add EdgeAsset info for letsexchange
paullinator Mar 16, 2026
7f0d82b
Add indices for pluginId/tokenId fields
paullinator Dec 12, 2025
7a21464
Add EdgeAsset info for exolix
paullinator Dec 13, 2025
bf2e22d
fixup! Add EdgeAsset info for exolix
j0ntz Apr 21, 2026
c5e820c
Add disablePartnerQuery feature
paullinator Dec 13, 2025
95dbce6
fixup! Add disablePartnerQuery feature
paullinator Mar 16, 2026
a1ed039
Use scoped logging
paullinator Dec 14, 2025
090df89
fixup! Use scoped logging
paullinator Mar 16, 2026
f3facca
Fix rates server bookmarking
paullinator Dec 15, 2025
9b1ad19
Optimize rates engine
paullinator Dec 15, 2025
65c24c1
fixup! Optimize rates engine
paullinator Mar 16, 2026
92df436
For a partner to run with soloPartnerId even if disabled in couch
paullinator Dec 18, 2025
0347960
Use semaphores for queryEngine
paullinator Dec 25, 2025
05c2fde
Add EdgeAsset info for bitrefill
paullinator Dec 27, 2025
d612126
fixup! Add EdgeAsset info for bitrefill
j0ntz Apr 21, 2026
5545161
Add rango query plugin
paullinator Dec 28, 2025
0f1581a
fixup! Add rango query plugin
j0ntz Apr 21, 2026
c327d59
Add max new transactions for letsexchange
paullinator Dec 24, 2025
f8962ef
fixup! Add max new transactions for letsexchange
j0ntz Apr 20, 2026
1a4c971
Add support for Binance Beacon Chain tokens for Letsexchange
paullinator Jan 7, 2026
6c5f486
Fix banxa by adding zcash.
paullinator Jan 7, 2026
3f3a949
Add retry when writing progress cache.
paullinator Jan 7, 2026
9c54024
Add opbnb to changenow
paullinator Feb 11, 2026
e5b3de7
Add monad
paullinator Feb 25, 2026
9d83a9c
Fix issue with testData.json
samholmes Jan 12, 2026
6abebaf
Fix API to use apiKey instead of appId
paullinator Dec 21, 2025
9ae8981
Fix partner plugin logging, token normalization, and cache handling
cursoragent Feb 27, 2026
c7a5d76
fixup! Fix partner plugin logging, token normalization, and cache han…
paullinator Mar 16, 2026
70c7be7
Add scripts to patch invalid token IDs and reset USD values.
paullinator Mar 26, 2026
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"assert": "^2.0.0",
"async-mutex": "^0.5.0",
"browserify-zlib": "^0.2.0",
"chai": "^4.3.4",
"eslint": "^8.19.0",
Expand Down
9 changes: 5 additions & 4 deletions src/bin/destroyPartition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import js from 'jsonfile'
import nano from 'nano'

import { pagination } from '../dbutils'
import { datelog } from '../util'
import { createScopedLog, datelog } from '../util'

const config = js.readFileSync('./config.json')
const nanoDb = nano(config.couchDbFullpath)
Expand Down Expand Up @@ -43,10 +43,11 @@ async function main(partitionName: string): Promise<void> {
return
}

const log = createScopedLog('destroy', partitionName)
try {
await pagination(transactions, reportsTransactions)
datelog(`Successfully Deleted: ${transactions.length} docs`)
datelog(`Successfully Deleted: partition ${partitionName}`)
await pagination(transactions, reportsTransactions, log)
log(`Successfully Deleted: ${transactions.length} docs`)
log(`Successfully Deleted: partition ${partitionName}`)

// Delete progress Cache
const split = partitionName.split('_')
Expand Down
5 changes: 4 additions & 1 deletion src/bin/fioPromo/fioLookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import path from 'path'

import { queryChangeNow } from '../../partners/changenow'
import { PluginParams, StandardTx } from '../../types'
import { createScopedLog } from '../../util'
import { defaultSettings } from './fioInfo'

let addressList: string[] = []
Expand Down Expand Up @@ -48,12 +49,14 @@ export async function getFioTransactions(
dateFrom: Date,
dateTo: Date
): Promise<StandardTx[]> {
const log = createScopedLog('fio', 'changenow')
// Get public keys from offset
const pluginConfig: PluginParams = {
settings: { dateFrom, dateTo, to: currencyCode },
apiKeys: {
changenowApiKey: config.changenowApiKey
}
},
log
}

const txnList = await queryChangeNow(pluginConfig)
Expand Down
222 changes: 222 additions & 0 deletions src/bin/fixTokenIds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import js from 'jsonfile'
import nano from 'nano'

import { DbTx } from '../types'
import { datelog } from '../util'
import { createTokenId, tokenTypes } from '../util/asEdgeTokenId'

const config = js.readFileSync('./config.json')
const nanoDb = nano(config.couchDbFullpath)

const QUERY_LIMIT = 500
const DRY_RUN = process.argv.includes('--dry-run')

const ALL_PARTITIONS = [
'edge_banxa',
'edge_bitaccess',
'edge_bitrefill',
'edge_bitsofgold',
'edge_bity',
'edge_changelly',
'edge_changehero',
'edge_changenow',
'edge_coinswitch',
'edge_exolix',
'edge_faast',
'edge_foxExchange',
'edge_godex',
'edge_kado',
'edge_letsexchange',
'edge_libertyx',
'edge_lifi',
'edge_moonpay',
'edge_paybis',
'edge_paytrie',
'edge_rango',
'edge_safello',
'edge_shapeshift',
'edge_sideshift',
'edge_simplex',
'edge_swapuz',
'edge_switchain',
'edge_thorchain',
'edge_totle',
'edge_transak',
'edge_wyre',
'edge_xanpool'
]

/**
* Re-derive the tokenId using createTokenId. Treats the existing tokenId
* value as a raw contract address and normalizes it. Returns undefined
* when the value is already correct or cannot be fixed.
*/
function normalizeTokenId(
pluginId: string | undefined,
currencyCode: string,
tokenId: string | null | undefined
): string | null | undefined {
if (tokenId == null || pluginId == null) return undefined

const tokenType = tokenTypes[pluginId] ?? null
if (tokenType == null) return undefined // chain doesn't support tokens

try {
const normalized = createTokenId(tokenType, currencyCode, tokenId)
return normalized !== tokenId ? normalized : undefined
} catch {
return undefined
}
}

interface FixStats {
scanned: number
fixed: number
errors: number
byPartition: Record<string, number>
byField: { deposit: number; payout: number }
}

fixTokenIds().catch(e => {
datelog(e)
process.exit(1)
})

async function fixTokenIds(): Promise<void> {
const reportsTransactions = nanoDb.use('reports_transactions')

const stats: FixStats = {
scanned: 0,
fixed: 0,
errors: 0,
byPartition: {},
byField: { deposit: 0, payout: 0 }
}

const partitions =
process.argv[2] != null && process.argv[2] !== '--dry-run'
? [process.argv[2]]
: ALL_PARTITIONS

if (DRY_RUN) datelog('DRY RUN — no changes will be written')

for (const partition of partitions) {
datelog(`Scanning partition: ${partition}`)
let bookmark: string | undefined

while (true) {
const query: any = {
selector: {
$or: [
{ depositTokenId: { $type: 'string' } },
{ payoutTokenId: { $type: 'string' } }
]
},
bookmark,
limit: QUERY_LIMIT
}

let result: any
try {
result = await reportsTransactions.partitionedFind(partition, query)
} catch (e) {
// Partition may not exist
const err = e as { statusCode?: number }
if (err.statusCode === 404) {
datelog(` Partition ${partition} not found, skipping`)
break
}
throw e
}

const { docs } = result
if (docs.length === 0) break

if (typeof result.bookmark === 'string' && docs.length === QUERY_LIMIT) {
bookmark = result.bookmark
} else {
bookmark = undefined
}

stats.scanned += docs.length

const docsToUpdate: any[] = []

for (const d of docs) {
const doc: DbTx = d
let changed = false

const fixedDeposit = normalizeTokenId(
doc.depositChainPluginId,
doc.depositCurrency,
doc.depositTokenId
)
if (fixedDeposit !== undefined) {
datelog(
` FIX ${doc._id} depositTokenId: "${doc.depositTokenId}" -> "${fixedDeposit}"`
)
doc.depositTokenId = fixedDeposit
changed = true
stats.byField.deposit++
}

const fixedPayout = normalizeTokenId(
doc.payoutChainPluginId,
doc.payoutCurrency,
doc.payoutTokenId
)
if (fixedPayout !== undefined) {
datelog(
` FIX ${doc._id} payoutTokenId: "${doc.payoutTokenId}" -> "${fixedPayout}"`
)
doc.payoutTokenId = fixedPayout
changed = true
stats.byField.payout++
}

if (changed) {
doc.usdValue = -1
docsToUpdate.push(d)
stats.byPartition[partition] = (stats.byPartition[partition] ?? 0) + 1
}
}

if (docsToUpdate.length > 0) {
stats.fixed += docsToUpdate.length
if (!DRY_RUN) {
try {
await reportsTransactions.bulk({ docs: docsToUpdate })
datelog(` Wrote ${docsToUpdate.length} fixed docs in ${partition}`)
} catch (e) {
datelog(` Error writing bulk update for ${partition}:`, e)
stats.errors++
}
} else {
datelog(
` Would write ${docsToUpdate.length} fixed docs in ${partition}`
)
}
}

if (bookmark == null) break
}
}

datelog('\n=== Summary ===')
datelog(`Total documents scanned: ${stats.scanned}`)
datelog(`Total documents fixed: ${stats.fixed}`)
datelog(` Deposit tokenIds fixed: ${stats.byField.deposit}`)
datelog(` Payout tokenIds fixed: ${stats.byField.payout}`)
if (Object.keys(stats.byPartition).length > 0) {
datelog('Fixes by partition:')
for (const [partition, count] of Object.entries(stats.byPartition)) {
datelog(` ${partition}: ${count}`)
}
}
if (stats.errors > 0) {
datelog(`Errors encountered: ${stats.errors}`)
}
if (DRY_RUN) {
datelog('DRY RUN complete — no changes were made')
}
}
69 changes: 69 additions & 0 deletions src/bin/resetUsdValues.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import js from 'jsonfile'
import nano from 'nano'

import { DbTx } from '../types'
import { datelog } from '../util'

const config = js.readFileSync('./config.json')
const nanoDb = nano(config.couchDbFullpath)

const QUERY_LIMIT = 1000

resetUsdValues().catch(e => {
datelog(e)
process.exit(1)
})

async function resetUsdValues(): Promise<void> {
const partitionName = process.argv[2]
if (partitionName == null) {
console.error('Usage: resetUsdValues <partitionName>')
process.exit(1)
}

const reportsTransactions = nanoDb.use('reports_transactions')
let bookmark: string | undefined
let totalUpdated = 0

while (true) {
const query: any = {
selector: {
usdValue: { $gte: 0 }
},
bookmark,
limit: QUERY_LIMIT
}

const result: any = await reportsTransactions.partitionedFind(
partitionName,
query
)
const { docs } = result
if (docs.length === 0) break

if (typeof result.bookmark === 'string' && docs.length === QUERY_LIMIT) {
bookmark = result.bookmark
} else {
bookmark = undefined
}

for (const d of docs) {
const doc: DbTx = d
doc.usdValue = -1
}

try {
await reportsTransactions.bulk({ docs })
totalUpdated += docs.length
datelog(`Updated ${docs.length} docs (${totalUpdated} total)`)
} catch (e) {
datelog('Error doing bulk update', e)
}

if (bookmark == null) break
}

datelog(
`Done. Set usdValue to -1 for ${totalUpdated} docs in ${partitionName}`
)
}
32 changes: 22 additions & 10 deletions src/bin/testpartner.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { thorchain as plugin } from '../partners/thorchain'
import { PluginParams } from '../types.js'
import { PluginParams } from '../types'
import { createScopedLog } from '../util'

const pluginParams: PluginParams = {
settings: {
offset: 0
},
apiKeys: {
thorchainAddress: ''
async function main(): Promise<void> {
const partnerId = process.argv[2]
if (partnerId == null) {
console.log(
'Usage: node -r sucrase/register src/bin/testpartner.ts <partnerId>'
)
process.exit(1)
}

const pluginParams: PluginParams = {
settings: {},
apiKeys: {},
log: createScopedLog('edge', partnerId)
}

// Dynamically import the partner plugin
const pluginModule = await import(`../partners/${partnerId}`)
const plugin = pluginModule[partnerId]
if (plugin?.queryFunc == null) {
throw new Error(`Plugin ${partnerId} does not have a queryFunc`)
}
}

async function main(): Promise<void> {
const result = await plugin.queryFunc(pluginParams)
console.log(JSON.stringify(result, null, 2))
}
Expand Down
Loading
Loading