dsl

package
v0.7.11 Latest Latest
Warning

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

Go to latest
Published: May 19, 2022 License: Apache-2.0 Imports: 12 Imported by: 0

README

Rosetta Constructor DSL

The Rosetta Constructor DSL (domain-specific language) makes it easy to write Workflows for the constructor package.

This DSL is most commonly used for writing automated Construction API tests for the rosetta-cli.

Before reading more about the Rosetta Constructor DSL, we recommend learning about the frameworks used in the constructor to coordinate the creation of transactions.

Syntax

At a basic level, the Rosetta Constructor DSL syntax looks like this:

// line comment
<workflow name>(<concurrency>){
  <scenario 1 name>{
    <output path> = <action type>(<input>); // another comment
  },
  <scenario 2 name>{
    <output path 2> = <action type>(<input>);
  }
}
Basic Example

Here is a specific example for Bitcoin:

request_funds(1){
  find_account{
    currency = {
      "symbol":"tBTC",
      "decimals":8
    };
    random_account = find_balance({
      "minimum_balance":{
        "value": "0",
        "currency": {{currency}}
      },
      "create_limit":1
    });
  },
  request{
    min_balance = load_env("MIN_BALANCE");
    adjusted_min = {{min_balance}} + 600;
    loaded_account = find_balance({
      "account_identifier": {{random_account.account_identifier}},
      "minimum_balance":{
        "value": {{adjusted_min}},
        "currency": {{currency}}
      }
    });
  }
}

create_account(1){
  create_account{
    network = {"network":"Testnet3", "blockchain":"Bitcoin"};
    key = generate_key({"curve_type":"secp256k1"});
    account = derive({
      "network_identifier": {{network}},
      "public_key": {{key.public_key}}
    });
    save_account({
      "account_identifier": {{account.account_identifier}},
      "keypair": {{key}}
    });
  }
}

If you were to write the same thing by hand in raw syntax, it would look like:

[
  {
    "name": "request_funds",
    "concurrency": 1,
    "scenarios": [
      {
        "name": "find_account",
        "actions": [
          {
            "input": "{\"symbol\":\"tBTC\", \"decimals\":8}",
            "type": "set_variable",
            "output_path": "currency"
          },
          {
            "input": "{\"minimum_balance\":{\"value\": \"0\", \"currency\": {{currency}}}, \"create_limit\":1}",
            "type": "find_balance",
            "output_path": "random_account"
          }
        ]
      },
      {
        "name": "request",
        "actions": [
          {
            "type": "load_env",
            "output_path": "min_balance",
            "input": "MIN_BALANCE"
          },
          {
            "type": "math",
            "ouput_path": "adjusted_min",
            "input": "{\"operation\":\"addition\", \"left_value\": {{min_balance}}, \"right_value\": \"600\"}"
          },
          {
            "input": "{\"account_identifier\": {{random_account.account_identifier}}, \"minimum_balance\":{\"value\": {{adjusted_min}}, \"currency\": {{currency}}}}",
            "type": "find_balance",
            "output_path": "loaded_account"
          }
        ]
      }
    ]
  },
  {
    "name": "create_account",
    "concurrency": 1,
    "scenarios": [
      {
        "name": "create_account",
        "actions": [
          {
            "input": "{\"network\":\"Testnet3\", \"blockchain\":\"Bitcoin\"}",
            "type": "set_variable",
            "output_path": "network"
          },
          {
            "input": "{\"curve_type\": \"secp256k1\"}",
            "type": "generate_key",
            "output_path": "key"
          },
          {
            "input": "{\"network_identifier\": {{network}}, \"public_key\": {{key.public_key}}}",
            "type": "derive",
            "output_path": "account"
          },
          {
            "input": "{\"account_identifier\": {{account.account_identifier}}, \"keypair\": {{key}}}",
            "type": "save_account"
          }
        ]
      }
    ]
  }
]

Note, if you plan to run the automated Construction API tester in CI for create_account workflow, you may wish to provide prefunded accounts when running the tester (otherwise you would need to manually fund generated accounts).

Workflows

Workflows are defined using the following syntax:

<workflow name>(<concurrency>){
...
}

Note, concurrency must be provided when defining a Workflow and no 2 Workflows can have the same name.

Scenarios

Scenarios are defined using the following syntax:

<workflow name>(<concurrency>){
  <scenario name>{
  ...
  }
}

Scenarios must be defined within a Workflow and no 2 Scenarios in the same Worfklow can have the same name.

It is also important to note that Workflows containing multiple Scenarios should be separated by a comma:

<workflow name>(<concurrency>){
  <scenario name>{
  ...
  },
  <scenario name 2>{
  ...
  }
}
Functions

In the Rosetta Constructor DSL, it is possible to invoke functions (where the function name is an Action.Type) but not possible to define your own functions (yet!).

Inputs

The input for all functions is a JSON blob that will be evaluated by the Worker. It is possible to reference other variables in an input using the syntax {{var}} where var must follow this syntax. The Rosetta Constructor DSL compiler will automatically check that referenced variables are previously defined.

End Line

Function invocations can span multiple lines (if you "pretty print" the JSON blob) but each function call line must end with a semi-colon.

Native Invocation

The Rosetta Constructor DSL provides optional "native invocation" support for 2 Action.Types:

  • math
  • set_variable

"Native invocation" in this case means that the caller does not need to invoke the Action.Type in the normal format:

<output path> = <function name>(<input>);
math

math can be invoked by following the syntax:

<output path> = <left side> <operator> <right side>;

A simple addition would look like:

a = 10 + {{fee}};

Instead of:

a = math({"operation":"addition","left_side":"10","right_side":{{fee}}});
set_variable

set_variable can be invoked by following the syntax:

<output path> = <input>

A simple set would look like:

a = {"message": "hello"};

Instead of:

a = set_variable({"message": "hello"});
Recursive Calls

It is not possible to invoke a function from the input of another function. There MUST be exactly 1 function call per line.

For example, this is not allowed:

a = 1 + load_env("value");
Comments

It is possible to add new line comments of comments at the end of lines using a double slash (//).

Status

The Rosetta Constructor DSL should be considered ALPHA and may include breaking changes in later releases. If you have any ideas on how to improve the language, please open an issue in rosetta-sdk-go!

Documentation

Index

Constants

View Source
const (
	// RosettaFileExtension is the file extension for all constructor files.
	RosettaFileExtension = ".ros"
)

Variables

View Source
var (
	ErrCannotOpenFile     = errors.New("file cannot be opened")
	ErrIncorrectExtension = errors.New("expected .ros file extension")

	ErrEOF     = errors.New("reached end of file")
	ErrScanner = errors.New("scanner error")

	ErrUnexpectedEOF = errors.New("unexpected EOF")

	ErrSyntax = errors.New("incorrect syntax")

	ErrParsingWorkflowName        = errors.New("cannot parse workflow name")
	ErrParsingWorkflowConcurrency = errors.New("cannot parse workflow concurrency")
	ErrDuplicateWorkflowName      = errors.New("duplicate workflow name")

	ErrParsingScenarioName   = errors.New("cannot parse scenario name")
	ErrDuplicateScenarioName = errors.New("duplicate scenario name")

	ErrInvalidActionType              = errors.New("invalid action type")
	ErrCannotSetVariableWithoutOutput = errors.New("cannot set variable without output path")
	ErrVariableUndefined              = errors.New("variable undefined")
	ErrInvalidMathSymbol              = errors.New("invalid math symbol")
)

DSL Errors

Functions

This section is empty.

Types

type Error

type Error struct {
	Line         int    `json:"line"`
	LineContents string `json:"line_contents"`
	Err          error  `json:"err"`
}

Error contains a parsing error and context about where the error occurred in the file.

func Parse

func Parse(ctx context.Context, file string) ([]*job.Workflow, *Error)

Parse loads a Rosetta constructor file and attempts to parse it into []*job.Workflow.

func (*Error) Log

func (e *Error) Log()

Log prints the *Error to the console in red.

Jump to

Keyboard shortcuts

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