Onchain Data Grammar
To be a rollup, Paima state has to eventually be written to the L1. As a sovereign rollup, the way the data is stored is fairly simple (calling a contract function that simply emits its input as an event) and we provide a way to generate a grammar for this data.
Paima has its own format for representing L2 data called Paima Concise that resembles a bar-separated string (ex: c|3|100|
). This was chosen as
- It is human-readable, which not only helps with coding & debugging, but also helps users verify the content of the string when signing from their wallet such as MetaMask
- It is easy to combine with many parsing tools (given the prevalence of CSV) and so it avoids having to write a lot of custom parers to Paima Concise in multiple programming languages & tools
- It is easy to combine with other formats if desired. For example, you could use base64 to encode one of the fields in the bar-separated string (although we recommend using PaimaParser defined below instead)
Paima comes with two classes to help generate these bar-separated strings
// write paima-concise encoding
import { builder } from '@paimas/sdk/concise';
// read paima-concise encoding
import { consumer } from '@paima/sdk/concise';
Defining a grammar
We allow defining more complex grammars on top of this notation using PaimaParser
. The process has two steps:
- Define a base grammar (which Paima will then internally convert into EBNF form)
- Define how to read & write tokens with this grammar
// First, define your grammar which Paima will turn into EBNF form internally
const myGrammar = `
createdLobby = c|numOfRounds|isPractice?
joinedLobby = j|*lobbyID
`;
Defining types
Unlike typical EBNF notation where things are defined down to generic terms like DIGIT
or ALPHANUMERIC
, we instead define the terminal terms in Typescript
- Define the type of each token in a row
// Setup the type definitions for the result of parsing
export interface CreatedLobbyInput {
// left-side of the equation
input: 'createdLobby';
// right-side of the equation (other than the starting prefix)
numOfRounds: number;
isPractice: boolean;
}