Tuesday, December 3, 2019

Node.js sequelize MySQL JSON function 사용하기

select * from actionlog where JSON_EXTRACT(action, '$name')='reward'

const actionLogs: ActionLog[] = await ActionLog.findAll({
    where: Sequelize.where(
        Sequelize.fn('JSON_EXTRACT',
            Sequelize.col('action'),
            '$.name'),
        'reward')
})

Tuesday, October 8, 2019

MariaDB /usr/local/etc/my.cnf.d No such file or directory


$ mysql.server start
/usr/local/Cellar/mariadb/10.3.10/bin/my_print_defaults: Can't read dir of '/usr/local/etc/my.cnf.d' (Errcode: 2 "No such file or directory")
Fatal error in defaults handling. Program aborted
Starting MariaDB
./usr/local/Cellar/mariadb/10.3.10/bin/my_print_defaults: Can't read dir of '/usr/local/etc/my.cnf.d' (Errcode: 2 "No such file or directory")
Fatal error in defaults handling. Program aborted
/usr/local/Cellar/mariadb/10.3.10/bin/my_print_defaults: Can't read dir of '/usr/local/etc/my.cnf.d' (Errcode: 2 "No such file or directory")
Fatal error in defaults handling. Program aborted
191008 10:52:51 mysqld_safe Logging to '/usr/local/var/mysql/namjungsoo-MacBook-Pro.local.err'.
191008 10:52:51 mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql
ERROR!
해결 방법: 아래의 명령을 통해서 폴더를 만들어준다.
mkdir /usr/local/etc/my.cnf.d

Wednesday, September 4, 2019

MariaDB Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

mysql.server start
Starting MariaDB
.190904 09:57:41 mysqld_safe Logging to '/usr/local/var/mysql/duongame-MacBook-Pro.local.err'.
190904 09:57:42 mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql
 SUCCESS!

Tuesday, September 3, 2019

BitcoinSV Node.js bitsocket example

아래는 BitcoinSV의 실시간 event를 받을수 있는 bitsocket의 example이다.
Node.js로 작성했으며, 다음과 같은 패키지를 npm으로 설치해야 한다.

>npm i -S btoa
>npm i -S eventsource

var btoa = require('btoa')
var EventSource = require('eventsource')

// Write a bitquery
var query = {
  "v": 3, "q": { "find": {} }
}

// Encode it in base64 format
var b64 = btoa(JSON.stringify(query))

// Subscribe
var bitsocket = new EventSource('https://genesis.bitdb.network/s/1FnauZ9aUH2Bex6JzdcV4eNX7oLSSEbxtN/'+b64)

// Event handler
bitsocket.onmessage = function(e) {
  console.log(e.data)
}
//호출결과는 다음과 같으며 실시간으로 계속 메세지가 추가된다.
{"type":"open","data":[]}
{
    "type": "u",
    "data": [{
        "tx": {
            "h": "0c07b01307b14e3935bcdbaf50770c0e4a4e23aeb9c09c49550e09a5ad570652"
        },
        "in": [{
            "i": 0,
            "b0": "MEUCIQD6VwsndQUrrpmFCJPlxuAF1fUmZcPAx5UgC803Som2cQIgZuwlNDM3Puu/3wqqzTd5cFbUO8fEX4Q5Y9jCBdKMoDtB",
            "b1": "A8ydsZIv8Hew5jLQLoKpxqunqCx2xT18H1aKd3XIlURe",
            "str": "3045022100fa570b2775052bae99850893e5c6e005d5f52665c3c0c795200bcd374a89b671022066ec253433373eebbfdf0aaacd37797056d43bc7c45f843963d8c205d28ca03b41 03cc9db1922ff077b0e632d02e82a9c6aba7a82c76c53d7c1f568a7775c895445e",
            "e": {
                "h": "07225863412d4d037cb5514ccf94a29583691367218f28eced772c0ef1e9a866",
                "i": 1,
                "a": "1EomR6yvfRUCUeR9RdiLE8AUkveW6wA2uz"
            },
            "h0": "3045022100fa570b2775052bae99850893e5c6e005d5f52665c3c0c795200bcd374a89b671022066ec253433373eebbfdf0aaacd37797056d43bc7c45f843963d8c205d28ca03b41",
            "h1": "03cc9db1922ff077b0e632d02e82a9c6aba7a82c76c53d7c1f568a7775c895445e"
        }],
        "out": [{
            "i": 0,
            "b0": {
                "op": 118
            },
            "b1": {
                "op": 169
            },
            "b2": "4QBR3rSIWSQI33JyQGzqWd/mEcY=",
            "s2": "�\u0000Q޴�Y$\b�rr@l�Y��\u0011�",
            "b3": {
                "op": 136
            },
            "b4": {
                "op": 172
            },
            "e": {
                "v": 1000,
                "i": 0,
                "a": "1MWhRPAtAdXFSTgZrkrRuDy5xsofz63nHD"
            },
            "h2": "e10051deb488592408df7272406cea59dfe611c6"
        }, {
            "i": 1,
            "b0": {
                "op": 118
            },
            "b1": {
                "op": 169
            },
            "b2": "l3HYfq/xcSUVBLXAClhqHDwqGj4=",
            "s2": "�q�~��q%\u0015\u0004��\nXj\u001c<*\u001a>",
            "b3": {
                "op": 136
            },
            "b4": {
                "op": 172
            },
            "e": {
                "v": 6695136,
                "i": 1,
                "a": "1EomR6yvfRUCUeR9RdiLE8AUkveW6wA2uz"
            },
            "h2": "9771d87eaff171251504b5c00a586a1c3c2a1a3e"
        }],
        "_id": "5cbe972233dedb166dc469c8"
    }]
}

Node.js SSE example

Node.js로 작성한 SSE(Server Sent Event) 예제이다.


//서버
const express = require('express')
const serveStatic = require('serve-static')
const SseStream = require('ssestream')

const app = express()
app.use(serveStatic(__dirname))
app.get('/sse', (req, res) => {
  console.log('new connection')

  const sseStream = new SseStream(req)
  sseStream.pipe(res)
  const pusher = setInterval(() => {
    sseStream.write({
      data: new Date().toTimeString()
    })
  }, 1000)

  res.on('close', () => {
    console.log('lost connection')
    clearInterval(pusher)
    sseStream.unpipe(res)
  })
})

app.listen(8080, (err) => {
  if (err) throw err
  console.log('server ready on http://localhost:8080')
})

//클라이언트
var EventSource = require('eventsource')
var es = new EventSource('http://localhost:8080/sse')
es.onmessage = e => {
    console.log(e.data)
}

Wednesday, August 28, 2019

BitcoinSV generate new address javascript

BitcoinSV는 기존의 Bitcoin Core의 라이브러리인 bitcoinjs-lib(https://github.com/bitcoinjs/bitcoinjs-lib)를 사용할수도 있지만, MoneyButton에서 제공한 bsv(https://github.com/moneybutton/bsv)가 현재로서는 최선의 선택이다. 

다음과 같이 bsv라이브러리를 설치하자.
> npm i -S bsv

그리고 다음과 같이 network에 맞는 코드를 사용해서 address를 생성하자. 
### testnet address 생성
const bsv = require('bsv')const privateKey = bsv.PrivateKey.fromRandom('testnet')

// WIF는 저장해야할 private key의 string이다.
// 콘솔에 출력되는 값을 복사하여 보관하면 된다.
console.log(privateKey.toWIF())

// 마찬가지로 address 문자열을 복사하여 보관하자.
const address = bsv.Address.fromPrivateKey(privateKey, 'testnet')
console.log(address.toString())

### mainnet address 생성
const bsv = require('bsv')const privateKey = bsv.PrivateKey.fromRandom()

// WIF는 저장해야할 private key의 string이다.
// 콘솔에 출력되는 값을 복사하여 보관하면 된다.
console.log(privateKey.toWIF())

// 마찬가지로 address 문자열을 복사하여 보관하자.
const address = bsv.Address.fromPrivateKey(privateKey)
console.log(address.toString())

testnet과 mainnet의 차이는 단순히 fromRandom, fromPrivateKey를 호출할 때 'testnet'이라는 문자열을 추가적으로 전달함으로서 가능하다. 

mainnet은 private key가 K, L로 시작되고 testnet은 c로 시작되는 점이 차이점이다.

Wednesday, August 21, 2019

Node.js destructing typescript


아래와 같이 req.body의 userId, contentId, amount를 destructing을 할때 javascript에서는 다음과 같이 했었다.

const { userId, contentId, amount} = req.body 

그러나 우리는 typescript를 사용할 것이므로 userId 등에 각각 정확한 타입을 기입하고 싶을 때는 아래와 같이 하면된다.

const {
userId, contentId, amount
}: {
userId: string, contentId: string, amount: number
} = req.body

Node.js check top level module environment require.main

Python의 아래와 같이 Node.js의 node에서 바로 실행되는 함수 여부임을 알수 있게 해주는 것이 있다.
if __name__ == "__main__":

다음과 같이 하면 된다.
if (require.main === module) {
}

Wednesday, July 31, 2019

How to make redis client async via bluebird in Node.js

var redis = require('redis')
var client = redis.createClient(port, 'ip', {password: 'password'})
var bluebird = require('bluebird')
bluebird.promisifyAll(redis);

async function main2() {
    console.log('main')

    await client.watchAsync("foo")

    const result = await client.getAsync("foo")
    console.log(`get ${result}`)

    const results = await client.multi().set("foo", "some heavy computation").execAsync()
    console.log(`exec ${results}`)
}

main2()

Thursday, May 23, 2019

How to check open ports and processes in macOS


사용중인 포트 오류를 해결하기 위해서 프로세스를 kill 하기 위해 다음과 같은 명령어로 확인할 수 있습니다.

lsof -i -P

How to optimize Visual Studio Code tab settings (disappears and preview double click)

Visual Studio Code 탭 설정 최적화 하는 방법입니다.
F1을 눌러서 settings.json을 연 다음에 다음과 같은 텍스트를 추가 합니다.

1. 탭이 전체가 다 사라졌을때 되살리는 방법
"workbench.editor.showTabs": true

2. 더블 클릭을 하지 않으면 다른 파일이 현재 탭을 덮어씌우는 현상 해결
"workbench.editor.enablePreview": false

Friday, February 22, 2019

Linux libuv socket server example

#include <stdio.h>
#include <stdlib.h>
#include <uv.h>

// uv_handle_t > uv_stream_t > uv_tcp_t

const int backlog = 128;
const int buffer_size = 1024;
uv_fs_t open_req;
uv_fs_t read_req;
uv_tcp_t *client; // 연결해온 클라이언트(처리를 편하게 하기 위해)

void on_new_connection(uv_stream_t *server, int status);
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t suggested_size);
void on_client_read(uv_stream_t *client, ssize_t nread, uv_buf_t buf);
void on_client_write(uv_write_t *req, int status);
void on_file_open(uv_fs_t *req);
void on_file_read(uv_fs_t *req);

// 클라이언트와 연결 후, 클라이언트에서 데이터를 로드
void on_new_connection(uv_stream_t *server, int status) {
  if (status == -1) {
    fprintf(stderr, "error on_new_connection");
    uv_close((uv_handle_t*) client, NULL);
    return;
  }

  // 클라이언트를 유지하기위한 메모리를 확보
  client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
  // loop에 등록
  uv_tcp_init(uv_default_loop(), client);

  // accept
  int result = uv_accept(server, (uv_stream_t*) client);

  if (result == 0) { // success
    // 클라이언트에서 데이터를 읽어 내고, alloc_buffer에서 확보 한 영역에 기록 callback을 호출
    uv_read_start((uv_stream_t*) client, alloc_buffer, on_client_read);
  } else { // error
    uv_close((uv_handle_t*) client, NULL);
  }
}

// suggeseted_size에서 전달 된 영역을 확보
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t suggested_size) {
  return uv_buf_init((char*) malloc(suggested_size), suggested_size);
}

// tcp 클라이언트에서받은 파일 이름을 열기
void on_client_read(uv_stream_t *_client, ssize_t nread, uv_buf_t buf) {
  if (nread == -1) {
    fprintf(stderr, "error on_client_read");
    uv_close((uv_handle_t*) client, NULL);
    return;
  }

  // 클라이언트로부터 받은 데이터
  // 데이터는 buf.base에 저장되어있다.
  char *filename = buf.base;
  int mode = 0;

  // 파일 열기
  uv_fs_open(uv_default_loop(), &open_req, filename, O_RDONLY, mode, on_file_open);
}

// client에 돌려 준 뒤 뒷정리
void on_client_write(uv_write_t *req, int status) {
  if (status == -1) {
    fprintf(stderr, "error on_client_write");
    uv_close((uv_handle_t*) client, NULL);
    return;
  }

  // 메모리 해제
  free(req);
  // 여기에 해제하기 위해 붙여 놓았다.
  char *buffer = (char*) req->data;
  free(buffer);

  // tcp connection 닫기
  uv_close((uv_handle_t*) client, NULL);
}

// 열려있는 파일의 내용을 보기
void on_file_open(uv_fs_t *req) {
  if (req->result == -1) {
    fprintf(stderr, "error on_file_read");
    uv_close((uv_handle_t*) client, NULL);
    return;
  }

  // 파일로부터 읽어 들인 데이터를 저장할 버퍼
  char *buffer = (char *) malloc(sizeof(char) * buffer_size);

  // 로드 등록, 쓰기 버퍼를 지정
  int offset = -1;
  // data 필드에 넣어 콜백 함수에 전달
  read_req.data = (void*) buffer;
  // 이곳은 비동기 콜백
  uv_fs_read(uv_default_loop(), &read_req, req->result, buffer, sizeof(char) * buffer_size, offset, on_file_read);
  // read 등록하면 해제
  uv_fs_req_cleanup(req);
}

// 파일의 내용을 클라이언트에 반환
void on_file_read(uv_fs_t *req) {
  if (req->result < 0) {
    fprintf(stderr, "error on_file_read");
    uv_close((uv_handle_t*) client, NULL);
  } else if (req->result == 0) { // 읽은 후 닫기
    uv_fs_t close_req;
    uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
    uv_close((uv_handle_t*) client, NULL);
  } else { // 읽은 내용을 클라이언트에 반환
    // 쓰기 영역 확보
    uv_write_t *write_req = (uv_write_t *) malloc(sizeof(uv_write_t));

    // 클라이언트에 반환 내용
    // req->data 에 들어가있는 버퍼의 포인터로부터 로드
    char *message = (char*) req->data;

    // uv_write 사용 uv_buf_t 준비
    uv_buf_t buf = uv_buf_init(message, sizeof(message));
    buf.len = req->result;
    buf.base = message;
    int buf_count = 1;

    // on_client_write 내에서 해제 할 수 있도록
    // 포인터를 저장하고 전달한다.
    write_req->data = (void*) message;

    // client로 buf를 기록
    uv_write(write_req, (uv_stream_t*) client, &buf, buf_count, on_client_write);
  }
  // 동기화에 해제
  uv_fs_req_cleanup(req);
}

int main(void) {
  // Network I/O 구조체
  uv_tcp_t server;
  // loop에 등록
  uv_tcp_init(uv_default_loop(), &server);
  // 주소 가져오기
  struct sockaddr_in bind_addr = uv_ip4_addr("0.0.0.0", 7000);
  // bind
  uv_tcp_bind(&server, bind_addr);

  // uv_stream_t: uv_handle_t의 서브클래스, uv_tcp_t의 부모
  // listen
  int r = uv_listen((uv_stream_t*) &server, backlog, on_new_connection);
  if (r) {
    // 에러 처리
    fprintf(stderr, "error uv_listen");
    return 1;
  }

  // loop 시작
  uv_run(uv_default_loop());

  return 0;
}

Wednesday, February 13, 2019

BitcoinSV build on macOS

brew install berkeley-db

--
Compiled using the following commands

(most of them are from bitcoin core library)
cd <directory of your choice>
Download source

xcode-select --install

When the popup appears, click Install.

Then install Homebrew.
brew install automake libtool boost miniupnpc openssl pkg-config protobuf python qt libevent qrencode
If you want to build the disk image with make deploy (.dmg / optional), you need RSVG:

brew install librsvg
Build core
./autogen.sh
./configure
make

For GUI use (Not functional there is no -qt distribution)
./configure --with-gui=qt5

if you have already build then:
make clean
./autogen.sh
./configure --with-gui=qt5
make

It is recommended to build and run the unit tests:
make check
(not tested)

You can also create a .dmg that contains the .app bundle (optional):

make deploy
Core is now available at ./src/bitcoind
Tested on macOS Mojave 10.14

8GB RAM

2.5 GHZ intel i5 x64

QT is not functional there is no -qt distribution