Skip to content

Zilliqa/gozilliqa-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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
  • getVersion
  • getNodeType
  • getNumPeers
  • 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
  • getTransactionsForTxBlockEx
  • getTxnBodiesForTxBlock
  • getTxnBodiesForTxBlockEx
  • 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.