UNPKG

@blockbee/api

Version:

BlockBee's Library for NodeJS

463 lines (365 loc) 12.7 kB
/** * BlockBee's Node.js Library * @author BlockBee <info@blockbee.io> */ class BlockBee { static #baseURL = 'https://api.blockbee.io' constructor( coin, ownAddress, callbackUrl, parameters = {}, bbParams = {}, apiKey ) { if ( !apiKey ) { throw new Error('Missing API Key') } if (!coin || !callbackUrl) { throw new Error('Missing required parameters') } coin = coin.replace('/', '_') BlockBee.getSupportedCoins(apiKey).then(validCoins => { if ( !validCoins.hasOwnProperty(coin) ) { throw new Error('The cryptocurrency/token requested is not supported.') } }) this.coin = coin this.ownAddress = ownAddress this.callbackUrl = callbackUrl this.parameters = parameters this.bbParams = bbParams this.apiKey = apiKey this.paymentAddress = '' } /** * Gets all the supported cryptocurrencies and tokens from the API * @param apiKey * @returns {Promise<{}|null>} */ static async getSupportedCoins( apiKey ) { const info = await this.getInfo(null, true, apiKey) if ( !info ) { return null } delete info['fee_tiers'] const coins = {} for ( const chain of Object.keys(info) ) { const data = info[chain] const isBaseCoin = data.hasOwnProperty('ticker') if ( isBaseCoin ) { coins[chain] = data } else { const baseTicker = `${chain}_` Object.entries(data).forEach(( [token, subData] ) => { coins[baseTicker + token] = subData }) } } return coins } /** * Actually makes the request to the API returning the address. * It's necessary to run this before running the other non-static functions * @returns {Promise<*|null>} */ async getAddress() { if ( !this.coin || !this.callbackUrl || !this.apiKey ) { return null } let callbackUrl = new URL(this.callbackUrl) const parameters = this.parameters if ( Object.entries(parameters).length > 0 ) { Object.entries(parameters).forEach(( [k, v] ) => callbackUrl.searchParams.append(k, v)) } const params = this.ownAddress ? { ...this.bbParams, ...{ callback: encodeURI(callbackUrl.toString()), address: this.ownAddress, apikey: this.apiKey } } : { ...this.bbParams, ...{ callback: encodeURI(callbackUrl.toString()), apikey: this.apiKey } } const response = await BlockBee.#_request_get(this.coin, 'create', params) const addressIn = response.address_in this.paymentAddress = addressIn return addressIn } /** * Checks the logs related to a request. * (Can be used to check for callbacks) * @returns {Promise<any|null>} */ async checkLogs() { if ( !this.coin || !this.callbackUrl ) { return null } let callbackUrl = new URL(this.callbackUrl) const parameters = this.parameters if ( Object.entries(parameters).length > 0 ) { Object.entries(parameters).forEach(( [k, v] ) => callbackUrl.searchParams.append(k, v)) } callbackUrl = encodeURI(callbackUrl.toString()) const params = { callback: callbackUrl, apikey: this.apiKey } const response = await BlockBee.#_request_get(this.coin, 'logs', params) if ( response.status === 'success' ) { return response } return null } /** * Gets the QRCode for a payment. * @param value * @param size * @returns {Promise<any|null>} */ async getQrcode( value = null, size = 512 ) { let address = this.paymentAddress if ( !address ) { address = await this.getAddress() } const params = { address: address, apikey: this.apiKey } if ( value ) { params['value'] = value } params['size'] = size const response = await BlockBee.#_request_get(this.coin, 'qrcode', params) if ( response.status === 'success' ) { return response } return null } /** * Get information related to a cryptocurrency/token. * If coin=null it calls the /info/ endpoint returning general information * @param coin * @param assoc * @param apiKey * @returns {Promise<any|null>} */ static async getInfo( coin = null, assoc = false, apiKey = '' ) { const params = {} if ( !coin ) { params['prices'] = 0 } return await this.#_request_get(coin, 'info', params) } /** * Gets an estimate of the blockchain fees for the coin provided. * @param coin * @param apiKey * @param addresses * @param priority * @returns {Promise<any|null>} */ static async getEstimate( coin, apiKey = '', addresses = 1, priority = 'default' ) { return await BlockBee.#_request_get(coin, 'estimate', { addresses, priority }) } /** * This method allows you to easily convert prices from FIAT to Crypto or even between cryptocurrencies * @param coin * @param value * @param from * @param apiKey * @returns {Promise<any|null>} */ static async getConvert( coin, value, from, apiKey = '' ) { return await BlockBee.#_request_get(coin, 'convert', { value, from }) } static async createPayout( coin, requests, apiKey, process = false ) { if ( !requests ) { throw new Error('No requests provided') } const body = { 'outputs': requests } let endpoint = 'payout/request/bulk' if ( process ) { endpoint = endpoint + '/process' } return await BlockBee.#_request_post(coin, endpoint, apiKey, body, true) } static async listPayouts( coin, status, page, apiKey, requests = false ) { const params = {} if ( status ) { params.status = status } if ( page ) { params.p = page } let endpoint = 'payout/list' if ( requests ) { endpoint = 'payout/request/list' } return await this.#_request_get(coin, endpoint, {...params, apikey: apiKey}) } static async getPayoutWallet( coin, apiKey, balance = false ) { let wallet = await this.#_request_get(coin, 'payout/address', {apikey: apiKey}) const output = {address: wallet.address} if ( balance ) { wallet = await this.#_request_get(coin, 'payout/balance', {apikey: apiKey}) if ( wallet.status === 'success' ) { output.balance = wallet.balance } } return output } static async createPayoutByIds( apiKey, ids = [] ) { if ( ids.length === 0 ) { throw new Error('Please provide the Payout Request(s) ID(s)') } return await this.#_request_post('', 'payout/create', apiKey, {request_ids: ids.join(',')}) } static async processPayout( apiKey, id ) { const response = await this.#_request_post('', 'payout/process', apiKey, {payout_id: id}) return response.status === 'success' ? response : null } static async checkPayoutStatus( apiKey, id ) { if ( !id ) { throw new Error('Please provide the Payout ID') } return await this.#_request_post('', 'payout/status', apiKey, {payout_id: id}) } /** * Requests a Payment Link * @returns {Promise<*|null>} */ static async paymentRequest( redirectUrl, notifyUrl, value, apiKey, params = {}, bbParams = {} ) { if (!notifyUrl) { throw new Error('notifyUrl is required') } if (!redirectUrl) { throw new Error('paymentRequest is required') } redirectUrl = new URL(redirectUrl) notifyUrl = new URL(notifyUrl) if ( Object.entries(params).length > 0 ) { Object.entries(params).forEach(( [k, v] ) => redirectUrl.searchParams.append(k, v)) Object.entries(params).forEach(( [k, v] ) => notifyUrl.searchParams.append(k, v)) } const reqParams = { ...bbParams, ...{ redirect_url: encodeURI(redirectUrl.toString()), notify_url: encodeURI(notifyUrl.toString()), value: value, apikey: apiKey } } return await BlockBee.#_request_get('', 'checkout/request', reqParams) } /** * Fetch payment logs * @param {string} token * @param {string} apiKey * @returns {Promise<null|Object>} */ static async paymentLogs( token, apiKey ) { const params = { apikey: apiKey, token: token } return await BlockBee.#_request_get('', 'checkout/logs', params) } /** * Requests a Deposit Link * @returns {Promise<*|null>} */ static async depositRequest( notifyUrl, apiKey, parameters = {}, bbParams = {} ) { if ( !notifyUrl ) { throw new Error('notifyUrl is required') } notifyUrl = new URL(notifyUrl) if ( Object.entries(parameters).length > 0 ) { Object.entries(parameters).forEach(( [k, v] ) => notifyUrl.searchParams.append(k, v)) } const params = { ...bbParams, ...{ notify_url: encodeURI(notifyUrl.toString()), apikey: apiKey } } return await BlockBee.#_request_get('', 'deposit/request', params) } /** * Fetch deposit logs * @param {string} token * @param {string} apiKey * @returns {Promise<null|Object>} */ static async depositLogs( token, apiKey ) { if ( !token ) { throw new Error('Token is Empty') } const params = { apikey: apiKey, token: token } return await BlockBee.#_request_get('', 'deposit/logs', params) } /** * Helper function to make a request to API * @param coin * @param endpoint * @param params * @returns {Promise<any>} */ static async #_request_get( coin = null, endpoint = '', params = {} ) { const url = coin ? new URL(`${this.#baseURL}/${coin.replace('_', '/')}/${endpoint}/`) : new URL(`${this.#baseURL}/${endpoint}/`) if ( params ) { Object.keys(params).forEach(key => url.searchParams.append(key, params[key])) } const fetchParams = { method: 'GET', headers: { referer: this.#baseURL }, credentials: 'include' } const response = await fetch(url, fetchParams) const response_obj = await response.json() if ( response_obj.status === 'error' ) { throw new Error(response_obj.error) } return response_obj } static async #_request_post( coin, endpoint, apiKey, body = {}, isJson = false ) { const baseURL = this.#baseURL const coinPath = coin ? `${coin.replace('_', '/')}` : '' let url = new URL(`${baseURL}/${endpoint}/`) if ( coin ) { url = new URL(`${baseURL}/${coinPath}/${endpoint}/`) } url.searchParams.append('apikey', apiKey) const headers = {} let data if ( isJson ) { headers['Content-Type'] = 'application/json' data = JSON.stringify(body) } else { data = new URLSearchParams(body).toString() headers['Content-Type'] = 'application/x-www-form-urlencoded' } const fetchParams = { method: 'POST', headers: headers, body: data } const response = await fetch(url, fetchParams) const response_obj = await response.json() if ( response_obj.status === 'error' ) { throw new Error(response_obj.error) } return response_obj } } module.exports = BlockBee