æternity Documentation Hub
Aeternity.comAeternity GitHub
  • æternity Hub
  • Developer Documentation
  • Aeternity Expansions
    • PULL_REQUEST_TEMPLATE
    • AEX X
    • AEXS
      • AEX 1
      • aex-10
      • AEX 11 Fungible Token Standard
      • AEX-130: æpps Metadata Format Specification
      • aex-141
      • AEX 2
      • AEX-3
      • AEX-4
      • AEX 5
      • AEX 7
      • AEX 8
      • aex-9
    • .github
      • ISSUE_TEMPLATE
        • aexpansion
  • AeMdw - Aeternity Middleware
    • Changelog
    • docs
      • AE MDW Architecture
      • AeMdw Hyperhain Setup Documentation
      • AeMdw Docker Setup Documentation
  • Æternity <> Ethereum Bridge
    • Changelog
  • aepp-cli-js
    • CHANGELOG
    • Contributor guide
    • reference
    • user-guide
    • .github
      • ISSUE_TEMPLATE
  • Hyperchain Bridge
    • Changelog
  • æternity's JavaScript SDK
    • Installation
      • Changelog
      • Compatibility Table
      • Quick Start
      • Transaction options
      • Development
        • Releases
      • guides
        • The range of possible address length
        • AENS (æternity naming system)
        • Batch Transactions
        • How to build a wallet
        • Connect an æpp to a wallet
        • Contract Events
        • Contracts
        • Error Handling
        • JWT usage
        • Ledger Hardware Wallet
        • Low vs High level API
        • Aeternity snap for MetaMask
        • Oracles
        • PayingForTx (Meta-Transactions)
        • Typed data hashing and signing
        • Usage with TypeScript
        • migration
          • Migration to 10.0.0
          • Migration to 11.0.0
          • Migration to 12.0.0
          • Migration to 13.0.0
          • Migration to 14.0.0
          • Migration to 7.0.0
          • Migration to 9.0.0
      • tutorials
        • vuejs
          • Vue.js HelloWorld
    • Examples
      • How to connect wallet to æpp using æternity's JS SDK
        • Sample æpp for contracts
        • iframe-based wallet
        • WebExtension-based wallet
    • .github
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
  • AEproject
    • Changelog
    • docs
      • Quick Start
      • AEproject Library
      • Migration from 3.x.x to 4.x.x
      • Migration from 4.x.x to 5.x.x
      • Upcoming Version Support
      • cli
        • Local Environment
        • Project Initialization
        • Unit Testing
    • .github
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
  • aerepl
    • Changelog
  • aescan
    • Changelog
    • Contributor Covenant Code of Conduct
    • Aescan Contributing Guide
    • LICENSE
    • .github
      • pull_request_template
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
    • docs
      • BRANCHING_STRATEGY
  • Sophia Support for Visual Studio Code
    • Changelog
  • aesophia
    • Changelog
    • Contributing to Sophia
    • docs
      • aeso_aci
      • aeso_compiler
      • Introduction
      • sophia
      • Contract examples
      • Features
      • Standard library
      • Syntax
  • aesophia_cli
    • Changelog
  • aesophia_http
    • Changelog
  • Æ Studio - Formerly known as 🔥 Fire Editor ! Aeternity's easy to use editor for writing smart contr
    • ideas
  • aeternity
    • .github
      • The Æternity Code of Conduct
      • Contributing to the Aeternity node
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
    • Welcome to Aeternity node documentation
      • Summary
      • Node API
      • Introduction
      • Build from source
      • Configuration
      • CUDA Miner
      • debian_ubuntu_packaging
      • Docker
      • Fork resistance in Aeternity nodes
      • Garbage Collection
      • Hacking the Aeternity Codebase
      • Hardware Requirements
      • hyperchains
      • Installation
      • Network Monitoring
      • Operation
      • Rebar Quick Guide
      • Stratum
      • Testing
      • Update
      • release-notes
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • About this release
        • next-ceres
          • GH-3706-micro_block_gas_limit_used_gas
          • GH-4009-allow_contract_call_by_name
          • GH-4056-add_raw_data_pointers_to_AENS
          • GH-4080-wildcard_aens_delegation_signature
          • GH3417-tamper_protection_on_ga_meta_tx
          • aega_only_allow_attach_for_fresh_accounts
          • aens_auction_adjustments
          • aens_preclaim_optional
          • deprecate_swagger
          • fate_extensions
        • next
          • GH-3088-db_direct_access-as-default
          • GH-4087_http_endpoint_info_inner_txs
          • GH4157-control-mempool-sync-start
    • Emergency patching of OTP modules
    • rosetta
    • apps
      • aehttp
        • priv
          • rosetta_README
    • data
      • aecore
        • Token migration contract
  • Hyperchains whitepaper
    • Hyperchains: Bridging Security and Scalability Through Periodic Synchronization
    • LICENSE
    • Periodically-Syncing-HyperChains
    • generations
    • Glossary
    • Hyperchain Properties
    • staking
  • æternity protocol
    • æternity naming system
    • Gossip
    • Stratum
    • SYNC
    • Serialization formats
    • State Channels
      • Off-chain
      • On-chain
      • Authentication
      • Channel off-chain state
    • æternity consensus protocol
      • Bitcoin-NG for æternity
      • Coinbase at height
      • consensus
      • Coins locking
    • Smart Contracts
      • The æternity Ethereum virtual machine (AEVM)
      • contract_state_tree
      • Contract Transactions
      • Virtual machines on the æternity blockchain
      • contracts
      • Events
      • fate
      • The Solidity Language
      • sophia
      • sophia_stdlib
    • Generalized accounts
      • Generalized accounts - explained
      • generalized_accounts
    • Oracles
      • Oracle life cycle examples
      • Oracle state tree
      • Oracle transactions
      • oracles
    • Sync
      • P2P messages
      • Mempool/TX-pool synchronization
    • node
      • æternity node API
        • Account management - intended usage
        • Encoding scheme for API identifiers and byte arrays
        • State channel WebSocket API
        • Channels - intended usage
        • Contracts - intended usage
        • Mining - intended usage
        • Naming System - intended usage
        • Oracles - intended usage
        • Spending coins - intended usage
        • examples
          • æternity node channel WebSocket API examples
            • json-rpc
              • sc_ws_basic_open_close
              • sc_ws_basic_open_close_server
              • sc_ws_broken_open_params
              • sc_ws_close_mutual
              • sc_ws_close_solo
              • sc_ws_leave_reconnect
              • sc_ws_leave_reestablish
              • sc_ws_leave_reestablish_responder_stays
              • sc_ws_leave_reestablish_wrong_fsm_id
              • sc_ws_min_depth_is_modifiable
              • sc_ws_min_depth_not_reached_timeout
              • sc_ws_opening_ping_pong
              • sc_ws_reconnect_early
              • sc_ws_slash
              • sc_ws_snapshot_solo
              • sc_ws_timeout_open
              • sc_ws_update_with_meta
              • abort_updates
                • sc_ws_abort_deposit
                • sc_ws_abort_offchain_update
                • sc_ws_abort_settle
                • sc_ws_abort_shutdown
                • sc_ws_abort_slash
                • sc_ws_abort_snapshot_solo
                • sc_ws_abort_withdraw
                • sc_ws_can_not_abort_while_open
              • assume_min_depth
                • sc_ws_basic_open_close
              • both_sign
                • init_per_group
                • conflicts
                  • sc_ws_conflict_deposit_and_offchain_update
                  • sc_ws_conflict_two_deposits
                  • sc_ws_conflict_two_offchain_updates
                  • sc_ws_conflict_two_withdrawals
                  • sc_ws_conflict_withdrawal_and_deposit
                  • sc_ws_conflict_withdrawal_and_offchain_update
              • changeable_fee
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
                • sc_ws_set_fee_close_mutual
                • sc_ws_set_fee_close_solo
                • sc_ws_set_fee_create
                • sc_ws_set_fee_deposit
                • sc_ws_set_fee_settle
                • sc_ws_set_fee_slash
                • sc_ws_set_fee_snapshot
                • sc_ws_set_fee_withdrawal
              • changeable_fee_higher_than_gas_price
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
              • changeable_fee_lower_than_gas_price
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
              • changeable_gas_price
                • sc_ws_optional_params_close_solo
                • sc_ws_optional_params_create
                • sc_ws_optional_params_deposit
                • sc_ws_optional_params_settle
                • sc_ws_optional_params_slash
                • sc_ws_optional_params_snapshot
                • sc_ws_optional_params_withdrawal
              • changeable_nonce
                • sc_ws_optional_params_fail_close_mutual
                • sc_ws_optional_params_fail_close_solo
                • sc_ws_optional_params_fail_create
                • sc_ws_optional_params_fail_deposit
                • sc_ws_optional_params_fail_force_progress
                • sc_ws_optional_params_fail_settle
                • sc_ws_optional_params_fail_slash
                • sc_ws_optional_params_fail_snapshot
                • sc_ws_optional_params_fail_withdrawal
              • continuous
                • init_per_group
                • sc_ws_deposit
                • sc_ws_failed_update
                • sc_ws_generic_messages
                • sc_ws_ping_pong
                • sc_ws_update_conflict
                • sc_ws_withdraw
              • contracts
                • init_per_group
                • sc_ws_basic_contracts
                • sc_ws_environment_contract
                • sc_ws_nameservice_contract
                • sc_ws_oracle_contract
                • sc_ws_remote_call_contract
                • sc_ws_remote_call_contract_refering_onchain_data
                • sc_ws_wrong_call_data
              • force_progress
                • sc_ws_force_progress_based_on_offchain_state
                • sc_ws_force_progress_based_on_onchain_state
              • only_one_signs
                • init_per_group
                • sc_ws_conflict_on_new_offchain
                • sc_ws_conflict_snapshot_and_offchain_update
                • conflicts
                  • sc_ws_conflict_deposit_and_offchain_update
                  • sc_ws_conflict_two_deposits
                  • sc_ws_conflict_two_offchain_updates
                  • sc_ws_conflict_two_withdrawals
                  • sc_ws_conflict_withdrawal_and_deposit
                  • sc_ws_conflict_withdrawal_and_offchain_update
              • reconnect
                • sc_ws_basic_client_reconnect_i
                • sc_ws_basic_client_reconnect_i_w_reestablish
                • sc_ws_basic_client_reconnect_r
              • with_meta
                • init_per_group
                • sc_ws_deposit
                • sc_ws_remote_call_contract
                • sc_ws_withdraw
              • generalized_accounts
                • both
                  • sc_ws_basic_open_close
                • initiator
                  • sc_ws_basic_open_close
                • responder
                  • sc_ws_basic_open_close
  • Superhero Wallet
    • Changelog
    • Contributing & Guidelines
    • docs
      • Deep link URL Schema
    • .github
      • ISSUE_TEMPLATE
        • bug_report
        • feature_request
  • aerepl-web-bridge
    • AereplApi
    • aerepl_components
Powered by GitBook
On this page
  • Introduction
  • 1. Specify imports
  • 2. Setup compiler
  • 3. Create an instance of the SDK
  • 4. Initialize the contract instance
  • By source code
  • By path to source code (available only in Node.js)
  • By ACI and bytecode
  • By ACI and contract address
  • Create contract instance
  • Options
  • Keep bytecode and ACI for future use
  • 5. Deploy the contract
  • 6. Call contract entrypoints
  • a) Stateful entrypoints
  • b) Regular entrypoints
  • c) Payable entrypoints
  • Transaction options
  • Sophia datatype cheatsheet
  • Generate file system object in Node.js

Was this helpful?

Export as PDF
  1. æternity's JavaScript SDK
  2. Installation
  3. guides

Contracts

PreviousContract EventsNextError Handling

Last updated 18 days ago

Was this helpful?

Introduction

The smart contract language of the æternity blockchain is . It is a functional language in the ML family, strongly typed and has restricted mutable state.

Before interacting with contracts using the SDK you should get familiar with Sophia itself first. Have a look into and start rapid prototyping using .

1. Specify imports

// node.js import
const { AeSdk, AccountMemory, Node } = require('@aeternity/aepp-sdk');
// ES import
import { AeSdk, AccountMemory, Node } from '@aeternity/aepp-sdk';
// additionally you may need to import CompilerCli or CompilerHttp

2. Setup compiler

Compiler primarily used to generate bytecode to deploy a contract. Skip this step if you have a contract bytecode or need to interact with an already deployed contract. Out-of-the-box SDK supports and implemented in and respectively.

CompilerCli is available only in Node.js and requires Erlang installed (escript available in $PATH), Windows is supported.

const compiler = new CompilerCli();

CompilerHttp requires a hosted compiler service. Preferable to host your own compiler service since is planned to be decommissioned. An example of how to run it using .

const compiler = new CompilerHttp('https://v8.compiler.aepps.com'); // host your own compiler

3. Create an instance of the SDK

When creating an instance of the SDK you need to provide an account which will be used to sign transactions like ContractCreateTx and ContractCallTx that will be broadcasted to the network.

const node = new Node('https://testnet.aeternity.io'); // ideally host your own node
const account = new AccountMemory(SECRET_KEY);

const aeSdk = new AeSdk({
  nodes: [{ name: 'testnet', instance: node }],
  accounts: [account],
  onCompiler: compiler, // remove if step #2 skipped
});

Note:

  • You can provide multiple accounts to the SDK.

    • This is specifically important and useful for writing tests.

4. Initialize the contract instance

To do so, we need to prepare an options object, which can be done in multiple ways.

By source code

const sourceCode = ... // source code of the contract
const options = { sourceCode }

Note:

  • const fileSystem = ... // key-value map with name of the include as key and source code of the include as value
    const options = { sourceCode, fileSystem }

By path to source code (available only in Node.js)

It can be used with both CompilerCli and CompilerHttp. This way contract imports would be handled automatically, with no need to provide fileSystem option.

const sourceCodePath = './example.aes';
const options = { sourceCodePath };

By ACI and bytecode

If you pre-compiled the contracts you can also initialize a contract instance by providing ACI and bytecode:

const aci = ... // ACI of the contract
const bytecode = ... // bytecode of the contract
const options = { aci, bytecode }

By ACI and contract address

In many cases an application doesn't need to deploy a contract or verify its bytecode. In this case you'd want to initialize the instance by just providing the ACI and the contract address. This is also possible:

const aci = ... // ACI of the contract
const address = ... // the address of the contract
const options = { aci, address }

Create contract instance

Do it by Contract::initialize.

const contract = await Contract.initialize({ ...aeSdk.getContext(), ...options });

AeSdk:getContext is used to get base options to instantiate contracts. These options include the current account, node, and compiler. They are referenced using Proxy class, pointing to the latest values specified in AeSdk. So, if you change the selected node in the AeSdk instance, it will be also changed in bound contract instances.

Options

  • Following attributes can be provided via options to Contract::initialize:

    • aci (default: obtained via onCompiler)

      • The Contract ACI.

    • address

      • The address where the contract is located at.

      • To be used if a contract is already deployed.

    • fileSystem (default: {})

      • Key-value map with name of the include as key and source code of the include as value.

    • validateBytecode (default: false)

      • Compare source code with on-chain version.

      • For most of these additional options it doesn't make sense to define them at contract instance level.

      • You wouldn't want to provide an amount to each transaction or use the same nonce which would result in invalid transactions.

      • For options like ttl or gasPrice it does absolutely make sense to set this on contract instance level.

Keep bytecode and ACI for future use

After the contract is initialized you can persist values of contract._aci and contract.$options.bytecode. They can be provided for subsequent contract initializations to don't depend on a compiler.

5. Deploy the contract

If you have a Sophia contract source code that looks like this:

contract Increment =

    record state =
        { count: int }

    entrypoint init(start: int) =
        { count = start }

    stateful entrypoint increment(value: int) =
        put(state{ count = state.count + value })

    entrypoint get_count() =
        state.count

The contract can be deployed using the contract in two different ways:

const tx = await contract.$deploy([1]);
// or
const tx = await contract.init(1);

// after successful deployment you can look up the transaction and the deploy information
console.log(tx); // { owner, transaction, address, result, rawTx }

Note:

  • Deployment is only possible if the contract instance was initialized by providing source code or bytecode.

  • The init entrypoint is a special function which is only called once for deployment, initializes the contract's state and doesn't require the stateful declaration.

  • In Sophia all public functions are called entrypoints and need to be declared as stateful if they should produce changes to the state of the smart contract, see increment(value: int).

6. Call contract entrypoints

a) Stateful entrypoints

According to the example above you can call the stateful entrypoint increment by using one of the following lines:

const tx = await contract.increment(3); // recommended
// or
const tx = await contract.increment(3, { callStatic: false });
// or
const tx = await contract.$call('increment', [3]);

Note:

  • The callStatic: false option provide an explicit way to tell the SDK to sign and broadcast the transaction.

  • When using the increment function directly the SDK will automatically determine if it's a stateful entrypoint.

b) Regular entrypoints

The æternity node can expose an API endpoint that allows to execute a dry-run for a transaction. You can make use of that functionality to get the result of entrypoints that don't execute state changes. Following lines show how you can do that using the SDK for the get_count entrypoint of the example above:

const tx = await contract.get_count(); // recommended
// or
const tx = await contract.get_count({ callStatic: true });

// access the decoded result returned by the execution of the entrypoint
console.log(tx.decodedResult);

Note:

  • The callStatic option provide an explicit way to tell the SDK to perform a dry-run and to NOT broadcast the transaction.

  • When using the get_count function directly the SDK will automatically determine that the function is not declared stateful and thus perform a dry-run, too.

c) Payable entrypoints

You will probably also write functions that require an amount of aettos to be provided. These functions must be declared with payable and (most likely) stateful. Let's assume you have declared following Sophia entrypoint which checks if a required amount of aettos has been provided before it continues execution:

payable stateful entrypoint fund_project(project_id: int) =
        require(Call.value >= 50, 'at least 50 aettos need to be provided')
        // further logic ...

In order to successfully call the fund_project entrypoint you need to provide at least 50 aettos. You can do this by providing the desired amount of aettos using one of the following lines:

const tx = await contract.fund_project(1, { amount: 50 }); // recommended
// or
const tx = await contract.$call('fund_project', [1], { amount: 50 });

Transaction options

Sophia datatype cheatsheet

Generate file system object in Node.js

Both compiler classes implement the that can be used to generate bytecode and ACI without a Contract instance.

For each transaction you can choose a specific account to use for signing (by default the first account will be used), see .

If your contract includes external dependencies which are not part of the you should initialize the contract using:

other which will be provided to every transaction that is initiated using the contract instance. You should be aware that:

As already stated various times in the guide it is possible to provide as object to a function of the SDK that builds and potentially broadcasts a transaction. This object can be passed as additional param to each of these functions and overrides the default settings.

Sometimes you might wonder how to pass params to the JavaScript method that calls an entrypoint of your Sophia smart contract. The conversion between JS and Sophia values is handled by aepp-calldata library. Refer to to find the right type to use.

To do so you can use function. In most cases, you don't need to do it explicitly. Prefer to use sourceCodePath instead sourceCode in, and instead in CompilerBase.

Sophia
aepp-sophia-examples
AEstudio
aesophia_cli
aesophia_http
CompilerCli
CompilerHttp
compiler.aepps.com
docker-compose
same interface
transaction options
standard library
transaction options
transaction options
its documentation
getFileSystem
Contract::initialize
compile
compileBySourceCode