@indigo-labs/dexter
Version:
Customizable Typescript SDK for interacting with Cardano DEXs
138 lines (137 loc) • 5.18 kB
JavaScript
import { BaseDataProvider } from './base-data-provider';
import axios from 'axios';
import { Asset } from '../../dex/models/asset';
import Bottleneck from 'bottleneck';
import { appendSlash } from '../../utils';
const API_BURST_SIZE = 500;
const API_COOLDOWN_SIZE = 10;
const API_COOLDOWN_MS = 1000;
export class BlockfrostProvider extends BaseDataProvider {
/**
* https://docs.blockfrost.io/
*/
constructor(config, requestConfig = {}) {
super();
this._requestConfig = Object.assign({}, {
timeout: 5000,
proxyUrl: '',
}, requestConfig);
this._api = axios.create({
baseURL: (appendSlash(requestConfig.proxyUrl)) + config.url,
timeout: this._requestConfig.timeout,
headers: {
'Content-Type': 'application/json',
project_id: config.projectId,
},
});
// https://docs.blockfrost.io/#section/Limits
this._limiter = new Bottleneck({
reservoir: API_BURST_SIZE,
reservoirIncreaseAmount: API_COOLDOWN_SIZE,
reservoirIncreaseInterval: API_COOLDOWN_MS,
reservoirIncreaseMaximum: API_BURST_SIZE,
});
}
/**
* https://docs.blockfrost.io/#tag/Cardano-Addresses/paths/~1addresses~1%7Baddress%7D~1utxos/get
* https://docs.blockfrost.io/#tag/Cardano-Addresses/paths/~1addresses~1%7Baddress%7D~1utxos~1%7Basset%7D/get
*/
async utxos(address, asset) {
return this.sendPaginatedRequest(`/addresses/${address}/utxos/${asset ? asset.identifier() : ''}`)
.then((results) => {
return results.map((utxo) => {
return {
txHash: utxo.tx_hash,
address: utxo.address,
datumHash: utxo.data_hash,
outputIndex: utxo.output_index,
assetBalances: utxo.amount.reduce((assets, amount) => {
assets.push({
asset: amount.unit === 'lovelace' ? amount.unit : Asset.fromIdentifier(amount.unit),
quantity: BigInt(amount.quantity),
});
return assets;
}, []),
};
});
});
}
/**
* https://docs.blockfrost.io/#tag/Cardano-Transactions/paths/~1txs~1%7Bhash%7D~1utxos/get
*/
async transactionUtxos(txHash) {
return this._limiter.schedule(() => this._api.get(`/txs/${txHash}/utxos`))
.then((response) => {
return response.data.outputs.map((utxo) => {
return {
txHash: response.data.hash,
address: utxo.address,
datumHash: utxo.data_hash,
datum: utxo.inline_datum,
outputIndex: utxo.output_index,
assetBalances: utxo.amount.reduce((assets, amount) => {
assets.push({
asset: amount.unit === 'lovelace' ? amount.unit : Asset.fromIdentifier(amount.unit),
quantity: BigInt(amount.quantity),
});
return assets;
}, []),
};
});
});
}
/**
* https://docs.blockfrost.io/#tag/Cardano-Assets/paths/~1assets~1%7Basset%7D~1transactions/get
*/
async assetTransactions(asset) {
return this.sendPaginatedRequest(`/assets/${asset.identifier()}/transactions`)
.then((results) => {
return results.map((tx) => {
return {
hash: tx.tx_hash,
};
});
});
}
/**
* https://docs.blockfrost.io/#tag/Cardano-Assets/paths/~1assets~1%7Basset%7D~1transactions/get
*/
async assetAddresses(asset) {
return this.sendPaginatedRequest(`/assets/${asset.identifier()}/addresses`)
.then((results) => {
return results.map((result) => {
return {
address: result.address,
quantity: BigInt(result.quantity),
};
});
});
}
/**
* https://docs.blockfrost.io/#tag/Cardano-Scripts/paths/~1scripts~1datum~1%7Bdatum_hash%7D/get
*/
async datumValue(datumHash) {
return this._limiter.schedule(() => this._api.get(`/scripts/datum/${datumHash}`))
.then((response) => {
return response.data.json_value;
});
}
/**
* https://docs.blockfrost.io/#section/Concepts
*/
sendPaginatedRequest(url, page = 1, results = []) {
return this._limiter.schedule(() => this._api.get(url, {
params: {
page,
},
})).then((response) => {
results = results.concat(response.data);
page++;
// Possibly more data to grab
if (response.data.length === 100) {
return this.sendPaginatedRequest(url, page, results);
}
return results;
});
}
}