'use strict' /** * Copyright (c) 2017~2021, OBCon Inc. * All rights reserved. */ /** * @file * @copyright 2017~2021, OBCon Inc. * @author gye hyun james kim [pnuskgh@gmail.com] */ const jwt = require("jsonwebtoken"); const uuidv4 = require("uuid/v4"); const crypto = require('crypto'); const querystring = require("querystring"); const moment = require('moment'); const fetch = require('node-fetch'); //--- 업비트 개발자 센터 : https://docs.upbit.com/ class Upbit { constructor() { this._url_api = 'https://api.upbit.com/v1'; //--- 업비트(Upbit) Open API 주소 this._endPoint = null; this._api_key = null; this._api_secret = null; //--- https://docs.upbit.com/docs/user-request-guide //--- Remaining-Req 헤더로 잔여 요청수 확인 가능 this._api_limit = { exchange: { order: { second: 8, minute: 200 }, other: { second: 30, minute: 900 } }, quotation: { websocket: { second: 5, minute: 100 }, rest: { second: 10, minute: 600 } } }; } set api_key(newValue) { this._api_key = newValue; } set api_secret(newValue) { this._api_secret = newValue; } //--- string, number, bigint, boolean, function, undefined, symbol //--- object : null, object, array _obconTypeof(param) { return Object.prototype.toString.call(param).replace(/\[object /g, '').replace(/\]/g, '').toLowerCase(); } async run() { if (this._api_secret == '') { return; } let formatInt = Intl.NumberFormat('ko-KR', { minimumFractionDigits: 0, maximumFractionDigits: 0 }); let formatFloat = Intl.NumberFormat('ko-KR', { minimumFractionDigits: 2, maximumFractionDigits: 10 }); console.log('------------------------------------------------------------'); console.log('--- Exchange API : 자산'); let ret = await this.market_all(true); if (typeof(ret.code) != 'undefined') { console.log('Error', ret); } else { if (this._obconTypeof(ret) == 'array') { for (let item of ret) { console.log(item); } } else { console.log(ret); } } console.log(''); } _getHeaders(params=null) { let payload = { access_key: this._api_key, nonce: uuidv4(), }; if (params != null) { const hash = crypto.createHash('sha512'); const query = querystring.encode(params); console.log('query', query); payload.query_hash = hash.update(query, 'utf-8').digest('hex'); payload.query_hash_alg = 'SHA512'; } let token = jwt.sign(payload, this._api_secret); return { Authorization: `Bearer ${token}` }; } async _call(endPoint, method='get', params=null) { try { let url = `${this._url_api}${endPoint}`; if ((method == 'get') && (params != null)) { url = url + '?' + Object.keys(params).map(key => `${encodeURIComponent(key.replace(/[!'()*]/g, escape))}=${encodeURIComponent(String(params[key]).replace(/[!'()*]/g, escape))}`).join('&'); } let options = { method: method, mode: 'cors', cache: 'no-cache', headers: this._getHeaders(params) }; console.log(url, options); let res = await fetch(url, options); if (res.ok) { //--- 200 <= res.status < 300 console.log(res.url, res.status, JSON.stringify(res.headers)); return await res.json(); } else { return { code: res.status, message: JSON.stringify(res) }; } } catch(err) { //--- async 함수내에서 사용하여야 한다. console.log('Error', err); return { code: 999, message: JSON.stringify(err) }; } } //--- Exchange API //--- accounts : GET. 전체 계좌 조회 async accounts() { let endPoint = '/accounts'; return await this._call(endPoint, 'get', null); } //--- orders/chance : GET. 마켓별 주문 가능 정보 async orders_chance(market='KRW-BTC') { let endPoint = '/orders/chance'; let params = { market: market } return await this._call(endPoint, 'get', params); } //--- order : POST. 주문하기, GET. 개별 주문 조회, DELETE. 주문 취소 접수 //--- orders : GET. 주문 리스트 조회 //--- withdraws : GET. 출금 리스트 조회 //--- withdraw : GET. 개별 출금 조회 //--- withdraw/chance : GET. 출금 가능 정보 //--- withdraw/coin : POST. 코인 출금하기 //--- withdraw/krw : POST. 원화 출금하기 //--- deposits : GET. 입금 리스트 조회 //--- deposit : GET. 개별 입금 조회 //--- deposit/generate_coin_address : POST. 입금 주소 생성 요청 //--- deposits/coin_addresses : GET. 전체 입금 주소 조회 //--- deposits/coin_address : GET. 개별 입금 주소 조회 //--- deposits/krw : POST. 원화 입금하기 //--- status/wallet : GET. 입출금 현황 //--- api_keys : GET. API 키 리스트 조회 //--- Quotation API //--- market/all : GET. 마켓 코드 조회 async market_all(isDetails=false) { let endPoint = '/market/all'; let params = { isDetails: (isDetails) ? 'true':'false' } return await this._call(endPoint, 'get', params); } //--- candles/minutes/unit : GET. 분(Minute) 캔들 //--- candles/days : GET. 일(Day) 캔들 //--- candles/weeks : GET. 주(Week) 캔들 //--- candles/months : GET. 월(Month) 캔들 //--- //--- trades/ticks : GET. 최근 체결 내역 //--- ticker : GET. 현재가 정보 //--- orderbook : GET. 호가 정보 조회 //--- WebSocket을 이용한 업비트 시세 수신 //--- wss://api.upbit.com/websocket/v1 } module.exports = Upbit; //--- cd C:\work\obcon\obcon //--- node include/Upbit.js let appl = new Upbit() //--- 유효기간 : 2022.03.11 11:28 만료 appl.api_key = '9oyYViymxrmJlqPiZy4cI63flartQ9xvjJISu0QJ'; appl.api_secret = 'P8lnEX0UqbaDCJ7HAWubyx99AOKHKlIKZx5Qlvqp'; appl.run();