코드로 신규 스팀 계정 생성 정리. Resource Credits, Account Creation Token.

in SCT.암호화폐.Crypto2 months ago (edited)

이타인클럽입니다.
꿈의 의미를 파악하고, 잘 기록하기 위해 모바일 앱을 만들고 있습니다.
여기서 스팀 블록체인을 이용하여 꿈 내용을 기록하려고 합니다.
프로젝트에 대한 자세한 내용은 다음을 참고하세요.

Dream Journal을 위한 스팀앱 개발중!

처음에 계획에 없었는데, 만들다보니 스팀 Dapp이 되어가고 있습니다.
앱을 사용하려면 스팀 계정을 생성해야 합니다.
스팀 계정을 스팀 공식 사이트에서 할 수도 있지만, 모바일 앱이고, 일종의 서비스이다 보니 앱 자체에서 그 기능을 수행하는 것이 바람직합니다.

코드에서 계정 생성 흐름

스팀헌트의 계정 생성 방법을 보고 공식 사이트가 아닌 곳에서 계정 생성이 가능하다는 것을 봤지만, 정보를 찾아도 잘 나오지 않았습니다.

열심히 찾던 중, @jacobyu님께서 예전에 구현해 놓으신 글을 보고, 연락을 드렸더니 흔쾌히 소스코드를 공유해주셨습니다! 너무 고맙습니다.

먼저 계정 생성 흐름을 간략히 정리해보겠습니다. 다른 사람의 계정을 생성하는 방법은 두 가지입니다.

  1. 3 STEEM을 내고 즉시 생성한다.
  2. 새로운 계정을 만들기 위한 creator 계정의 Resource Credits을 이용해서 생성

이 내용은 스팀 개발 사이트에 정리되어 있습니다.
https://github.com/steemit/devportal-tutorials-js/tree/master/tutorials/26_create_account

여기서는 2번, Resource Credits을 이용하는 방법을 설명합니다. 그 흐름은 다음과 같습니다.

  1. 만들고자 하는 계정이 존재하는지, 적당한 계정이름인지 체크
  2. Account Creation Token (ACT) 생성 요청. 이 때 Resource Credits이 필요.
  3. ACT가 생성되면 (생성하면 영구 사용가능, 기간 만료 없음) 계정 생성 요청
  4. 계정 생성 완료

https://steemd.com 사이트에 가보면 자신의 Resource Credits (RC)을 볼 수 있습니다.
image.png

저는 지금 계정 생성 테스트한다고 RC가 31%정도입니다.
계정을 생성하기 위해서는 4,989,726,163,546 RC가 필요합니다.

스팀 설정

스팀 블록체인과 인터랙션하기 위해 dsteem 라이브러리를 사용합니다.
https://github.com/jnordberg/dsteem#readme

스팀 블록체인과 연결하기 위해 다음과 같이 설정합니다.

// steem api
const dsteem = require("dsteem");
// options
let opts = {};
//connect to production server
opts.addressPrefix = "STM";
opts.chainId =
  "0000000000000000000000000000000000000000000000000000000000000000";
// connect to server which is connected to the network/production
const client = new dsteem.Client("https://api.steemit.com");

계정 확인 코드

계정이 존재하는지 확인하는 코드입니다.

// check sanity of a username to be created
// @return availability of the username
const checkUsername = async (username) => {
  console.log("[checkUsername] username", username);
  //// check sanity
  // short length
  if (username.length < 3) {
    console.log("username must be longer than 3.", username);
    return false;
  }
  // long length
  if (username.length > 16) {
    console.log("username must be shorter than 16.", username);
    return false;
  }
  // taken
  try {
    let available = false;
    const account = await client.database.call("get_accounts", [[username]]);
    console.log("account:", account);
    if (account.length == 0) {
      available = true;
      console.log("username is avaliable", username);
    }
    return available;
  } catch (error) {
    console.log("the username aldready exists.", username);
    return false;
  }
};

ACT 생성 요청

ACT를 요청하기 위해서는 creator의 계정과 active key가 필요합니다.

입력 예: creator: 'etainclub'
active key: '5Kxxxxxxxxxxxxxxxxxxxxx'

// claim account creation token to create a new account
// @return success of failure of the claim
const claimAccountCreationToken = async (creator, activeKey) => {
  try {
    const privateKey = dsteem.PrivateKey.fromString(activeKey);
    let ops = [];
    const claim_op = [
      "claim_account",
      {
        creator: creator,
        fee: "0.000 STEEM",
        extensions: [],
      },
    ];
    ops.push(claim_op);
    const result = await client.broadcast.sendOperations(ops, privateKey);
    console.log("claim ACT result", result);
    if (result) return true;
    else return false;
  } catch (error) {
    console.log("error. claim failed", error);
    return false;
  }
};

생성 요청하면 RC가 충분하면 다음과 같은 결과를 얻습니다.

claim ACT result {id: "ff220d20230f94b98801f39350962602b5f96475", block_num: 45541274, trx_num: 1, expired: false} block_num: 45541274expired: false id: "ff220d20230f94b98801f39350962602b5f96475" trx_num: 1 __proto__: Object

참고로, SteemPeak에서 이와 같은 작업을 직접해볼 수 있습니다.
아래 그림을 보면 저는 2개의 ACT가 있습니다.
image.png

즉, 2개의 계정 생성을 요청할 수 있는 것입니다.
위에서 Create Account with Token (2 left)를 클릭하면 계정을 생성할 수 있습니다.

ACT 개수 확인 코드

ACT가 있는지 확인하는 코드입니다.

// check availabled claimed token
// @return availabivity of the token
const checkClaimedToken = async (username) => {
  try {
    const account = await client.database.call("get_accounts", [[username]]);
    const numTokens = account[0].pending_claimed_accounts;
    console.log("number of claimed tokens", numTokens);
    if (numTokens > 0) return true;
    else return false;
  } catch (error) {
    return false;
  }
};

계정 생성 코드

그럼 마지막으로 계정을 생성하는 코드입니다.
계정을 생성하기 위해 새로운 계정명과 암호, 그리고 creator 계정과 active key가 필요합니다.
여기서 새로 생성할 계정의 keys를 생성하기 위한 암호를 랜덤으로 정했습니다.
정작 중요한 것은 private key, owner key, active key, posting key이기 때문입니다.

const createAccount = async (username, creator, creatorActiveKey) => {
  //// check sanity: claimed account creation tokens
  if (!checkClaimedToken(creator)) {
    console.log("failed to create account due to no clamied token");
    return false;
  }

  // generate random password
  const password = Math.random().toString();
  // private active key of creator account
  const privateKey = dsteem.PrivateKey.fromString(creatorActiveKey);
  // create keys
  const ownerKey = dsteem.PrivateKey.fromLogin(username, password, "owner");
  const activeKey = dsteem.PrivateKey.fromLogin(username, password, "active");
  const postingKey = dsteem.PrivateKey.fromLogin(username, password, "posting");
  const memoKey = dsteem.PrivateKey.fromLogin(
    username,
    password,
    "memo"
  ).createPublic(opts.addressPrefix);

  const ownerAuth = {
    weight_threshold: 1,
    account_auths: [],
    key_auths: [[ownerKey.createPublic(opts.addressPrefix), 1]],
  };
  const activeAuth = {
    weight_threshold: 1,
    account_auths: [],
    key_auths: [[activeKey.createPublic(opts.addressPrefix), 1]],
  };
  const postingAuth = {
    weight_threshold: 1,
    account_auths: [],
    key_auths: [[postingKey.createPublic(opts.addressPrefix), 1]],
  };

  //// send creation operation
  // operation
  let ops = [];
  //create operation to transmit
  const create_op = [
    "create_claimed_account",
    {
      creator: creator,
      new_account_name: username,
      owner: ownerAuth,
      active: activeAuth,
      posting: postingAuth,
      memo_key: memoKey,
      json_metadata: "",
      extensions: [],
    },
  ];
  console.log(create_op);
  // push the creation operation
  ops.push(create_op);
  // broadcast operation to blockchain
  const result = await client.broadcast.sendOperations(ops, privateKey);
  if (result) {
    console.log("creation result", result);
    return true;
  } else {
    return false;
  }
};

계정을 생성하기 위한 active key는 코드에 포함시키지 않도록 주의합니다.
.env 파일에 넣거나 expo의 경우 constants에 넣어서 처리하도록 합니다.

참고.

저는 expo 프로젝트를 eject해서 사용하는데, constants에 넣어서 사용하고 있습니다.

// constants/keys.js
export const STEEM_CREATOR_ACCOUNT = "etainclub";
export const STEEM_CREATOR_ACTIVEKEY =
  "5Kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

// signup.js
import {
  STEEM_CREATOR_ACCOUNT,
  STEEM_CREATOR_ACTIVEKEY,
} from "../constants/keys";

claimAccountCreationToken(STEEM_CREATOR_ACCOUNT, STEEM_CREATOR_ACTIVEKEY);

그리고 또 주의할 것은 이와 같이 key를 포함하는 파일은 git에 포함되지 않도록 꼭 .gitignore에 추가해야 합니다.

테스트한다고 RC가 완전 바닥이 되어버렸네요. 얼른 스달을 스팀파워로 바꿨는데도 이모양입니다. 이정도로는 서비스 유지가 어렵겠네요 .ㅜ.,ㅜ

image.png

Sort:  

워우!! 엄청난 작업을 하고 계시는군요..!!!
앱 내에서 계정생성까지 된다면.. 아주 대박일 듯 싶습니다.!!

그리고 모바일로 글도 쓰고, 댓글도 달 수 있다면..!!!(그런 기능까지 생각하고 계신지는 몰라도요..!!)

혹시나 나중에 계정생성에 대한 계정생성 토큰이 필요하다면.. @upvu 에서 한번 제공 해드릴 수도 있을 것 같다는 생각이 듭니다. (공유는 해야겠지만요!)

active key가 필요하다보니.. 조금 어려운 부분이 있기는 한데...
api로 계정생성 정보를 받자니 비번이 들어가는 문제가 있기도 하구요...
계정생성 이후 앱내에서 다시 비번 변경 기능을 강제화 시켜서 유저에게 정하게 하는 것도 좋을 것 같다는 생각입니다..

매우 응원합니다.!!!

저는 그저 @jaycobyu님이 공유해주신 코드보고 구현하는 수준입니다. steemhunt사이트가 예쁘게 잘 되어 있어서 참고하고 있구요~

지원 말씀 너무 고맙습니다~ 키문제로 쉽지는 않아보이네요.

스팀파워가 이토록 개발에 절실히 필요한 적은 처음이네요~ 우선 되는대로 파워업을 해야겠습니다~ 앱 사용자가 많을 때의 이야기지만요~

관심 고맙습니다~

응원합니다!!

jacobyu님덕분에 해결했습니다. 너무 고맙습니다~

Coin Marketplace

STEEM 0.17
TRX 0.03
JST 0.036
BTC 10820.30
ETH 363.38
USDT 1.00
SBD 0.98