Categorygithub.com/Zilliqa/gozilliqa-sdk/v3

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# README

gozilliqa-sdk

The golang version of zilliqa blockchain library

Requirements

golang environment:

Installation

This sdk uses go mod to manage its dependent libraries.

To install dependencies:

go get ./...

To build:

go build ./...

To run the unit tests (which require access to the Zilliqa testnet):

go test ./...

Supports

Multisig support
  • aggregatedPubKey
  • multiVerify
  • tx block serialization
  • ds block serialization
  • verify tx block
  • verify ds block

State proof

  • getStateProof
  • verifyStateProof

ChainWalker

  • traversalBlock
  • websocket
Account API
  • fromFile
  • toFile
  • newHDAccount (with default derivation path "m/44'/313'/0'/0/${index}")
  • newHDAccountWithDerivationPath
Wallet API
  • createAccount
  • addByPrivateKey addByKeyStore
  • remove
  • setDefault
  • signTransaction (default account)
  • signTransactionWith (specific account)
  • SignBatch
  • SendBatch (using JSON-RPC batch request or WaitGroup)
TransactionFactory Transaction
  • sendTransaction
  • trackTx
  • confirm
  • isPending isInitialised isConfirmed isRejected
ContractFactory Contract
  • deploy
  • call
  • isInitialised isDeployed isRejected
  • getState
  • getAddressForContract
Crypto API
  • getDerivedKey (PBKDF2 and Scrypt)
  • generatePrivateKey
  • Schnorr.sign
  • Schnorr.verify
  • getPublicKeyFromPrivateKey
  • getAddressFromPublicKey
  • getAddressFromPrivateKey
  • encryptPrivateKey
  • decryptPrivateKey
JSON-RPC API

Blockchain-related methods

  • getNetworkId
  • getBlockchainInfo
  • getShardingStructure
  • getDsBlock
  • getLatestDsBlock
  • getNumDSBlocks
  • getDSBlockRate
  • getDSBlockListing
  • getTxBlock
  • getLatestTxBlock
  • getNumTxBlocks
  • getTxBlockRate
  • getTxBlockListing
  • getNumTransactions
  • getTransactionRate
  • getCurrentMiniEpoch
  • getCurrentDSEpoch
  • getPrevDifficulty
  • getPrevDSDifficulty

Transaction-related methods

  • createTransaction
  • getTransaction
  • getRecentTransactions
  • getTransactionsForTxBlock
  • getNumTxnsTxEpoch
  • getNumTxnsDSEpoch
  • getMinimumGasPrice

Contract-related methods

  • getSmartContractCode
  • getSmartContractInit
  • getSmartContractState
  • getSmartContracts
  • getContractAddressFromTransactionID

Account-related methods

  • getBalance
Validation
  • isAddress
  • isPublicjKey
  • isPrivateKey
  • isSignature
Util
  • byteArrayToHexString
  • hexStringToByteArray
  • generateMac
  • isByteString
  • encodeTransactionProto
  • toChecksumAddress
  • isValidChecksumAddress
  • bech32 encode decode
  • isBech32
  • fromBech32Address toBech32Address

Quick Start

Generate a large number of private keys:
func TestGeneratePrivateKey(t *testing.T) {
	for i := 0; i < 100000; i++ {
		privateKey, err := GeneratePrivateKey()
		if err != nil {
			panic("cannot generate private key")
		}

		prikeys := LaksaGo.EncodeHex(privateKey[:])
		if len(prikeys) != 64 {
			panic("generate private key error")
		}
		println("private key = " + prikeys)
		publickKey := GetPublicKeyFromPrivateKey(LaksaGo.DecodeHex(prikeys), true)
		pubkeys := LaksaGo.EncodeHex(publickKey)
		if len(pubkeys) != 66 {
			panic("generate public key error")
		}
		println("public key = " + pubkeys)

	}
}
Encrypt private key to a keystore file:
func TestKeystore_EncryptPrivateKey(t *testing.T) {
	ks := NewDefaultKeystore()
	kv, err := ks.EncryptPrivateKey(util.DecodeHex("24180e6b0c3021aedb8f5a86f75276ee6fc7ff46e67e98e716728326102e91c9"), []byte("xiaohuo"), 0)
	if err != nil {
		t.Error(err.Error())
	} else {
		println(kv)
	}
}
Decrypt private key from a keystore file:
func TestKeystore_DecryptPrivateKey(t *testing.T) {
	json := "{\"address\":\"b5c2cdd79c37209c3cb59e04b7c4062a8f5d5271\",\"id\":\"979daaf9-daf1-4002-8656-3cea134c9518\",\"version\":3,\"crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"26be10cdae0f397bdeead38e7fcc179957dd5e7ef95a1f0f53f37b7ad1355159\",\"kdf\":\"pbkdf2\",\"mac\":\"81d8e60bc08237e4ba154c0b27ad08562821d8c602ee8a492434128de48b66bc\",\"cipherparams\":{\"iv\":\"fc714ad6267c35a2df4cb3f8b8b3cc0d\"},\"kdfparams\":{\"n\":8192,\"c\":262144,\"r\":8,\"p\":1,\"dklen\":32,\"salt\":\"e22ef8a67a59299cee1532b6c6967bdfb0e75ca3c5dff852f9d8daa04683b0c1\"}}}"

	ks := NewDefaultKeystore()
	privateKey, err := ks.DecryptPrivateKey(json, "xiaohuo")
	if err != nil {
		t.Error(err.Error())
	} else {
		if strings.Compare(strings.ToLower(privateKey), "24180e6b0c3021aedb8f5a86f75276ee6fc7ff46e67e98e716728326102e91c9") != 0 {
			t.Error("decrypt private key failed")
		}
	}
}
Send a transfer transaction
func TestSendTransaction(t *testing.T) {
	if os.Getenv("CI") != "" {
		t.Skip("Skipping testing in CI environment")
	}
	wallet := NewWallet()
	wallet.AddByPrivateKey("e19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930")
	provider := provider2.NewProvider("https://dev-api.zilliqa.com/")

	gasPrice, err := provider.GetMinimumGasPrice()
	assert.Nil(t, err, err)

	tx := &transaction.Transaction{
		Version:      strconv.FormatInt(int64(util.Pack(333, 1)), 10),
		SenderPubKey: "0246E7178DC8253201101E18FD6F6EB9972451D121FC57AA2A06DD5C111E58DC6A",
		ToAddr:       "4BAF5faDA8e5Db92C3d3242618c5B47133AE003C",
		Amount:       "10000000",
		GasPrice:     gasPrice,
		GasLimit:     "1",
		Code:         "",
		Data:         "",
		Priority:     false,
	}

	err2 := wallet.Sign(tx, *provider)
	assert.Nil(t, err2, err2)

	rsp, err3 := provider.CreateTransaction(tx.ToTransactionPayload())
	assert.Nil(t, err3, err3)
	assert.Nil(t, rsp.Error, rsp.Error)

	resMap := rsp.Result.(map[string]interface{})
	hash := resMap["TranID"].(string)
	fmt.Printf("hash is %s\n", hash)
	tx.Confirm(hash, 1000, 3, provider)
	assert.True(t, tx.Status == core.Confirmed)
}

Send a batch of payment transactions

func TestBatchSendTransaction(t *testing.T) {
	runtime.GOMAXPROCS(runtime.NumCPU())
	if os.Getenv("CI") != "" {
		t.Skip("Skipping testing in CI environment")
	}
	wallet := NewWallet()
	wallet.AddByPrivateKey("e19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930")
	provider := provider2.NewProvider("https://dev-api.zilliqa.com/")

	gasPrice, err := provider.GetMinimumGasPrice()
	assert.Nil(t, err, err)

	var transactions []*transaction.Transaction
	for i := 0; i < 100; i++ {
		txn := &transaction.Transaction{
			Version:      strconv.FormatInt(int64(util.Pack(333, 1)), 10),
			SenderPubKey: "0246E7178DC8253201101E18FD6F6EB9972451D121FC57AA2A06DD5C111E58DC6A",
			ToAddr:       "4BAF5faDA8e5Db92C3d3242618c5B47133AE003C",
			Amount:       "10000000",
			GasPrice:     gasPrice,
			GasLimit:     "1",
			Code:         "",
			Data:         "",
			Priority:     false,
		}

		transactions = append(transactions, txn)
	}

	err2 := wallet.SignBatch(transactions, *provider)
	assert.Nil(t, err2, err2)

	batchSendingResult,err := wallet.SendBatchOneGo(transactions, *provider)
	if err != nil {
		t.Fail()
	} else {
		fmt.Println(batchSendingResult)
	}
}
Deploy a smart contract
func TestContract_Deploy(t *testing.T) {
	if os.Getenv("CI") != "" {
		t.Skip("Skipping testing in CI environment")
	}
	host := "https://dev-api.zilliqa.com/"
	privateKey := "e19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930"
	chainID := 333
	msgVersion := 1

	publickKey := keytools.GetPublicKeyFromPrivateKey(util.DecodeHex(privateKey), true)
	address := keytools.GetAddressFromPublic(publickKey)
	pubkey := util.EncodeHex(publickKey)
	provider := provider2.NewProvider(host)

	wallet := account.NewWallet()
	wallet.AddByPrivateKey(privateKey)

	code, _ := ioutil.ReadFile("./fungible.scilla")
	init := []core.ContractValue{
		{
			"_scilla_version",
			"Uint32",
			"0",
		},
		{
			"owner",
			"ByStr20",
			"0x" + address,
		},
		{
			"total_tokens",
			"Uint128",
			"1000000000",
		},
		{
			"decimals",
			"Uint32",
			"0",
		},
		{
			"name",
			"String",
			"BobCoin",
		},
		{
			"symbol",
			"String",
			"BOB",
		},
	}
	contract := Contract{
		Code:     string(code),
		Init:     init,
		Signer:   wallet,
		Provider: provider,
	}

	balAndNonce, _ := provider.GetBalance(address)

	gasPrice, _ := provider.GetMinimumGasPrice()

	deployParams := DeployParams{
		Version:      strconv.FormatInt(int64(util.Pack(chainID, msgVersion)), 10),
		Nonce:        strconv.FormatInt(balAndNonce.Nonce+1, 10),
		GasPrice:     gasPrice,
		GasLimit:     "10000",
		SenderPubKey: pubkey,
	}

	tx, err := contract.Deploy(deployParams)
	assert.Nil(t, err, err)
	tx.Confirm(tx.ID, 1000, 10, provider)
	assert.True(t, tx.Status == core.Confirmed)
}
Call a smart contract
func TestContract_Call(t *testing.T) {
	if os.Getenv("CI") != "" {
		t.Skip("Skipping testing in CI environment")
	}
	host := "https://dev-api.zilliqa.com/"
	privateKey := "e19d05c5452598e24caad4a0d85a49146f7be089515c905ae6a19e8a578a6930"
	chainID := 333
	msgVersion := 1

	publickKey := keytools.GetPublicKeyFromPrivateKey(util.DecodeHex(privateKey), true)
	address := keytools.GetAddressFromPublic(publickKey)
	pubkey := util.EncodeHex(publickKey)
	provider := provider2.NewProvider(host)

	wallet := account.NewWallet()
	wallet.AddByPrivateKey(privateKey)

	contract := Contract{
		Address:  "bd7198209529dC42320db4bC8508880BcD22a9f2",
		Signer:   wallet,
		Provider: provider,
	}

	args := []core.ContractValue{
		{
			"to",
			"ByStr20",
			"0x" + address,
		},
		{
			"tokens",
			"Uint128",
			"10",
		},
	}

	balAndNonce, err := provider.GetBalance("9bfec715a6bd658fcb62b0f8cc9bfa2ade71434a")
	assert.Nil(t, err, err)
	n := balAndNonce.Nonce + 1
	gasPrice, _ := provider.GetMinimumGasPrice()

	params := CallParams{
		Nonce:        strconv.FormatInt(n, 10),
		Version:      strconv.FormatInt(int64(util.Pack(chainID, msgVersion)), 10),
		GasPrice:     gasPrice,
		GasLimit:     "1000",
		SenderPubKey: pubkey,
		Amount:       "0",
	}

	tx, err2 := contract.Call("Transfer", args, params, true)
	assert.Nil(t, err2, err2)
	tx.Confirm(tx.ID, 1000, 3, provider)
	assert.True(t, tx.Status == core.Confirmed)
}

A note on versions

This module was originally referenced using pseudo-versions and releases up to v2.4.0 were published as github releases without backward compatibility. Sadly, go modules require version n (n>=2) modules to have a /v<n> tag in their paths, and so we now do. Since this is a breaking change, we've elected to bump the major version to 3, which means that in fact the go module path is now /v3. Hopefully the version churn will now stop.