Skip to content
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
2 changes: 2 additions & 0 deletions src/v3/providers/allProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { coingecko } from './coingecko/coingecko'
import { coinmarketcap } from './coinmarketcap/coinmarketcap'
// import { coinmonitor } from './coinmonitor'
import { coinstore } from './coinstore'
import { constantRates } from './constantRates'
import { couch } from './couch'
import { currencyconverter } from './currencyconverter'
import { edgerates } from './edgerates/edgerates'
Expand All @@ -19,6 +20,7 @@ const looselyOrderedProviders: RateProvider[] = [
wazirx,
coinmarketcap,
coingecko,
constantRates,
currencyconverter,
couch,
redis
Expand Down
141 changes: 50 additions & 91 deletions src/v3/providers/coingecko/coingecko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import {
type RateEngine,
type RateProvider,
type TokenMap,
type TokenTypeMap,
wasCrossChainDoc,
wasExistingMappings
} from '../../types'
import {
create30MinuteSyncInterval,
createTokenId,
expandReturnedCryptoRates,
isCurrent,
Expand Down Expand Up @@ -74,7 +74,7 @@ const asCoingeckoAssetResponse = asArray(

const asGeckoBulkUsdResponse = asObject(
asObject({
usd: asNumber
usd: asMaybe(asNumber)
})
)

Expand Down Expand Up @@ -111,15 +111,9 @@ const platformIdMappingSyncDoc = syncedDocument(
'coingecko:platforms',
asStringNullMap
)
manualTokenMappingsSyncDoc.sync(dbSettings).catch(e => {
console.error('manualTokenMappingsSyncDoc sync error', e)
})
automatedTokenMappingsSyncDoc.sync(dbSettings).catch(e => {
console.error('automatedTokenMappingsSyncDoc sync error', e)
})
platformIdMappingSyncDoc.sync(dbSettings).catch(e => {
console.error('platformIdMappingSyncDoc sync error', e)
})
create30MinuteSyncInterval(manualTokenMappingsSyncDoc, dbSettings)
create30MinuteSyncInterval(automatedTokenMappingsSyncDoc, dbSettings)
create30MinuteSyncInterval(platformIdMappingSyncDoc, dbSettings)
manualTokenMappingsSyncDoc.onChange(manualMappings => {
coingeckoTokenIdMap = {
...automatedTokenMappingsSyncDoc.doc,
Expand All @@ -133,25 +127,40 @@ automatedTokenMappingsSyncDoc.onChange(automatedMappings => {
}
})

const coingeckoToCrossChainMapping = async (
coingeckoAssets: ReturnType<typeof asCoingeckoAssetResponse>,
tokenTypes: TokenTypeMap
): Promise<CrossChainMapping> => {
const tokenMapping: RateEngine = async () => {
const uidMapping: TokenMap = {}
const crossChainMapping: CrossChainMapping = {}

// Add the mainnet currency mapping
for (const [key, value] of Object.entries(coingeckoMainnetCurrencyMapping)) {
if (value === null) continue
uidMapping[key] = {
id: value,
displayName: key
}
}

const json = await fetchCoingecko(
`${config.providers.coingeckopro.uri}/api/v3/coins/list?include_platform=true`
)
const tokenTypes = asCouchDoc(asTokenTypeMap)(
await dbSettings.get(TOKEN_TYPES_KEY)
)

const data = asCoingeckoAssetResponse(json)

const invertPlatformMapping: Record<string, string> = {}
for (const [key, value] of Object.entries(platformIdMappingSyncDoc.doc)) {
if (value === null) continue
invertPlatformMapping[value] = key
}

const platformPriorityDoc = await dbSettings.get('platformPriority')
const platformPriority = asCouchDoc(asNumberMap)(platformPriorityDoc).doc
const getPriority = (k: string): number =>
platformPriority[k] ?? Number.MAX_SAFE_INTEGER

const out: CrossChainMapping = {}

for (const asset of coingeckoAssets) {
let destAsset: { destChain: string; edgeTokenId: string } | undefined

for (const asset of data) {
const platforms = Object.entries(asset.platforms)

const sortedPlatforms = platforms.sort(
Expand All @@ -160,24 +169,32 @@ const coingeckoToCrossChainMapping = async (
getPriority(invertPlatformMapping[b[0]])
)

let destAsset: { destChain: string; edgeTokenId: string } | undefined

for (const [platform, address] of sortedPlatforms) {
const edgePluginId = invertPlatformMapping[platform]
if (edgePluginId == null) continue

const tokenType = tokenTypes[edgePluginId]
const tokenType = tokenTypes.doc[edgePluginId]
if (tokenType == null) continue

try {
const tokenId = createTokenId(tokenType, asset.symbol, address)
if (tokenId == null) continue

// Build cross-chain mappings and track the best platform
if (destAsset == null) {
destAsset = {
destChain: edgePluginId,
edgeTokenId: tokenId
}
// Create UID mapping for the best (first) platform
uidMapping[toCryptoKey({ pluginId: edgePluginId, tokenId })] = {
id: asset.id,
displayName: asset.name
}
} else {
out[`${edgePluginId}_${tokenId}`] = {
crossChainMapping[`${edgePluginId}_${tokenId}`] = {
sourceChain: edgePluginId,
destChain: destAsset.destChain,
currencyCode: asset.symbol,
Expand All @@ -191,67 +208,9 @@ const coingeckoToCrossChainMapping = async (
}
}

return out
}

const tokenMapping: RateEngine = async () => {
const mapping: TokenMap = {}

// Add the mainnet currency mapping
for (const [key, value] of Object.entries(coingeckoMainnetCurrencyMapping)) {
if (value === null) continue
mapping[key] = {
id: value,
displayName: key
}
}

const json = await fetchCoingecko(
`${config.providers.coingeckopro.uri}/api/v3/coins/list?include_platform=true`
)
const tokenTypes = asCouchDoc(asTokenTypeMap)(
await dbSettings.get(TOKEN_TYPES_KEY)
)

const data = asCoingeckoAssetResponse(json)

const invertPlatformMapping: Record<string, string> = {}
for (const [key, value] of Object.entries(platformIdMappingSyncDoc.doc)) {
if (value === null) continue
invertPlatformMapping[value] = key
}

for (const asset of data) {
const firstPlatform: [string, string] | undefined = Object.entries(
asset.platforms
)[0]
if (firstPlatform == null) continue

const [platform, contractAddress] = firstPlatform

const pluginId = invertPlatformMapping[platform]
if (pluginId == null) continue

try {
const tokenId = createTokenId(
tokenTypes.doc[pluginId],
asset.symbol,
contractAddress
)
if (tokenId == null) continue

mapping[toCryptoKey({ pluginId, tokenId })] = {
id: asset.id,
displayName: asset.name
}
} catch (e) {
// skip assets that we cannot create token id for
}
}

const combinedTokenMappings: TokenMap = {
...automatedTokenMappingsSyncDoc.doc,
...mapping
...uidMapping
}

await dbSettings.insert(
Expand All @@ -262,17 +221,15 @@ const tokenMapping: RateEngine = async () => {
})
)

const crossChainDocument = await dbSettings.get('crosschain:automated')
const crossChainDoc = asCrossChainDoc(crossChainDocument)
const crossChainMappings = await coingeckoToCrossChainMapping(
data,
tokenTypes.doc as TokenTypeMap
)
const crossChainDefaultDocument = await dbSettings.get('crosschain')
const crossChainDefaultDoc = asCrossChainDoc(crossChainDefaultDocument)
const crossChainAutoDocument = await dbSettings.get('crosschain:automated')
const crossChainAutoDoc = asCrossChainDoc(crossChainAutoDocument)
await dbSettings.insert(
wasCrossChainDoc({
id: crossChainDoc.id,
rev: crossChainDoc.rev,
doc: crossChainMappings
id: crossChainAutoDoc.id,
rev: crossChainAutoDoc.rev,
doc: { ...crossChainMapping, ...crossChainDefaultDoc.doc }
})
)
}
Expand All @@ -287,7 +244,9 @@ const getCurrentRates = async (ids: Set<string>): Promise<NumberMap> => {
)
const data = asGeckoBulkUsdResponse(json)
for (const [key, value] of Object.entries(data)) {
out[key] = value.usd
if (value.usd != null) {
out[key] = value.usd
}
}
} catch (e) {
console.error('coingecko current query error:', e)
Expand Down
6 changes: 5 additions & 1 deletion src/v3/providers/coingecko/defaultPluginIdMapping.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { StringNullMap } from '../../types'

export const coingeckoMainnetCurrencyMapping: StringNullMap = {
abstract: 'ethereum',
algorand: 'algorand',
arbitrum: 'ethereum',
avalanche: 'avalanche-2',
Expand All @@ -13,6 +14,7 @@ export const coingeckoMainnetCurrencyMapping: StringNullMap = {
bitcoingold: 'bitcoin-gold',
bitcoinsv: 'bitcoin-cash-sv',
bobevm: 'ethereum',
botanix: 'bitcoin',
cardano: 'cardano',
celo: 'celo',
coreum: 'coreum',
Expand Down Expand Up @@ -59,7 +61,7 @@ export const coingeckoMainnetCurrencyMapping: StringNullMap = {
ton: 'the-open-network',
tron: 'tron',
ufo: null,
vertcoin: null,
vertcoin: 'vertcoin',
wax: null,
zcash: 'zcash',
zcoin: 'zcoin',
Expand All @@ -68,6 +70,7 @@ export const coingeckoMainnetCurrencyMapping: StringNullMap = {
}

export const coingeckoPlatformIdMapping: StringNullMap = {
abstract: 'abstract',
algorand: 'algorand',
arbitrum: 'arbitrum-one',
avalanche: 'avalanche',
Expand All @@ -80,6 +83,7 @@ export const coingeckoPlatformIdMapping: StringNullMap = {
bitcoingold: null,
bitcoinsv: null,
bobevm: 'bob-network',
botanix: 'botanix',
cardano: 'cardano',
celo: 'celo',
coreum: 'coreum',
Expand Down
13 changes: 4 additions & 9 deletions src/v3/providers/coinmarketcap/coinmarketcap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
wasExistingMappings
} from '../../types'
import {
create30MinuteSyncInterval,
createTokenId,
expandReturnedCryptoRates,
isCurrent,
Expand Down Expand Up @@ -144,15 +145,9 @@ const platformIdMappingSyncDoc = syncedDocument(
'coinmarketcap:platforms',
asStringNullMap
)
userTokenMappingsSyncDoc.sync(dbSettings).catch(e => {
console.error('manualTokenMappingsSyncDoc sync error', e)
})
automatedTokenMappingsSyncDoc.sync(dbSettings).catch(e => {
console.error('automatedTokenMappingsSyncDoc sync error', e)
})
platformIdMappingSyncDoc.sync(dbSettings).catch(e => {
console.error('platformIdMappingSyncDoc sync error', e)
})
create30MinuteSyncInterval(userTokenMappingsSyncDoc, dbSettings)
create30MinuteSyncInterval(automatedTokenMappingsSyncDoc, dbSettings)
create30MinuteSyncInterval(platformIdMappingSyncDoc, dbSettings)
userTokenMappingsSyncDoc.onChange(userMappings => {
coinmarketcapTokenIdMap = {
...automatedTokenMappingsSyncDoc.doc,
Expand Down
4 changes: 4 additions & 0 deletions src/v3/providers/coinmarketcap/defaultPluginIdMapping.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { StringNullMap } from '../../types'

export const coinmarketcapMainnetCurrencyMapping: StringNullMap = {
abstract: '1027',
algorand: '4030',
arbitrum: '1027',
avalanche: '5805',
Expand All @@ -13,6 +14,7 @@ export const coinmarketcapMainnetCurrencyMapping: StringNullMap = {
bitcoingold: '2083',
bitcoinsv: '3602',
bobevm: '1027',
botanix: '1',
cardano: '2010',
celo: '5567',
coreum: '16399',
Expand Down Expand Up @@ -68,6 +70,7 @@ export const coinmarketcapMainnetCurrencyMapping: StringNullMap = {
}

export const coinmarketcapPlatformIdMapping: StringNullMap = {
abstract: '247',
algorand: '17',
arbitrum: '51',
avalanche: '28',
Expand All @@ -80,6 +83,7 @@ export const coinmarketcapPlatformIdMapping: StringNullMap = {
bitcoingold: null,
bitcoinsv: null,
bobevm: null,
botanix: null,
cardano: '29',
celo: '35',
coreum: null,
Expand Down
Loading
Loading