@cardano-sdk/blockfrost
Advanced tools
Comparing version 0.1.5 to 0.1.6
@@ -8,2 +8,3 @@ "use strict"; | ||
const ts_log_1 = require("ts-log"); | ||
const lodash_es_1 = require("lodash-es"); | ||
const formatBlockfrostError = (error) => { | ||
@@ -28,5 +29,5 @@ const blockfrostError = error; | ||
return { | ||
status_code, | ||
error: errorAsType2.errno.toString(), | ||
message: errorAsType1.message, | ||
error: errorAsType2.errno.toString() | ||
status_code | ||
}; | ||
@@ -45,2 +46,22 @@ } | ||
const blockfrost = new blockfrost_js_1.BlockFrostAPI(options); | ||
const fetchByAddressSequentially = async (props, accumulated = [], count = 0, page = 1) => { | ||
try { | ||
const response = await props.request(props.address, { count, page }); | ||
const totalCount = count + response.length; | ||
const maybeTranslatedResponse = props.responseTranslator | ||
? props.responseTranslator(props.address, response) | ||
: response; | ||
const newAccumulatedItems = [...accumulated, ...maybeTranslatedResponse]; | ||
if (response.length === 100) { | ||
return fetchByAddressSequentially(props, newAccumulatedItems, totalCount, page + 1); | ||
} | ||
return newAccumulatedItems; | ||
} | ||
catch (error) { | ||
if (error.status_code === 404) { | ||
return []; | ||
} | ||
throw error; | ||
} | ||
}; | ||
const ledgerTip = async () => { | ||
@@ -92,13 +113,28 @@ const block = await blockfrost.blocksLatest(); | ||
const submitTx = async (signedTransaction) => { | ||
await blockfrost.txSubmit(signedTransaction.to_bytes()); | ||
await blockfrost.txSubmit(signedTransaction); | ||
}; | ||
const utxoDelegationAndRewards = async (addresses, stakeKeyHash) => { | ||
const utxoResults = await Promise.all(addresses.map(async (address) => blockfrost.addressesUtxosAll(address).then((result) => BlockfrostToCore_1.BlockfrostToCore.addressUtxoContent(address, result)))); | ||
const utxoDelegationAndRewards = async (addresses, rewardAccount) => { | ||
const utxoResults = await Promise.all(addresses.map(async (address) => fetchByAddressSequentially({ | ||
address, | ||
request: (addr, pagination) => blockfrost.addressesUtxos(addr, pagination), | ||
responseTranslator: (addr, response) => BlockfrostToCore_1.BlockfrostToCore.addressUtxoContent(addr, response) | ||
}))); | ||
const utxo = utxoResults.flat(1); | ||
const accountResponse = await blockfrost.accounts(stakeKeyHash); | ||
const delegationAndRewards = { | ||
delegate: accountResponse.pool_id || undefined, | ||
rewards: BigInt(accountResponse.withdrawable_amount) | ||
}; | ||
return { utxo, delegationAndRewards }; | ||
if (rewardAccount !== undefined) { | ||
try { | ||
const accountResponse = await blockfrost.accounts(rewardAccount); | ||
const delegationAndRewards = { | ||
delegate: accountResponse.pool_id || undefined, | ||
rewards: BigInt(accountResponse.withdrawable_amount) | ||
}; | ||
return { delegationAndRewards, utxo }; | ||
} | ||
catch (error) { | ||
if (error.status_code === 404) { | ||
return { utxo }; | ||
} | ||
throw error; | ||
} | ||
} | ||
return { utxo }; | ||
}; | ||
@@ -110,3 +146,2 @@ const fetchRedeemers = async ({ redeemer_count, hash }) => { | ||
return response.map(({ purpose, script_hash, unit_mem, unit_steps, tx_index }) => ({ | ||
index: tx_index, | ||
executionUnits: { | ||
@@ -116,2 +151,3 @@ memory: Number.parseInt(unit_mem), | ||
}, | ||
index: tx_index, | ||
purpose: (() => { | ||
@@ -135,4 +171,4 @@ switch (purpose) { | ||
return response.map(({ address, amount }) => ({ | ||
address, | ||
quantity: BigInt(amount) | ||
quantity: BigInt(amount), | ||
stakeAddress: address | ||
})); | ||
@@ -147,7 +183,6 @@ }; | ||
const response = await blockfrost.txsPoolRetires(hash); | ||
return response.map(({ cert_index, pool_id, retiring_epoch }) => ({ | ||
return response.map(({ pool_id, retiring_epoch }) => ({ | ||
__typename: core_1.Cardano.CertificateType.PoolRetirement, | ||
epoch: retiring_epoch, | ||
certIndex: cert_index, | ||
poolId: pool_id, | ||
type: core_1.Cardano.CertificateType.PoolRetirement | ||
poolId: pool_id | ||
})); | ||
@@ -157,7 +192,10 @@ }; | ||
const response = await blockfrost.txsPoolUpdates(hash); | ||
return response.map(({ cert_index, pool_id, active_epoch }) => ({ | ||
return response.map(({ pool_id, active_epoch }) => ({ | ||
__typename: core_1.Cardano.CertificateType.PoolRegistration, | ||
epoch: active_epoch, | ||
certIndex: cert_index, | ||
poolId: pool_id, | ||
type: core_1.Cardano.CertificateType.PoolRegistration | ||
poolParameters: (() => { | ||
logger.warn('Omitting poolParameters for certificate in tx', hash); | ||
return null; | ||
})() | ||
})); | ||
@@ -168,7 +206,7 @@ }; | ||
return response.map(({ address, amount, cert_index, pot }) => ({ | ||
type: core_1.Cardano.CertificateType.MIR, | ||
__typename: core_1.Cardano.CertificateType.MIR, | ||
address, | ||
quantity: BigInt(amount), | ||
certIndex: cert_index, | ||
pot | ||
pot, | ||
quantity: BigInt(amount) | ||
})); | ||
@@ -179,3 +217,5 @@ }; | ||
return response.map(({ address, cert_index, registration }) => ({ | ||
type: registration ? core_1.Cardano.CertificateType.StakeRegistration : core_1.Cardano.CertificateType.StakeDeregistration, | ||
__typename: registration | ||
? core_1.Cardano.CertificateType.StakeRegistration | ||
: core_1.Cardano.CertificateType.StakeDeregistration, | ||
address, | ||
@@ -188,6 +228,6 @@ certIndex: cert_index | ||
return response.map(({ cert_index, index, address, active_epoch, pool_id }) => ({ | ||
type: core_1.Cardano.CertificateType.StakeDelegation, | ||
__typename: core_1.Cardano.CertificateType.StakeDelegation, | ||
address, | ||
certIndex: cert_index, | ||
delegationIndex: index, | ||
address, | ||
epoch: active_epoch, | ||
@@ -213,17 +253,13 @@ poolId: pool_id | ||
return { | ||
id: hash, | ||
blockHeader: { | ||
slot: response.slot, | ||
blockHash: response.block, | ||
blockHeight: response.block_height, | ||
blockHash: response.block | ||
slot: response.slot | ||
}, | ||
txSize: response.size, | ||
implicitCoin: { | ||
deposit: BigInt(response.deposit) | ||
}, | ||
body: { | ||
index: response.index, | ||
certificates: await fetchCertificates(response), | ||
fee: BigInt(response.fees), | ||
inputs, | ||
mint: await fetchMint(response), | ||
outputs, | ||
fee: BigInt(response.fees), | ||
validityInterval: { | ||
@@ -233,8 +269,13 @@ invalidBefore: parseValidityInterval(response.invalid_before), | ||
}, | ||
withdrawals: await fetchWithdrawals(response), | ||
mint: await fetchMint(response), | ||
certificates: await fetchCertificates(response) | ||
withdrawals: await fetchWithdrawals(response) | ||
}, | ||
id: hash, | ||
implicitCoin: { | ||
deposit: BigInt(response.deposit) | ||
}, | ||
index: response.index, | ||
txSize: response.size, | ||
witness: { | ||
redeemers: await fetchRedeemers(response) | ||
redeemers: await fetchRedeemers(response), | ||
signatures: {} | ||
} | ||
@@ -245,3 +286,6 @@ }; | ||
const queryTransactionsByAddresses = async (addresses) => { | ||
const addressTransactions = await Promise.all(addresses.map(async (address) => blockfrost.addressesTransactionsAll(address))); | ||
const addressTransactions = await Promise.all(addresses.map(async (address) => fetchByAddressSequentially({ | ||
address, | ||
request: (addr, pagination) => blockfrost.addressesTransactions(addr, pagination) | ||
}))); | ||
const transactionsArray = await Promise.all(addressTransactions.map((transactionArray) => queryTransactionsByHashes(transactionArray.map(({ tx_hash }) => tx_hash)))); | ||
@@ -256,11 +300,82 @@ return transactionsArray.flat(1); | ||
}; | ||
const accountRewards = async (stakeAddress, { lowerBound = 0, upperBound = Number.MAX_SAFE_INTEGER } = {}) => { | ||
const result = []; | ||
const batchSize = 100; | ||
let page = 1; | ||
let haveMorePages = true; | ||
while (haveMorePages) { | ||
const rewards = await blockfrost.accountsRewards(stakeAddress, { count: batchSize, page }); | ||
result.push(...rewards | ||
.filter(({ epoch }) => lowerBound <= epoch && epoch <= upperBound) | ||
.map(({ epoch, amount }) => ({ | ||
epoch, | ||
rewards: BigInt(amount) | ||
}))); | ||
haveMorePages = rewards[rewards.length - 1].epoch < upperBound && rewards.length === 100; | ||
page += 1; | ||
} | ||
return result; | ||
}; | ||
const rewardsHistory = async ({ stakeAddresses, epochs }) => { | ||
const allAddressRewards = await Promise.all(stakeAddresses.map((address) => accountRewards(address, epochs))); | ||
const accountRewardsByEpoch = lodash_es_1.groupBy(lodash_es_1.flatten(allAddressRewards), ({ epoch }) => epoch); | ||
return Object.keys(accountRewardsByEpoch).map((key) => ({ | ||
epoch: accountRewardsByEpoch[key][0].epoch, | ||
rewards: core_1.BigIntMath.sum(accountRewardsByEpoch[key].map(({ rewards }) => rewards)) | ||
})); | ||
}; | ||
const genesisParameters = async () => { | ||
const response = await blockfrost.genesis(); | ||
return { | ||
activeSlotsCoefficient: response.active_slots_coefficient, | ||
epochLength: response.epoch_length, | ||
maxKesEvolutions: response.max_kes_evolutions, | ||
maxLovelaceSupply: BigInt(response.max_lovelace_supply), | ||
networkMagic: response.network_magic, | ||
securityParameter: response.security_param, | ||
slotLength: response.slot_length, | ||
slotsPerKesPeriod: response.slots_per_kes_period, | ||
systemStart: new Date(response.system_start * 1000), | ||
updateQuorum: response.update_quorum | ||
}; | ||
}; | ||
const queryBlocksByHashes = async (hashes) => { | ||
const responses = await Promise.all(hashes.map((hash) => blockfrost.blocks(hash))); | ||
return responses.map((response) => { | ||
if (!response.epoch || !response.epoch_slot || !response.height || !response.slot || !response.block_vrf) { | ||
throw new core_1.ProviderError(core_1.ProviderFailure.Unknown, null, 'Queried unsupported block'); | ||
} | ||
return { | ||
confirmations: response.confirmations, | ||
date: new Date(response.time * 1000), | ||
epoch: response.epoch, | ||
epochSlot: response.epoch_slot, | ||
fees: BigInt(response.fees || '0'), | ||
header: { | ||
blockHash: response.hash, | ||
blockHeight: response.height, | ||
slot: response.slot | ||
}, | ||
nextBlock: response.next_block || undefined, | ||
previousBlock: response.previous_block || undefined, | ||
size: response.size, | ||
slotLeader: response.slot_leader, | ||
totalOutput: BigInt(response.output || '0'), | ||
txCount: response.tx_count, | ||
vrf: response.block_vrf | ||
}; | ||
}); | ||
}; | ||
const providerFunctions = { | ||
currentWalletProtocolParameters, | ||
genesisParameters, | ||
ledgerTip, | ||
networkInfo, | ||
queryBlocksByHashes, | ||
queryTransactionsByAddresses, | ||
queryTransactionsByHashes, | ||
rewardsHistory, | ||
stakePoolStats, | ||
submitTx, | ||
utxoDelegationAndRewards, | ||
queryTransactionsByAddresses, | ||
queryTransactionsByHashes, | ||
currentWalletProtocolParameters | ||
utxoDelegationAndRewards | ||
}; | ||
@@ -267,0 +382,0 @@ return Object.keys(providerFunctions).reduce((provider, key) => { |
@@ -0,3 +1,3 @@ | ||
import { Cardano, ProtocolParametersRequiredByWallet } from '@cardano-sdk/core'; | ||
import { Responses } from '@blockfrost/blockfrost-js'; | ||
import { Cardano, ProtocolParametersRequiredByWallet } from '@cardano-sdk/core'; | ||
declare type Unpacked<T> = T extends (infer U)[] ? U : T; | ||
@@ -9,14 +9,8 @@ declare type BlockfrostAddressUtxoContent = Responses['address_utxo_content']; | ||
declare type BlockfrostOutput = Unpacked<BlockfrostOutputs>; | ||
declare type BlockfrostUtxo = Unpacked<BlockfrostAddressUtxoContent>; | ||
export declare type BlockfrostTransactionContent = Unpacked<Responses['address_transactions_content']>; | ||
export declare type BlockfrostUtxo = Unpacked<BlockfrostAddressUtxoContent>; | ||
export declare const BlockfrostToCore: { | ||
addressUtxoContent: (address: string, blockfrost: Responses['address_utxo_content']) => Cardano.Utxo[]; | ||
transactionUtxos: (utxoResponse: Responses['tx_content_utxo']) => { | ||
inputs: { | ||
address: string; | ||
txId: string; | ||
index: number; | ||
}[]; | ||
outputs: Cardano.TxOut[]; | ||
}; | ||
blockToTip: (block: Responses['block_content']) => Cardano.Tip; | ||
currentWalletProtocolParameters: (blockfrost: Responses['epoch_param_content']) => ProtocolParametersRequiredByWallet; | ||
inputFromUtxo: (address: string, utxo: BlockfrostUtxo) => BlockfrostInput; | ||
@@ -43,12 +37,19 @@ inputs: (inputs: { | ||
}[]) => Cardano.TxOut[]; | ||
transactionUtxos: (utxoResponse: Responses['tx_content_utxo']) => { | ||
inputs: { | ||
address: string; | ||
txId: string; | ||
index: number; | ||
}[]; | ||
outputs: Cardano.TxOut[]; | ||
}; | ||
txContentUtxo: (blockfrost: Responses['tx_content_utxo']) => { | ||
hash: string; | ||
inputs: Cardano.TxIn[]; | ||
outputs: Cardano.TxOut[]; | ||
hash: string; | ||
}; | ||
txIn: (blockfrost: BlockfrostInput) => Cardano.TxIn; | ||
txOut: (blockfrost: BlockfrostOutput) => Cardano.TxOut; | ||
currentWalletProtocolParameters: (blockfrost: Responses['epoch_param_content']) => ProtocolParametersRequiredByWallet; | ||
}; | ||
export {}; | ||
//# sourceMappingURL=BlockfrostToCore.d.ts.map |
@@ -9,9 +9,2 @@ "use strict"; | ||
]), | ||
transactionUtxos: (utxoResponse) => ({ | ||
inputs: utxoResponse.inputs.map((input) => ({ | ||
...exports.BlockfrostToCore.txIn(input), | ||
address: input.address | ||
})), | ||
outputs: utxoResponse.outputs.map(exports.BlockfrostToCore.txOut) | ||
}), | ||
blockToTip: (block) => ({ | ||
@@ -22,2 +15,14 @@ blockNo: block.height, | ||
}), | ||
currentWalletProtocolParameters: (blockfrost) => ({ | ||
coinsPerUtxoWord: Number(blockfrost.coins_per_utxo_word), | ||
maxCollateralInputs: Number(blockfrost.max_collateral_inputs), | ||
maxTxSize: Number(blockfrost.max_tx_size), | ||
maxValueSize: Number(blockfrost.max_val_size), | ||
minFeeCoefficient: blockfrost.min_fee_a, | ||
minFeeConstant: blockfrost.min_fee_b, | ||
minPoolCost: Number(blockfrost.min_pool_cost), | ||
poolDeposit: Number(blockfrost.pool_deposit), | ||
protocolVersion: { major: blockfrost.protocol_major_ver, minor: blockfrost.protocol_minor_ver }, | ||
stakeKeyDeposit: Number(blockfrost.key_deposit) | ||
}), | ||
inputFromUtxo: (address, utxo) => ({ | ||
@@ -35,11 +40,18 @@ address, | ||
outputs: (outputs) => outputs.map((output) => exports.BlockfrostToCore.txOut(output)), | ||
transactionUtxos: (utxoResponse) => ({ | ||
inputs: utxoResponse.inputs.map((input) => ({ | ||
...exports.BlockfrostToCore.txIn(input), | ||
address: input.address | ||
})), | ||
outputs: utxoResponse.outputs.map(exports.BlockfrostToCore.txOut) | ||
}), | ||
txContentUtxo: (blockfrost) => ({ | ||
hash: blockfrost.hash, | ||
inputs: exports.BlockfrostToCore.inputs(blockfrost.inputs), | ||
outputs: exports.BlockfrostToCore.outputs(blockfrost.outputs), | ||
hash: blockfrost.hash | ||
outputs: exports.BlockfrostToCore.outputs(blockfrost.outputs) | ||
}), | ||
txIn: (blockfrost) => ({ | ||
txId: blockfrost.tx_hash, | ||
address: blockfrost.address, | ||
index: blockfrost.output_index, | ||
address: blockfrost.address | ||
txId: blockfrost.tx_hash | ||
}), | ||
@@ -56,20 +68,8 @@ txOut: (blockfrost) => { | ||
value: { | ||
coins: BigInt(blockfrost.amount.find(({ unit }) => unit === 'lovelace').quantity), | ||
assets | ||
assets, | ||
coins: BigInt(blockfrost.amount.find(({ unit }) => unit === 'lovelace').quantity) | ||
} | ||
}; | ||
}, | ||
currentWalletProtocolParameters: (blockfrost) => ({ | ||
maxTxSize: Number(blockfrost.max_tx_size), | ||
minFeeCoefficient: blockfrost.min_fee_a, | ||
minFeeConstant: blockfrost.min_fee_b, | ||
stakeKeyDeposit: Number(blockfrost.key_deposit), | ||
poolDeposit: Number(blockfrost.pool_deposit), | ||
minPoolCost: Number(blockfrost.min_pool_cost), | ||
coinsPerUtxoWord: Number(blockfrost.coins_per_utxo_word), | ||
maxValueSize: Number(blockfrost.max_val_size), | ||
maxCollateralInputs: blockfrost.max_collateral_inputs || undefined, | ||
protocolVersion: { major: blockfrost.protocol_major_ver, minor: blockfrost.protocol_minor_ver } | ||
}) | ||
} | ||
}; | ||
//# sourceMappingURL=BlockfrostToCore.js.map |
{ | ||
"name": "@cardano-sdk/blockfrost", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Blockfrost provider for Cardano JS SDK", | ||
@@ -18,2 +18,3 @@ "engines": { | ||
"lint": "eslint --ignore-path ../../.eslintignore \"**/*.ts\"", | ||
"lint:fix": "eslint --fix --ignore-path ../../.eslintignore \"**/*.ts\"", | ||
"test": "jest -c ./jest.config.js", | ||
@@ -28,3 +29,3 @@ "coverage": "shx echo No coverage report for this package", | ||
"@blockfrost/blockfrost-js": "^1.3.0", | ||
"@cardano-sdk/core": "0.1.5" | ||
"@cardano-sdk/core": " 0.1.6" | ||
}, | ||
@@ -31,0 +32,0 @@ "files": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
53681
512
0
+ Added@cardano-sdk/core@0.1.6(transitive)
- Removed@cardano-sdk/core@0.1.5(transitive)
Updated@cardano-sdk/core@ 0.1.6