Spaces:
Running
Running
| /** | |
| * 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(); | |