massa

package module
v0.0.0-...-212fe83 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 22, 2024 License: MIT Imports: 34 Imported by: 0

README

Go-Massa

Go-Massa is an SDK for the Massa blockchain. It allows you to generate and manage wallets, make native MAS transfers, and interact with Smart Contracts on the Massa network.

This SDK is a work in progress and is early in it's development lifecycle. It is not currently funded and is being built as a learning exercise. As such, there are no garuntees that it will reach a stable release and development may be sporadic or cease entirely at any time. Additionally, the public facing api is likely to change significantly as the design evolves.

Current Features

  • Generate Massa accounts.
  • Import existing Massa accounts from secret keys.
  • Securely persist secret keys to disk as per the Massa Standard for wallet files.
  • Automatic public API discovery and reconnection.
  • Initiate native MAS transfers.
  • Read smart contracts.
  • Call smart contracts.

Planned Work / In Progress

  • Add more examples.
  • Improve test coverage.
  • Add structured logger.
  • Top level functions for sending transactions.
  • Add support for seed phrases as per BIP-39.
  • Add support for Heirarchical Deterministic wallets as per SLIP-10.
  • API discovery improvements.
  • API service redundancy and transaction broadcast retries.
  • Utility for serializing smart contract parameters.
  • Read datastore keys and values.
  • Get native balances.
  • Deploy WASM bytecode.
  • Get Operations.
  • Get staking info.
  • ApiClient chain event streams.
  • Custom configuration improvements.
  • Unify all functionality under a "MassaClient".

Future Work

  • Investigate go-massa as a node client.

Usage

Wallet

Generating accounts:

wallet := massa.NewWallet()

if err := wallet.Init(); err != nil {
    log.Fatal(err)
}

// Empty password will result in a user prompt for a password
password := ""
addr, err := wallet.GenerateAccount(password)
if err != nil {
    log.Fatal(err)
}

acc, err := wallet.GetAccount(addr)
if err != nil {
    log.Fatal(err)
}

log.Printf("Account: %+v", acc)
ApiClient

Sending MAS to another account:

var (
    // Don't hardcode secrets in your applications...
    senderSecretKey = "S11JcqZoz6XXbRjN2nrw2CsuKNfcfqwX6Po2EsiwG6jHnhuVLzo"

    // Empty password will prompt for user input.
    senderPassword = ""

    // Amount must be in nanoMAS
    amount uint64 = 1_000_000_000 // 1 MAS

    jsonRpcApi = "https://buildnet.massa.net/api/v2"
    recipientAddr = "AU12oLjNkH8ywGaeqWuSE1CxdWLhG7hsCW8zZgasax1Csn3tW1mni"
)

apiClient := massa.NewApiClient()
if err := apiClient.Init(jsonRpcApi); err != nil {
    log.Fatal(err)
}

wallet := massa.NewWallet()
if err := wallet.Init(); err != nil {
    log.Fatal(err)
}

senderAddr, err := wallet.ImportAccount(senderSecretKey, senderPassword)
if err != nil {
    log.Fatal(err)
}

senderAcc, err := wallet.GetAccount(senderAddr)
if err != nil {
    log.Fatal(err)
}

opId, err := apiClient.SendTransaction(senderAcc, recipientAddr, amount)
if err != nil {
    log.Fatal(err)
}

log.Printf("Operation ID: %s", opId)

Documentation

Index

Constants

View Source
const (
	// Public API ports
	DEFAULT_GRPC_PORT     = "33037"
	DEFAULT_JSON_RPC_PORT = "33035"

	DEFAULT_PERIOD_OFFSET      uint64 = 5
	DEFAULT_READ_ONLY_CALL_FEE uint64 = 0.01 * 1e9
	MANTISSA_SCALE             uint32 = 9

	DEFAULT_TARGET_NUM_GRPC_AVAILABLE   uint32        = 3
	DEFAULT_GET_PROVIDER_MAX_RETRIES    uint32        = 3
	DEFAULT_GET_PROVIDER_RETRY_INTERVAL time.Duration = 5 * time.Second

	DEFAULT_KDF_ITER    = 600_000
	DEFAULT_KDF_KEY_LEN = 32

	SECRET_KEY_PREFIX              = "S"
	PUBLIC_KEY_PREFIX              = "P"
	ADDRESS_USER_PREFIX            = "AU"
	ADDRESS_CONTRACT_PREFIX        = "AS"
	OPERATION_ID_PREFIX            = "O"
	ADDRESS_PREIX_LENGTH    uint64 = 2
	KEYS_VERSION_NUMBER     uint64 = 0

	MAX_BLOCK_GAS = 4_294_967_295

	DEFAULT_MAINNET_JSON_RPC = "https://mainnet.massa.net/api/v2"
)

Variables

View Source
var (
	ErrWrongMac           = errors.New("derived mac does not match expected mac")
	ErrBadInitialAddrs    = errors.New("no available endpoints in initial API addresses")
	ErrTooManyRetries     = errors.New("too many retries on get provider request")
	ErrInvalidMassaPriv   = errors.New("invalid massa private key")
	ErrInvalidMassaPub    = errors.New("invalid massa public key")
	ErrPrivLength         = errors.New("private key has wrong length")
	ErrReadUvarint        = errors.New("failed reading version uvarint")
	ErrAccountNotFound    = errors.New("account not found for address")
	ErrRegAccountNotFound = errors.New("account not found in registry, please import account")
	ErrIsDir              = errors.New("provide path to file is directory path")
)
View Source
var (
	ErrOutOfRange = errors.New("slice index out of range")
)

Functions

func MaxI128

func MaxI128() *big.Int

func MaxU128

func MaxU128() *big.Int

func MaxU256

func MaxU256() *big.Int

func MinI128

func MinI128() *big.Int

func MinU128

func MinU128() *big.Int

func MinU256

func MinU256() *big.Int

func NewRegistry

func NewRegistry(homeDir string) *registry

func WithHome

func WithHome(home string) massaClientOptFunc

func WithMaxRetries

func WithMaxRetries(val uint32) apiClientOptFn

Configuration function that sets the maximum number of retries before a getProvider request will return an error.

func WithNumAvailable

func WithNumAvailable(val uint32) apiClientOptFn

Configuration function to set the target number of gRPC APIs that should be available at any one time. If not enough APIs are accessible then the embedded apiManager will attempt to discover more.

func WithRetryInterval

func WithRetryInterval(val time.Duration) apiClientOptFn

COnfiguration function that sets the amount of time to wait after a failed getProvider request before trying again.

func WithWalletHome

func WithWalletHome(dir string) walletOptFunc

Types

type ApiClient

type ApiClient struct {
	// contains filtered or unexported fields
}

ApiClient embeds an api manager that handles automatic api discovery, api reconnects, and getting api endpoints.

Exports methods for interacting with the blockchain through the JSON-RPC and gRPC APIs.

func NewApiClient

func NewApiClient(optFns ...apiClientOptFn) *ApiClient

Returns a pointer to a new ApiClient, configurable with the provided configuration functions.

func (*ApiClient) GetOperations

func (a *ApiClient) GetOperations(opIds ...string) ([]*massapb.OperationWrapper, error)

Gets the associated operations for the provided ids.

Returns an error if the request was not successful.

func (*ApiClient) Init

func (a *ApiClient) Init(ApiUrls ...string) error

Init carries out the following steps: Starts initial endpoint discovery, waits for an available gRPC endpoint, and instantiates public grpc service client.

Returns error on failure to instantiate client

func (*ApiClient) NewOperation

func (a *ApiClient) NewOperation(from string, opData OperationData) (Operation, error)

func (*ApiClient) ReadSC

func (a *ApiClient) ReadSC(caller string, callData CallData) ([]byte, error)

Issues a read-only contract call using the provided callData.

Returns the call result as a slice of bytes as well as an error in the event of failure.

func (*ApiClient) SendOperation

func (a *ApiClient) SendOperation(op Operation) (string, error)

type Args

type Args struct {
	// contains filtered or unexported fields
}

func (*Args) AddBool

func (a *Args) AddBool(val bool)

func (*Args) AddByteSlice

func (a *Args) AddByteSlice(val []byte)

func (*Args) AddFloat32

func (a *Args) AddFloat32(val float64)

func (*Args) AddFloat64

func (a *Args) AddFloat64(val float64)

func (*Args) AddInt128

func (a *Args) AddInt128(val Int128)

func (*Args) AddInt32

func (a *Args) AddInt32(val int32)

func (*Args) AddInt64

func (a *Args) AddInt64(val int64)

func (*Args) AddString

func (a *Args) AddString(val String)

func (*Args) AddUint128

func (a *Args) AddUint128(val Uint128)

func (*Args) AddUint256

func (a *Args) AddUint256(val Uint256)

func (*Args) AddUint32

func (a *Args) AddUint32(val uint32)

func (*Args) AddUint64

func (a *Args) AddUint64(val uint64)

func (*Args) AddUint8

func (a *Args) AddUint8(val uint8)

func (*Args) NextUint8

func (a *Args) NextUint8() (uint8, error)

type CallData

type CallData struct {
	Fee            uint64
	MaxGas         uint64
	Coins          uint64
	TargetAddress  string
	TargetFunction string
	Parameter      []byte
}

func NewCallData

func NewCallData(targetAddr, targetFunc string, params []byte, coins uint64) (CallData, error)

func (CallData) Type

func (c CallData) Type() OperationType

type GetProviderRequest

type GetProviderRequest struct {
	RpcType  RpcType
	Retries  uint32
	ResultCh chan apiProvider
	ErrorCh  chan error
}

A request that is used to asynchronously get an ApiProvider from the api manager.

type IMassaClient

type IMassaClient interface {

	// Wallet functionality
	GetAccount()
	GenerateAccount()
	ImportAccount()
	LoadAccount()
	LoadAccountFromPriv()
	GetWalletHome()
	SignOperation()
	SignMessage()

	// ApiClient functionality
	NewOperation()
	SendOperation()
	GetOperations()
	ReadSC()

	// MassaClient Functionality
	SendTransaction()
	CallSC()
}

Just for keeping track of public methods.

type Int128

type Int128 [2]uint64

func NewI128

func NewI128(i *big.Int) (Int128, error)

type Int32

type Int32 int32

type Int64

type Int64 int64

type MassaAccount

type MassaAccount struct {
	// contains filtered or unexported fields
}

func GenerateAccount

func GenerateAccount() (MassaAccount, error)

Generates a Massa Account and saves the corresponding keystore file to the default directory. The user will be prompted for a password.

Returns the generated account.

func LoadAccountFromPriv

func LoadAccountFromPriv(privEncoded string) (MassaAccount, error)

Loads the corresponding account and saves the keystore file at the default keystore location (see defaultKeystoreDir()). The user will be prompted for a password.

Returns the imported account.

func (*MassaAccount) Addr

func (m *MassaAccount) Addr() string

type MassaClient

type MassaClient struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(optFns ...massaClientOptFunc) *MassaClient

func (*MassaClient) CallSC

func (c *MassaClient) CallSC(callerAddr, targetAddr, targetFunc string, params []byte, coins uint64) (opId string, err error)

Calls a target smart contract with the provided call data from the caller address.

Returns the operationId of the call, as well as an error in the event of failure.

func (*MassaClient) ImportFromPriv

func (c *MassaClient) ImportFromPriv(privEncoded, password string) (addr string, err error)

func (*MassaClient) Init

func (c *MassaClient) Init(jsonRpcUrls ...string) error

func (*MassaClient) SendTransaction

func (c *MassaClient) SendTransaction(sender, recipientAddr string, amount uint64) (opId string, err error)

Sends a transaction from the sender address to the recipient address.

The amount argument should be a value in nanoMassa.

Returns the operationId of the transacton as well as an error on failure.

type MassaSignature

type MassaSignature struct {
	PublicKey  string
	Serialized []byte
	Encoded    string
}

type Operation

type Operation struct {
	// contains filtered or unexported fields
}

func (*Operation) Serialize

func (o *Operation) Serialize() ([]byte, string, error)

func (*Operation) Type

func (o *Operation) Type() OperationType

type OperationData

type OperationData interface {
	Type() OperationType
	// contains filtered or unexported methods
}

type OperationType

type OperationType int
const (
	OpType_Transaction OperationType = iota
	OpType_BuyRoll
	OpType_SellRoll
	OpType_ExecuteSC
	OpType_CallSC
)

type RegisteredAccount

type RegisteredAccount struct {
	// Name             string
	Address          string
	KeystoreFilePath string
}

type RpcType

type RpcType int

RpcType is an enum that represents one of two types of RPC that is available on each ApiProvider

const (
	JSON_RPC RpcType = iota
	GRPC
)

func (RpcType) String

func (r RpcType) String() string

type String

type String string

type TxData

type TxData struct {
	// contains filtered or unexported fields
}

func NewTxData

func NewTxData(amount uint64, recipientAddr string) TxData

func (TxData) Type

func (t TxData) Type() OperationType

type Uint128

type Uint128 [2]uint64

func NewU128

func NewU128(i *big.Int) (Uint128, error)

type Uint256

type Uint256 [4]uint64

func NewU256

func NewU256(i *big.Int) (Uint256, error)

type Uint32

type Uint32 uint32

type Uint64

type Uint64 uint64

type Uint8

type Uint8 uint8

type UnlockedAccount

type UnlockedAccount struct {
	// Name string
	*MassaAccount
}

type Wallet

type Wallet struct {
	// contains filtered or unexported fields
}

func NewWallet

func NewWallet(optFns ...walletOptFunc) *Wallet

func (*Wallet) GenerateAccount

func (s *Wallet) GenerateAccount(accountPassword string) (string, error)

TODO: Unit tests... Generates a new Massa Account, saves the keystore file, and registers the account with the wallet registry.

In the case where an empty string "" is provided as the password, the user will be prompted to imput a password.

Returns the address of the generated account and an error.

func (*Wallet) GetWalletHome

func (s *Wallet) GetWalletHome() string

func (*Wallet) ImportFromFile

func (s *Wallet) ImportFromFile(filePath, password string) (addr string, err error)

TODO: Unit tests... Derives a single account from the keystore file, registers the account with the wallet registry, and unlocks the account.

In the case where an empty string "" is provided as the password, the user will be prompted to imput a password.

Returns the address of the imported account and an error.

func (*Wallet) ImportFromPriv

func (s *Wallet) ImportFromPriv(privEncoded, password string) (addr string, err error)

TODO: Unit tests... Derives a single account from the prefixed and base58 encoded private key, persists it to disk, registers it with the wallet registry and unlocks the wallet.

In the case where an empty string "" is provided as the password, the user will be prompted to imput a password.

Returns the address of the imported account and an error.

func (*Wallet) Init

func (s *Wallet) Init() error

This function creates the wallet home directory if it is not already present and creates a registry file that keeps track of which accounts have been previously imported.

func (*Wallet) KeystoreDir

func (s *Wallet) KeystoreDir() string

func (*Wallet) ListUnlockedAccounts

func (w *Wallet) ListUnlockedAccounts() (addrs []string)

func (*Wallet) SignMessage

func (w *Wallet) SignMessage(addr string, msg string) (MassaSignature, error)

Takes an arbitrary message and signs the blake3 digest of it's utf-8 decoded bytes.

func (*Wallet) SignOperation

func (w *Wallet) SignOperation(op Operation) (Operation, error)

func (*Wallet) UnlockAccount

func (s *Wallet) UnlockAccount(addr, password string) error

TODO: Unit tests... Unlocks the account corresponding to the provided address. If the account is not registered or the wallet file is not present an error will be returned.

Directories

Path Synopsis
examples
protos

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL