KardiaChain Golang SDK

This is the guide how to use Golang SDK

Initializing

func SetupKardiaClient() (Node, error){
	url := "https://dev-1.kardiachain.io"
	lgr, err := zap.NewProduction()
	if err != nil {
        return nil, err
    }
    node, err := NewNode(url, lgr)
    if err != nil {
    	return nil, err
    }
    return node, nil
}

API

Info

type IInfo interface {
    Url() string
    IsAlive() bool
    NodeInfo(ctx context.Context) (*NodeInfo, error)
    GetCirculatingSupply(ctx context.Context) (*big.Int, error)
    KardiaCall(ctx context.Context, args SMCCallArgs) ([]byte, error)
}

Blocks

type IBlock interface {
	LatestBlockNumber(ctx context.Context) (uint64, error)
	BlockByHash(ctx context.Context, hash string) (*Block, error)
	BlockByHeight(ctx context.Context, height uint64) (*Block, error)
	BlockHeaderByHash(ctx context.Context, hash string) (*Header, error)
	BlockHeaderByNumber(ctx context.Context, number uint64) (*Header, error)
}

Addresses

type IAddress interface {
    Balance(ctx context.Context, addressHash string) (string, error)
    StorageAt(ctx context.Context, addressHash string, key string) ([]byte, error)
    Code(ctx context.Context, addressHash string) (common.Bytes, error)
    NonceAt(ctx context.Context, addressHash string) (uint64, error)
}

Transactions

type ITx interface {
    GetTransaction(ctx context.Context, hash string) (*Transaction, error)
    GetTransactionReceipt(ctx context.Context, txHash string) (*Receipt, error)
    SendTransaction(ctx context.Context, tx *types.Transaction) error
    SendRawTransaction(ctx context.Context, tx *types.Transaction) error
}

Examples

Note: Examples can be found at ^_test.go

Create Wallet

func Test() {
    address, privKey, err := GenerateWallet()
    fmt.Println("WalletAddress", address.Hex())
    fmt.Println("WalletPrivateKey", privateKeyStr)
}

Send SignedTx

func SendSignedTx() {
	receivedAddress := common.HexToAddress("0x59173FAF22C3fEd212Ec6B5Ea2E50f7644b614f3")
	privateKey, err := crypto.HexToECDSA("63e16b5334e76d63ee94f35bd2a81c721ebbbb27e81620be6fc1c448c767eed9")
	if err != nil {
	    return
	}

	publicKey := privateKey.Public()
	publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
	if !ok {
		return
	}
	fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)

	node, err := setupTestNodeInterface()
	assert.Nil(t, err)
	nonce, err := node.NonceAt(context.Background(), fromAddress.String())
	assert.Nil(t, err)
	balance, err := node.Balance(context.Background(), fromAddress.String())
	assert.Nil(t, err)
	gasLimit := uint64(3100000)
	gasPrice := big.NewInt(1000000000)
	// Send 1 KAI to from test account to receivedAddress
	var Hydro = big.NewInt(1000000000000000000) // 18 decimals
	oneKai := new(big.Int).Mul(new(big.Int).SetInt64(1), Hydro)

	//nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte
	tx := types.NewTransaction(nonce, receivedAddress, oneKai, gasLimit, gasPrice, nil)
	signedTx, err := types.SignTx(types.HomesteadSigner{}, tx, privateKey)
	assert.Nil(t, err)

	err = node.SendTransaction(context.Background(), signedTx)
	assert.Nil(t, err)
	fmt.Printf("tx sent: %s", signedTx.Hash().Hex())
}

Interact with SMC

Function Definition

{
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "_delAddr",
        "type": "address"
      }
    ],
    "name": "getDelegationRewards",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },

Create Node Instance

n, err := NewNode("https://dev-1.kardiachain.io", zap.L())
if err != nil {
	return 
}

Create Contract Instance

// validatorSMC ABI can be found at smc package
validatorSmcAbi, err := abi.JSON(strings.NewReader(smc.ValidatorABI))
if err != nil {
    return err
}
validatorUtil := &Contract{
    Abi: &validatorSmcAbi,
}
n.validatorSMC = validatorUtil

Build payload

payload, err := n.validatorSMC.Abi.Pack("getDelegationRewards", common.HexToAddress(delegatorAddress))
if err != nil {
    n.lgr.Error("Error packing delegation rewards payload: ", zap.Error(err))
    return nil, err
}

Send payload

res, err := n.KardiaCall(ctx, ConstructCallArgs(validatorSMCAddr, payload))
if err != nil {
    n.lgr.Error("GetDelegationRewards KardiaCall error: ", zap.Error(err))
    return nil, err
}

Get response

var result struct {
    Rewards *big.Int
}
// unpack result
err = n.validatorSMC.Abi.UnpackIntoInterface(&result, "getDelegationRewards", res)
if err != nil {
    n.lgr.Error("Error unpacking delegation rewards: ", zap.Error(err))
    return nil, err
}

Subscribe NewHeader event

func TestSubscription_NewBlockHead(t *testing.T) {
	lgr, err := zap.NewProduction()
	assert.Nil(t, err)
	url := "wss://ws-dev.kardiachain.io/ws"

	node, err := NewNode(url, lgr)
	assert.Nil(t, err)

	headersCh := make(chan *types.Header)
	sub, err := node.SubscribeNewHead(context.Background(), headersCh)
	assert.Nil(t, err, "cannot subscribe")

	for {
		select {
		case err := <-sub.Err():
			log.Fatal(err)
		case header := <-headersCh:
			fmt.Println(header.Hash().Hex())
		}
	}
}

Subscribe log filters

node, err := NewNode("wss://ws-dev.kardiachain.io", zap.L())
if err != nil {
    return err
}
smcAddress := "0x0f0524Aa6c70d8B773189C0a6aeF3B01719b0b47"
args := kardia.FilterArgs{
    Address: []string{smcAddress},
}
logEventCh := make(chan *Log)
sub, err := node.KaiSubscribe(context.Background(), logEventCh, "logs", args)
if err != nil {
    return err
}

for {
    select {
    case err := <-sub.Err():
        lgr.Debug("subscribe err", zap.Error(err))
    case log := <-logEventCh:
        logger.Debug("Log", zap.Any("detail", log))
        // Process event
    }
}

Note: More filters args can be found at Kardia RPC API

Last updated