|
| 1 | +/** |
| 2 | + * New rates server should use the following API |
| 3 | + * POST /api/v3/rates |
| 4 | + * BODY { |
| 5 | + * "targetFiat": "USD", |
| 6 | + * "crypto": [ |
| 7 | + * { |
| 8 | + * "isoDate": "2025-06-23T15:52:30.000Z", |
| 9 | + * "pluginId": "bitcoin", |
| 10 | + * }, |
| 11 | + * { |
| 12 | + * "isoDate": "2025-06-23T15:52:30.000Z", |
| 13 | + * "pluginId": "ethereum" |
| 14 | + * }, |
| 15 | + * { |
| 16 | + * "isoDate": "2025-06-23T15:52:30.000Z", |
| 17 | + * "pluginId": "ethereum", |
| 18 | + * "tokenId": "dac17f958d2ee523a2206206994597c13d831ec7", |
| 19 | + * } |
| 20 | + * ], |
| 21 | + * "fiat": [{"fiatCode": "GBP"}, {"fiatCode": "EUR"}] |
| 22 | + * } |
| 23 | + * |
| 24 | + * Response would be |
| 25 | + * { |
| 26 | + * "targetFiat": "USD", |
| 27 | + * "crypto": [ |
| 28 | + * { |
| 29 | + * "isoDate": "2025-06-23T15:52:30.000Z", |
| 30 | + * "pluginId": "bitcoin", |
| 31 | + * "rate": 103102.23 |
| 32 | + * }, |
| 33 | + * { |
| 34 | + * "isoDate": "2025-06-23T15:52:30.000Z", |
| 35 | + * "pluginId": "ethereum" |
| 36 | + * "rate": 2304.23 |
| 37 | + * }, |
| 38 | + * { |
| 39 | + * "isoDate": "2025-06-23T15:52:30.000Z", |
| 40 | + * "pluginId": "ethereum", |
| 41 | + * "tokenId": "dac17f958d2ee523a2206206994597c13d831ec7", |
| 42 | + * "rate": 1.002 |
| 43 | + * } |
| 44 | + * ], |
| 45 | + * "fiat": [ |
| 46 | + * { |
| 47 | + * "fiatCode": "GBP", |
| 48 | + * "rate": 1.32 |
| 49 | + * }, { |
| 50 | + * "fiatCode": "EUR" |
| 51 | + * "rate": 1.08 |
| 52 | + * } |
| 53 | + * ] |
| 54 | + * } |
| 55 | + */ |
| 56 | + |
| 57 | +/** |
| 58 | + * If no date is provided, rate queries should round down to the nearest minute. |
| 59 | + * If a date is provided, rate queries should round down to the nearest 5 min interval |
| 60 | + * since most historical rates are only accurate to 5 minutes |
| 61 | + */ |
| 62 | + |
| 63 | +/** |
| 64 | + * Crypto rates are stored in the `rates_data` |
| 65 | + * database. |
| 66 | + * |
| 67 | + * Doc id uses isoDate as the docId |
| 68 | + */ |
| 69 | + |
| 70 | +const ratesDocExample = { |
| 71 | + _id: '2025-06-23T15:55:00.000Z', |
| 72 | + chains: { |
| 73 | + bitcoin: { |
| 74 | + currencyCode: 'BTC', |
| 75 | + USD: 101234.09 |
| 76 | + }, |
| 77 | + ethereum: { |
| 78 | + currencyCode: 'ETH', |
| 79 | + USD: 2310.09 |
| 80 | + } |
| 81 | + }, |
| 82 | + tokens: { |
| 83 | + dac17f958d2ee523a2206206994597c13d831ec7: { |
| 84 | + currencyCode: 'USDT', |
| 85 | + USD: 1.0001 |
| 86 | + }, |
| 87 | + a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48: { |
| 88 | + currencyCode: 'USDC', |
| 89 | + USD: 1.0002 |
| 90 | + } |
| 91 | + }, |
| 92 | + fiat: { |
| 93 | + CAD: { USD: 0.73 }, |
| 94 | + EUR: { USD: 1.15 }, |
| 95 | + GBP: { USD: 1.35 } |
| 96 | + } |
| 97 | +} |
| 98 | + |
| 99 | +/** |
| 100 | + * To prevent double querying assets that exist on |
| 101 | + * multiple chains, a document will be used |
| 102 | + * to map tokenId assets to another asset on a main chain |
| 103 | + * like Ethereum. |
| 104 | + * |
| 105 | + * The examples below maps Arbitrum and Zksync to Ethereum and |
| 106 | + * USDT/USDC on Solana to the same assets on Ethereum. |
| 107 | + * |
| 108 | + * These docs will be in the `rates_mappings` database |
| 109 | + */ |
| 110 | + |
| 111 | +// PluginID mappings should be manually edited, not autogenerated since |
| 112 | +// these ONLY refer to Edge pluginIds and not partner slugs |
| 113 | +const pluginIdMappings = { |
| 114 | + _id: 'pluginIdMappings', |
| 115 | + data: { |
| 116 | + // Map arbitrum and zksync to ethereum since they are the same asset |
| 117 | + arbitrum: 'ethereum', |
| 118 | + zksync: 'ethereum' |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +/** |
| 123 | + * Token mappings should be auto generated from partner APIs. ie. the |
| 124 | + * coingecko /api/v3/coins/list?include_platform=true endpoint will return all the |
| 125 | + * contract addresses on all chains for each asset supported. |
| 126 | + * |
| 127 | + * The mappings below should be refreshed once per day |
| 128 | + */ |
| 129 | +const tokenMappings = { |
| 130 | + _id: 'tokenMappings', |
| 131 | + data: { |
| 132 | + // USDT from solana to ethereum |
| 133 | + Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB: { |
| 134 | + sourceChain: 'solana', // Only used for easy visual reference |
| 135 | + destChain: 'ethereum', // Only used for easy visual reference |
| 136 | + currencyCode: 'USDT', // Only used for easy visual reference |
| 137 | + tokenId: 'dac17f958d2ee523a2206206994597c13d831ec7' |
| 138 | + }, |
| 139 | + // USDC from solana to ethereum |
| 140 | + EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: { |
| 141 | + sourceChain: 'solana', // Only used for easy visual reference |
| 142 | + destChain: 'ethereum', // Only used for easy visual reference |
| 143 | + currencyCode: 'USDC', // Only used for easy visual reference |
| 144 | + tokenId: 'a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' |
| 145 | + } |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +/** |
| 150 | + * For each rate provider there will be a document that maps |
| 151 | + * the rate provider's unique identifiers to either pluginIds or tokenIds |
| 152 | + * The pluginIdMap should be manually entered as it references Edge |
| 153 | + * pluginIds. The tokenIdMap should be auto generated from partner APIs |
| 154 | + * since it only references contract addresses. For the tokenIds, use the first |
| 155 | + * chain that is returned by the partner API. All other chains would first |
| 156 | + * get translated by the tokenMappings doc above. |
| 157 | + */ |
| 158 | + |
| 159 | +const coinmarketcapPluginIdMap = { |
| 160 | + _id: 'coinmarketcapPluginIdMap', |
| 161 | + data: { |
| 162 | + // Mapping from Edge pluginIds to CMC ids of main chain assets |
| 163 | + bitcoin: 1, |
| 164 | + ethereum: 1027, |
| 165 | + ripple: 52 |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | +const coinmarketcapTokenIdMap = { |
| 170 | + _id: 'coinmarketcapTokenIdMap', |
| 171 | + data: { |
| 172 | + // Maps the contract address to the CMC id |
| 173 | + dac17f958d2ee523a2206206994597c13d831ec7: { |
| 174 | + id: 825, |
| 175 | + slug: 'tether' |
| 176 | + }, |
| 177 | + a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48: { |
| 178 | + id: 3408, |
| 179 | + slug: 'usd-coin' |
| 180 | + } |
| 181 | + } |
| 182 | +} |
| 183 | + |
| 184 | +/** |
| 185 | + * Used to map legacy currency codes to pluginId/tokenId which |
| 186 | + * would be used for a one time conversion of old db data to |
| 187 | + * the new format. This needs to be hand edited :( |
| 188 | + */ |
| 189 | +const legacyCurrencyCodeMap = { |
| 190 | + _id: 'legacyCurrencyCodeMap', |
| 191 | + data: { |
| 192 | + BTC: { pluginId: 'bitcoin', tokenId: null }, |
| 193 | + ETH: { pluginId: 'ethereum', tokenId: null }, |
| 194 | + XRP: { pluginId: 'ripple', tokenId: null }, |
| 195 | + USDC: { |
| 196 | + pluginId: 'ethereum', |
| 197 | + tokenId: 'a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' |
| 198 | + } |
| 199 | + } |
| 200 | +} |
0 commit comments