Simplified Contract Interactions on Tezos

Mike Radin
The Cryptonomic Aperiodical
2 min readAug 12, 2019

ConseilJS 0.2.9 beta has a fun new feature that simplifies contract invocation significantly. Reading the Micheline parameter definition to understand call patterns is not for the faint of heart, see for example, taken from KT1UvfyLytrt71jh63YV4Yex5SmbNXpWHxtg:

parameter (or (or (or (or (or (pair %build (pair (string %game) (address %player1)) (address %player2)) (string %game)) (pair %play (pair (pair (string %game) (int %i)) (int %j)) (int %move))) (pair %setGameMetaData (pair (string %game) (string %name)) (string %value))) (pair %setMetaData (string %name) (string %value))) (bool %setPause));

ConseilJS can now extract entry points. The above Michelson gets parsed into:

[ { name: '%build',
parameters:
[ { name: undefined, type: 'string' },
{ name: undefined, type: 'address' },
{ name: undefined, type: 'address' } ],
structure: '(Left (Left (Left (Left (Left (Pair (Pair $PARAM $PARAM) $PARAM))))))',
generateParameter: [Function: generateParameter] },
{ name: '%game',
parameters: [ { name: undefined, type: 'string' } ],
structure: '(Left (Left (Left (Left (Right $PARAM)))))',
generateParameter: [Function: generateParameter] },
{ name: '%play',
parameters:
[ { name: undefined, type: 'string' },
{ name: undefined, type: 'int' },
{ name: undefined, type: 'int' },
{ name: undefined, type: 'int' } ],
structure: '(Left (Left (Left (Right (Pair (Pair (Pair $PARAM $PARAM) $PARAM) $PARAM)))))',
generateParameter: [Function: generateParameter] },
{ name: '%setGameMetaData',
parameters:
[ { name: undefined, type: 'string' },
{ name: undefined, type: 'string' },
{ name: undefined, type: 'string' } ],
structure: '(Left (Left (Right (Pair (Pair $PARAM $PARAM) $PARAM))))',
generateParameter: [Function: generateParameter] },
{ name: '%setMetaData',
parameters:
[ { name: undefined, type: 'string' },
{ name: undefined, type: 'string' } ],
structure: '(Left (Right (Pair $PARAM $PARAM)))',
generateParameter: [Function: generateParameter] },
{ name: '%setPause',
parameters: [ { name: undefined, type: 'bool' } ],
structure: '(Right $PARAM)',
generateParameter: [Function: generateParameter] } ]

This functionality takes advantage of Michelson annotations. If the developer didn’t annotate their code the results are still presented in a friendly format, but lack the richness they otherwise have above. The next snippet is taken from KT1WRUe3csC1jiThN9KUtaji2bd412upfn1E.

parameter (list (pair (pair nat nat) (pair nat (pair nat (pair nat nat)))));

Which becomes

[ { name: undefined,
parameters:
[ { name: undefined, type: 'list (nat)' },
{ name: undefined, type: 'nat' },
{ name: undefined, type: 'nat' },
{ name: undefined, type: 'nat' },
{ name: undefined, type: 'nat' },
{ name: undefined, type: 'nat' } ],
structure: '((Pair (Pair $PARAM $PARAM) (Pair $PARAM (Pair $PARAM (Pair $PARAM $PARAM)))))',
generateParameter: [Function: generateParameter] } ]

The conseilJS method that makes this possible is TezosContractIntrospector.generateEntryPointsFromParams(params) There are two others, generateEntryPointsFromCode(code) which takes the full contract and generateEntryPointsFromAddress() that can read the contract from the chain directly.

What’s more is that ConseilJS can also generate the parameter invocation payload. Taking the first entry point from the first example we can do the following with this function call entryPoints[0].generateParameter(‘“some text”’, ‘“an address”’, ‘“another address”’):

(Left (Left (Left (Left (Left (Pair (Pair “some text” “an address”) “another address”))))))

We hope this functionality encouraged contract developers to annotate their code, and broadens the Tezos smart contract accessibility.

--

--