Only this pageAll pages
Powered by GitBook
1 of 8

cashkit

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Configs

Loading...

CONTRIBUTING

Contributions are welcome! Open an issue on here.

Explorer

React + gRPC + bchd = 💚

This project is under development. Stuff can break.

Live Transactions

Blocks

Development

  • Runing Envoy + React + Tests in a single terminal

    • cd cashweb/

    • docker-compose build

    • docker-compose up

  • Running separatly [3 terminals]

    • React app:

      • npm install

      • npm start

        or

      • docker build -f Dockerfile.dev -t webclient .

      • docker run -p 3000:3000 -v /app/node_modules -v $(pwd):/app webclient

    • Tests: npm run test

    • Envoy:

      • cd envoy/

      • docker build -t envoy .

      • docker run -p 8080:8080 envoy

  • Go to the browser at localhost:3000

Commands (Others)

  • Recreate proto files: ./src/protos/genproto.sh

What do you get?

  • React

  • gPRC, Web gRPC

  • Typescript

  • Hooks

  • Lazy loading, Code splitting

  • Error boundaries

  • Hot Reload

  • Components.

    • Memoized Components. (Prevents unnecessary rerendering)

    • Components: They are dumb, they only display the data provided. It may contain some conditional operators and are easy to memoize.

    • Containers: They are smart components the are aware of the props. (Props could be directly from the parent or from the store.) These smart components can make calls to business logic code or update the app state.

  • Views: These components contain containers and are also aware of the app state.

  • Redux: Consists of Actions, Reducers, Sagas and other business logic.

  • Utils: Consists of helper functions.

  • Protos: Used to connect to gRPC Server and act as a connection client.

  • Managers:

    • gRPC Manager. inspired from grpc-bchrpc-browser

  • Docker/Docker Compose: Containerises the application.

    • Hot reload via shared volumes in development mode.

  • Envoy: Envoy translates the HTTP/ 1.1 calls produced by the client into HTTP/ 2 calls that can be handled by the services.

  • Node interaction: Live Transactions, Fetch Transaction details, Fetch Block details

  • Scripts:

    • genproto.sh

  • Testing: Snapshot testing of Components.

Why Envoy?

After doing a lot of research and figuring out many ways to interact with gRPC server through web client. I ended up following this approach:

  • With Envoy (Current approach). grpc/grpc-web

Testing

  • Snapshot Testing

What else?

:information_source: Eventually this project will have:

  • Ability to interact with a local bchd node(private). :white_check_mark:

  • Ability to subscribe to custom events via cashserver(private). :white_check_mark:

  • Docker and Docker-Compose :white_check_mark:

  • Protos for interactions with cashserver.

  • Fetch SLP token data and more interactions.

  • Block Subscription.

  • Create a wallet and submit transactions.

  • Fetch address information.

  • Play a game via scanning a QR code [Separate module].

  • Kubernetes configs + docs.

  • Travis/circle CI configs + docs.

  • more...

:speaker: Private repositories will be made public in coming week(s).

Donations

bitcoincash:qre3vyl5amlua9a80fg9ta3ck806fvqvly9frxe6n4

qrcode

License

MIT

License: MIT

Introduction

Bitcoin Cash is an ideal blockchain with incredible throughput capacity, ability to scale, low transaction fees, 0-confirmation, and soon an EVM compatible side chain and much more. It’s a gem waiting to be discovered by the many.

There is a huge demand for Software Engineers and Developers who work on the Bitcoin Cash Ecosystem. This open-source organization consists of many small and medium-sized projects which use but are not limited to various node implementations(BCHD), libraries, languages(Javascript, Go, Cashscript, and Python), and cutting-edge technologies like gRPC and Docker. I hope that this organization will act as the go-to place for the new developer(s) to experiment and build something that can help grow the ecosystem.

Donations

bitcoincash:qre3vyl5amlua9a80fg9ta3ck806fvqvly9frxe6n4

qrcode

Contribution

Feel free to open an issue on here and let's discuss.

License

MIT

Explorer
CashScript SLP
Protos
Node Configs

Node Configs

BCHD Node Configs

Configs

Mac

Executable

Config path

Executable path

Bchd/

/Users/user-name/Library/Application Support/Bchd/bchd.conf

/Users/user-name/go/bin/bchd

Bchwallet/

/Users/user-name/Library/Application Support/Bchwallet/bchwallet.conf

/Users/user-name/go/bin/bchwallet

Bchctl/

/Users/user-name/Library/Application Support/Bchctl/bchctl.conf

/Users/user-name/go/bin/bchctl

bchwallet config

File: bchwallet.conf

username=<your-rpc-user-name>
password=<your-rpc-password>
bchdusername=<your-rpc-user-name>
bchdpassword=<your-rpc-password>
rpccert=./rpc.crt # See certificates.md
rpckey=./rpc.key # See certificates.md

bchctl config

File: bchctl.conf

rpcuser=<your-rpc-user-name>
rpcpass=<your-rpc-password>
rpccert=./rpc.crt # See certificates.md

bchd config

File: bchd.conf

[Application Options]
rpcuser=<your-rpc-user-name>
rpcpass=<your-rpc-password>
rpclisten=:8334
rpccert=./rpc.crt
rpckey=./rpc.key
grpclisten=[::]:8335
prunedepth=300
txindex=1
addrindex=1
debuglevel=info

Certificates.

Auto Generation

  • Post running the bchd on your local machine, you should be able to find the certificate and key that are generated by bchd. You can use that for local development purposes.

See Sample bchd config: https://github.com/gcash/bchd/blob/master/sample-bchd.conf rpccert=~/.bchd/rpc.cert rpckey=~/.bchd/rpc.key

Custom generation

Output files

  • ca.key: Certificate Authority private key file (this shouldn't be shared in real-life)

  • ca.crt: Certificate Authority trust certificate (this should be shared with users in real-life)

  • server.key: Server private key, password protected (this shouldn't be shared)

  • server.csr: Server certificate signing request (this should be shared with the CA owner)

  • server.crt: Server certificate signed by the CA (this would be sent back by the CA owner) - keep on server

  • server.pem: Conversion of server.key into a format gRPC likes (this shouldn't be shared)

#!/bin/bash

# Changes these CN's to match your hosts in your environment if needed.
SERVER_CN=localhost
# Step 1: Generate Certificate Authority + Trust Certificate (ca.crt)
openssl genrsa -passout pass:1111 -des3 -out ca.key 4096
openssl req -passin pass:1111 -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=${SERVER_CN}"

# Step 2: Generate the Server Private Key (server.key)
openssl genrsa -passout pass:1111 -des3 -out server.key 4096

# Step 3: Get a certificate signing request from the CA (server.csr)
openssl req -passin pass:1111 -new -key server.key -out server.csr -subj "/CN=${SERVER_CN}" -config certs.cnf

# Step 4: Sign the certificate with the CA we created (it's called self signing) - server.crt
openssl x509 -req -passin pass:1111 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -extensions req_ext -extfile certs.cnf

# Step 5: Convert the server certificate to .pem format (server.pem) - usable by gRPC
openssl pkcs8 -topk8 -nocrypt -passin pass:1111 -in server.key -out server.pem

# Addon: Generating unencrypted key for bchd server
# openssl rsa -in server.pem -out key.unencrypted.pem -passin pass:1111

certs.cnf

[ req ]
default_bits = 4096
distinguished_name = dn
req_extensions = req_ext
prompt = no

[ dn ]
CN = localhost

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
DNS.2 = 127.0.0.1

CODE_OF_CONDUCT

Please be nice to everyone.

Protos

All Protos used by Cashkit. ⚙️

This repo contains all proto files and generated code used by the cashkit org.

https://github.com/cashkit/protos/tree/main/bchrpc

#!/bin/bash

export PATH="$PATH:$(go env GOPATH)/bin"

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative bchrpc/bchrpc.proto
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative kitrpc/kitrpc.proto

CashScript SLP

TOKENS

Valid transaction using the FT.cash contract with single OP_RETURN: https://explorer.bitcoin.com/bch/tx/a71eae6cd8864dca5e184f49093f1b0b9cb49572959354f9ad72e5d0c0a3fa8c

Valid transaction using the FT.cash contract with 2 OP_RETURN (SLP AND MEMO): https://explorer.bitcoin.com/bch/tx/9d1893ddedd9f1d041521c3f98508883856c3efde2406980dd3aa7af1c1b19bb

FT.cash

pragma cashscript ^0.6.3;

contract FT(bytes20 owner) {
    // Warning: This method 'reclaim' should only be used in testing.
    // Backdoor to reclaim funds,
    function reclaim(pubkey pk, sig s) {
        require(checkSig(s, pk));
    }

    function createToken(
        pubkey pk,
        sig s,
        bytes20 recipientPkh,
        bytes lokadId,
        bytes tokenType,
        string actionType,
        string symbol,
        string name,
        string documentURI,
        string documentHash,
        bytes decimals,
        bytes baton,
        bytes initialQuantity,
        int minerFee,
        //string memoText
    ) {  
        require(hash160(pk) == owner);
        require(checkSig(s, pk));

        int dust = 546;

        bytes token = new OutputNullData([
            lokadId,
            tokenType,
            bytes(actionType),
            bytes(symbol),
            bytes(name),
            bytes(documentURI),
            bytes(documentHash),
            decimals,
            baton,
            initialQuantity
        ]);

        // bytes memo = new OutputNullData([
        //     0x6d02,
        //     bytes(memoText)
        // ]);

        int changeAmount = int(bytes(tx.value)) - minerFee - dust;
        if (changeAmount >= dust) {
            bytes34 recipient = new OutputP2PKH(bytes8(dust), recipientPkh);
            // Get the change back to the contract i.e Pay to Script Hash which is the current contract.
            bytes32 change = new OutputP2SH(bytes8(changeAmount), hash160(tx.bytecode));
            //require(hash256(token + recipient + change + memo) == tx.hashOutputs);
            require(hash256(token + recipient + change) == tx.hashOutputs);
        } else {
            require(hash256(token) == tx.hashOutputs);
        }

    }
}

Usage

// Check the tokens/genesis.tsx

// import { hexToBin } from '@bitauth/libauth'
const lokadId = '0x534c5000'
...

const lokadIdBin = hexToBin(lokadId.substring(2))
...

const tx = await contract.functions
  .createToken(
    userPk,
    new SignatureTemplate(user),
    userPkh,
    lokadIdBin,
    ...
    minerFee,
  )
  .withOpReturn([
    lokadId,
    ...
    initialQuantity
  ])
  .to(slpRecipient, dust)
  .to(contract.address, change)
  // .withOpReturn([
  //   '0x6d02',
  //   strr,
  // ])
  .withHardcodedFee(minerFee)
  //.build()
  .send();

Valid transactions

  • NFT1-Group: https://explorer.bitcoin.com/bch/tx/110426292c63fe0db0932b4dc1c49594127e9b2e1a6d66a3e5696a830de9f3dd

    • Genesis: 5000

  • NFT1-Child: https://explorer.bitcoin.com/bch/tx/546c0ca35ac4612a5ed800acc27b7c67888c874717fd1e385c07a9790240701b

    • Genesis: 1

    • Document URI: (hex to utf8)456c656374726963204d6f75736520302e346d20362e306b67 = Electric Mouse 0.4m 6.0kg

    • Document hash: 4335393041313135313339423742383046324543323237334431364436353744 = C590A115139B7B80F2EC2273D16D657D

NFT1-Group & NFT1-Child contract.

NFT.cash

pragma cashscript ^0.6.0;

contract NFT(bytes20 owner) {
    // Warning: This method 'reclaim' should only be used in testing.
    // Backdoor to reclaim funds,
    function reclaim(pubkey pk, sig s) {
        require(hash160(pk) == owner);
        require(checkSig(s, pk));
    }

    // Warning: This method 'createNFTChild' should only be used in testing.
    // Backdoor to reclaim funds,
    function createNFTChild(pubkey pk, sig s) {
        require(hash160(pk) == owner);
        require(checkSig(s, pk));
    }

    function createNFTGroup(
        pubkey pk,
        sig s,
        bytes20 recipientPkh,
        string actionType,
        string symbol,
        string name,
        string documentURI,
        string documentHash,
        int minerFee,
    ) {  

        require(hash160(pk) == owner);
        require(checkSig(s, pk));

        bytes announcement = new OutputNullData([
            0x534c5000,
            0x81,
            bytes(actionType),
            bytes(symbol),
            bytes(name),
            bytes(documentURI),
            bytes(documentHash),
            0x00,
            0xff, // Trick: Keep this number above the number of transactions you would expect.
            0x0000000000001388
        ]);
        // Calculate leftover money after fee (1000 sats)
        // Add change output if the remainder can be used
        // otherwise donate the remainder to the miner
        // int minerFee = 1000;
        int dust = 546;
        int changeAmount = int(bytes(tx.value)) - dust - minerFee;

        // require(changeAmount > dust);

        if (changeAmount >= minerFee) {
            bytes34 recipient = new OutputP2PKH(bytes8(dust), recipientPkh);
            bytes32 change = new OutputP2SH(bytes8(changeAmount), hash160(tx.bytecode));
            require(hash256(announcement + recipient + change) == tx.hashOutputs);
        } else {
            require(hash256(announcement) == tx.hashOutputs);
        }
    }
}

Meep

https://explorer.bitcoin.com/bch/tx/dc8cbc6486709dea0f23db356549a23d53714a1845172c034fec201cd55c203f

meep