Giter Club home page Giter Club logo

ckb-demo-ruby-sdk's Introduction

How to use

Prerequisites

First you will need to have ckb compiled of course. Feel free to just following the official build steps in the README. We will customize configs later.

You will also need mruby-contracts. Follow the steps in the README to build it, you will need the generated mruby contract file at build/argv_source_entry.

If you don't want to build mruby-contracts yourself, we have a prebuilt binary at here.

Configure CKB

Before we are using this SDK, we will need a customized CKB config for the following purposes:

  • We will need a stable RPC port we can connect to.
  • We will need to include mruby contract as a system cell. Notice it's also possible to create a new cell with mruby contract as the cell data, then referencing this cell later. Here for simplicity, we are sticking to a system cell.
  • Depending on computing resource you have, you can also set CKB to dummy mining mode to save CPU resources. In dummy mode, CKB will randomly sleep for certain amount of time acting as a "mining" time instead of doing expensive calculations.

First you need a dummy folder to store all the configs, assuming we are using /home/ubuntu/node1, we can do:

$ cp -r <path to ckb>/nodes_template /home/ubuntu/node1
$ cp <path to mruby-contracts>/build/argv_source_entry /home/ubuntu/node1/spec/cells/

In this newly created folder, change the file default.json to the following content:

{
    "data_dir": "default",
    "ckb": {
        "chain": "spec/dev.json"
    },
    "logger": {
        "file": "ckb.log",
        "filter": "info,chain=debug",
        "color": true
    },
    "rpc": {
        "listen_addr": "0.0.0.0:8114"
    },
    "network": {
        "listen_addresses": ["/ip4/0.0.0.0/tcp/8115"],
        "boot_nodes": [],
        "reserved_nodes": [],
        "max_peers": 8
    },
    "sync": {
        "verification_level": "Full",
        "orphan_block_limit": 1024
    },
    "pool": {
        "max_pool_size": 10000,
        "max_orphan_size": 10000,
        "max_proposal_size": 10000,
        "max_cache_size": 1000,
        "max_pending_size": 10000
    },
    "miner": {
        "max_tx": 1024,
        "max_prop": 1024,
        "new_transactions_threshold": 8,
        "type_hash": "0xaeeb7a04b3766acbf86b51b03aa97f4c7a409a1211ac259dc58bc7ad89805561"
    }
}

Notice the miner type hash here is the wallet address for the private key e79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3.

Also, change the file spec/dev.json to the following content:

{
    "name": "ckb",
    "genesis": {
        "seal": {
            "nonce": 0,
            "proof": [0]
        },
        "version": 0,
        "parent_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "timestamp": 0,
        "txs_commit": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "txs_proposal": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "difficulty": "0x100",
        "cellbase_id": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "uncles_hash": "0x0000000000000000000000000000000000000000000000000000000000000000"
    },
    "params": {
        "initial_block_reward": 50000
    },
    "system_cells": [
        {"path": "cells/verify"},
        {"path": "cells/always_success"},
        {"path": "cells/argv_source_entry"}
    ],
    "pow": {
        "Dummy": null
    }
}

And you can try launching CKB using configs here:

./target/release/ckb -c /home/ubuntu/node1/default.json run

Here release version of ckb is used, tho debug version will also work.

You can verify CKB is running by issuing RPC calls:

$ curl -d '{"id": 2, "jsonrpc": "2.0", "method":"get_tip_header","params": []}' -H 'content-type:application/json' 'http://localhost:8114'
{"jsonrpc":"2.0","result":{"raw":{"cellbase_id":"0xd56eab3c0fc9647fa3451a132cd967a4d4f1fc768b8a515ddbd46fb91d5a7a1f","difficulty":"0x20000","number":2,"parent_hash":"0x2726a2938313c5f920b46d224c9ef21e3c9aa3098e340116819680b88f585484","timestamp":1542609053701,"txs_commit":"0xd56eab3c0fc9647fa3451a132cd967a4d4f1fc768b8a515ddbd46fb91d5a7a1f","txs_proposal":"0x0000000000000000000000000000000000000000000000000000000000000000","uncles_count":0,"uncles_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","version":0},"seal":{"nonce":5039870112347525463,"proof":[]}},"id":2}

Running SDK

Now we can setup the Ruby SDK:

$ git clone https://github.com/nervosnetwork/ckb-demo-ruby-sdk
$ cd ckb-demo-ruby-sdk
$ bundle
$ bundle exec pry -r ./lib/ckb/wallet.rb
[1] pry(main)>

In the Ruby shell, we can start playing with the SDK.

Basic wallet

[1] pry(main)> miner = Ckb::Wallet.from_hex(Ckb::Api.new, "e79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3")
[2] pry(main)> alice = Ckb::Wallet.from_hex(Ckb::Api.new, "76e853efa8245389e33f6fe49dcbd359eb56be2f6c3594e12521d2a806d32156")
[3] pry(main)> miner.get_balance
=> 100000
[4] pry(main)> alice.get_balance
=> 0
[5] pry(main)> miner.send_capacity(alice.address, 12345)
=> "0xd7abc1407eb07d334fea86ef0e9b12b2273833137327c2a53f2d8ba1be1e4d85"
[6] pry(main)> # wait for some time
[7] pry(main)> alice.get_balance
=> 12345
[8] pry(main)> miner.get_balance
=> 337655

Notice miner's balance keeps growing with every new block.

If your miner balance is always 0, you might want to run the following command:

[8] pry(main)> miner.address
=> "0x8ce92152fd9613b80470837eb4bd46be12793662d5c22b489a63f475f2612b1d"

And see if the miner address returned in your environment matches the value here, if not, it means that the mruby contract cell compiled in your environment is not exactly the same as the one we use here. In this case, please edit type_hash part in /home/ubuntu/foo/bar/spec.json with your value, and restart CKB, now miner should be able to pick up tokens mined in newer blocks.

User defined token

We can also create user defined token that's separate from CKB. A new user defined token is made of 2 parts:

  • A token name
  • Token's admin pubkey, only token's admin can issue new tokens. Other user can only transfer already created tokens to others.

Ruby SDK here provides an easy way to create a token from an existing wallet

[1] pry(main)> admin = Ckb::Wallet.from_hex(Ckb::Api.new, "e79f3207ea4980b7fed79956d5934249ceac4751a4fae01a0f7c4a96884bc4e3")
[2] pry(main)> alice = Ckb::Wallet.from_hex(Ckb::Api.new, "76e853efa8245389e33f6fe49dcbd359eb56be2f6c3594e12521d2a806d32156")
[3] pry(main)> token_info = admin.created_token_info("Token 1")
=> #<Ckb::TokenInfo:0x0000561fee8cf550 @name="Token 1", @pubkey="024a501efd328e062c8675f2365970728c859c592beeefd6be8ead3d901330bc01">
[4] pry(main)> # token info represents the meta data for a token
[5] pry(main)> # we can assemble a wallet for user defined token with token info structure
[6] pry(main)> admin_token1 = admin.udt_wallet(token_info)
[7] pry(main)> alice_token1 = alice.udt_wallet(token_info)

Now we can create this token from a user with CKB capacities(since the cell used to hold the tokens will take some capacity):

[9] pry(main)> admin.get_balance
=> 3737655
[10] pry(main)> # here we are creating 10000000 tokens for "Token 1", we put those tokens in a cell with 10000 CKB capacity
[11] pry(main)> admin.create_udt_token(10000, "Token 1", 10000000)
[12] pry(main)> admin_token1.get_balance
=> 10000000
[13] pry(main)> alice_token1.get_balance
=> 0

Now that the token is created, we can implement a token transfer process between CKB capacities and user defined tokens. Specifically, we are demostrating the following process:

  • Alice signs signatures providing a certain number of CKB capacities in exchange of some user defined tokens. Notice CKB contracts here can ensure that no one can spend alice's signed capacities without providing tokens for Alice
  • Then admin provides user defined tokens for Alice in exchange for Alice's capacities.

Notice CKB is flexible to implement many other types of transaction for this problem, here we are simply listing one solution here. You are not limited to only this solution.

The following code fulfills this step:

[15] pry(main)> # Alice is paying 10999 CKB capacities for 12345 token 1, alice will also spare 3000 CKB capacities to hold the returned token 1.
[15] pry(main)> partial_tx = alice_token1.generate_partial_tx_for_udt_cell(12345, 3000, 10999)
[18] pry(main)> admin_token1.send_amount(12345, partial_tx)
[19] pry(main)> admin_token1.get_balance
=> 9987655
[20] pry(main)> alice_token1.get_balance
=> 12345

ckb-demo-ruby-sdk's People

Contributors

xxuejie avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.