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.

CODE_OF_CONDUCT

Please be nice to everyone.

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.

ExplorerCashScript SLPProtosNode Configs

Donations

bitcoincash:qre3vyl5amlua9a80fg9ta3ck806fvqvly9frxe6n4

Contribution

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

License

MIT

here
qrcode

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

Node Configs

BCHD Node Configs

Configs

Mac

Executable

Config path

Executable path

Bchd/

bchwallet config

File: bchwallet.conf

bchctl config

File: bchctl.conf

bchd config

File: bchd.conf

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: 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)

certs.cnf

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)

  • /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

    https://github.com/gcash/bchd/blob/master/sample-bchd.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
    rpcuser=<your-rpc-user-name>
    rpcpass=<your-rpc-password>
    rpccert=./rpc.crt # See certificates.md
    [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
    #!/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
    [ 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

    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

    Commands (Others)

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

    What do you get?

    • React

    • gPRC, Web gRPC

    • Typescript

    • Hooks

    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).

    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.

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

    Donations

    bitcoincash:qre3vyl5amlua9a80fg9ta3ck806fvqvly9frxe6n4

    License

    MIT

    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 .

  • Go to the browser at localhost:3000

  • 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.

  • 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...

  • grpc/grpc-web
    qrcode
    docker run -p 8080:8080 envoy
    License: MIT

    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

    Usage

    Valid transactions

    • NFT1-Group:

      • Genesis: 5000

    • NFT1-Child:

    NFT1-Group & NFT1-Child contract.

    NFT.cash

    Meep

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

  • Document hash: 4335393041313135313339423742383046324543323237334431364436353744 = C590A115139B7B80F2EC2273D16D657D

  • https://explorer.bitcoin.com/bch/tx/110426292c63fe0db0932b4dc1c49594127e9b2e1a6d66a3e5696a830de9f3dd
    https://explorer.bitcoin.com/bch/tx/546c0ca35ac4612a5ed800acc27b7c67888c874717fd1e385c07a9790240701b
    https://explorer.bitcoin.com/bch/tx/dc8cbc6486709dea0f23db356549a23d53714a1845172c034fec201cd55c203f
    meep
    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);
            }
    
        }
    }
    // 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();
    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);
            }
        }
    }