massa

package module
v1.0.5 Latest Latest
Warning

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

Go to latest
Published: Dec 6, 2025 License: MIT Imports: 12 Imported by: 0

README ΒΆ

massa-go

Massa Go SDK

A comprehensive Go toolkit for the Massa blockchain ecosystem, providing smart contract development capabilities, client libraries, and wallet functionality.

πŸš€ Features

  • Smart Contract SDK (sc/): Pure Go SDK for developing WebAssembly-compatible smart contracts
  • Blockchain Client (client/): Interface to communicate with the Massa blockchain
  • Wallet Management (wallet/): Account creation and transaction signing utilities
  • Complete Examples: End-to-end examples of smart contract development and deployment

Requirements

  • GO go 1.25+

Installation

go get github.com/nafsilabs/massa-go

πŸ“¦ Components

πŸ”§ Smart Contract SDK (sc/)

A pure Go SDK for developing smart contracts on the Massa blockchain that compile to WebAssembly. This SDK provides a comprehensive set of functions for interacting with the Massa blockchain, similar to the official massa-as-sdk but written in native Go.

Key Features:

  • Pure Go Implementation: Write smart contracts in native Go syntax
  • WebAssembly Compilation: Compiles to WASM compatible with Massa blockchain
  • Complete API Coverage: Implements all major Massa blockchain functions
  • Type Safety: Full Go type system with compile-time safety
  • Memory Management: Automatic WebAssembly memory handling
  • Testing Support: Mock implementations for local development and testing

Quick Start:

package main

import massa "github.com/nafsilabs/massa-go/sc"

func main() {
    // Generate an event
    massa.GenerateEvent("Hello, Massa!")
    
    // Store data
    massa.SetString("greeting", "Hello from Go!")
    
    // Get caller information
    caller := massa.Caller()
    massa.Printf("Called by: %s", caller.String())
}
🌐 Blockchain Client (client/)

A comprehensive node client that enables you to communicate with the Massa blockchain. It offers an interface to retrieve data directly from the blockchain, interact with smart contracts, acquire and monitor events, and perform additional actions.

Features:

  • Blockchain data retrieval
  • Smart contract deployment
  • Smart contract interaction
  • Event monitoring
  • Transaction broadcasting
  • Connection management with automatic reconnection
  • WebSocket and HTTP API support
  • Multi-client connection pooling

Quick Start:

package main

import "github.com/nafsilabs/massa-go/client"

func main() {
    // Connect to Massa testnet
    massaClient, err := client.NewTestnetClient()
    if err != nil {
        panic(err)
    }
    defer massaClient.Close()
    
    // Get node status
    status, err := massaClient.GetNodeStatus()
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Connected to node: %s (slot %d)\n", 
        status.NodeID, status.CurrentSlot)
    
    // Subscribe to events
    eventHandler := func(event *client.Event) {
        fmt.Printf("Event: %s\n", event.Data)
    }
    
    subscriptionID, err := massaClient.SubscribeToEvents(
        &client.EventFilter{}, eventHandler)
    if err != nil {
        panic(err)
    }
    
    // Deploy a smart contract
    deployResult, err := massaClient.DeployContract(
        &client.ContractDeploymentRequest{
            Bytecode: contractBytecode,
            MaxGas:   1000000,
            Coins:    "0",
        }, 
        account, 
        "password",
    )
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Contract deployed: %s\n", 
        deployResult.ContractAddress)
}

Source code inspired by: https://github.com/massalabs/station/tree/main/pkg and https://github.com/massalabs/massa-web3 Smart contract deployment inspired by: https://github.com/massalabs/massa-standards/blob/main/smart-contracts/assembly/contracts/deployer/deployer.ts

πŸ’Ό Wallet Management (wallet/)

Wallet functionality for creating accounts with public and private keys used to sign Massa blockchain transactions.

Features:

  • Account generation
  • Key management
  • Transaction signing
  • Address derivation

Some implementation ideas from: https://github.com/massalabs/station/tree/main/pkg

πŸ“š Examples (examples/)

Complete examples demonstrating:

  • Smart contract development
  • Wallet account creation
  • Client usage for deployment
  • Smart contract interaction

πŸƒβ€β™‚οΈ Quick Start

1. Initialize your project
go mod init your-massa-project
go get github.com/nafsilabs/massa-go
2. Create a Smart Contract
// main.go
package main

import massa "github.com/nafsilabs/massa-go/sc"

func main() {
    massa.GenerateEvent("Hello, Massa!")
    massa.SetString("greeting", "Hello from Go!")
}
3. Build for WebAssembly
export GOOS=js
export GOARCH=wasm
go build -ldflags="-s -w" -o contract.wasm main.go
4. Deploy and Interact
package main

import (
    "context"
    "log"

    "github.com/nafsilabs/massa-go"
)

func main() {
    // Create a Massa gRPC client
    client, err := massa.NewMassaClient(&massa.ClientConfig{
        Address: "testnet.massa.net:33035",
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    ctx := context.Background()

    // Use wallet and client together (see examples/ for full flows)
    // ...

    _ = ctx
}

πŸ—οΈ Project Structure

massa-go/
β”œβ”€β”€ massa.go               # High-level SDK entrypoint
β”œβ”€β”€ sc/                    # Smart Contract SDK
β”‚   β”œβ”€β”€ sc.go              # WebAssembly imports
β”‚   β”œβ”€β”€ address.go         # Address operations
β”‚   β”œβ”€β”€ storage.go         # Storage functions
β”‚   β”œβ”€β”€ context.go         # Execution context
β”‚   β”œβ”€β”€ contract.go        # Contract interactions
β”‚   β”œβ”€β”€ coins.go           # Balance and transfers
β”‚   β”œβ”€β”€ events.go          # Events and logging
β”‚   β”œβ”€β”€ crypto.go          # Cryptographic functions
β”‚   └── op_datastore.go    # Operation datastore
β”œβ”€β”€ client/                # Blockchain client
β”œβ”€β”€ wallet/                # Wallet management
β”œβ”€β”€ examples/
β”‚   └── smart_contract/    # Example smart contract
β”‚       β”œβ”€β”€ main.go        # Contract implementation
β”‚       β”œβ”€β”€ build.sh       # Build script
β”‚       └── README.md      # Example documentation
└── README.md             # This file

πŸ“– Documentation

Smart Contract SDK

The sc/ package provides comprehensive smart contract development capabilities:

  • Address Operations: Validation, creation, and utilities
  • Storage Management: Persistent key-value storage
  • Context Access: Execution environment information
  • Contract Interactions: Calling other contracts and bytecode operations
  • Coin Operations: Balance queries and transfers
  • Event System: Structured event generation and logging
  • Cryptography: Hashing, signatures, and utilities
  • Operation Datastore: Access to operation-level data
API Modules
Module Description
Address Address validation, creation, and utilities
Storage Persistent key-value storage operations
Context Execution context (caller, timestamp, gas, etc.)
Contract Contract calls, bytecode operations, messaging
Coins Balance queries and coin transfers
Events Event generation and structured logging
Crypto Cryptographic functions (hashing, signatures)
OpDatastore Operation-level data access

πŸ§ͺ Testing

The SDK provides mock implementations for testing:

func TestContract(t *testing.T) {
    // The SDK automatically uses mocks when not in WASM runtime
    caller := massa.Caller() // Returns mock address
    massa.SetString("test", "value")
    value := massa.GetString("test")
    // Test your contract logic...
}

πŸ“¦ Publishing

Create an annotated tag and push it to the remote:

# create an annotated tag
git tag -a vX.Y.Z -m "Release vX.Y.Z"

# push the specific tag to origin
git push origin vX.Y.Z

# (optional) push all local tags
git push --tags

πŸ” Security Best Practices

  1. Input Validation: Always validate addresses, amounts, and parameters
  2. Access Control: Implement proper permission checks
  3. Error Handling: Handle errors gracefully and don't expose internals
  4. Gas Management: Be mindful of gas costs for operations
  5. State Consistency: Use atomic operations for multi-step changes

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ”— References

πŸ“ž Support


Built with ❀️ for the Massa ecosystem

Documentation ΒΆ

Overview ΒΆ

Package jsonrpc provides a JSON-RPC 2.0 client that sends JSON-RPC requests and receives JSON-RPC responses using HTTP.

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func Params ΒΆ

func Params(params ...interface{}) interface{}

Params is a helper function that uses the same parameter syntax as Call(). But you should consider to always use NewRequest() instead.

e.g. to manually create an RPCRequest object:

request := &RPCRequest{
  Method: "myMethod",
  Params: Params("Alex", 35, true),
}

same with new request: request := NewRequest("myMethod", "Alex", 35, true)

If you know what you are doing you can omit the Params() call but potentially create incorrect rpc requests:

request := &RPCRequest{
  Method: "myMethod",
  Params: 2, <-- invalid since a single primitive value must be wrapped in an array --> no magic without Params()
}

correct:

request := &RPCRequest{
  Method: "myMethod",
  Params: []int{2}, <-- invalid since a single primitive value must be wrapped in an array
}

Types ΒΆ

type ClientConfig ΒΆ added in v1.0.4

type ClientConfig = client.ClientConfig

type HTTPError ΒΆ

type HTTPError struct {
	Code int
	// contains filtered or unexported fields
}

HTTPError represents a error that occurred on HTTP level.

An error of type HTTPError is returned when a HTTP error occurred (status code) and the body could not be parsed to a valid RPCResponse object that holds a RPCError.

Otherwise a RPCResponse object is returned with a RPCError field that is not nil.

func (*HTTPError) Error ΒΆ

func (e *HTTPError) Error() string

Error function is provided to be used as error object.

type MassaClient ΒΆ added in v1.0.4

type MassaClient = client.MassaClient

func NewMassaClient ΒΆ added in v1.0.4

func NewMassaClient(cfg *ClientConfig) (*MassaClient, error)

type RPCClient ΒΆ

type RPCClient interface {
	// Call is used to send a JSON-RPC request to the server endpoint.
	//
	// The spec states, that params can only be an array or an object, no primitive values.
	// So there are a few simple rules to notice:
	//
	// 1. no params: params field is omitted. e.g. Call("getinfo")
	//
	// 2. single params primitive value: value is wrapped in array. e.g. Call("getByID", 1423)
	//
	// 3. single params value array or object: value is unchanged. e.g. Call("storePerson", &Person{Name: "Alex"})
	//
	// 4. multiple params values: always wrapped in array. e.g. Call("setDetails", "Alex, 35, "Germany", true)
	//
	// Examples:
	//   Call("getinfo") -> {"method": "getinfo"}
	//   Call("getPersonId", 123) -> {"method": "getPersonId", "params": [123]}
	//   Call("setName", "Alex") -> {"method": "setName", "params": ["Alex"]}
	//   Call("setMale", true) -> {"method": "setMale", "params": [true]}
	//   Call("setNumbers", []int{1, 2, 3}) -> {"method": "setNumbers", "params": [1, 2, 3]}
	//   Call("setNumbers", 1, 2, 3) -> {"method": "setNumbers", "params": [1, 2, 3]}
	//   Call("savePerson", &Person{Name: "Alex", Age: 35}) -> {"method": "savePerson", "params": {"name": "Alex", "age": 35}}
	//   Call("setPersonDetails", "Alex", 35, "Germany") -> {"method": "setPersonDetails", "params": ["Alex", 35, "Germany"}}
	//
	// for more information, see the examples or the unit tests
	Call(method string, params ...interface{}) (*RPCResponse, error)
	CallWID(method string, params ...interface{}) (*RPCResponse, error)

	// CallRaw is like Call() but without magic in the requests.Params field.
	// The RPCRequest object is sent exactly as you provide it.
	// See docs: NewRequest, RPCRequest, Params()
	//
	// It is recommended to first consider Call() and CallFor()
	CallRaw(request *RPCRequest) (*RPCResponse, error)

	// CallFor is a very handy function to send a JSON-RPC request to the server endpoint
	// and directly specify an object to store the response.
	//
	// out: will store the unmarshaled object, if request was successful.
	// should always be provided by references. can be nil even on success.
	// the behaviour is the same as expected from json.Unmarshal()
	//
	// method and params: see Call() function
	//
	// if the request was not successful (network, http error) or the rpc response returns an error,
	// an error is returned. if it was an JSON-RPC error it can be casted
	// to *RPCError.
	//
	CallFor(out interface{}, method string, params ...interface{}) error

	// CallBatch invokes a list of RPCRequests in a single batch request.
	//
	// Most convenient is to use the following form:
	// CallBatch(RPCRequests{
	//   NewRequest("myMethod1", 1, 2, 3),
	//   NewRequest("myMethod2", "Test"),
	// })
	//
	// You can create the []*RPCRequest array yourself, but it is not recommended and you should notice the following:
	// - field Params is sent as provided, so Params: 2 forms an invalid json (correct would be Params: []int{2})
	// - you can use the helper function Params(1, 2, 3) to use the same format as in Call()
	// - field JSONRPC is overwritten and set to value: "2.0"
	// - field ID is overwritten and set incrementally and maps to the array position (e.g. requests[5].ID == 5)
	//
	//
	// Returns RPCResponses that is of type []*RPCResponse
	// - note that a list of RPCResponses can be received unordered so it can happen that: responses[i] != responses[i].ID
	// - RPCPersponses is enriched with helper functions e.g.: responses.HasError() returns  true if one of the responses holds an RPCError
	CallBatch(requests RPCRequests) (RPCResponses, error)

	// CallBatchRaw invokes a list of RPCRequests in a single batch request.
	// It sends the RPCRequests parameter is it passed (no magic, no id autoincrement).
	//
	// Consider to use CallBatch() instead except you have some good reason not to.
	//
	// CallBatchRaw(RPCRequests{
	//   &RPCRequest{
	//     ID: 123,            // this won't be replaced in CallBatchRaw
	//     JSONRPC: "wrong",   // this won't be replaced in CallBatchRaw
	//     Method: "myMethod1",
	//     Params: []int{1},   // there is no magic, be sure to only use array or object
	//   },
	//   &RPCRequest{
	//     ID: 612,
	//     JSONRPC: "2.0",
	//     Method: "myMethod2",
	//     Params: Params("Alex", 35, true), // you can use helper function Params() (see doc)
	//   },
	// })
	//
	// Returns RPCResponses that is of type []*RPCResponse
	// - note that a list of RPCResponses can be received unordered
	// - the id's must be mapped against the id's you provided
	// - RPCPersponses is enriched with helper functions e.g.: responses.HasError() returns  true if one of the responses holds an RPCError
	CallBatchRaw(requests RPCRequests) (RPCResponses, error)
}

RPCClient sends JSON-RPC requests over HTTP to the provided JSON-RPC backend.

RPCClient is created using the factory function NewClient().

func NewClient ΒΆ

func NewClient(endpoint string) RPCClient

NewClient returns a new RPCClient instance with default configuration.

endpoint: JSON-RPC service URL to which JSON-RPC requests are sent.

func NewClientWithOpts ΒΆ

func NewClientWithOpts(endpoint string, opts *RPCClientOpts) RPCClient

NewClientWithOpts returns a new RPCClient instance with custom configuration.

endpoint: JSON-RPC service URL to which JSON-RPC requests are sent.

opts: RPCClientOpts provide custom configuration

type RPCClientOpts ΒΆ

type RPCClientOpts struct {
	HTTPClient    *http.Client
	CustomHeaders map[string]string
}

RPCClientOpts can be provided to NewClientWithOpts() to change configuration of RPCClient.

HTTPClient: provide a custom http.Client (e.g. to set a proxy, or tls options)

CustomHeaders: provide custom headers, e.g. to set BasicAuth

type RPCError ΒΆ

type RPCError struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
	// MetaHash hack
	CountBlocks int64 `json:"countBlocks"`
	KnownBlocks int64 `json:"knownBlocks,omitempty"`
	KnwonBlock  int64 `json:"knwonBlock,omitempty"` // Π΄Π° Π΄Π°
}

RPCError represents a JSON-RPC error object if an RPC error occurred.

Code: holds the error code

Message: holds a short error message

Data: holds additional error data, may be nil

See: http://www.jsonrpc.org/specification#error_object

func (*RPCError) Error ΒΆ

func (e *RPCError) Error() string

Error function is provided to be used as error object.

type RPCRequest ΒΆ

type RPCRequest struct {
	Method  string      `json:"method"`
	Params  interface{} `json:"params,omitempty"`
	ID      int         `json:"id,omitempty"`
	JSONRPC string      `json:"jsonrpc"`
}

RPCRequest represents a JSON-RPC request object.

Method: string containing the method to be invoked

Params: can be nil. if not must be an json array or object

ID: may always set to 1 for single requests. Should be unique for every request in one batch request.

JSONRPC: must always be set to "2.0" for JSON-RPC version 2.0

See: http://www.jsonrpc.org/specification#request_object

Most of the time you shouldn't create the RPCRequest object yourself. The following functions do that for you: Call(), CallFor(), NewRequest()

If you want to create it yourself (e.g. in batch or CallRaw()), consider using Params(). Params() is a helper function that uses the same parameter syntax as Call().

e.g. to manually create an RPCRequest object:

request := &RPCRequest{
  Method: "myMethod",
  Params: Params("Alex", 35, true),
}

If you know what you are doing you can omit the Params() call to avoid some reflection but potentially create incorrect rpc requests:

request := &RPCRequest{
  Method: "myMethod",
  Params: 2, <-- invalid since a single primitive value must be wrapped in an array --> no magic without Params()
}

correct:

request := &RPCRequest{
  Method: "myMethod",
  Params: []int{2}, <-- invalid since a single primitive value must be wrapped in an array
}

func NewRequest ΒΆ

func NewRequest(method string, params ...interface{}) *RPCRequest

NewRequest returns a new RPCRequest that can be created using the same convenient parameter syntax as Call()

e.g. NewRequest("myMethod", "Alex", 35, true)

type RPCRequests ΒΆ

type RPCRequests []*RPCRequest

RPCRequests is of type []*RPCRequest. This type is used to provide helper functions on the request list

type RPCResponse ΒΆ

type RPCResponse struct {
	JSONRPC string      `json:"jsonrpc"`
	Result  interface{} `json:"result,omitempty"`
	ID      int         `json:"id,int"`
	Error   *RPCError   `json:"error,omitempty"`

	// metahash
	Version string      `json:"version,omitempty"`
	Data    interface{} `json:"data,omitempty"`
}

RPCResponse represents a JSON-RPC response object.

Result: holds the result of the rpc call if no error occurred, nil otherwise. can be nil even on success.

Error: holds an RPCError object if an error occurred. must be nil on success.

ID: may always be 0 for single requests. is unique for each request in a batch call (see CallBatch())

JSONRPC: must always be set to "2.0" for JSON-RPC version 2.0

See: http://www.jsonrpc.org/specification#response_object

func (*RPCResponse) GetBool ΒΆ

func (RPCResponse *RPCResponse) GetBool() (bool, error)

GetBool converts the rpc response to a bool and returns it.

If result was not a bool an error is returned.

func (*RPCResponse) GetFloat ΒΆ

func (RPCResponse *RPCResponse) GetFloat() (float64, error)

GetFloat converts the rpc response to float64 and returns it.

If result was not an float64 an error is returned.

func (*RPCResponse) GetInt ΒΆ

func (RPCResponse *RPCResponse) GetInt() (int64, error)

GetInt converts the rpc response to an int64 and returns it.

If result was not an integer an error is returned.

func (*RPCResponse) GetObject ΒΆ

func (RPCResponse *RPCResponse) GetObject(toType interface{}) error

GetObject converts the rpc response to an arbitrary type.

The function works as you would expect it from json.Unmarshal()

func (*RPCResponse) GetString ΒΆ

func (RPCResponse *RPCResponse) GetString() (string, error)

GetString converts the rpc response to a string and returns it.

If result was not a string an error is returned.

type RPCResponses ΒΆ

type RPCResponses []*RPCResponse

RPCResponses is of type []*RPCResponse. This type is used to provide helper functions on the result list

func (RPCResponses) AsMap ΒΆ

func (res RPCResponses) AsMap() map[int]*RPCResponse

AsMap returns the responses as map with response id as key.

func (RPCResponses) GetByID ΒΆ

func (res RPCResponses) GetByID(id int) *RPCResponse

GetByID returns the response object of the given id, nil if it does not exist.

func (RPCResponses) HasError ΒΆ

func (res RPCResponses) HasError() bool

HasError returns true if one of the response objects has Error field != nil

type Varint ΒΆ

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

func NewVarint ΒΆ

func NewVarint() *Varint

NewVarint creates a new variant

func (*Varint) Append ΒΆ

func (vt *Varint) Append(number *big.Int) error

Append adds data to the variant

func (*Varint) AppendBytes ΒΆ

func (vt *Varint) AppendBytes(bytes []byte)

AppendBytes appends bytes to the variant

func (*Varint) AppendString ΒΆ

func (vt *Varint) AppendString(str string) error

AppendString appends string to the variant

func (*Varint) GetBytes ΒΆ

func (vt *Varint) GetBytes() []byte

GetBytes returns byte data from variant

type Wallet ΒΆ added in v1.0.4

type Wallet = wallet.Wallet

func LoadWallet ΒΆ added in v1.0.4

func LoadWallet(path string) (*Wallet, error)

func NewWallet ΒΆ added in v1.0.4

func NewWallet(config *WalletConfig) *Wallet

type WalletConfig ΒΆ added in v1.0.4

type WalletConfig = wallet.WalletConfig

Directories ΒΆ

Path Synopsis
other gRPC client methods
other gRPC client methods
sc
Package sc provides a comprehensive Go SDK for developing Massa smart contracts that compile to WebAssembly.
Package sc provides a comprehensive Go SDK for developing Massa smart contracts that compile to WebAssembly.

Jump to

Keyboard shortcuts

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