@talismn/token-rates 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/declarations/src/TokenRates.d.ts +11 -5
- package/dist/declarations/src/types.d.ts +90 -32
- package/dist/talismn-token-rates.cjs.dev.js +178 -46
- package/dist/talismn-token-rates.cjs.prod.js +178 -46
- package/dist/talismn-token-rates.esm.js +175 -39
- package/package.json +14 -15
- package/CHANGELOG.md +0 -178
@@ -1,7 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import { Token, TokenId } from "@talismn/chaindata-provider";
|
2
2
|
import { TokenRatesList } from "./types";
|
3
|
-
export declare
|
4
|
-
|
5
|
-
|
3
|
+
export declare class TokenRatesError extends Error {
|
4
|
+
response?: Response;
|
5
|
+
constructor(message: string, response?: Response);
|
6
6
|
}
|
7
|
-
export
|
7
|
+
export type CoingeckoConfig = {
|
8
|
+
apiUrl: string;
|
9
|
+
apiKeyName?: string;
|
10
|
+
apiKeyValue?: string;
|
11
|
+
};
|
12
|
+
export declare const DEFAULT_COINGECKO_CONFIG: CoingeckoConfig;
|
13
|
+
export declare function fetchTokenRates(tokens: Record<TokenId, Token>, config?: CoingeckoConfig): Promise<TokenRatesList>;
|
@@ -1,38 +1,96 @@
|
|
1
1
|
import { TokenId } from "@talismn/chaindata-provider";
|
2
|
+
export declare const SUPPORTED_CURRENCIES: {
|
3
|
+
readonly btc: {
|
4
|
+
readonly name: "Bitcoin";
|
5
|
+
readonly symbol: "₿";
|
6
|
+
};
|
7
|
+
readonly eth: {
|
8
|
+
readonly name: "Ethereum";
|
9
|
+
readonly symbol: "Ξ";
|
10
|
+
};
|
11
|
+
readonly dot: {
|
12
|
+
readonly name: "Polkadot";
|
13
|
+
readonly symbol: "D";
|
14
|
+
};
|
15
|
+
readonly usd: {
|
16
|
+
readonly name: "US Dollar";
|
17
|
+
readonly symbol: "$";
|
18
|
+
};
|
19
|
+
readonly cny: {
|
20
|
+
readonly name: "Chinese Yuan";
|
21
|
+
readonly symbol: "¥";
|
22
|
+
};
|
23
|
+
readonly eur: {
|
24
|
+
readonly name: "Euro";
|
25
|
+
readonly symbol: "€";
|
26
|
+
};
|
27
|
+
readonly gbp: {
|
28
|
+
readonly name: "British Pound";
|
29
|
+
readonly symbol: "£";
|
30
|
+
};
|
31
|
+
readonly cad: {
|
32
|
+
readonly name: "Canadian Dollar";
|
33
|
+
readonly symbol: "C$";
|
34
|
+
};
|
35
|
+
readonly aud: {
|
36
|
+
readonly name: "Australian Dollar";
|
37
|
+
readonly symbol: "A$";
|
38
|
+
};
|
39
|
+
readonly nzd: {
|
40
|
+
readonly name: "New Zealand Dollar";
|
41
|
+
readonly symbol: "NZ$";
|
42
|
+
};
|
43
|
+
readonly jpy: {
|
44
|
+
readonly name: "Japanese Yen";
|
45
|
+
readonly symbol: "¥";
|
46
|
+
};
|
47
|
+
readonly rub: {
|
48
|
+
readonly name: "Russian Ruble";
|
49
|
+
readonly symbol: "₽";
|
50
|
+
};
|
51
|
+
readonly krw: {
|
52
|
+
readonly name: "South Korean Won";
|
53
|
+
readonly symbol: "₩";
|
54
|
+
};
|
55
|
+
readonly idr: {
|
56
|
+
readonly name: "Indonesian Rupiah";
|
57
|
+
readonly symbol: "Rp";
|
58
|
+
};
|
59
|
+
readonly php: {
|
60
|
+
readonly name: "Philippine Peso";
|
61
|
+
readonly symbol: "₱";
|
62
|
+
};
|
63
|
+
readonly thb: {
|
64
|
+
readonly name: "Thai Baht";
|
65
|
+
readonly symbol: "฿";
|
66
|
+
};
|
67
|
+
readonly vnd: {
|
68
|
+
readonly name: "Vietnamese Dong";
|
69
|
+
readonly symbol: "₫";
|
70
|
+
};
|
71
|
+
readonly inr: {
|
72
|
+
readonly name: "Indian Rupee";
|
73
|
+
readonly symbol: "₹";
|
74
|
+
};
|
75
|
+
readonly try: {
|
76
|
+
readonly name: "Turkish Lira";
|
77
|
+
readonly symbol: "₺";
|
78
|
+
};
|
79
|
+
readonly sgd: {
|
80
|
+
readonly name: "Singapore Dollar";
|
81
|
+
readonly symbol: "S$";
|
82
|
+
};
|
83
|
+
};
|
84
|
+
export type TokenRateCurrency = keyof typeof SUPPORTED_CURRENCIES;
|
85
|
+
export type TokenRateData = {
|
86
|
+
price: number;
|
87
|
+
marketCap?: number;
|
88
|
+
change24h?: number;
|
89
|
+
};
|
90
|
+
export type TokenRates = Record<TokenRateCurrency, TokenRateData | null>;
|
2
91
|
export type TokenRatesList = Record<TokenId, TokenRates>;
|
3
|
-
export type TokenRateCurrency = keyof TokenRates;
|
4
92
|
export type DbTokenRates = {
|
5
93
|
tokenId: TokenId;
|
6
94
|
rates: TokenRates;
|
7
95
|
};
|
8
|
-
export
|
9
|
-
/** us dollar rate */
|
10
|
-
usd: number | null;
|
11
|
-
/** australian dollar rate */
|
12
|
-
aud: number | null;
|
13
|
-
/** new zealand dollar rate */
|
14
|
-
nzd: number | null;
|
15
|
-
/** canadian dollar rate */
|
16
|
-
cud: number | null;
|
17
|
-
/** hong kong dollar rate */
|
18
|
-
hkd: number | null;
|
19
|
-
/** euro rate */
|
20
|
-
eur: number | null;
|
21
|
-
/** british pound sterling rate */
|
22
|
-
gbp: number | null;
|
23
|
-
/** japanese yen rate */
|
24
|
-
jpy: number | null;
|
25
|
-
/** south korean won rate */
|
26
|
-
krw: number | null;
|
27
|
-
/** chinese yuan rate */
|
28
|
-
cny: number | null;
|
29
|
-
/** russian yuan rate */
|
30
|
-
rub: number | null;
|
31
|
-
/** btc rate */
|
32
|
-
btc: number | null;
|
33
|
-
/** eth rate */
|
34
|
-
eth: number | null;
|
35
|
-
/** dot rate */
|
36
|
-
dot: number | null;
|
37
|
-
};
|
38
|
-
export declare const NewTokenRates: () => TokenRates;
|
96
|
+
export declare const newTokenRates: () => TokenRates;
|
@@ -1,13 +1,6 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
4
|
-
|
5
3
|
var dexie = require('dexie');
|
6
|
-
var axios = require('axios');
|
7
|
-
|
8
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
9
|
-
|
10
|
-
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
11
4
|
|
12
5
|
class TalismanTokenRatesDatabase extends dexie.Dexie {
|
13
6
|
constructor() {
|
@@ -23,54 +16,166 @@ class TalismanTokenRatesDatabase extends dexie.Dexie {
|
|
23
16
|
// https://dexie.org/docs/Version/Version.stores()#warning
|
24
17
|
tokenRates: "tokenId"
|
25
18
|
});
|
26
|
-
|
27
|
-
// this.on("ready", async () => {})
|
28
19
|
}
|
29
20
|
}
|
30
|
-
|
31
21
|
const db = new TalismanTokenRatesDatabase();
|
32
22
|
|
33
|
-
const
|
23
|
+
const SUPPORTED_CURRENCIES = {
|
24
|
+
btc: {
|
25
|
+
name: "Bitcoin",
|
26
|
+
symbol: "₿"
|
27
|
+
},
|
28
|
+
eth: {
|
29
|
+
name: "Ethereum",
|
30
|
+
symbol: "Ξ"
|
31
|
+
},
|
32
|
+
dot: {
|
33
|
+
name: "Polkadot",
|
34
|
+
symbol: "D"
|
35
|
+
},
|
36
|
+
usd: {
|
37
|
+
name: "US Dollar",
|
38
|
+
symbol: "$"
|
39
|
+
},
|
40
|
+
cny: {
|
41
|
+
name: "Chinese Yuan",
|
42
|
+
symbol: "¥"
|
43
|
+
},
|
44
|
+
eur: {
|
45
|
+
name: "Euro",
|
46
|
+
symbol: "€"
|
47
|
+
},
|
48
|
+
gbp: {
|
49
|
+
name: "British Pound",
|
50
|
+
symbol: "£"
|
51
|
+
},
|
52
|
+
cad: {
|
53
|
+
name: "Canadian Dollar",
|
54
|
+
symbol: "C$"
|
55
|
+
},
|
56
|
+
aud: {
|
57
|
+
name: "Australian Dollar",
|
58
|
+
symbol: "A$"
|
59
|
+
},
|
60
|
+
nzd: {
|
61
|
+
name: "New Zealand Dollar",
|
62
|
+
symbol: "NZ$"
|
63
|
+
},
|
64
|
+
jpy: {
|
65
|
+
name: "Japanese Yen",
|
66
|
+
symbol: "¥"
|
67
|
+
},
|
68
|
+
rub: {
|
69
|
+
name: "Russian Ruble",
|
70
|
+
symbol: "₽"
|
71
|
+
},
|
72
|
+
krw: {
|
73
|
+
name: "South Korean Won",
|
74
|
+
symbol: "₩"
|
75
|
+
},
|
76
|
+
idr: {
|
77
|
+
name: "Indonesian Rupiah",
|
78
|
+
symbol: "Rp"
|
79
|
+
},
|
80
|
+
php: {
|
81
|
+
name: "Philippine Peso",
|
82
|
+
symbol: "₱"
|
83
|
+
},
|
84
|
+
thb: {
|
85
|
+
name: "Thai Baht",
|
86
|
+
symbol: "฿"
|
87
|
+
},
|
88
|
+
vnd: {
|
89
|
+
name: "Vietnamese Dong",
|
90
|
+
symbol: "₫"
|
91
|
+
},
|
92
|
+
inr: {
|
93
|
+
name: "Indian Rupee",
|
94
|
+
symbol: "₹"
|
95
|
+
},
|
96
|
+
try: {
|
97
|
+
name: "Turkish Lira",
|
98
|
+
symbol: "₺"
|
99
|
+
},
|
100
|
+
// hkd: { name: "Hong Kong Dollar", symbol: "HK$" },
|
101
|
+
sgd: {
|
102
|
+
name: "Singapore Dollar",
|
103
|
+
symbol: "S$"
|
104
|
+
}
|
105
|
+
// twd: { name: "Taiwanese Dollar", symbol: "NT$" },
|
106
|
+
};
|
107
|
+
const newTokenRates = () => ({
|
108
|
+
btc: null,
|
109
|
+
eth: null,
|
110
|
+
dot: null,
|
34
111
|
usd: null,
|
35
|
-
|
36
|
-
nzd: null,
|
37
|
-
cud: null,
|
38
|
-
hkd: null,
|
112
|
+
cny: null,
|
39
113
|
eur: null,
|
40
114
|
gbp: null,
|
115
|
+
cad: null,
|
116
|
+
aud: null,
|
117
|
+
nzd: null,
|
41
118
|
jpy: null,
|
42
|
-
krw: null,
|
43
|
-
cny: null,
|
44
119
|
rub: null,
|
45
|
-
|
46
|
-
|
47
|
-
|
120
|
+
krw: null,
|
121
|
+
idr: null,
|
122
|
+
php: null,
|
123
|
+
thb: null,
|
124
|
+
vnd: null,
|
125
|
+
inr: null,
|
126
|
+
try: null,
|
127
|
+
// hkd: null,
|
128
|
+
sgd: null
|
129
|
+
// twd: null,
|
48
130
|
});
|
49
131
|
|
50
|
-
|
51
|
-
|
132
|
+
class TokenRatesError extends Error {
|
133
|
+
constructor(message, response) {
|
134
|
+
super(message);
|
135
|
+
this.response = response;
|
136
|
+
}
|
137
|
+
}
|
52
138
|
|
53
139
|
// every currency in this list will be fetched from coingecko
|
54
140
|
// comment out unused currencies to save some bandwidth!
|
55
|
-
const coingeckoCurrencies =
|
56
|
-
//
|
57
|
-
//
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
141
|
+
const coingeckoCurrencies = Object.keys(SUPPORTED_CURRENCIES);
|
142
|
+
// api returns a 414 error if the url is too long, max length is about 8100 characters
|
143
|
+
// so use 7900 to be safe
|
144
|
+
const MAX_COINGECKO_URL_LENGTH = 7900;
|
145
|
+
const DEFAULT_COINGECKO_CONFIG = {
|
146
|
+
apiUrl: "https://api.coingecko.com"
|
147
|
+
};
|
62
148
|
|
63
149
|
// export function tokenRates(tokens: WithCoingeckoId[]): TokenRatesList {}
|
64
|
-
async function fetchTokenRates(tokens) {
|
150
|
+
async function fetchTokenRates(tokens, config = DEFAULT_COINGECKO_CONFIG) {
|
65
151
|
// create a map from `coingeckoId` -> `tokenId` for each token
|
66
152
|
const coingeckoIdToTokenIds = Object.values(tokens)
|
67
153
|
// ignore testnet tokens
|
68
154
|
.filter(({
|
69
155
|
isTestnet
|
70
|
-
}) => !isTestnet)
|
156
|
+
}) => !isTestnet).flatMap(token => {
|
157
|
+
// BEGIN: LP tokens have a rate which is calculated later on, using the rates of two other tokens.
|
158
|
+
//
|
159
|
+
// This section contains the logic such that: if token is an LP token, then fetch the rates for the two underlying tokens.
|
160
|
+
if (token.type === "evm-uniswapv2") {
|
161
|
+
if (!token.evmNetwork) return [];
|
162
|
+
const getToken = (evmNetworkId, tokenAddress, coingeckoId) => ({
|
163
|
+
id: evmErc20TokenId(evmNetworkId, tokenAddress),
|
164
|
+
coingeckoId
|
165
|
+
});
|
166
|
+
const token0 = token.coingeckoId0 ? [getToken(token.evmNetwork.id, token.tokenAddress0, token.coingeckoId0)] : [];
|
167
|
+
const token1 = token.coingeckoId1 ? [getToken(token.evmNetwork.id, token.tokenAddress1, token.coingeckoId1)] : [];
|
168
|
+
return [...token0, ...token1];
|
169
|
+
}
|
170
|
+
// END: LP tokens have a rate which is calculated later on, using the rates of two other tokens.
|
71
171
|
|
72
|
-
|
73
|
-
|
172
|
+
// ignore tokens which don't have a coingeckoId
|
173
|
+
if (!token.coingeckoId) return [];
|
174
|
+
return [{
|
175
|
+
id: token.id,
|
176
|
+
coingeckoId: token.coingeckoId
|
177
|
+
}];
|
178
|
+
})
|
74
179
|
|
75
180
|
// get each token's coingeckoId
|
76
181
|
.reduce((coingeckoIdToTokenIds, {
|
@@ -83,31 +188,55 @@ async function fetchTokenRates(tokens) {
|
|
83
188
|
}, {});
|
84
189
|
|
85
190
|
// create a list of coingeckoIds we want to fetch
|
86
|
-
const coingeckoIds = Object.keys(coingeckoIdToTokenIds);
|
191
|
+
const coingeckoIds = Object.keys(coingeckoIdToTokenIds).sort();
|
87
192
|
|
88
193
|
// skip network request if there is nothing for us to fetch
|
89
194
|
if (coingeckoIds.length < 1) return {};
|
90
195
|
|
91
|
-
// construct a coingecko request
|
92
|
-
|
93
|
-
const currenciesSerialized = coingeckoCurrencies.join(",");
|
94
|
-
const
|
196
|
+
// construct a coingecko request, sort args to help proxies with caching
|
197
|
+
|
198
|
+
const currenciesSerialized = coingeckoCurrencies.sort().join(",");
|
199
|
+
const safelyGetCoingeckoUrls = coingeckoIds => {
|
200
|
+
const idsSerialized = coingeckoIds.join(",");
|
201
|
+
const queryUrl = `${config.apiUrl}/api/v3/simple/price?ids=${idsSerialized}&vs_currencies=${currenciesSerialized}&include_market_cap=true&include_24hr_change=true`;
|
202
|
+
if (queryUrl.length > MAX_COINGECKO_URL_LENGTH) {
|
203
|
+
const half = Math.floor(coingeckoIds.length / 2);
|
204
|
+
return [...safelyGetCoingeckoUrls(coingeckoIds.slice(0, half)), ...safelyGetCoingeckoUrls(coingeckoIds.slice(half))];
|
205
|
+
}
|
206
|
+
return [queryUrl];
|
207
|
+
};
|
95
208
|
|
96
209
|
// fetch the token prices from coingecko
|
97
210
|
// the response should be in the format:
|
98
211
|
// {
|
99
212
|
// [coingeckoId]: {
|
100
213
|
// [currency]: rate
|
214
|
+
// [currency_24h_change]: percent
|
215
|
+
// [currency_market_cap]: value
|
101
216
|
// }
|
102
217
|
// }
|
103
|
-
|
218
|
+
|
219
|
+
const coingeckoHeaders = new Headers();
|
220
|
+
if (config.apiKeyName && config.apiKeyValue) {
|
221
|
+
coingeckoHeaders.set(config.apiKeyName, config.apiKeyValue);
|
222
|
+
}
|
223
|
+
const coingeckoPrices = await Promise.all(safelyGetCoingeckoUrls(coingeckoIds).map(async queryUrl => await fetch(queryUrl, {
|
224
|
+
headers: coingeckoHeaders
|
225
|
+
}).then(response => {
|
226
|
+
if (response.status !== 200) throw new TokenRatesError(`Failed to fetch token rates`, response);
|
227
|
+
return response.json();
|
228
|
+
}))).then(responses => Object.assign({}, ...responses));
|
104
229
|
|
105
230
|
// build a TokenRatesList from the token prices result
|
106
231
|
const ratesList = Object.fromEntries(coingeckoIds.flatMap(coingeckoId => {
|
107
232
|
const tokenIds = coingeckoIdToTokenIds[coingeckoId];
|
108
|
-
const rates =
|
233
|
+
const rates = newTokenRates();
|
109
234
|
for (const currency of coingeckoCurrencies) {
|
110
|
-
|
235
|
+
if (coingeckoPrices[coingeckoId]?.[currency]) rates[currency] = {
|
236
|
+
price: coingeckoPrices[coingeckoId][currency],
|
237
|
+
marketCap: coingeckoPrices[coingeckoId][`${currency}_market_cap`],
|
238
|
+
change24h: coingeckoPrices[coingeckoId][`${currency}_24h_change`]
|
239
|
+
};
|
111
240
|
}
|
112
241
|
return tokenIds.map(tokenId => [tokenId, rates]);
|
113
242
|
}));
|
@@ -115,12 +244,15 @@ async function fetchTokenRates(tokens) {
|
|
115
244
|
// return the TokenRatesList
|
116
245
|
return ratesList;
|
117
246
|
}
|
118
|
-
function hasCoingeckoId(token) {
|
119
|
-
return "coingeckoId" in token && typeof token.coingeckoId === "string";
|
120
|
-
}
|
121
247
|
|
122
|
-
|
248
|
+
// TODO: Move this into a common module which can then be imported both here and into EvmErc20Module
|
249
|
+
// We can't import this directly from EvmErc20Module because this package doesn't depend on `@talismn/balances`
|
250
|
+
const evmErc20TokenId = (chainId, tokenContractAddress) => `${chainId}-evm-erc20-${tokenContractAddress}`.toLowerCase();
|
251
|
+
|
252
|
+
exports.DEFAULT_COINGECKO_CONFIG = DEFAULT_COINGECKO_CONFIG;
|
253
|
+
exports.SUPPORTED_CURRENCIES = SUPPORTED_CURRENCIES;
|
123
254
|
exports.TalismanTokenRatesDatabase = TalismanTokenRatesDatabase;
|
255
|
+
exports.TokenRatesError = TokenRatesError;
|
124
256
|
exports.db = db;
|
125
257
|
exports.fetchTokenRates = fetchTokenRates;
|
126
|
-
exports.
|
258
|
+
exports.newTokenRates = newTokenRates;
|
@@ -1,13 +1,6 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
4
|
-
|
5
3
|
var dexie = require('dexie');
|
6
|
-
var axios = require('axios');
|
7
|
-
|
8
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
9
|
-
|
10
|
-
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
11
4
|
|
12
5
|
class TalismanTokenRatesDatabase extends dexie.Dexie {
|
13
6
|
constructor() {
|
@@ -23,54 +16,166 @@ class TalismanTokenRatesDatabase extends dexie.Dexie {
|
|
23
16
|
// https://dexie.org/docs/Version/Version.stores()#warning
|
24
17
|
tokenRates: "tokenId"
|
25
18
|
});
|
26
|
-
|
27
|
-
// this.on("ready", async () => {})
|
28
19
|
}
|
29
20
|
}
|
30
|
-
|
31
21
|
const db = new TalismanTokenRatesDatabase();
|
32
22
|
|
33
|
-
const
|
23
|
+
const SUPPORTED_CURRENCIES = {
|
24
|
+
btc: {
|
25
|
+
name: "Bitcoin",
|
26
|
+
symbol: "₿"
|
27
|
+
},
|
28
|
+
eth: {
|
29
|
+
name: "Ethereum",
|
30
|
+
symbol: "Ξ"
|
31
|
+
},
|
32
|
+
dot: {
|
33
|
+
name: "Polkadot",
|
34
|
+
symbol: "D"
|
35
|
+
},
|
36
|
+
usd: {
|
37
|
+
name: "US Dollar",
|
38
|
+
symbol: "$"
|
39
|
+
},
|
40
|
+
cny: {
|
41
|
+
name: "Chinese Yuan",
|
42
|
+
symbol: "¥"
|
43
|
+
},
|
44
|
+
eur: {
|
45
|
+
name: "Euro",
|
46
|
+
symbol: "€"
|
47
|
+
},
|
48
|
+
gbp: {
|
49
|
+
name: "British Pound",
|
50
|
+
symbol: "£"
|
51
|
+
},
|
52
|
+
cad: {
|
53
|
+
name: "Canadian Dollar",
|
54
|
+
symbol: "C$"
|
55
|
+
},
|
56
|
+
aud: {
|
57
|
+
name: "Australian Dollar",
|
58
|
+
symbol: "A$"
|
59
|
+
},
|
60
|
+
nzd: {
|
61
|
+
name: "New Zealand Dollar",
|
62
|
+
symbol: "NZ$"
|
63
|
+
},
|
64
|
+
jpy: {
|
65
|
+
name: "Japanese Yen",
|
66
|
+
symbol: "¥"
|
67
|
+
},
|
68
|
+
rub: {
|
69
|
+
name: "Russian Ruble",
|
70
|
+
symbol: "₽"
|
71
|
+
},
|
72
|
+
krw: {
|
73
|
+
name: "South Korean Won",
|
74
|
+
symbol: "₩"
|
75
|
+
},
|
76
|
+
idr: {
|
77
|
+
name: "Indonesian Rupiah",
|
78
|
+
symbol: "Rp"
|
79
|
+
},
|
80
|
+
php: {
|
81
|
+
name: "Philippine Peso",
|
82
|
+
symbol: "₱"
|
83
|
+
},
|
84
|
+
thb: {
|
85
|
+
name: "Thai Baht",
|
86
|
+
symbol: "฿"
|
87
|
+
},
|
88
|
+
vnd: {
|
89
|
+
name: "Vietnamese Dong",
|
90
|
+
symbol: "₫"
|
91
|
+
},
|
92
|
+
inr: {
|
93
|
+
name: "Indian Rupee",
|
94
|
+
symbol: "₹"
|
95
|
+
},
|
96
|
+
try: {
|
97
|
+
name: "Turkish Lira",
|
98
|
+
symbol: "₺"
|
99
|
+
},
|
100
|
+
// hkd: { name: "Hong Kong Dollar", symbol: "HK$" },
|
101
|
+
sgd: {
|
102
|
+
name: "Singapore Dollar",
|
103
|
+
symbol: "S$"
|
104
|
+
}
|
105
|
+
// twd: { name: "Taiwanese Dollar", symbol: "NT$" },
|
106
|
+
};
|
107
|
+
const newTokenRates = () => ({
|
108
|
+
btc: null,
|
109
|
+
eth: null,
|
110
|
+
dot: null,
|
34
111
|
usd: null,
|
35
|
-
|
36
|
-
nzd: null,
|
37
|
-
cud: null,
|
38
|
-
hkd: null,
|
112
|
+
cny: null,
|
39
113
|
eur: null,
|
40
114
|
gbp: null,
|
115
|
+
cad: null,
|
116
|
+
aud: null,
|
117
|
+
nzd: null,
|
41
118
|
jpy: null,
|
42
|
-
krw: null,
|
43
|
-
cny: null,
|
44
119
|
rub: null,
|
45
|
-
|
46
|
-
|
47
|
-
|
120
|
+
krw: null,
|
121
|
+
idr: null,
|
122
|
+
php: null,
|
123
|
+
thb: null,
|
124
|
+
vnd: null,
|
125
|
+
inr: null,
|
126
|
+
try: null,
|
127
|
+
// hkd: null,
|
128
|
+
sgd: null
|
129
|
+
// twd: null,
|
48
130
|
});
|
49
131
|
|
50
|
-
|
51
|
-
|
132
|
+
class TokenRatesError extends Error {
|
133
|
+
constructor(message, response) {
|
134
|
+
super(message);
|
135
|
+
this.response = response;
|
136
|
+
}
|
137
|
+
}
|
52
138
|
|
53
139
|
// every currency in this list will be fetched from coingecko
|
54
140
|
// comment out unused currencies to save some bandwidth!
|
55
|
-
const coingeckoCurrencies =
|
56
|
-
//
|
57
|
-
//
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
141
|
+
const coingeckoCurrencies = Object.keys(SUPPORTED_CURRENCIES);
|
142
|
+
// api returns a 414 error if the url is too long, max length is about 8100 characters
|
143
|
+
// so use 7900 to be safe
|
144
|
+
const MAX_COINGECKO_URL_LENGTH = 7900;
|
145
|
+
const DEFAULT_COINGECKO_CONFIG = {
|
146
|
+
apiUrl: "https://api.coingecko.com"
|
147
|
+
};
|
62
148
|
|
63
149
|
// export function tokenRates(tokens: WithCoingeckoId[]): TokenRatesList {}
|
64
|
-
async function fetchTokenRates(tokens) {
|
150
|
+
async function fetchTokenRates(tokens, config = DEFAULT_COINGECKO_CONFIG) {
|
65
151
|
// create a map from `coingeckoId` -> `tokenId` for each token
|
66
152
|
const coingeckoIdToTokenIds = Object.values(tokens)
|
67
153
|
// ignore testnet tokens
|
68
154
|
.filter(({
|
69
155
|
isTestnet
|
70
|
-
}) => !isTestnet)
|
156
|
+
}) => !isTestnet).flatMap(token => {
|
157
|
+
// BEGIN: LP tokens have a rate which is calculated later on, using the rates of two other tokens.
|
158
|
+
//
|
159
|
+
// This section contains the logic such that: if token is an LP token, then fetch the rates for the two underlying tokens.
|
160
|
+
if (token.type === "evm-uniswapv2") {
|
161
|
+
if (!token.evmNetwork) return [];
|
162
|
+
const getToken = (evmNetworkId, tokenAddress, coingeckoId) => ({
|
163
|
+
id: evmErc20TokenId(evmNetworkId, tokenAddress),
|
164
|
+
coingeckoId
|
165
|
+
});
|
166
|
+
const token0 = token.coingeckoId0 ? [getToken(token.evmNetwork.id, token.tokenAddress0, token.coingeckoId0)] : [];
|
167
|
+
const token1 = token.coingeckoId1 ? [getToken(token.evmNetwork.id, token.tokenAddress1, token.coingeckoId1)] : [];
|
168
|
+
return [...token0, ...token1];
|
169
|
+
}
|
170
|
+
// END: LP tokens have a rate which is calculated later on, using the rates of two other tokens.
|
71
171
|
|
72
|
-
|
73
|
-
|
172
|
+
// ignore tokens which don't have a coingeckoId
|
173
|
+
if (!token.coingeckoId) return [];
|
174
|
+
return [{
|
175
|
+
id: token.id,
|
176
|
+
coingeckoId: token.coingeckoId
|
177
|
+
}];
|
178
|
+
})
|
74
179
|
|
75
180
|
// get each token's coingeckoId
|
76
181
|
.reduce((coingeckoIdToTokenIds, {
|
@@ -83,31 +188,55 @@ async function fetchTokenRates(tokens) {
|
|
83
188
|
}, {});
|
84
189
|
|
85
190
|
// create a list of coingeckoIds we want to fetch
|
86
|
-
const coingeckoIds = Object.keys(coingeckoIdToTokenIds);
|
191
|
+
const coingeckoIds = Object.keys(coingeckoIdToTokenIds).sort();
|
87
192
|
|
88
193
|
// skip network request if there is nothing for us to fetch
|
89
194
|
if (coingeckoIds.length < 1) return {};
|
90
195
|
|
91
|
-
// construct a coingecko request
|
92
|
-
|
93
|
-
const currenciesSerialized = coingeckoCurrencies.join(",");
|
94
|
-
const
|
196
|
+
// construct a coingecko request, sort args to help proxies with caching
|
197
|
+
|
198
|
+
const currenciesSerialized = coingeckoCurrencies.sort().join(",");
|
199
|
+
const safelyGetCoingeckoUrls = coingeckoIds => {
|
200
|
+
const idsSerialized = coingeckoIds.join(",");
|
201
|
+
const queryUrl = `${config.apiUrl}/api/v3/simple/price?ids=${idsSerialized}&vs_currencies=${currenciesSerialized}&include_market_cap=true&include_24hr_change=true`;
|
202
|
+
if (queryUrl.length > MAX_COINGECKO_URL_LENGTH) {
|
203
|
+
const half = Math.floor(coingeckoIds.length / 2);
|
204
|
+
return [...safelyGetCoingeckoUrls(coingeckoIds.slice(0, half)), ...safelyGetCoingeckoUrls(coingeckoIds.slice(half))];
|
205
|
+
}
|
206
|
+
return [queryUrl];
|
207
|
+
};
|
95
208
|
|
96
209
|
// fetch the token prices from coingecko
|
97
210
|
// the response should be in the format:
|
98
211
|
// {
|
99
212
|
// [coingeckoId]: {
|
100
213
|
// [currency]: rate
|
214
|
+
// [currency_24h_change]: percent
|
215
|
+
// [currency_market_cap]: value
|
101
216
|
// }
|
102
217
|
// }
|
103
|
-
|
218
|
+
|
219
|
+
const coingeckoHeaders = new Headers();
|
220
|
+
if (config.apiKeyName && config.apiKeyValue) {
|
221
|
+
coingeckoHeaders.set(config.apiKeyName, config.apiKeyValue);
|
222
|
+
}
|
223
|
+
const coingeckoPrices = await Promise.all(safelyGetCoingeckoUrls(coingeckoIds).map(async queryUrl => await fetch(queryUrl, {
|
224
|
+
headers: coingeckoHeaders
|
225
|
+
}).then(response => {
|
226
|
+
if (response.status !== 200) throw new TokenRatesError(`Failed to fetch token rates`, response);
|
227
|
+
return response.json();
|
228
|
+
}))).then(responses => Object.assign({}, ...responses));
|
104
229
|
|
105
230
|
// build a TokenRatesList from the token prices result
|
106
231
|
const ratesList = Object.fromEntries(coingeckoIds.flatMap(coingeckoId => {
|
107
232
|
const tokenIds = coingeckoIdToTokenIds[coingeckoId];
|
108
|
-
const rates =
|
233
|
+
const rates = newTokenRates();
|
109
234
|
for (const currency of coingeckoCurrencies) {
|
110
|
-
|
235
|
+
if (coingeckoPrices[coingeckoId]?.[currency]) rates[currency] = {
|
236
|
+
price: coingeckoPrices[coingeckoId][currency],
|
237
|
+
marketCap: coingeckoPrices[coingeckoId][`${currency}_market_cap`],
|
238
|
+
change24h: coingeckoPrices[coingeckoId][`${currency}_24h_change`]
|
239
|
+
};
|
111
240
|
}
|
112
241
|
return tokenIds.map(tokenId => [tokenId, rates]);
|
113
242
|
}));
|
@@ -115,12 +244,15 @@ async function fetchTokenRates(tokens) {
|
|
115
244
|
// return the TokenRatesList
|
116
245
|
return ratesList;
|
117
246
|
}
|
118
|
-
function hasCoingeckoId(token) {
|
119
|
-
return "coingeckoId" in token && typeof token.coingeckoId === "string";
|
120
|
-
}
|
121
247
|
|
122
|
-
|
248
|
+
// TODO: Move this into a common module which can then be imported both here and into EvmErc20Module
|
249
|
+
// We can't import this directly from EvmErc20Module because this package doesn't depend on `@talismn/balances`
|
250
|
+
const evmErc20TokenId = (chainId, tokenContractAddress) => `${chainId}-evm-erc20-${tokenContractAddress}`.toLowerCase();
|
251
|
+
|
252
|
+
exports.DEFAULT_COINGECKO_CONFIG = DEFAULT_COINGECKO_CONFIG;
|
253
|
+
exports.SUPPORTED_CURRENCIES = SUPPORTED_CURRENCIES;
|
123
254
|
exports.TalismanTokenRatesDatabase = TalismanTokenRatesDatabase;
|
255
|
+
exports.TokenRatesError = TokenRatesError;
|
124
256
|
exports.db = db;
|
125
257
|
exports.fetchTokenRates = fetchTokenRates;
|
126
|
-
exports.
|
258
|
+
exports.newTokenRates = newTokenRates;
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { Dexie } from 'dexie';
|
2
|
-
import axios from 'axios';
|
3
2
|
|
4
3
|
class TalismanTokenRatesDatabase extends Dexie {
|
5
4
|
constructor() {
|
@@ -15,54 +14,166 @@ class TalismanTokenRatesDatabase extends Dexie {
|
|
15
14
|
// https://dexie.org/docs/Version/Version.stores()#warning
|
16
15
|
tokenRates: "tokenId"
|
17
16
|
});
|
18
|
-
|
19
|
-
// this.on("ready", async () => {})
|
20
17
|
}
|
21
18
|
}
|
22
|
-
|
23
19
|
const db = new TalismanTokenRatesDatabase();
|
24
20
|
|
25
|
-
const
|
21
|
+
const SUPPORTED_CURRENCIES = {
|
22
|
+
btc: {
|
23
|
+
name: "Bitcoin",
|
24
|
+
symbol: "₿"
|
25
|
+
},
|
26
|
+
eth: {
|
27
|
+
name: "Ethereum",
|
28
|
+
symbol: "Ξ"
|
29
|
+
},
|
30
|
+
dot: {
|
31
|
+
name: "Polkadot",
|
32
|
+
symbol: "D"
|
33
|
+
},
|
34
|
+
usd: {
|
35
|
+
name: "US Dollar",
|
36
|
+
symbol: "$"
|
37
|
+
},
|
38
|
+
cny: {
|
39
|
+
name: "Chinese Yuan",
|
40
|
+
symbol: "¥"
|
41
|
+
},
|
42
|
+
eur: {
|
43
|
+
name: "Euro",
|
44
|
+
symbol: "€"
|
45
|
+
},
|
46
|
+
gbp: {
|
47
|
+
name: "British Pound",
|
48
|
+
symbol: "£"
|
49
|
+
},
|
50
|
+
cad: {
|
51
|
+
name: "Canadian Dollar",
|
52
|
+
symbol: "C$"
|
53
|
+
},
|
54
|
+
aud: {
|
55
|
+
name: "Australian Dollar",
|
56
|
+
symbol: "A$"
|
57
|
+
},
|
58
|
+
nzd: {
|
59
|
+
name: "New Zealand Dollar",
|
60
|
+
symbol: "NZ$"
|
61
|
+
},
|
62
|
+
jpy: {
|
63
|
+
name: "Japanese Yen",
|
64
|
+
symbol: "¥"
|
65
|
+
},
|
66
|
+
rub: {
|
67
|
+
name: "Russian Ruble",
|
68
|
+
symbol: "₽"
|
69
|
+
},
|
70
|
+
krw: {
|
71
|
+
name: "South Korean Won",
|
72
|
+
symbol: "₩"
|
73
|
+
},
|
74
|
+
idr: {
|
75
|
+
name: "Indonesian Rupiah",
|
76
|
+
symbol: "Rp"
|
77
|
+
},
|
78
|
+
php: {
|
79
|
+
name: "Philippine Peso",
|
80
|
+
symbol: "₱"
|
81
|
+
},
|
82
|
+
thb: {
|
83
|
+
name: "Thai Baht",
|
84
|
+
symbol: "฿"
|
85
|
+
},
|
86
|
+
vnd: {
|
87
|
+
name: "Vietnamese Dong",
|
88
|
+
symbol: "₫"
|
89
|
+
},
|
90
|
+
inr: {
|
91
|
+
name: "Indian Rupee",
|
92
|
+
symbol: "₹"
|
93
|
+
},
|
94
|
+
try: {
|
95
|
+
name: "Turkish Lira",
|
96
|
+
symbol: "₺"
|
97
|
+
},
|
98
|
+
// hkd: { name: "Hong Kong Dollar", symbol: "HK$" },
|
99
|
+
sgd: {
|
100
|
+
name: "Singapore Dollar",
|
101
|
+
symbol: "S$"
|
102
|
+
}
|
103
|
+
// twd: { name: "Taiwanese Dollar", symbol: "NT$" },
|
104
|
+
};
|
105
|
+
const newTokenRates = () => ({
|
106
|
+
btc: null,
|
107
|
+
eth: null,
|
108
|
+
dot: null,
|
26
109
|
usd: null,
|
27
|
-
|
28
|
-
nzd: null,
|
29
|
-
cud: null,
|
30
|
-
hkd: null,
|
110
|
+
cny: null,
|
31
111
|
eur: null,
|
32
112
|
gbp: null,
|
113
|
+
cad: null,
|
114
|
+
aud: null,
|
115
|
+
nzd: null,
|
33
116
|
jpy: null,
|
34
|
-
krw: null,
|
35
|
-
cny: null,
|
36
117
|
rub: null,
|
37
|
-
|
38
|
-
|
39
|
-
|
118
|
+
krw: null,
|
119
|
+
idr: null,
|
120
|
+
php: null,
|
121
|
+
thb: null,
|
122
|
+
vnd: null,
|
123
|
+
inr: null,
|
124
|
+
try: null,
|
125
|
+
// hkd: null,
|
126
|
+
sgd: null
|
127
|
+
// twd: null,
|
40
128
|
});
|
41
129
|
|
42
|
-
|
43
|
-
|
130
|
+
class TokenRatesError extends Error {
|
131
|
+
constructor(message, response) {
|
132
|
+
super(message);
|
133
|
+
this.response = response;
|
134
|
+
}
|
135
|
+
}
|
44
136
|
|
45
137
|
// every currency in this list will be fetched from coingecko
|
46
138
|
// comment out unused currencies to save some bandwidth!
|
47
|
-
const coingeckoCurrencies =
|
48
|
-
//
|
49
|
-
//
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
139
|
+
const coingeckoCurrencies = Object.keys(SUPPORTED_CURRENCIES);
|
140
|
+
// api returns a 414 error if the url is too long, max length is about 8100 characters
|
141
|
+
// so use 7900 to be safe
|
142
|
+
const MAX_COINGECKO_URL_LENGTH = 7900;
|
143
|
+
const DEFAULT_COINGECKO_CONFIG = {
|
144
|
+
apiUrl: "https://api.coingecko.com"
|
145
|
+
};
|
54
146
|
|
55
147
|
// export function tokenRates(tokens: WithCoingeckoId[]): TokenRatesList {}
|
56
|
-
async function fetchTokenRates(tokens) {
|
148
|
+
async function fetchTokenRates(tokens, config = DEFAULT_COINGECKO_CONFIG) {
|
57
149
|
// create a map from `coingeckoId` -> `tokenId` for each token
|
58
150
|
const coingeckoIdToTokenIds = Object.values(tokens)
|
59
151
|
// ignore testnet tokens
|
60
152
|
.filter(({
|
61
153
|
isTestnet
|
62
|
-
}) => !isTestnet)
|
154
|
+
}) => !isTestnet).flatMap(token => {
|
155
|
+
// BEGIN: LP tokens have a rate which is calculated later on, using the rates of two other tokens.
|
156
|
+
//
|
157
|
+
// This section contains the logic such that: if token is an LP token, then fetch the rates for the two underlying tokens.
|
158
|
+
if (token.type === "evm-uniswapv2") {
|
159
|
+
if (!token.evmNetwork) return [];
|
160
|
+
const getToken = (evmNetworkId, tokenAddress, coingeckoId) => ({
|
161
|
+
id: evmErc20TokenId(evmNetworkId, tokenAddress),
|
162
|
+
coingeckoId
|
163
|
+
});
|
164
|
+
const token0 = token.coingeckoId0 ? [getToken(token.evmNetwork.id, token.tokenAddress0, token.coingeckoId0)] : [];
|
165
|
+
const token1 = token.coingeckoId1 ? [getToken(token.evmNetwork.id, token.tokenAddress1, token.coingeckoId1)] : [];
|
166
|
+
return [...token0, ...token1];
|
167
|
+
}
|
168
|
+
// END: LP tokens have a rate which is calculated later on, using the rates of two other tokens.
|
63
169
|
|
64
|
-
|
65
|
-
|
170
|
+
// ignore tokens which don't have a coingeckoId
|
171
|
+
if (!token.coingeckoId) return [];
|
172
|
+
return [{
|
173
|
+
id: token.id,
|
174
|
+
coingeckoId: token.coingeckoId
|
175
|
+
}];
|
176
|
+
})
|
66
177
|
|
67
178
|
// get each token's coingeckoId
|
68
179
|
.reduce((coingeckoIdToTokenIds, {
|
@@ -75,31 +186,55 @@ async function fetchTokenRates(tokens) {
|
|
75
186
|
}, {});
|
76
187
|
|
77
188
|
// create a list of coingeckoIds we want to fetch
|
78
|
-
const coingeckoIds = Object.keys(coingeckoIdToTokenIds);
|
189
|
+
const coingeckoIds = Object.keys(coingeckoIdToTokenIds).sort();
|
79
190
|
|
80
191
|
// skip network request if there is nothing for us to fetch
|
81
192
|
if (coingeckoIds.length < 1) return {};
|
82
193
|
|
83
|
-
// construct a coingecko request
|
84
|
-
|
85
|
-
const currenciesSerialized = coingeckoCurrencies.join(",");
|
86
|
-
const
|
194
|
+
// construct a coingecko request, sort args to help proxies with caching
|
195
|
+
|
196
|
+
const currenciesSerialized = coingeckoCurrencies.sort().join(",");
|
197
|
+
const safelyGetCoingeckoUrls = coingeckoIds => {
|
198
|
+
const idsSerialized = coingeckoIds.join(",");
|
199
|
+
const queryUrl = `${config.apiUrl}/api/v3/simple/price?ids=${idsSerialized}&vs_currencies=${currenciesSerialized}&include_market_cap=true&include_24hr_change=true`;
|
200
|
+
if (queryUrl.length > MAX_COINGECKO_URL_LENGTH) {
|
201
|
+
const half = Math.floor(coingeckoIds.length / 2);
|
202
|
+
return [...safelyGetCoingeckoUrls(coingeckoIds.slice(0, half)), ...safelyGetCoingeckoUrls(coingeckoIds.slice(half))];
|
203
|
+
}
|
204
|
+
return [queryUrl];
|
205
|
+
};
|
87
206
|
|
88
207
|
// fetch the token prices from coingecko
|
89
208
|
// the response should be in the format:
|
90
209
|
// {
|
91
210
|
// [coingeckoId]: {
|
92
211
|
// [currency]: rate
|
212
|
+
// [currency_24h_change]: percent
|
213
|
+
// [currency_market_cap]: value
|
93
214
|
// }
|
94
215
|
// }
|
95
|
-
|
216
|
+
|
217
|
+
const coingeckoHeaders = new Headers();
|
218
|
+
if (config.apiKeyName && config.apiKeyValue) {
|
219
|
+
coingeckoHeaders.set(config.apiKeyName, config.apiKeyValue);
|
220
|
+
}
|
221
|
+
const coingeckoPrices = await Promise.all(safelyGetCoingeckoUrls(coingeckoIds).map(async queryUrl => await fetch(queryUrl, {
|
222
|
+
headers: coingeckoHeaders
|
223
|
+
}).then(response => {
|
224
|
+
if (response.status !== 200) throw new TokenRatesError(`Failed to fetch token rates`, response);
|
225
|
+
return response.json();
|
226
|
+
}))).then(responses => Object.assign({}, ...responses));
|
96
227
|
|
97
228
|
// build a TokenRatesList from the token prices result
|
98
229
|
const ratesList = Object.fromEntries(coingeckoIds.flatMap(coingeckoId => {
|
99
230
|
const tokenIds = coingeckoIdToTokenIds[coingeckoId];
|
100
|
-
const rates =
|
231
|
+
const rates = newTokenRates();
|
101
232
|
for (const currency of coingeckoCurrencies) {
|
102
|
-
|
233
|
+
if (coingeckoPrices[coingeckoId]?.[currency]) rates[currency] = {
|
234
|
+
price: coingeckoPrices[coingeckoId][currency],
|
235
|
+
marketCap: coingeckoPrices[coingeckoId][`${currency}_market_cap`],
|
236
|
+
change24h: coingeckoPrices[coingeckoId][`${currency}_24h_change`]
|
237
|
+
};
|
103
238
|
}
|
104
239
|
return tokenIds.map(tokenId => [tokenId, rates]);
|
105
240
|
}));
|
@@ -107,8 +242,9 @@ async function fetchTokenRates(tokens) {
|
|
107
242
|
// return the TokenRatesList
|
108
243
|
return ratesList;
|
109
244
|
}
|
110
|
-
function hasCoingeckoId(token) {
|
111
|
-
return "coingeckoId" in token && typeof token.coingeckoId === "string";
|
112
|
-
}
|
113
245
|
|
114
|
-
|
246
|
+
// TODO: Move this into a common module which can then be imported both here and into EvmErc20Module
|
247
|
+
// We can't import this directly from EvmErc20Module because this package doesn't depend on `@talismn/balances`
|
248
|
+
const evmErc20TokenId = (chainId, tokenContractAddress) => `${chainId}-evm-erc20-${tokenContractAddress}`.toLowerCase();
|
249
|
+
|
250
|
+
export { DEFAULT_COINGECKO_CONFIG, SUPPORTED_CURRENCIES, TalismanTokenRatesDatabase, TokenRatesError, db, fetchTokenRates, newTokenRates };
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@talismn/token-rates",
|
3
|
-
"version": "0.
|
3
|
+
"version": "1.0.0",
|
4
4
|
"author": "Talisman",
|
5
5
|
"homepage": "https://talisman.xyz",
|
6
6
|
"license": "GPL-3.0-or-later",
|
@@ -20,29 +20,28 @@
|
|
20
20
|
"engines": {
|
21
21
|
"node": ">=18"
|
22
22
|
},
|
23
|
-
"scripts": {
|
24
|
-
"test": "jest",
|
25
|
-
"lint": "eslint src --max-warnings 0",
|
26
|
-
"clean": "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
27
|
-
},
|
28
23
|
"dependencies": {
|
29
|
-
"
|
30
|
-
"
|
31
|
-
"dexie": "^3.2.4"
|
24
|
+
"dexie": "^4.0.9",
|
25
|
+
"@talismn/chaindata-provider": "0.8.0"
|
32
26
|
},
|
33
27
|
"devDependencies": {
|
34
|
-
"@
|
35
|
-
"
|
36
|
-
"@types/jest": "^27.5.1",
|
37
|
-
"eslint": "^8.52.0",
|
28
|
+
"@types/jest": "^29.5.14",
|
29
|
+
"eslint": "^8.57.1",
|
38
30
|
"jest": "^29.7.0",
|
39
|
-
"ts-jest": "^29.
|
40
|
-
"typescript": "^5.
|
31
|
+
"ts-jest": "^29.2.5",
|
32
|
+
"typescript": "^5.6.3",
|
33
|
+
"@talismn/tsconfig": "0.0.2",
|
34
|
+
"@talismn/eslint-config": "0.0.3"
|
41
35
|
},
|
42
36
|
"eslintConfig": {
|
43
37
|
"root": true,
|
44
38
|
"extends": [
|
45
39
|
"@talismn/eslint-config/base"
|
46
40
|
]
|
41
|
+
},
|
42
|
+
"scripts": {
|
43
|
+
"test": "jest",
|
44
|
+
"lint": "eslint src --max-warnings 0",
|
45
|
+
"clean": "rm -rf dist .turbo node_modules"
|
47
46
|
}
|
48
47
|
}
|
package/CHANGELOG.md
DELETED
@@ -1,178 +0,0 @@
|
|
1
|
-
# @talismn/token-rates
|
2
|
-
|
3
|
-
## 0.3.0
|
4
|
-
|
5
|
-
### Minor Changes
|
6
|
-
|
7
|
-
- 123647e: - Additional currencies support for token rate
|
8
|
-
- New Dollar sign icon
|
9
|
-
- 123647e: Add extra currency options
|
10
|
-
|
11
|
-
### Patch Changes
|
12
|
-
|
13
|
-
- c4d5967: bump typescript version
|
14
|
-
- 620b7eb: Dependency updates
|
15
|
-
- Updated dependencies [03939d5]
|
16
|
-
- Updated dependencies [ade2908]
|
17
|
-
- Updated dependencies [c4d5967]
|
18
|
-
- Updated dependencies [620b7eb]
|
19
|
-
- Updated dependencies [5aadf99]
|
20
|
-
- Updated dependencies [4cace80]
|
21
|
-
- @talismn/chaindata-provider@0.8.0
|
22
|
-
|
23
|
-
## 0.2.0
|
24
|
-
|
25
|
-
### Minor Changes
|
26
|
-
|
27
|
-
- b920ab98: Added GPL licence
|
28
|
-
|
29
|
-
### Patch Changes
|
30
|
-
|
31
|
-
- 3c1a8b10: Dependency updates
|
32
|
-
- Updated dependencies [3c1a8b10]
|
33
|
-
- Updated dependencies [b920ab98]
|
34
|
-
- @talismn/chaindata-provider@0.7.0
|
35
|
-
|
36
|
-
## 0.1.18
|
37
|
-
|
38
|
-
### Patch Changes
|
39
|
-
|
40
|
-
- @talismn/chaindata-provider@0.6.0
|
41
|
-
|
42
|
-
## 0.1.17
|
43
|
-
|
44
|
-
### Patch Changes
|
45
|
-
|
46
|
-
- Updated dependencies [1a2fdc73]
|
47
|
-
- @talismn/chaindata-provider@0.5.0
|
48
|
-
|
49
|
-
## 0.1.16
|
50
|
-
|
51
|
-
### Patch Changes
|
52
|
-
|
53
|
-
- f7aca48b: eslint rules
|
54
|
-
- 01bf239b: fix: packages publishing with incorrect interdependency versions
|
55
|
-
- Updated dependencies [f7aca48b]
|
56
|
-
- Updated dependencies [48f0222e]
|
57
|
-
- Updated dependencies [01bf239b]
|
58
|
-
- @talismn/chaindata-provider@0.4.4
|
59
|
-
|
60
|
-
## 0.1.15
|
61
|
-
|
62
|
-
### Patch Changes
|
63
|
-
|
64
|
-
- 6643a4e4: fix: tokenRates in @talismn/balances-react
|
65
|
-
- Updated dependencies [79f6ccf6]
|
66
|
-
- Updated dependencies [c24dc1fb]
|
67
|
-
- @talismn/chaindata-provider@0.4.3
|
68
|
-
|
69
|
-
## 0.1.14
|
70
|
-
|
71
|
-
### Patch Changes
|
72
|
-
|
73
|
-
- @talismn/chaindata-provider@0.4.2
|
74
|
-
|
75
|
-
## 0.1.13
|
76
|
-
|
77
|
-
### Patch Changes
|
78
|
-
|
79
|
-
- 8adc7f06: feat: switched build tool to preconstruct
|
80
|
-
- Updated dependencies [8adc7f06]
|
81
|
-
- @talismn/chaindata-provider@0.4.1
|
82
|
-
|
83
|
-
## 0.1.12
|
84
|
-
|
85
|
-
### Patch Changes
|
86
|
-
|
87
|
-
- 4aa691d: feat: new balance modules
|
88
|
-
- Updated dependencies [4aa691d]
|
89
|
-
- @talismn/chaindata-provider@0.2.1
|
90
|
-
|
91
|
-
## 0.1.11
|
92
|
-
|
93
|
-
### Patch Changes
|
94
|
-
|
95
|
-
- @talismn/chaindata-provider@0.2.0
|
96
|
-
|
97
|
-
## 0.1.10
|
98
|
-
|
99
|
-
### Patch Changes
|
100
|
-
|
101
|
-
- fix: a variety of improvements from the wallet integration
|
102
|
-
- Updated dependencies
|
103
|
-
- @talismn/chaindata-provider@0.1.10
|
104
|
-
|
105
|
-
## 0.1.9
|
106
|
-
|
107
|
-
### Patch Changes
|
108
|
-
|
109
|
-
- Updated dependencies [8ecb8214]
|
110
|
-
- @talismn/chaindata-provider@0.1.9
|
111
|
-
|
112
|
-
## 0.1.8
|
113
|
-
|
114
|
-
### Patch Changes
|
115
|
-
|
116
|
-
- @talismn/chaindata-provider@0.1.8
|
117
|
-
|
118
|
-
## 0.1.7
|
119
|
-
|
120
|
-
### Patch Changes
|
121
|
-
|
122
|
-
- db04d0d: fix: missing token rates and empty token rates requests
|
123
|
-
- @talismn/chaindata-provider@0.1.7
|
124
|
-
|
125
|
-
## 0.1.6
|
126
|
-
|
127
|
-
### Patch Changes
|
128
|
-
|
129
|
-
- ca50757: feat: implemented token fiat rates in @talismn/balances
|
130
|
-
- Updated dependencies [ca50757]
|
131
|
-
- @talismn/chaindata-provider@0.1.6
|
132
|
-
|
133
|
-
## 0.1.5
|
134
|
-
|
135
|
-
### Patch Changes
|
136
|
-
|
137
|
-
- Updated dependencies [d66c5bc]
|
138
|
-
- @talismn/chaindata-provider@0.1.5
|
139
|
-
|
140
|
-
## 0.1.4
|
141
|
-
|
142
|
-
### Patch Changes
|
143
|
-
|
144
|
-
- @talismn/chaindata-provider@0.1.4
|
145
|
-
|
146
|
-
## 0.1.3
|
147
|
-
|
148
|
-
### Patch Changes
|
149
|
-
|
150
|
-
- Updated dependencies [d5f69f7]
|
151
|
-
- @talismn/chaindata-provider@0.1.3
|
152
|
-
|
153
|
-
## 0.1.2
|
154
|
-
|
155
|
-
### Patch Changes
|
156
|
-
|
157
|
-
- 5af305c: switched build output from esm to commonjs for ecosystem compatibility
|
158
|
-
- Updated dependencies [5af305c]
|
159
|
-
- @talismn/chaindata-provider@0.1.2
|
160
|
-
|
161
|
-
## 0.1.1
|
162
|
-
|
163
|
-
### Patch Changes
|
164
|
-
|
165
|
-
- Fixed publish config
|
166
|
-
- Updated dependencies
|
167
|
-
- @talismn/chaindata-provider@0.1.1
|
168
|
-
|
169
|
-
## 0.1.0
|
170
|
-
|
171
|
-
### Minor Changes
|
172
|
-
|
173
|
-
- 43c1a3a: Initial release
|
174
|
-
|
175
|
-
### Patch Changes
|
176
|
-
|
177
|
-
- Updated dependencies [43c1a3a]
|
178
|
-
- @talismn/chaindata-provider@0.1.0
|