Starting with SmartPy Part 5: Interacting with Smart Contracts

Using ConseilJS to invoke, ping and fund contracts

Mike Radin
The Cryptonomic Aperiodical
3 min readAug 16, 2019

--

We left off in Part 4 having learned how to compose, test and deploy smart contracts using SmartPy on the Tezos platform with a web-based IDE. It’s been an interesting exercise, but thus far rather academic. In this section we’ll cover interaction concepts for blockchains in general and demonstrate how they are applicable on Tezos using ConseilJS.

Smart contracts extend the trustless cryptographic guarantees of simple state transitions recoded in simple transactions to executable logic and record storage. There are several interaction patterns for smart contracts

Ping

Invoke a contract without any parameters or value transfer. This simply records a transaction of an account calling a contract. Since this is on a blockchain, the record of this invocation will remain a permanent part of the chain stored on archival nodes. This kind of a call is the equivalent of raising your hand when asked a binary question. Conseil, directly or via ConseilJS, can then be used to extract all the invocation records or to count the number of those calls.

The contract in this case receives no funds nor parameters, but it can still execute logic based on chain state, including the address of the account that invoked in. In SmartPy this is the sp.sender parameter.

Tezos chain interaction code is contained in the TezosNodeWriter namespace of ConseilJS. The function call in Typescript to ping a contract address looks as follows.

const result = await TezosNodeWriter.sendContractPing(tezosServer, keyStore, contractAddress, operationFee, '', storageLimit, gasLimit)

The empty quotes above represent an empty derivation path that would be necessary for hardware-signed operations but is unnecessary for software-signed operations.

Invoke

Invoking a contract with parameters is of course the more common use-case. We’ve demonstrated this almost immediately in Part 1. In this pattern, a contract gets some arguments, but is not funded with any value. The 0 below is the amount argument.

const result = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keyStore, contractAddress, 0, operationFee, '', storageLimit, gasLimit, entryPoint, parameters)

There is one more, optional, parameter in that function — parameterFormat, which defaults to TezosTypes.TezosParameterFormat.Micheline, but can also be TezosTypes.TezosParameterFormat.Michelson. More on this shortly.

Fund

It is certainly possible to send a balance to a contract along with parameters — simply replace the 0 with an amount expressed in micro-xtz. Meaning to send 1xtz the amount must be 1000000.

const result = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keyStore, contractAddress, amount, operationFee, '', storageLimit, gasLimit, entryPoint, parameters)

For that matter, it is possible to invoke a contract with an amount but without parameters .That argument is optional in the sendContractInvocationOperation method. A word of warning about transferring balances to smart contracts on Tezos. As of Protocol 004, accounts with code — smart contracts are not spendable. Meaning that unless the contract has some sort of transfer or refund logic, balances sent to it become irrecoverable.

Entry Points

A new feature of Tezos Protocol 005 is a set of convinience features for contracts. This was a breaking change to prior releases, for those of you already familar with Tezos. There are several pre-defined entry points as well as an option to specify a custom one right in the transaction operation that is invoking the contract. This argument is optional in ConseilJS as the older, tree-based entry point specification is still honored.

Composing parameters

Michelson may look quite foreign to most developers. To take away the need for custom code and manual parameter construction, ConseilJS 0.2.9 added the ability to automatically parse parameter templates in the TezosContractIntrospector namespace. There are several methods available including generateEntryPointsFromAddress that can extract the parameters from a contract on the chain and generateEntryPointsFromParams that takes just the Michelson contract parameter section.

const entryPoints = TezosContractIntrospector.generateEntryPointsFromParams('parameter (pair %simpleSum (int :addend) (int :augend));');entryPoints[0].generateParameter(1, 2);

We used a slightly modified version of the Mechelson parameters section, the content of entryPoints following that call is

[ { name: '%simpleSum',
parameters:
[ { name: ':addend', type: 'int' },
{ name: ':augend', type: 'int' } ],
structure: '(Pair $PARAM $PARAM)',
generateParameter: [Function: generateParameter] } ]

The invocation parameter string produced by generateParameter is

(Pair 1 2)

Armed with this we can now invoke the contract deployed earlier as

const result = await TezosNodeWriter.sendContractInvocationOperation(tezosServer, keyStore, contractAddress, 0, operationFee, '', storageLimit, gasLimit, undefined, "(Pair 1 2)", TezosTypes.TezosParameterFormat.Michelson)

For more information about ConseilJS contract methods, please review the documentation site.

From basic concepts to actual deployment and interactions, we’ve come a long way on our smart contract journey. Now, you’re well-versed in the end-to-end process of blockchain programming. We hope that this tutorial has helped jump start your Tezos adventure. Best of luck! Sincerely, your friends at Cryptonomic.

--

--