The golang version of zilliqa blockchain library
golang environment:
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 ./...
Blockchain-related methods
Transaction-related methods
Contract-related methods
Account-related methods
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)
}
}
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)
}
}
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")
}
}
}
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)
}
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)
}
}
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)
}
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)
}
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.