Skip to content

Example Go code for send a transaction

alexjlan edited this page Apr 25, 2020 · 6 revisions
package main

import (
	"encoding/hex"
	"fmt"
	"math/big"
	"time"

	"github.com/Oneledger/protocol/action"
	"github.com/Oneledger/protocol/action/transfer"
	"github.com/Oneledger/protocol/client"
	"github.com/Oneledger/protocol/data/accounts"
	"github.com/Oneledger/protocol/data/balance"
	"github.com/Oneledger/protocol/data/chain"
	"github.com/Oneledger/protocol/data/keys"
	"github.com/Oneledger/protocol/utils"
	"github.com/google/uuid"
)

func main() {

	// connect to the node running at localhost or directly connect to https://fullnode-sdk.chronos.oneledger.network
	conn := "http://127.0.0.1:26602"
	//conn := "https://fullnode-sdk.chronos.oneledger.network"

	//connect to the sdk port (26606 for testnet, 38606 for mainnet)
	cli, err := client.NewServiceClient(conn)
	if err != nil {
		panic(err)
	}

	// ==================================== create account =================================================

	// load keystore folder as wallet folder
	wallet, err := accounts.NewWalletKeyStore("./keystore")
	if err != nil {
		panic(err)
	}
	// if you already have accounts in the keystore
	fmt.Println(wallet.ListAddresses())

	//generating a new account
	acc, err := accounts.GenerateNewAccount(chain.ONELEDGER, "testing")
	if err != nil {
		panic(err)
	}
	if !wallet.Open(acc.Address(), "123") {
		panic("error opening wallet")
	}
	err = wallet.Add(acc)
	if err != nil {
		panic(err)
	}
	wallet.Close()

	// ==================================== send transaction ===============================================
	//sender address, suppose you already created it in your keystore by "olclient account add"
	from, _ := hex.DecodeString(utils.TrimAddress("0lt87b38386d6b6ea805f6c3a5f82b48fb16ab899f5"))
	if err := keys.Address(from).Err(); err != nil {
		panic(err)
	}
	//receiver address
	to, _ := hex.DecodeString(utils.TrimAddress("0lt63b05eefad9462d6b24a55b261773a3f8c977588"))

	// 1 OLT is with 18 zeros as decimals.
	value, ok := big.NewInt(0).SetString("1000000000000000000", 10)
	if !ok {
		panic("failed to parse value")
	}
	// sending 1 OLT.
	amount := action.Amount{
		Currency: "OLT",
		Value:    *(balance.NewAmountFromBigInt(value)),
	}

	fee := action.Fee{
		Price: action.Amount{
			Currency: "OLT",                                                 // only OLT is allowed as fee for now
			Value:    *balance.NewAmountFromBigInt(big.NewInt(10000000000)), // minimal gas price is 10^-9 OLT
		},
		Gas: 40000, // recommend gas by default},
	}

	offlineTxCreation := true

	var packet []byte
	//create transaction without interact with node
	if offlineTxCreation {
		newuuid, _ := uuid.NewUUID()
		send := transfer.Send{
			From:   from,
			To:     to,
			Amount: amount,
		}
		data, err := send.Marshal()
		if err != nil {
			panic(err)
		}
		raw := action.RawTx{
			Type: action.SEND,
			Data: data,
			Fee:  fee,
			Memo: newuuid.String(), // you can add any information here
		}

		packet = raw.RawBytes()

		//create transaction with help of node sdk
	} else {
		req := client.SendTxRequest{
			From:     from,
			To:       to,
			Amount:   amount,
			GasPrice: action.Amount{},
			Gas:      0,
		}
		reply, err := cli.CreateRawSend(req)
		if err != nil {
			panic(err)
		}
		packet = reply.RawTx

	}
	// sign the tx
	ok = wallet.Open(keys.Address(from), "123")
	if !ok {
		panic("failed to open the wallet for address: " + keys.Address(from).String())
	}
	signer, signed, err := wallet.SignWithAddress(packet, from)
	if err != nil {
		panic(err)
	}
	wallet.Close()

	// broadcast to network
	response, err := cli.TxSync(client.BroadcastRequest{
		RawTx:     packet,
		Signature: signed,
		PublicKey: signer,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("broadcast", response)
	time.Sleep(5 * time.Second)

	// Query the network for transaction
	req := client.TxRequest{
		Hash:  response.TxHash.String(),
		Prove: true,
	}
	reply := client.TxResponse{}

	err = cli.Call("query.Tx", &req, &reply)
	fmt.Println("tx: ", reply.Result.Hash.String(), reply.Result.Height)

}