@blockfrost/blockfrost-js
Advanced tools
Comparing version 4.2.0-beta.1 to 4.2.0-beta.2
import { components } from './types/OpenApi'; | ||
import { BlockFrostAPI } from './BlockFrostAPI'; | ||
import { BlockFrostIPFS } from './BlockFrostIPFS'; | ||
import { deriveAddress, getFingerprint, parseAsset, verifyWebhookSignature } from './utils/helpers'; | ||
import { BlockfrostClientError, BlockfrostServerError, SignatureVerificationError } from './utils/errors'; | ||
import { deriveAddress, getFingerprint, parseAsset } from './utils/helpers'; | ||
import { BlockfrostClientError, BlockfrostServerError } from './utils/errors'; | ||
declare type Responses = components['schemas']; | ||
export { BlockFrostAPI, BlockFrostIPFS, BlockfrostClientError, BlockfrostServerError, SignatureVerificationError, parseAsset, getFingerprint, deriveAddress, verifyWebhookSignature, }; | ||
export { BlockFrostAPI, BlockFrostIPFS, BlockfrostClientError, BlockfrostServerError, parseAsset, getFingerprint, deriveAddress, }; | ||
export type { Responses }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.verifyWebhookSignature = exports.deriveAddress = exports.getFingerprint = exports.parseAsset = exports.SignatureVerificationError = exports.BlockfrostServerError = exports.BlockfrostClientError = exports.BlockFrostIPFS = exports.BlockFrostAPI = void 0; | ||
exports.deriveAddress = exports.getFingerprint = exports.parseAsset = exports.BlockfrostServerError = exports.BlockfrostClientError = exports.BlockFrostIPFS = exports.BlockFrostAPI = void 0; | ||
const BlockFrostAPI_1 = require("./BlockFrostAPI"); | ||
@@ -12,6 +12,4 @@ Object.defineProperty(exports, "BlockFrostAPI", { enumerable: true, get: function () { return BlockFrostAPI_1.BlockFrostAPI; } }); | ||
Object.defineProperty(exports, "parseAsset", { enumerable: true, get: function () { return helpers_1.parseAsset; } }); | ||
Object.defineProperty(exports, "verifyWebhookSignature", { enumerable: true, get: function () { return helpers_1.verifyWebhookSignature; } }); | ||
const errors_1 = require("./utils/errors"); | ||
Object.defineProperty(exports, "BlockfrostClientError", { enumerable: true, get: function () { return errors_1.BlockfrostClientError; } }); | ||
Object.defineProperty(exports, "BlockfrostServerError", { enumerable: true, get: function () { return errors_1.BlockfrostServerError; } }); | ||
Object.defineProperty(exports, "SignatureVerificationError", { enumerable: true, get: function () { return errors_1.SignatureVerificationError; } }); |
import { GotError, ErrorType } from '../types'; | ||
export declare class SignatureVerificationError extends Error { | ||
detail: { | ||
webhookPayload: unknown; | ||
signatureHeader: string; | ||
} | undefined; | ||
constructor(message: string, detail?: { | ||
signatureHeader: string; | ||
webhookPayload: unknown; | ||
}); | ||
} | ||
export declare class BlockfrostServerError extends Error { | ||
@@ -13,0 +3,0 @@ status_code: number; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.handleError = exports.isBlockfrostErrorResponse = exports.BlockfrostClientError = exports.BlockfrostServerError = exports.SignatureVerificationError = void 0; | ||
exports.handleError = exports.isBlockfrostErrorResponse = exports.BlockfrostClientError = exports.BlockfrostServerError = void 0; | ||
const got_1 = require("got"); | ||
class SignatureVerificationError extends Error { | ||
constructor(message, detail) { | ||
super(message); | ||
this.name = 'SignatureVerificationError'; | ||
this.message = message; | ||
this.detail = detail; | ||
Object.setPrototypeOf(this, SignatureVerificationError.prototype); | ||
} | ||
} | ||
exports.SignatureVerificationError = SignatureVerificationError; | ||
class BlockfrostServerError extends Error { | ||
@@ -16,0 +6,0 @@ constructor(error) { |
@@ -15,11 +15,1 @@ import { ParseAssetResult } from '../types/utils'; | ||
export declare const parseAsset: (hex: string) => ParseAssetResult; | ||
/** | ||
* Verifies webhook signature | ||
* | ||
* @param {string|Buffer} webhookPayload Buffer or stringified payload of the webhook request. | ||
* @param {string|Buffer} signatureHeader Blockfrost-Signature header. | ||
* @param {string} secret Auth token for the webhook. | ||
* @param {number} [timestampToleranceSeconds=600] Time tolerance affecting signature validity. By default signatures older than 600s are considered invalid. | ||
* @returns {boolean} Whether the signature is valid. | ||
* */ | ||
export declare const verifyWebhookSignature: (webhookPayload: unknown, signatureHeader: string, secret: string, timestampToleranceSeconds?: number) => boolean; |
@@ -6,8 +6,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.verifyWebhookSignature = exports.parseAsset = exports.getFingerprint = exports.hexToString = exports.deriveAddress = void 0; | ||
const crypto_1 = require("crypto"); | ||
exports.parseAsset = exports.getFingerprint = exports.hexToString = exports.deriveAddress = void 0; | ||
const cardano_serialization_lib_nodejs_1 = require("@emurgo/cardano-serialization-lib-nodejs"); | ||
const cip14_js_1 = __importDefault(require("@emurgo/cip14-js")); | ||
const errors_1 = require("./errors"); | ||
const index_1 = require("./index"); | ||
/** | ||
@@ -26,11 +23,25 @@ * Derives an address with derivation path m/1852'/1815'/account'/role/addressIndex | ||
: cardano_serialization_lib_nodejs_1.NetworkInfo.mainnet().network_id(); | ||
const baseAddr = cardano_serialization_lib_nodejs_1.BaseAddress.new(networkId, cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()), cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(mainStakeKey.to_raw_key().hash())); | ||
const utxoPubKeyHash = utxoPubKey.to_raw_key().hash(); | ||
const mainStakeKeyHash = mainStakeKey.to_raw_key().hash(); | ||
const utxoStakeCred = cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(utxoPubKeyHash); | ||
const mainStakeCred = cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(mainStakeKeyHash); | ||
const baseAddr = cardano_serialization_lib_nodejs_1.BaseAddress.new(networkId, utxoStakeCred, mainStakeCred); | ||
utxoStakeCred.free(); | ||
mainStakeCred.free(); | ||
utxoPubKeyHash.free(); | ||
mainStakeCred.free(); | ||
const baseAddrBech32 = baseAddr.to_address().to_bech32(); | ||
baseAddr.free(); | ||
if (role === 2 && !isByron) { | ||
const addressSpecificStakeKey = accountKey.derive(2).derive(addressIndex); | ||
const stakeKeyHash = addressSpecificStakeKey.to_raw_key().hash(); | ||
const stakeCred = cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(stakeKeyHash); | ||
// always return stake address | ||
const rewardAddr = cardano_serialization_lib_nodejs_1.RewardAddress.new(networkId, cardano_serialization_lib_nodejs_1.StakeCredential.from_keyhash(addressSpecificStakeKey.to_raw_key().hash())) | ||
.to_address() | ||
.to_bech32(); | ||
const rewardAddr = cardano_serialization_lib_nodejs_1.RewardAddress.new(networkId, stakeCred); | ||
const rewardAddrBech32 = rewardAddr.to_address().to_bech32(); | ||
rewardAddr.free(); | ||
addressSpecificStakeKey.free(); | ||
stakeKeyHash.free(); | ||
return { | ||
address: rewardAddr, | ||
address: rewardAddrBech32, | ||
path: [role, addressIndex], | ||
@@ -44,9 +55,14 @@ }; | ||
const byronAddress = cardano_serialization_lib_nodejs_1.ByronAddress.icarus_from_key(utxoPubKey, protocolMagic); | ||
const byronAddrBase58 = byronAddress.to_base58(); | ||
byronAddress.free(); | ||
return { | ||
address: byronAddress.to_base58(), | ||
address: byronAddrBase58, | ||
path: [role, addressIndex], | ||
}; | ||
} | ||
mainStakeKey.free(); | ||
utxoPubKey.free(); | ||
accountKey.free(); | ||
return { | ||
address: baseAddr.to_address().to_bech32(), | ||
address: baseAddrBech32, | ||
path: [role, addressIndex], | ||
@@ -80,66 +96,1 @@ }; | ||
exports.parseAsset = parseAsset; | ||
/** | ||
* Verifies webhook signature | ||
* | ||
* @param {string|Buffer} webhookPayload Buffer or stringified payload of the webhook request. | ||
* @param {string|Buffer} signatureHeader Blockfrost-Signature header. | ||
* @param {string} secret Auth token for the webhook. | ||
* @param {number} [timestampToleranceSeconds=600] Time tolerance affecting signature validity. By default signatures older than 600s are considered invalid. | ||
* @returns {boolean} Whether the signature is valid. | ||
* */ | ||
const verifyWebhookSignature = (webhookPayload, signatureHeader, secret, timestampToleranceSeconds = 600) => { | ||
let timestamp; | ||
let signature; | ||
if (Array.isArray(signatureHeader)) { | ||
throw new errors_1.SignatureVerificationError('Unexpected: An array was passed as a header'); | ||
} | ||
const decodedWebhookPayload = Buffer.isBuffer(webhookPayload) | ||
? webhookPayload.toString('utf8') | ||
: webhookPayload; | ||
const decodedSignatureHeader = Buffer.isBuffer(signatureHeader) | ||
? signatureHeader.toString('utf8') | ||
: signatureHeader; | ||
// Parse signature header (example: t=1648550558,v1=162381a59040c97d9b323cdfec02facdfce0968490ec1732f5d938334c1eed4e) | ||
const tokens = decodedSignatureHeader.split(','); | ||
for (const token of tokens) { | ||
const [key, value] = token.split('='); | ||
switch (key) { | ||
case 't': | ||
timestamp = Number(value); | ||
break; | ||
case 'v1': | ||
signature = value; | ||
break; | ||
default: | ||
console.warn(`Cannot parse part of the signature header, key "${key}" is not supported by this version of Blockfrost SDK.`); | ||
} | ||
} | ||
if (!timestamp || !signature) { | ||
throw new errors_1.SignatureVerificationError('Invalid signature header format', { | ||
signatureHeader: decodedSignatureHeader, | ||
webhookPayload: decodedWebhookPayload, | ||
}); | ||
} | ||
// Recreate signature by concatenating timestamp with stringified payload, | ||
// then compute HMAC using sha256 and provided secret (auth token) | ||
const signaturePayload = `${timestamp}.${decodedWebhookPayload}`; | ||
const hmac = (0, crypto_1.createHmac)('sha256', secret) | ||
.update(signaturePayload) | ||
.digest('hex'); | ||
if (hmac !== signature) { | ||
return false; | ||
} | ||
// computed hmac should match signature parsed from a signature header | ||
const currentTimestamp = Math.floor(new Date().getTime() / 1000); | ||
if (currentTimestamp - timestamp > timestampToleranceSeconds) { | ||
if ((0, index_1.isDebugEnabled)()) { | ||
console.info(`Invalid signature. Blockfrost signature timestamp is out of range!`); | ||
} | ||
return false; | ||
} | ||
else { | ||
// Successfully validate the signature only if it is within tolerance | ||
return true; | ||
} | ||
}; | ||
exports.verifyWebhookSignature = verifyWebhookSignature; |
import { Options, ValidatedOptions, PaginationOptions, AdditionalEndpointOptions, AllMethodOptions } from '../types'; | ||
export declare const isDebugEnabled: () => boolean; | ||
export declare const validateOptions: (options?: Options | undefined) => ValidatedOptions; | ||
@@ -4,0 +3,0 @@ export declare const getAdditionalParams: (options?: AdditionalEndpointOptions | undefined) => AdditionalEndpointOptions; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.paginateMethod = exports.getAllMethodOptions = exports.getPaginationOptions = exports.getAdditionalParams = exports.validateOptions = exports.isDebugEnabled = void 0; | ||
exports.paginateMethod = exports.getAllMethodOptions = exports.getPaginationOptions = exports.getAdditionalParams = exports.validateOptions = void 0; | ||
const config_1 = require("../config"); | ||
const limiter_1 = require("./limiter"); | ||
const isDebugEnabled = () => process.env.BLOCKFROST_DEBUG === 'true'; | ||
exports.isDebugEnabled = isDebugEnabled; | ||
const validateOptions = (options) => { | ||
@@ -22,3 +20,3 @@ var _a, _b, _c, _d, _e; | ||
} | ||
const debug = (_a = options.debug) !== null && _a !== void 0 ? _a : (0, exports.isDebugEnabled)(); | ||
const debug = (_a = options.debug) !== null && _a !== void 0 ? _a : process.env.BLOCKFROST_DEBUG === 'true'; | ||
let rateLimiter; | ||
@@ -25,0 +23,0 @@ if (options.rateLimiter === false) { |
{ | ||
"name": "@blockfrost/blockfrost-js", | ||
"version": "4.2.0-beta.1", | ||
"version": "4.2.0-beta.2", | ||
"description": "A JavaScript/TypeScript SDK for interacting with the https://blockfrost.io API", | ||
@@ -32,3 +32,3 @@ "keywords": [ | ||
"dependencies": { | ||
"@emurgo/cardano-serialization-lib-nodejs": "^10.0.4", | ||
"@emurgo/cardano-serialization-lib-nodejs": "^10.1.0", | ||
"@emurgo/cip14-js": "3.0.1", | ||
@@ -35,0 +35,0 @@ "bottleneck": "^2.19.5", |
321049
64
7802