mirror of
https://github.com/planetmint/planetmint-go.git
synced 2025-09-13 03:40:10 +00:00
112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
package lib
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"os/user"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"sigs.k8s.io/yaml"
|
|
)
|
|
|
|
func readSequenceFromFile(seqFile *os.File) (sequence uint64, err error) {
|
|
scanner := bufio.NewScanner(seqFile)
|
|
|
|
// read the first line
|
|
if !scanner.Scan() {
|
|
if err := scanner.Err(); err != nil {
|
|
return 0, fmt.Errorf("reading sequence file: %w", err)
|
|
}
|
|
return 0, fmt.Errorf("sequence file empty: %s", seqFile.Name())
|
|
}
|
|
|
|
sequenceString := scanner.Text()
|
|
|
|
// check for additional lines
|
|
if scanner.Scan() {
|
|
return 0, fmt.Errorf("malformed sequence file %s: contains multiple lines", seqFile.Name())
|
|
}
|
|
|
|
sequence, err = strconv.ParseUint(sequenceString, 10, 64)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("parsing sequence number: %w", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func getSequenceFromChain(clientCtx client.Context) (sequence uint64, err error) {
|
|
account, err := clientCtx.AccountRetriever.GetAccount(clientCtx, clientCtx.FromAddress)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("retrieving account: %w", err)
|
|
}
|
|
return account.GetSequence(), nil
|
|
}
|
|
|
|
func getOrCreateSequenceDirectory() (path string, err error) {
|
|
usr, err := user.Current()
|
|
if err != nil {
|
|
return "", fmt.Errorf("getting current user: %w", err)
|
|
}
|
|
|
|
path = filepath.Join(GetConfig().RootDir, "sequence")
|
|
|
|
// expand tilde to user's home directory
|
|
if strings.HasPrefix(path, "~/") {
|
|
path = filepath.Join(usr.HomeDir, path[2:])
|
|
}
|
|
|
|
// create directory if it doesn't exist
|
|
if err := os.MkdirAll(path, os.ModePerm); err != nil {
|
|
return "", fmt.Errorf("creating sequence directory: %w", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func openSequenceFile(fromAddress sdk.AccAddress) (file *os.File, err error) {
|
|
path, err := getOrCreateSequenceDirectory()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
addrHex := hex.EncodeToString(fromAddress)
|
|
filename := filepath.Join(path, addrHex)
|
|
|
|
file, err = os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("opening sequence file: %w", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// ParseTxResponse converts output buffer to TxResponse
|
|
func ParseTxResponse(out *bytes.Buffer) (txResponse sdk.TxResponse, err error) {
|
|
// Convert string numbers to actual numbers
|
|
numericRegex := regexp.MustCompile(`"([0-9]+?)"`)
|
|
jsonStr := numericRegex.ReplaceAllString(out.String(), "${1}")
|
|
|
|
// We might have YAML here, so we need to convert to JSON first, because TxResponse struct lacks `yaml:"height,omitempty"`, etc.
|
|
// Since JSON is a subset of YAML, passing JSON through YAMLToJSON is a no-op and the result is the byte array of the JSON again.
|
|
jsonBytes, err := yaml.YAMLToJSON([]byte(jsonStr))
|
|
if err != nil {
|
|
return sdk.TxResponse{}, fmt.Errorf("converting YAML to JSON: %w", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(jsonBytes, &txResponse); err != nil {
|
|
return sdk.TxResponse{}, fmt.Errorf("unmarshaling transaction response: %w", err)
|
|
}
|
|
|
|
return
|
|
}
|