Skip to content

Commit 592c474

Browse files
authored
Add support 0x Swap Quote fetching (#105)
1 parent 925438f commit 592c474

File tree

13 files changed

+1120
-317
lines changed

13 files changed

+1120
-317
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "set.js",
3-
"version": "0.4.12",
3+
"version": "0.5.0",
44
"description": "A javascript library for interacting with the Set Protocol v2",
55
"keywords": [
66
"set.js",

src/Set.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
SlippageIssuanceAPI,
3434
PerpV2LeverageAPI,
3535
PerpV2LeverageViewerAPI,
36+
UtilsAPI,
3637
} from './api/index';
3738

3839
const ethersProviders = require('ethers').providers;
@@ -134,6 +135,12 @@ class Set {
134135
*/
135136
public blockchain: BlockchainAPI;
136137

138+
/**
139+
* An instance of the UtilsAPI class. Contains interfaces for fetching swap quotes from 0x Protocol,
140+
* prices and token metadata from coingecko, and network gas prices from various sources
141+
*/
142+
public utils: UtilsAPI;
143+
137144
/**
138145
* Instantiates a new Set instance that provides the public interface to the Set.js library
139146
*/
@@ -155,7 +162,7 @@ class Set {
155162
assertions
156163
);
157164
this.system = new SystemAPI(ethersProvider, config.controllerAddress);
158-
this.trade = new TradeAPI(ethersProvider, config.tradeModuleAddress, config.zeroExApiKey);
165+
this.trade = new TradeAPI(ethersProvider, config.tradeModuleAddress, config.zeroExApiKey, config.zeroExApiUrls);
159166
this.navIssuance = new NavIssuanceAPI(ethersProvider, config.navIssuanceModuleAddress);
160167
this.priceOracle = new PriceOracleAPI(ethersProvider, config.masterOracleAddress);
161168
this.debtIssuance = new DebtIssuanceAPI(ethersProvider, config.debtIssuanceModuleAddress);
@@ -164,6 +171,7 @@ class Set {
164171
this.perpV2Leverage = new PerpV2LeverageAPI(ethersProvider, config.perpV2LeverageModuleAddress);
165172
this.perpV2LeverageViewer = new PerpV2LeverageViewerAPI(ethersProvider, config.perpV2LeverageModuleViewerAddress);
166173
this.blockchain = new BlockchainAPI(ethersProvider, assertions);
174+
this.utils = new UtilsAPI(ethersProvider, config.zeroExApiKey, config.zeroExApiUrls);
167175
}
168176
}
169177

src/api/TradeAPI.ts

Lines changed: 12 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,12 @@ import SetTokenAPI from './SetTokenAPI';
2727
import Assertions from '../assertions';
2828

2929
import {
30-
TradeQuoter,
31-
CoinGeckoDataService,
32-
GasOracleService
30+
TradeQuoter
3331
} from './utils';
3432

3533
import {
3634
TradeQuote,
37-
CoinGeckoTokenData,
38-
CoinGeckoTokenMap,
39-
GasOracleSpeed,
40-
CoinGeckoCoinPrices
35+
ZeroExApiUrls
4136
} from '../types';
4237

4338
/**
@@ -53,18 +48,17 @@ export default class TradeAPI {
5348
private assert: Assertions;
5449
private provider: Provider;
5550
private tradeQuoter: TradeQuoter;
56-
private coinGecko: CoinGeckoDataService;
57-
private chainId: number;
5851

5952
public constructor(
6053
provider: Provider,
6154
tradeModuleAddress: Address,
6255
zeroExApiKey?: string,
56+
zeroExApiUrls?: ZeroExApiUrls
6357
) {
6458
this.provider = provider;
6559
this.tradeModuleWrapper = new TradeModuleWrapper(provider, tradeModuleAddress);
6660
this.assert = new Assertions();
67-
this.tradeQuoter = new TradeQuoter(zeroExApiKey);
61+
this.tradeQuoter = new TradeQuoter(zeroExApiKey, zeroExApiUrls);
6862
}
6963

7064
/**
@@ -150,7 +144,8 @@ export default class TradeAPI {
150144
* @param isFirmQuote (Optional) Whether quote request is indicative or firm
151145
* @param feePercentage (Optional) Default: 0
152146
* @param feeRecipient (Optional) Default: 0xD3D555Bb655AcBA9452bfC6D7cEa8cC7b3628C55
153-
* @param excludedSources (Optional) Exchanges to exclude (Default: ['Kyber', 'Eth2Dai', 'Uniswap', 'Mesh'])
147+
* @param excludedSources (Optional) Exchanges to exclude (Default: ['Kyber', 'Eth2Dai', 'Mesh'])
148+
* @param simulatedChainId (Optional) ChainId of target network (useful when using a forked development client)
154149
*
155150
* @return {Promise<TradeQuote>}
156151
*/
@@ -168,6 +163,7 @@ export default class TradeAPI {
168163
feePercentage?: number,
169164
feeRecipient?: Address,
170165
excludedSources?: string[],
166+
simulatedChainId?: number,
171167
): Promise<TradeQuote> {
172168
this.assert.schema.isValidAddress('fromToken', fromToken);
173169
this.assert.schema.isValidAddress('toToken', toToken);
@@ -176,9 +172,12 @@ export default class TradeAPI {
176172
this.assert.schema.isValidJsNumber('toTokenDecimals', toTokenDecimals);
177173
this.assert.schema.isValidString('rawAmount', rawAmount);
178174

179-
const chainId = (await this.provider.getNetwork()).chainId;
175+
// The forked Hardhat network has a chainId of 31337 so we can't rely on autofetching this value
176+
const chainId = (simulatedChainId !== undefined)
177+
? simulatedChainId
178+
: (await this.provider.getNetwork()).chainId;
180179

181-
return this.tradeQuoter.generate({
180+
return this.tradeQuoter.generateQuoteForTrade({
182181
fromToken,
183182
toToken,
184183
fromTokenDecimals,
@@ -197,67 +196,4 @@ export default class TradeAPI {
197196
excludedSources,
198197
});
199198
}
200-
201-
/**
202-
* Fetches a list of tokens and their metadata from CoinGecko. Each entry includes
203-
* the token's address, proper name, decimals, exchange symbol and a logo URI if available.
204-
* For Ethereum, this is a list of tokens tradeable on Uniswap, for Polygon it's a list of
205-
* tokens tradeable on Sushiswap's Polygon exchange. Method is useful for acquiring token decimals
206-
* necessary to generate a trade quote and images for representing available tokens in a UI.
207-
*
208-
* @return List of tradeable tokens for chain platform
209-
*/
210-
public async fetchTokenListAsync(): Promise<CoinGeckoTokenData[]> {
211-
await this.initializeForChain();
212-
return this.coinGecko.fetchTokenList();
213-
}
214-
215-
/**
216-
* Fetches the same info as `fetchTokenList` in the form of a map indexed by address. Method is
217-
* useful if you're cacheing the token list and want quick lookups for a variety of trades.
218-
*
219-
* @return Map of token addresses to token metadata
220-
*/
221-
public async fetchTokenMapAsync(): Promise<CoinGeckoTokenMap> {
222-
await this.initializeForChain();
223-
return this.coinGecko.fetchTokenMap();
224-
}
225-
226-
/**
227-
* Fetches a list of prices vs currencies for the specified inputs from CoinGecko
228-
*
229-
* @param contractAddresses String array of contract addresses
230-
* @param vsCurrencies String array of currency codes (see CoinGecko api for a complete list)
231-
*
232-
* @return List of prices vs currencies
233-
*/
234-
public async fetchCoinPricesAsync(
235-
contractAddresses: string[],
236-
vsCurrencies: string[]
237-
): Promise<CoinGeckoCoinPrices> {
238-
await this.initializeForChain();
239-
return this.coinGecko.fetchCoinPrices({contractAddresses, vsCurrencies});
240-
}
241-
242-
/**
243-
* Fetches the recommended gas price for a specified execution speed.
244-
*
245-
* @param speed (Optional) string value: "average" | "fast" | "fastest" (Default: fast)
246-
*
247-
* @return Number: gas price
248-
*/
249-
public async fetchGasPriceAsync(speed?: GasOracleSpeed): Promise<number> {
250-
await this.initializeForChain();
251-
const oracle = new GasOracleService(this.chainId);
252-
return oracle.fetchGasPrice(speed);
253-
}
254-
255-
256-
private async initializeForChain() {
257-
if (this.coinGecko === undefined) {
258-
const network = await this.provider.getNetwork();
259-
this.chainId = network.chainId;
260-
this.coinGecko = new CoinGeckoDataService(network.chainId);
261-
}
262-
}
263199
}

0 commit comments

Comments
 (0)