import * as elliptic from 'elliptic' ; import * as qs from 'querystring' ; import * as rp from 'request-promise' ; import * as _ from 'underscore' ; import { CreateInvoiceArgs , GetInvoicesArgs , PairClientResponse , } from '../models/client' ; import { Cryptography as crypto } from './cryptography' ; import { Invoice } from '../models/invoice' ; import { Rate } from '../models/rate' ; export class BTCPayClient { private clientId : string ; private userAgent : string ; private options : any ; constructor ( private host , private kp , private tokens = { } ) { this . host = this . host . replace ( /\/+$/ , '' ) ; this . clientId = crypto . get_sin_from_key ( this . kp ) ; this . userAgent = 'node-btcpay' ; this . options = { headers : { 'Content-Type' : 'application/json' , Accept : 'application/json' , 'User-Agent' : this . userAgent , 'X-Accept-Version' : '2.0.0' , } , json : true , } ; } public async pair_client ( code ) { const re = new RegExp ( '^\\w{7}$' ) ; if ( ! re . test ( code ) ) { throw new Error ( 'pairing code is not valid' ) ; } const payload = { id : this . clientId , pairingCode : code , } ; return this . unsigned_request ( '/tokens' , payload ) . then ( ( data ) => { const _data = data [ 0 ] ; const _res = { } ; _res [ _data . facade ] = _data . token ; return _res ; } ) ; } public async get_rates ( currencyPairs , storeID ) { return this . signed_get_request ( '/rates' , { currencyPairs : currencyPairs . join ( ',' ) , storeID , } ) ; } public async create_invoice ( payload , token ? ) { const re = new RegExp ( '^[A-Z]{3}$' ) ; if ( ! re . test ( payload . currency ) ) { throw new Error ( 'Currency is invalid' ) ; } if ( isNaN ( parseFloat ( payload . price as any ) ) ) { throw new Error ( 'Price must be a float' ) ; } return this . signed_post_request ( '/invoices' , payload , token ) ; } public async get_invoice ( invoiceId , token ? ) { return this . signed_get_request ( '/invoices/' + invoiceId , token ) ; } public async get_invoices ( params ? , token ? ) { return this . signed_get_request ( '/invoices' , params , token ) ; } private create_signed_headers ( uri , payload ) { return { 'X-Identity' : Buffer . from ( this . kp . getPublic ( ) . encodeCompressed ( ) ) . toString ( 'hex' ) , 'X-Signature' : crypto . sign ( uri + payload , this . kp ) . toString ( 'hex' ) , } ; } private async signed_get_request ( path , params = { } , token = _ . values ( this . tokens ) [ 0 ] ) { params . token = token ; const _options = JSON . parse ( JSON . stringify ( this . options ) ) ; const _uri = this . host + path ; const _payload = '?' + qs . stringify ( params ) ; _ . extend ( _options . headers , this . create_signed_headers ( _uri , _payload ) ) ; _options . uri = _uri ; _options . qs = params ; return rp . get ( _options ) . then ( ( resp ) => resp . data ) ; } private async signed_post_request ( path , payload , token = _ . values ( this . tokens ) [ 0 ] ) { payload . token = token ; const _uri = this . host + path ; const _payload = JSON . stringify ( payload ) ; const _options = JSON . parse ( JSON . stringify ( this . options ) ) ; _ . extend ( _options . headers , this . create_signed_headers ( _uri , _payload ) ) ; _options . uri = _uri ; _options . body = payload ; return rp . post ( _options ) . then ( ( resp ) => resp . data ) ; } private async unsigned_request ( path , payload ) { const _mixin = { method : 'POST' , uri : this . host + path , body : payload , } ; const _options = { ... JSON . parse ( JSON . stringify ( this . options ) ) , ... _mixin } ; return rp ( _options ) . then ( ( resp ) => resp . data ) ; } }