Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This is the suggested template for new AEXs.
Note that an AEX number will be assigned by an editor. When opening a pull
request to submit your AEX, please use an abbreviated title in the filename,aex-draft_title_abbrev.md.
The title should be 44 characters or less.
"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the AEX.
A short (~200 word) description of the technical issue being addressed.
The motivation should clearly explain why existing specifications are inadequate to address the problem that the AEX solves. AEX submissions without sufficient motivation may be rejected outright.
The technical specification should describe the syntax and semantics of any new or changed feature. The specification should be detailed enough to allow competing, interoperable implementations.
The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.
All AEXs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The AEX must explain how the author proposes to deal with these incompatibilities. AEX submissions without a sufficient backwards compatibility treatise may be rejected outright.
The implementations, if applicable, must be completed before any AEX is given status "Last Call", and it needs be completed before the AEX is accepted. There is merit to the approach of reaching consensus on the specification and rationale before writing code, but the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.
Copyright and related rights go here if the License and License-Code
fields don't cover the copyright requirements.
AEX: <to be assigned by editors>
Title: <AEX title>
Author: <a list of the author's or authors' name(s) and/or username(s), or name(s) and email(s), e.g. (use with the parentheses or triangular brackets): FirstName LastName (@GitHubUsername), FirstName LastName <[email protected]>, FirstName (@GitHubUsername) and GitHubUsername (@GitHubUsername)>
License: <license names, abbreviated>
License-Code (*optional): <license names, abbreviated>
Discussions-To: <URL>
Status: <Draft | Review | Last Call (yyyy-mm-dd to yyyy-mm-dd) | Final | Active | Updated | Superseded | Rejected | Withdrawn>
Type: <Interface | Informational | Meta>
Created: <date created on, in ISO 8601 (yyyy-mm-dd) format>
Requires (*optional): <AEX number(s)>
Replaces (*optional): <AEX number(s)>
Updates (*optional): <AEX number(s)>Here you'll find a curated set of development resources spanning blockchain infrastructure, programming language support, cross-chain bridges, SDKs, and developer tooling. Whether you're a seasoned blockchain developer or just starting your journey with æternity, these tools are designed to streamline your development process and unlock the full potential of decentralized technology.
From our Sophia smart contract language support to JavaScript SDKs, middleware tools, and integration bridges, we provide a robust ecosystem that empowers developers to create cutting-edge blockchain applications with efficiency and ease.
Explore the sidebar to dive into specific tools and technologies, and start building with æternity today.
If you want to go back to other sections of the Documentation Hub, click one of the links below or click on "Documentation Hub" in the upper left corner at the top of the sidebar.
When opening a pull request to submit a new AEX, please use the suggested template:
Documentation Hub
The Aeternity Expansions (AEX), or aexpansions, are standards proposed by the community at large, i.e. everyone. Some of them can be mandatory in a specific context, e.g. AEX-1 describes the set of rules governing this repository, but are restricted to the application layer.
The purpose of this repository is to provide a high quality and accessible set of specifications; ideally together with implementations ready to be used if applicable.
If you want to contribute please follow these steps:
Read
Fork this repository
Add your proposal to your fork, using the template provided
Submit a pull request to the AEX repository
Each proposal should go into the AEXS directory. If you need to embed images
or other assets add a subdirectory in the assets directory with the number
of your proposal once assigned, e.g. assets/aex-1/image.png.
Everything beyond step 4 is governed by .
Read for more details.
Draft - an AEX that is open for consideration and is undergoing rapid iteration and changes.
Review - an AEX that is done with its initial iteration and in review by a wide audience.
Last Call - In review by a wide audience - last call for accepting changes.
Final - an AEX that has been in Last Call for at least 2 weeks and all technical changes that were requested have been addressed by the author.
This README is released under the license.
Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like A clear and concise description of what you want to happen.
Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.
Additional context Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like A clear and concise description of what you want to happen.
Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.
Additional context Add any other context or screenshots about the feature request here.
Active - proposal can be in constant flux. No unaddressed substantiated objections are left, crucial or cosmetic updates only.
Updated - signalling that an updating standard might have to be considered
Superseded - an AEX that is deprecated because other AEX supersedes it.
Rejected - editors deemed this proposal to be unworkable
Withdrawn - signalling that the proposal is no longer relevant.
Withdrawn
Inter-Wallet Communication
Withdrawn
Data Serialization
Draft
Message Signing
Review
Fungible Token Standard
Final
Derivation path for deterministic wallets
Draft
æpps Meta Information Format
Review
Non-Fungible Token Standard
Active
AEX process
Withdrawn
Third-party Wallet Provider Support
Active
Secret storage format
Withdrawn
æternity wallet deep linking specification
Paste here the link to the topic on forum.aeternity.com
Paste here the url where the content of the AEX can be found
If you would like to submit an AEX and it has already been written as a draft (see the for an example), please submit it as a .
If you are considering a proposal but would like to get some feedback on the idea before submitting a draft, then continue opening an issue as a thread for discussion. Note that the more clearly and completely you state your idea the higher the quality of the feedback you are likely to receive.
Keep in mind the following guidelines from :
Each AEX must have a champion - someone who writes the AEX using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. The AEX champion (a.k.a. Author) should first attempt to ascertain whether the idea is AEX- able. Posting to the the Protocol Discussion forum or opening an issue is the best way to go about this.
Before you begin, vet your idea, this will save you time. Ask the Aeternity community first if an idea is original to avoid wasting time on something that will be be rejected based on prior research (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Aeternity is used. Examples of appropriate public forums to gauge interest around your AEX include the and the issues section of this repository. In particular, the issues section of this repository is an excellent place to discuss your proposal with the community and start creating more formalised language around your AEX.
Once the champion has asked the Aeternity community as to whether an idea has any chance of acceptance, a draft AEX should be presented as a pull request. This gives the author a chance to flesh out the draft AEX to make properly formatted, of high quality, and to address initial concerns about the proposal.
This guide explains basic interactions on getting access to accounts on Aeternity snap for MetaMask using JS SDK.
Run the code from below you need:
a MetaMask extension 12.2.4 or above installed in Chrome or Firefox browser;
to setup an account in MetaMask (create a new one or restore by mnemonic phrase).
Firstly, you need to create a factory of MetaMask accounts
Using the factory, you can create instances of specific accounts by providing an index
The private key for the account would be derived in the MetaMask browser extension using the provided index and the mnemonic phrase it was initialized with. The private key won't leave the extension.
The complete examples of how to use it in browser can be found .
Account can be persisted and restored by saving values of index, address properties
It can be used to remember accounts between app restarts.
In addition to the above, it is possible to get access to a sequence of accounts that already have been used on chain. It is needed, for example, to restore the previously used accounts in case the user connects MetaMask to an app that doesn't aware of them.
If the user rejects an action (snap installation or connection, address retrieving or transaction/message signing) you will get an exception as a plain object with property code equals 4001, and message equals "User rejected the request.".
If the snap downgrade is requested, the code will be -32602.
This application is created for interacting with the æternity <> EVM Bridge contracts provided by Acurast. Executing proper bridge actions using this application will result in moving the sent funds to the other chain.
Before running the application, first project dependencies needs to be installed with the following command:
Afterwards, to run the application locally in development mode, following command needs to be run at the project directory:
Note: for support questions, please use the . This repository's issues are reserved for feature requests and bug reports.
Do you want to request a feature or report a bug?
What is the current behavior?
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem
Aeproject can already be used for testing and setup with the upcoming node versions.
Use aeproject init --next to initialize a new project that has the necessary adjustments to use the latest versions.
Use aeproject init --update --next to update an existing project with the adjustments to use the latest versions.
Describe the bug A clear and concise description of what the bug is.
To Reproduce Steps to reproduce the behavior:
Go to '...'
Click on '....'
Scroll down to '....'
Choose the wallet example from examples folder (the simplest is iframe-based wallet)
Start the wallet according to its readme
Start this æpp, which will start on port 9001
Connect this æpp to a choosed wallet according to its readme
Prerequisite: refer SDK installation
Install required dependencies with npm install
Start the application npm run serve
change occurrences of utils.getSdk() to use utils.getSdk({ ignoreVersion: true }) if needed or use the same option for manually initialized sdk Node and CompilerHttp
update docker-compose.yml to use the latest node and compiler tags or specify it manually in running with aeproject env --nodeVersion latest --compilerVersion latest
See error
Expected behavior A clear and concise description of what you expected to happen.
Screenshots If applicable, add screenshots to help explain your problem.
Please tell us about your environment:
Node Version: v0.0.0
Protocol Version: 1
Compiler version: v0.0.0
VM Version: fate | fate2
SDK Version: v0.0.0
Python version: v3.7.0
Other information (e.g. detailed explanation, stack traces, related issues, suggestions how to fix, links for us to have context, eg. forum, telegram, etc)
What is the expected behavior?
What is the motivation / use case for changing the behavior?
Please tell us about your environment:
CLI Version: v0.0.0
Node Version: v0.0.0
NPM Version: v0.0.0
Protocol Version: 1
Compiler version: v0.0.0
Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. forum, telegram, etc)
aeproject init [folder]Optionally a folder can be specified for the project to be initialized in, otherwise the current directory is used.
Creates a new project structure with a few folders in which the developer can create contracts and tests, as well as installing needed dependencies.
For upgrade from old AEproject versions check out Migration from 3.x.x to 4.x.x and Migration from 4.x.x to 5.x.x.
aeproject init --updateUpdates the project structure and needed artifacts to the latest version, as well as installing needed dependencies.
The additional parameter --next can be used to either initialize or update a project with changes for an upcoming hard-fork if available.
This application doesn't contain any secrets and can be run by any machine with the following packages installed: node, npm, yarn
After completing the Getting started successfully, following command will build the application and make it ready to be served either on a local machine or on a server:
To serve the build, there is a need for an additional package called serve, can be installed via:
with yarn:
without yarn:
Finally, to run the build:
Project has a Dockerfile in place. So, it can be easly run in a docker container with the following commands:
build the container:
and run:
it should be served at localhost:3000
If you want to run the bridge on free cloud service, following steps can be taken:
Fork this repository
Create an account for a cloud deployment service (Vercel, Netlify, AWS etc)
Connect your GitHub account to your cloud platform selection
Create a new app under your cloud service
Configure your application using your forked repo with the standard node application deployment settings
Deploy and self host your bridge application
assertedType, use decode insteadIf you used it like
then you have to rewrite it using decode method
Instead of TransactionValidator stamp use verifyTransaction function. The function accepts
a transaction, and a Node instance for validation (instead of network id), it doesn't return
an unpacked transaction anymore, just an array of errors. Each error contains a verbose message
(msg before), unique key (for easy comparison), checkedKeys array (txKey before). Usingnode instead of networkId allows to ensure transaction validation, so warnings are errors
now (type field removed).
SCHEMA doesn't contain validation schema anymore. This wasn't supposed to be used by external
developers.
If you used buildHash like
then use
If you used it with a falsy raw then
buildTxHash don't have raw switch anymore, it returns th_-encoded string in all cases,
but it still accepts transactions as a string and as a buffer.
If you were passing verifyTx: false to sdk factory then use verify: false instead.
name as string,
version as integer,
networkId as string,
contractAddress as ct-encoded string.
aci is part of a complete contract ACI. It defines a type of data to sign. For example, the ACI
corresponds to the data
domain and data are fate-encoded before hashing. aci is prepared for hashing according to RFC8785.
AccountBase:signTypedData — calculates signature, supported in AccountMemory and in aepp-wallet connection;
hashTypedData — calculates the overall hash of typed data to sign;
hashJson — deterministic hashing of an arbitrary JS value, used to calculate hash(aci);
hashDomain — use for debugging or to prepare the hash value for smart contract.
import { AccountMetamaskFactory } from '@aeternity/aepp-sdk';
const accountFactory = new AccountMetamaskFactory();const account = await accountFactory.initialize(0);
console.log(account.address); // 'ak_2dA...'
console.log(await account.signTransaction('tx_...')); // 'tx_...' (with signature added)import { AccountMetamask } from '@aeternity/aepp-sdk';
const accountIndex = accountToPersist.index;
const accountAddress = accountToPersist.address;
const accountFactory = new AccountMetamaskFactory();
const restoredAccount = new AccountMetamask(accountFactory.provider, accountIndex, accountAddress);import { Node } from '@aeternity/aepp-sdk';
const node = new Node('https://testnet.aeternity.io');
const accounts = await accountFactory.discover(node);
console.log(accounts[0].address); // 'ak_2dA...'yarnyarn startyarn buildyarn global add servenpm -g install serveserve -s builddocker build -t aepp-bridge .docker run -d -p 3000:80 aepp-bridgeconst sdk = await Universal({ ... })
sdk.waitMined(false)const sdk = await Universal.compose({
deepProps: { Ae: { defaults: { waitMined: false } } }
})({ ... })sdk.spend(amount, receiver, { waitMined: false });const sdk = await Universal({ ... })
sdk.deepProps({ Ae: { defaults: { waitMined: false } } })const payload = Crypto.decodeBase64Check(Crypto.assertedType('tx_...', 'tx'));const payload = TxBuilderHelper.decode('tx_...', 'tx');const hash = TxBuilderHelper.buildHash('xx', Buffer.from([1, 2, 3]), { raw: true });const hash = Crypto.hash(Buffer.from([1, 2, 3]));const hash = TxBuilderHelper.encode(Crypto.hash(Buffer.from([1, 2, 3])), 'xx');{
"record": [
{ "name": "foo", "type": "string" },
{ "name": "bar", "type": "int" }
]
}{ "foo": "test", "bar": 42 }The document describes and defines the deep linking specification that every æternity supported wallet can implement and follow to redirect users to a specific activity or page inside the application.
URI based deep linking enables websites or applications to interact with native applications registered to listen for aeternity URI scheme and trigger wallet actions like open wallet accounts directly from third-party applications.
This also enables users to sign transaction using desktop or mobile based wallets without the need to copy or remember long addresses. This is especially beneficial for mobile wallet users as they can simply click on the wallet deep link to open the wallet app from the vendor app, confirm the transaction and return back to the vendor app through the callback url.
ae:
aeternity:
View/Open Account in the wallet
URI: aeternity:<wallet_address>
Associated wallet app will:
Open the wallet app
Check if the address exists or not
https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki
https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki
https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki
https://hackmd.io/s/BJObJntjQ
This package is expected to work in these environments:
nodejs>=18.19
Browser using script tag, umd
webpack@4
requires a fix to work with mjs build
webpack@5
@vue/cli@4 (webpack@4)
AeSdk is a general, high-level interface that wraps multiple low-level interfaces. A general interface is preferred for its simplicity and resilience to breaking changes.
But there is also low-level interfaces. It's excellent for additional control, and as a teaching tool to understand the underlying operations. Most real-world requirements involves a series of low-level operations, so the SDK provides abstractions for these.
The aeternity node exposes . This API is described in the . SDK uses this document to generate a TypeScript client. The result client (implemented in ) a basically a mapping of all node endpoints as functions.
So to get a transaction based on its hash you would invoke node.getTransactionByHash('th_fWEsg152BNYcrqA9jDh9VVpacYojCUb1yu45zUnqhmQ3dAAC6'). In this way the SDK is simply a mapping of the raw API calls into JavaScript.
Any blockchain state change requires signing a transaction. Transaction should be built according to the . SDK implements it in , , and . requires fewer arguments than , but it expects the node instance provided in arguments.
Example spend call, using æternity's SDK abstraction:
The same spend execution, but using low-level SDK functions:
In this example we will send 1 AE coin from one account to another. For more specific information on setups with Frameworks and TypeScript, please refer to the installation instructions.
For the following snippets in the guide you need to specify multiple imports.
To receive some AE you can use the . Just paste sender's address, hit Top UP and you'll immediately get some test coins.
This example shows:
how to create an instance of the SDK using the AeSdk class
how to spend (send) 1 AE from the account the SDK instance was initialized with to some other AE address
Note:
You may remove code from Step 2 as this serves only for one-time creation
The spend function expects the amount to be spent in aettos (the smallest possible unit, 1 AE equal to 1 000 000 000 000 000 000 aettos)
See and track your transactions
This aexpansion specify the derivation path used in the Aeternity blockchain for deterministic wallets
The aexpansion is meant to avoid incompatibility with deterministic wallet implementations across the Aeternity landscape and to make it easy for the derivation path to be found.
Accounts derivation path is taken from , except that in all path segments hardened derivation is used since does not support public derivation.
The derivation path (m/purpose'/coin_type'/account_index'/change'/address_index') is therefore:
m/44H/457H/${account_index}H/0H/${address_index}H
where account_index and address_index are integer starting from 0.
The coin type value for Aeternity, 457, has been generated on random.org and is registered in .
This is a sample wallet that expects an æpp to be loaded into its iframe.
Start this wallet, which will start on port 9000
Start the , which will start on port 9001
Visit to see the æpp included into this wallet
Prerequisite:
Install required dependencies with npm install
Start the application npm run serve
This folder contains examples of code samples that you can run autonomously. Create a new issue to suggest another example.
(VueJS)
(VueJS)
In æternity ecosystem, the app that has access to user's private keys and grants other apps access to them is called wallet. Respectively, the app that is granted access is called aepp.
This folder has been created to showcase the æternity SDK integration to both wallets and aepps.
If you are trying these examples after checking out this repo,
you want to first run npm install, from the repo root, to get all the SDK dependencies installed,
and only then, move to individual apps installations.
The Sample project (Distributed App or dapp) shows how you can create a simple æternity æpp, dependent on a Wallet, in this case: offering the possibility to work with contracts.
The example project shows how you can create a simple æternity wallet as a Chrome/Firefox browser extension. This approach is actively used in.
The example project shows how you can create a simple æternity wallet that opens æpps in iframe. This approach is actively used in .
This guide describes the process of migrating to SDK version 7.0.0
SDK will not accept url, internalUrl init arguments anymore:
Remove deprecated function setKeypair
SDK will not accept keypair init argument anymore:
Change all of AENS method's first argument from nameId to name
Add new compiler methods to RPC communication (base-app update required)
Drop compiler version to version >= 4.0.0 && version < 5.0.0
Change node compatibility range to node >= 5.0.0 && node < 6.0.0
This is a sample wallet as an WebExtension. It works with æpp opened in a browser where it is installed.
Install this wallet to Chrome or Firefox
Start the , which will start on port 9001
Visit
This wallet should attempt to connect to the æpp
Prerequisite:
Install required dependencies with npm install
Start the build server in watch mode npm run serve
Open
Enable "Developer mode" at the right top conner
aeproject envThe command is responsible for setting up a healthy local environment. The env command helps developers run a local node and a local compiler in dev-mode using docker. To spawn a fully functional environment it can take a couple of minutes depending on your system.
If using Windows, WSL 2 needs to be used for AEproject to work normally, see https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers
You can stop both the node and the compiler by running
aeproject env --stopThere are optional parameters --nodeVersion and --compilerVersion. To specify a specific version of node or compiler, or both
This also applies to the commands aeproject node and aeproject compiler.
To see whether you have running instances of the nodes along with a compiler you could run the following command
Note: By default AEproject uses the latest-bundle tag of the official .
Compatibility:
the sdk from @aeternity/aepp-sdk@14 >= v14.0.0 is compatible with NODE_TAG >= v7.1.0 and COMPILER_TAG >= v8.0.0
due to a bug in the devmode plugin, NODE_TAG = v7.1.0 is not compatible with aeproject
Firewalls and any other security feature can block your docker/docker-compose requests. Please check that docker/docker-compose is NOT in its blocked list or has permission to make requests.
While base64-encoded strings have a constant length depending on the length of data to encode. In base58 it depends on the exact data to encode, e.g. it is shorter if encoded data have more leading zeroes.
Building an aepp you may need to know the range of possible address lengths to validate an user-provided addresses (though better to use ) or for designs of address-related components. Doing manual tests you may conclude that account address length is between 52 and 53 chars, but it is not correct.
Running the above code you would get something like { '51': 55, '52': 5021, '53': 4924 }
depending on generated accounts. So, while the most of addresses have length between 52 and 53
chars, there is a ~0.55% chance to get an address of 51 chars.
Theoretically there can be even shorter addresses if they lucky to be prefixed with a long
sequence of 0.
Running the above code you would get output like
Therefore the minimum address length is 41 chars. All these addresses valid, for exampleak_11111111111111111111111111111111273Yts
AeMdw is a middleware that acts as a caching and reporting layer for the . It responds to queries more efficiently than the node and supports additional queries.
The middleware runs an Aeternity Node alongside it in the same Docker container and BEAM VM instance. This node can be configured using the aeternity.yaml file or by passing environment variables, just like configuring the node directly.
This guide explains you how to perform a PayingForTx (also known as meta-transaction) using the SDK.
It is a very powerful and efficient solution that is crucial for onboarding new users into you ecosystem. By making use of the PayingForTx you will be able to cover the fees of your users.
Describe the bug A clear and concise description of what the bug is.
To Reproduce Steps to reproduce the behavior:
Go to '...'
Click on '....'
Scroll down to '....'
AEX: 4
Title: æternity wallet deep linking specification
Author: Shubhendu Shekhar (@shekhar-shubhendu), Andrea Giacobino (@noandrea)
License: BSD-3-Clause
Discussions-To: https://forum.aeternity.com/t/aex-4-aeternity-wallet-deep-linking-specification/3231
Status: Withdrawn
Type: Standards Track
Created: 2019-04-03const { AeSdk, AccountMemory, Node } = require('@aeternity/aepp-sdk');AEX: 10
Title: Derivation path for deterministic wallets
Author: Andrea Giacobino (@noandrea), Denis Davidyuk (@davidyuk)
License: BSD-3-Clause
Discussions-To: https://forum.aeternity.com/t/aex-10-derivation-path-for-deterministic-wallets/3586
License-Code: ISC
Status: Final
Type: Informational
Created: 2019-03-04aeproject env --nodeVersion v7.2.0
# or
aeproject env --compilerVersion v8.0.0
# or
aeproject env --nodeVersion v7.2.0 --compilerVersion v8.0.0aeproject env --infoIf the account is found with the wallet, then the user is redirected to the account information page of the provided address.
If the account is not found then prompt the user with an account not found message.
Example
aeternity:ak_2i2fioFMoEffBPeT3EBZEsxK1w579BuCgYE8WiMiADEQqUguU2
Payment
URI: aeternity:<receiver_address>/<amount>/<vendor_identifier>?callback=<url>
This URI scheme enables vendors to generate direct payment request URIs to user wallet.
Vendor generates a address for receiving payment.
Creates the URI substituting receiver_address with newly created address, amount with amount requested, vendor_identifier with a human readable identifier that can be used to correctly identify vendor and requested payment, and url with a callback URL that accepts a transaction id under txId query param.
Example
aeternity:ak_2gUJrd11cy65yqZ7mg1ULUG4kZ5r6v6vNqVtmA8HqUGKCf6kNf/125.12/myaeshop-ref9834?callback=https://myaeshop.com/verify
Sign and Broadcast
URI: aeternity:<transaction>/<network_id>/<label>?return=<txId/tx>&callback=<url>
This URI scheme enables users to sign (and broadcast) the transaction using deep linking enabled user wallet.
The user generates the transaction to be signed
Creates the URI substituting transaction and network_id with their respective value, label a human-readable text regarding the transaction and provides the query param return which indicates the return value type in the callback URL. It can contain only two possible values of string type:
txId: which indicates that the wallet needs to broadcast the transaction and return the transaction id
tx: means that the callback URL expects a signed transaction back.
And at last, substitutes the query param url which contains a callback URL that accepts a transaction id under txId query param and signed transaction output under tx query param.
Example
aeternity:tx_+E0MAaEBK4bq9XiZ/0QVdOa8Hs9V18v6dGZYIa8XXNYFpQh6yq6hAR8To7CL8AFABmKmi2nYdfeAPOxMCGR/btXYTHiXvVCjCoJOIAADgFcJyZ8=/ae_uat/sample_tx?return=tx&callback=https://myaeshop.com/verify
Typically somebody that you want to pay the transaction for (e.g. a new user of your decentralized aepp) signs the inner transaction (e.g. of type ContractCallTx) with a specific signature that is used for inner transactions.
You can then collect the signed inner transaction, wrap it into a PayingForTx and broadcast it to the network.
We provided following two NodeJS examples which you can take a look at:
Note:
A PayingForTx can wrap any kind of other transaction type supported by the protocol as inner transaction.
Game developers that want to quickly onboard new users.
Governance aepps that want people to vote on important proposals without having them to pay anything.
Custodians that want to offer an additional services to cover the transaction fees of their clients.
... many more!
See error
Expected behavior A clear and concise description of what you expected to happen.
Screenshots If applicable, add screenshots to help explain your problem.
Please tell us about your environment:
Node Version: v0.0.0
Protocol Version: 1
Compiler version: v0.0.0
VM Version: fate | fate2
SDK Version: v0.0.0
Python version: v3.7.0
Other information (e.g. detailed explanation, stack traces, related issues, suggestions how to fix, links for us to have context, eg. forum, telegram, etc)
Press "Load unpacked" button and choose the dist folder
requires aliases to ESM versions of autorest deps vue-cli4
@vue/cli@5 (webpack@5)
vue@3
AeSdk, Contract instances can't be reactive vue-3
create-react-app@4 (webpack@4)
mjs build is not compatible with webpack@4 cra-webpack-4
create-react-app@5 (webpack@5)
create-react-native-app@3 (webpack@4)
mjs build is not compatible with webpack@4 cra-webpack-4
meteor@2
requires an environment where Buffer is instanceof Uint8Array jest
typescript>=4.8
requires tsconfig.json adjustments typescript
vite@3
requires build.target: 'es2020' and bigint: true in vite.config.js vite
Always verify transactions before sending them to the node (can be disabled using the option verify: false)
import { AccountMemory } from '@aeternity/aepp-sdk';
const result = new Array(10000)
.fill()
.map(() => AccountMemory.generate().address.length)
.reduce((p, n) => ({ ...p, [n]: (p[n] ?? 0) + 1 }), {});
console.log(result);import { AccountMemory, Encoding, encode, decode } from '@aeternity/aepp-sdk';
const publicKey = decode(AccountMemory.generate().address);
for (let i = -1; i < publicKey.length; i += 1) {
if (i >= 0) publicKey[i] = 0;
const address = encode(publicKey, Encoding.AccountAddress);
console.log(address.length, address);
}@aeternity/aeproject@4node@16 is no longer supported, please update to v18 or higher
updated to @aeternity/aepp-sdk@14 to the latest version, see the migration guide for additional reference.
the aeproject provided utils.getSdk({}) has to be adjusted to pass a reference to the sdk used utils.getSdk(AeppSdk, {}) where AeppSdk can be imported using import * as AeppSdk from "@aeternity/aepp-sdk";
@aeternity/aepp-sdk@14 requires aeternity node version >= 7.1.0
Following utils have been removed and cannot be used anymore:
utils.getFilesystem() discontinued, as it is now natively available in the sdk via import, e.g. const { getFileSystem } = require("@aeternity/aepp-sdk");
This guide shows you how to handle errors originating from the SDK. SDK by default exports the following error classes from file errors.ts
// import required error classes
import {
AeSdk,
Node,
AccountMemory,
ArgumentError,
InvalidAensNameError,
} from '@aeternity/aepp-sdk';
// setup
const payerAccount = AccountMemory.generate();
const newUserAccount = AccountMemory.generate();
const node = new Node('https://testnet.aeternity.io');
const aeSdk = new AeSdk({
nodes: [{ name: 'testnet', instance: node }],
accounts: [payerAccount, newUserAccount],
});
// catch exceptions
try {
const spendTxResult = await aeSdk.spend(-1, newUserAccount.address, { onAccount: payerAccount });
} catch (err) {
if (err instanceof ArgumentError) {
console.log(`Amount specified is not valid, ${err.message}`);
} else if (err instanceof InvalidAensNameError) {
console.log(`Address specified is not valid, ${err.message}`);
}
}
// using generic error classes
import { AensError, TransactionError, BaseError } from '@aeternity/aepp-sdk';
try {
const spendTxResult = await aeSdk.spend(1, 'ak_2tv', { onAccount: payerAccount });
} catch (err) {
if (err instanceof AensError) {
// address or AENS related errors
} else if (err instanceof TransactionError) {
// transaction errors
} else if (err instanceof BaseError) {
// match any errors from the SDK
}
}When initializing a contract instance using the source code and providing the ACI
or obtaining it via http compiler (default) you will be able to access the emitEvents entrypoint of the Sophia contract above as follows:
Note:
As you can see the event log will be automatically decoded in case you perform a ContractCallTx directly
Of course it is also possible to decode the event log if you request the transaction details from the node for a transaction that has been mined already. You can request the transaction details by providing the tx-hash and then decode the event log using the contract as follows:
contract EventEmitter =
datatype event =
FirstEvent(int)
| AnotherEvent(indexed address, string)
entrypoint emitEvents(value: int, msg: string) =
Chain.event(FirstEvent(value))
Chain.event(AnotherEvent(Call.caller, msg))The secret storage specification, although is being currently used for secret-key storage, should not be limited to it and should be used as a standard way of storing secret text/plain text (esp. user related or user-owned) in an encrypted format.
Having a standard way for encryption and storage of data enables
Interoperability, not only between æternity and æpps but also between the æpps.
Easy migration from an aeternity-supported wallet to another.
The data should always be stored in a .json file.
Each file should have a minimum of 1 JSON object with the following required fields
secret_type specifies the type of the encrypted data.
(optional) secret_format specifies the format of the encrypted data,
if not specified then a consumer should assume raw bytes
symmetric_alg specifies the algorithm used for symmetric encryption of the secret. This should be authenticated encryption and the only option is xsalsa20-poly1305 currently.
The ciphertext is the output of symmectric_alg , i.e. the output of libsodiums crypto_secretbox_easy, which is MAC + CIPHER with an upper-limit of 512 bytes.
cipher_params params used for successful decryption of the ciphertext
kdf specifies the methods used for key derivation.
kdf_params are the params used by the kdf
id is a Version 4 UUID
version currently 1. Defines the version of secret storage format.
Each JSON Object can also have an optional name field, which can be a human-readable name for the secret.
Specifying an appropriate secret_type helps consumers to decide the proper way
of handling the decrypted data without having to store additional metadata.
The following secret_type values have been proposed:
ed25519-bip39-mnemonic
ed25519-slip0010-masterkey
This list should be expanded with adoption.
It is not advised to use this format as a store for arbitrary binary data.
https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition
Download a full backup from Aeternity Downloads.
Create a data directory under the root repository directory and extract the backup using the following command:
This will extract the mnesia and mdw.db folders to the data directory.
Run the following command to start the application on the mainnet:
To check if the application is running properly, visit the /status endpoint and ensure that node_height is higher than 600000.
Create the necessary directories for data storage and logs:
Ensure the directories have the correct permissions to allow the middleware to write to them:
If you want to use a database snapshot:
Download a full backup from Aeternity Downloads.
Extract the backup to the data directory:
This will place the mnesia and mdw.db folders under the data directory.
Start the container with the following command:
This command starts the middleware in a docker container. The middleware will be available at http://localhost:4000. Note that you can pass the -d flag to run the container in detached mode.
To check if the middleware is running properly, visit the /status endpoint and ensure that node_height is higher than 0.
To check the logs, run the following command:
To check the status of the container, run the following command:
To stop the container, run the following command:
To restart the container, run the following command:
Edit the configuration file docker/aeternity.yaml to specify network settings:
ae_mainnet for mainnet
ae_uat for testnet
A custom network name if running your own network or a hyperchain
You can also pass environment variables to configure the node, similar to standard Aeternity Node configuration.
Refer to Aeternity Configuration Docs for more details.
to install Ledger Live;
to install [email protected] or above app from Ledger Live to HW;
to have Ledger HW connected to computer, unlocked, with aeternity app opened.
To work with accounts on Ledger HW firstly you need to choose a transport implementation. Ledger HW can be connected through USB or Bluetooth using a specific NPM package.
After creating a transport instance you need to create a factory of Ledger accounts
Using the factory, you can create instances of specific accounts by providing an index
The private key for the account would be derived on the Ledger device using the provided index and the mnemonic phrase it was initialized with. The private key won't leave the device.
The complete examples of how to use it in nodejs and browser can be found here.
To protect from MITM attacks is it recommended to ensure that the accessed account is the account actually available on Ledger. To do so, the app should show to user the address it have access to, the same as Ledger HW should show the address on its screen, and user should ensure that addresses the same. To trigger verification process you need to use getAddress method
Account can be persisted and restored by saving values of index, address properties
It can be used to remember accounts between app restarts.
In addition to the above, it is possible to get access to a sequence of accounts that already have been used on chain. It is needed, for example, to restore the previously used accounts in case the user connects Ledger HW to an app that doesn't aware of them.
If the user rejects a transaction/message signing or address confirmation you will get an exception inherited from TransportStatusError (exposed in '@ledgerhq/hw-transport' package). With the message "Ledger device: Condition of use not satisfied (denied by the user?) (0x6985)". Also, statusCode equals 0x6985, and statusText equals CONDITIONS_OF_USE_NOT_SATISFIED.
In the test/exampleTest.js file you can find an example for unit testing using AEproject.
Javascript testing framework used with mocha for assertions, documented at https://www.chaijs.com/api/assert/
Helper and utilities for AEproject use, e.g. prefunded wallets, network definition and utility functions for SDK initialization and snapshotting.
Read AEproject Library for a more detailed explanation about the usage of these imports.
Provide your initializations in mocha which need to be done once before all tests:
Initialize the default SDK instance with provided utils:
Get the filesystem definition for (custom) includes of the given contract:
Read the contract source from the filesystem:
Initialize the contract instance:
Deploy the contract:
Create a snapshot of the chain state once before all tests. This allows you to rollback to a clean state after each test if needed:
Rollback to the previously created snapshot after each test for a clean state in the following tests:
Use mocha for test setup and chai for assert. Then implement contract usage using the aeternity sdk as explained in the guide at https://github.com/aeternity/aepp-sdk-js/blob/develop/docs/guides/contracts.md#5-call-contract-entrypoints
npm install -g @vue/cliconst sender = AccountMemory.generate();
console.log('Sender address:', sender.address);
console.log('Sender secret key:', sender.secretKey);const NODE_URL = 'https://testnet.aeternity.io';
// replace <SENDER_SECRET_KEY> with the generated secretKey from step 2
const sender = new AccountMemory('<SENDER_SECRET_KEY>');
(async function () {
const node = new Node(NODE_URL);
const aeSdk = new AeSdk({
nodes: [{ name: 'testnet', instance: node }],
accounts: [sender],
});
// spend one AE
await aeSdk.spend(1e18, '<RECIPIENT_ADDRESS>');
// replace <RECIPIENT_ADDRESS>, Ideally you use address from Superhero Wallet you have created before
})();Universal({
url,
internalUrl,
});const nodeInstance = await Node({ url, internalUrl });
Universal({
nodes: [{ name: 'testnet', instance: nodeInstance }],
});Universal({ keypair });Universal({
accounts: [MemoryAccount({ keypair })],
});const client = Universal({ ... })
await client.aensUpdate('cm_ad1wdsa...', ...)
await client.aensTransfer('cm_ad1wdsa...', ...)
await client.aensRevoke('cm_ad1wdsa...', ...)const client = Universal({ ... })
await client.aensUpdate('testname.chain', ...)
await client.aensTransfer('testname.chain', ...)
await client.aensRevoke('testname.chain', ...)52 ak_XsSLpN161dHo77k82CZHDnUCDpVG1JSujZjbGYhNKTgMy5exZ
52 ak_13P6GKgb4VcxJHrb5Vnhb66RNBGgdnFLVJS8RaLcrAeseZmuc
52 ak_115z6Ns8nevqahWHQfYU3QNJbK7PsX2rWxoPQRcpvWzB4U77s
51 ak_111dqrd5iRqVHQe2T2JdZe79bqNBVCkWPqSc1JAXMW6F2vvT
50 ak_1111PM8Acd6qZCjioCqPt6PcTuWVxxS22gt2ytCdH82FY4C
51 ak_111113q5w8zgNNjAgLbxrMmA8qBNCv8aVHBM7eLm7JbfcgVe
50 ak_111111UGVF8HYKFC7hLzwffE8JR5vQKQ9z4BiYJYCVcEGna
49 ak_1111111wnTfJ9TWagQmzk42ADoUqVg1VvNMG7t8Fo8SQGf
50 ak_11111111389cwfh57Mw1d4uYXps2orpWxc9Zoov7PdW6G7S
49 ak_111111111G6iURaQ8ycLUNERoocnfJPQ8J7bopyndikHFM
49 ak_11111111116b9WMyCB85kS4YkDfP9D3LhqUu5eG7AEfrLg
48 ak_11111111111urvTGsQm76A4yTbApC8DJ1rLggAFKXiZXp
48 ak_1111111111119eSHeN26TTHqgKpcEVTmbCHEbQgAHJkjd
48 ak_11111111111115QmcWAusFcLUq2MfYLXdxnFEhPkRrQu5
47 ak_11111111111111c7Y1hucPEYuPH6ZY5sFdKo6dhb86gk
47 ak_1111111111111116qaT3Ac44qzDFevr9Czj1S9p9Y46r
47 ak_11111111111111114KqRXnNJJwVDnphudyDt4XDmjLn7
46 ak_11111111111111111XGs41KwLTa74AMCwx3gYYAHv81
46 ak_1111111111111111114sffTSqJvTbsAjsQykvVsDcV8
45 ak_1111111111111111111wVeBwZE5g63oPLdnrQC7TuP
45 ak_11111111111111111111Y4FSQ8pV3J8f96h3SS68Df
45 ak_1111111111111111111114ZmkEyJVpPoE6bFrxSt3n
44 ak_1111111111111111111111hEHXkLzkWadzEyFn6pw
44 ak_11111111111111111111111A6y5vKi2SUtEiqyw1H
44 ak_1111111111111111111111112PszJecmUrBA1wHbx
43 ak_1111111111111111111111111yqJmD1ujq7rtGX6
43 ak_111111111111111111111111113hoVWLS2aptDtG
42 ak_111111111111111111111111111PhgEh1GA292t
42 ak_1111111111111111111111111111Z6ci7mUpU7i
42 ak_111111111111111111111111111119gETXQQAsT
42 ak_11111111111111111111111111111136u6WXDf6
41 ak_1111111111111111111111111111111PqPZYur
41 ak_11111111111111111111111111111111273Ytsnpm install -g @aeternity/aeprojectBaseError
├── ArgumentError
├── IllegalArgumentError
├── ArgumentCountMismatchError
├── InsufficientBalanceError
├── MissingParamError
├── NoSerializerFoundError
├── RequestTimedOutError
├── TxTimedOutError
├── TypeError
├── UnsupportedPlatformError
├── UnsupportedProtocolError
├── NotImplementedError
├── UnsupportedVersionError
├── LogicError
│
├── InternalError
│ └── UnexpectedTsError
│
├── AccountError
│ └── UnavailableAccountError
│
├── AensError
│ ├── AensPointerContextError
│ ├── InsufficientNameFeeError
│ └── InvalidAensNameError
│
├── AeppError
│ ├── InvalidRpcMessageError
│ ├── MissingCallbackError
│ ├── UnAuthorizedAccountError
│ ├── UnknownRpcClientError
│ └── UnsubscribedAccountError
│
├── ChannelError
│ ├── ChannelCallError
│ ├── ChannelConnectionError
│ ├── ChannelPingTimedOutError
│ ├── UnexpectedChannelMessageError
│ ├── ChannelIncomingMessageError
│ └── UnknownChannelStateError
│
├── CompilerError
│ └── InvalidAuthDataError
│
├── ContractError
│ ├── BytecodeMismatchError
│ ├── DuplicateContractError
│ ├── InactiveContractError
│ ├── InvalidMethodInvocationError
│ ├── MissingContractAddressError
│ ├── MissingContractDefError
│ ├── MissingFunctionNameError
│ ├── NodeInvocationError
│ ├── NoSuchContractFunctionError
│ ├── NotPayableFunctionError
│ ├── MissingEventDefinitionError
│ └── AmbiguousEventDefinitionError
│
├── CryptographyError
│ ├── InvalidChecksumError
│ ├── MerkleTreeHashMismatchError
│ ├── MissingNodeInTreeError
│ ├── UnknownNodeLengthError
│ └── UnknownPathNibbleError
│
├── NodeError
│ ├── DuplicateNodeError
│ └── NodeNotFoundError
│
├── TransactionError
│ ├── DecodeError
│ ├── PayloadLengthError
│ ├── DryRunError
│ ├── IllegalBidFeeError
│ ├── InvalidSignatureError
│ ├── InvalidTxError
│ ├── PrefixNotFoundError
│ ├── SchemaNotFoundError
│ ├── TagNotFoundError
│ └── TxNotInChainError
│
├── WalletError
│ ├── AlreadyConnectedError
│ ├── NoWalletConnectedError
│ └── RpcConnectionError
│
├── RpcError
│ ├── RpcInvalidTransactionError
│ ├── RpcRejectedByUserError
│ ├── RpcUnsupportedProtocolError
│ ├── RpcConnectionDenyError
│ ├── RpcNotAuthorizeError
│ ├── RpcPermissionDenyError
│ └── RpcInternalError// events emitted by contract calls are automatically decoded
const tx = await contract.emitEvents(1337, 'this message is not indexed');
console.log(tx.decodedEvents);
/*
[
{
name: 'AnotherEvent',
args: [
'fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk',
'this message is not indexed'
],
contract: {
name: 'EventEmitter',
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh'
}
},
{
name: 'FirstEvent',
args: [1337n],
contract: {
name: 'EventEmitter',
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh'
}
}
]
*/const txHash = 'th_2YV3AmAz2kXdTnQxXtR2uxQi3KuLS9wfvXyqKkQQ2Y6dE6RnET';
// aeSdk is an instance of the AeSdk class
const txInfo = await aeSdk.api.getTransactionInfoByHash(txHash);
// decode events using contract instance
const decodedUsingContract = contract.$decodeEvents(txInfo.callInfo.log);
console.log(decodedUsingContract);
/*
[
{
name: 'AnotherEvent',
args: [
'fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk',
'this message is not indexed'
],
contract: {
name: 'EventEmitter',
address: 'ct_fKhQBiNQkDfoZcVF1ZzPzY7Lig6FnHDCLyFYBY33ZjfzGYPps'
}
},
{
name: 'FirstEvent',
args: [1337n],
contract: {
name: 'EventEmitter',
address: 'ct_fKhQBiNQkDfoZcVF1ZzPzY7Lig6FnHDCLyFYBY33ZjfzGYPps'
}
}
]
*/AEX: 3
Title: Secret storage format
Author: Sascha Hanse <[email protected]>, Shubhendu Shekhar (@shekhar-shubhendu)
License: BSD-3-Clause
Discussions-To: https://forum.aeternity.com/t/aex-3-secure-storage-format/3220
Status: Active
Type: Informational
Created: 2019-04-03{
"crypto": {
"secret_type": "ed25519-slip0010-masterkey",
"symmetric_alg": "xsalsa20-poly1305",
"ciphertext":"66891af8a59e83f0c600435a0681413644588f296240ab922ee357fa5ffa857f2709f8753b2b70d35625203adc6bf6e8",
"cipher_params": {
"nonce": "b085597ac8351330b469e9845fc9fb8cefa07e51cb7736a"
},
"kdf": "argon2id",
"kdf_params": {
"memlimit_kib": 65536,
"opslimit": 3,
"salt": "somesaltyness",
"parallelism": 1,
}
},
"id": "b1ff1e48-4e3e-4caf-818e-c8a7c3559d97",
"name": "main",
"version": 1
}tar -xvzf path-to-backup.tar.gz -C datatar -xvzf path-to-backup.tar.gz -C datagit clone https://github.com/aeternity/ae_mdw && cd ae_mdwdocker compose upmkdir -p data/mnesia data/mdw.db logchown -R 1000 data logdocker run -it --name ae_mdw \
-p 4000:4000 \
-p 4001:4001 \
-p 3113:3113 \
-p 3013:3013 \
-p 3014:3014 \
-v ${PWD}/data/mnesia:/home/aeternity/node/data/mnesia \
-v ${PWD}/data/mdw.db:/home/aeternity/node/data/mdw.db \
-v ${PWD}/log:/home/aeternity/ae_mdw/log \
-v ${PWD}/docker/aeternity.yaml:/home/aeternity/.aeternity/aeternity/aeternity.yaml \
aeternity/ae_mdw:latestdocker logs ae_mdwdocker ps -adocker stop ae_mdwdocker start ae_mdwimport { AccountLedgerFactory } from '@aeternity/aepp-sdk';
const accountFactory = new AccountLedgerFactory(transport);const account = await accountFactory.initialize(0);
console.log(account.address); // 'ak_2dA...'
console.log(await account.signTransaction('tx_...')); // 'tx_...' (with signature added)await accountFactory.getAddress(<account index>, true)import { AccountLedger } from '@aeternity/aepp-sdk';
const accountIndex = accountToPersist.index;
const accountAddress = accountToPersist.address;
const restoredAccount = new AccountLedger(transport, accountIndex, accountAddress);import { Node } from '@aeternity/aepp-sdk';
const node = new Node('https://testnet.aeternity.io');
const accounts = await accountFactory.discover(node);
console.log(accounts[0].address); // 'ak_2dA...'aeproject testimport { assert } from "chai";
import { before, describe, afterEach, it } from "mocha";import { utils } from "@aeternity/aeproject";
import * as AeppSdk from "@aeternity/aepp-sdk";
import { Contract, getFileSystem } from "@aeternity/aepp-sdk";before(async () => ...)aeSdk = utils.getSdk(AeppSdk, {});const fileSystem = await getFileSystem(EXAMPLE_CONTRACT_SOURCE);const sourceCode = utils.getContractContent(EXAMPLE_CONTRACT_SOURCE);contract = await Contract.initialize({ ...aeSdk.getContext(), sourceCode, fileSystem });await contract.init();await utils.createSnapshot(aeSdk);afterEach(async () => {
await utils.rollbackSnapshot(aeSdk);
});it("ExampleContract: set and get", async () => {
const set = await contract.set(42, {
onAccount: utils.getDefaultAccounts()[1],
});
assert.equal(set.decodedEvents[0].name, "SetXEvent");
assert.equal(
set.decodedEvents[0].args[0],
utils.getDefaultAccounts()[1].address,
);
assert.equal(set.decodedEvents[0].args[1], 42);
const { decodedResult } = await contract.get();
assert.equal(decodedResult, 42);
});vue create my-projectcd my-projectnpm install @aeternity/aepp-sdk<!-- src/components/HelloWorld.vue -->
<script>
import { AeSdk, Node } from '@aeternity/aepp-sdk'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Loading latest block ...'
}
},
async mounted () {
// Init required Node class
const node = new Node('https://testnet.aeternity.io')
// Init SDK instance with AeSdk class
const aeSdk = new AeSdk({
nodes: [{ name: 'test-net', instance: node }],
})
// Start using the SDK
const height = await aeSdk.getHeight()
this.msg = 'Current Block: ' + height
}
}
</script>npm run serveFollowing commands have been removed and cannot be used anymore. Most of them didn't work properly or aren't used by anyone:
aeproject compatibility (discontinued)
aeproject deploy
deployment isn't supported in aeproject anymore, alternatively use the or the programmatically
aeproject export (discontinued)
aeproject tx-inspector
manual tx inspection is moved to the
aeproject init
added the folder argument to create a new folder for the project initialization
The latest available node and compiler will always be used with starting the testing environment.
Testing is now handled locally in the project using mocha and chai as direct dev dependencies.
@aeternity/aeproject is added itself as dependency and includes some library-functions that can be used in testing.
networks includes network definitions for local development, testnet and mainnet
wallets includes example wallets that are prefunded in local development
utils includes helper functions for testing
getFilesystem(source) to get the filesystem definition for a given contract for deployment
getSdk() get an instance of the SDK for local development
initialized with all prefunded wallets for onAccount to be used calling from different accounts
awaitKeyBlocks(aeSdk, number) await a certain number of key-blocks
createSnapshot(aeSdk) create a snapshot for local testing
rollbackSnapshot(aeSdk) rollback to previously created snapshot in local testing
Upgrade your project
adds new files needed
including new example contract and tests
prompts for files to replaced
docker setup for the node, compiler dev-mode setup should be accepted
example contract and example tests should not be accepted if used in your project for testing
automatically installs needed dependencies and removes unnecessary ones
Adapt Testing Setup (compare your tests with test/exampleTest.js) to
include const { assert } = require('chai'); for assertions
replace NETWORKS import with const { networks } = require('@aeternity/aeproject'); for networks definition
If you want to see a more advanced implementation you can take a look into the repository of the Superhero Wallet
First you need to create a bridge between your extension and the page. This can be done as follows:
Then you need to initialize AeSdkWallet class in your extension and subscribe for new runtime connections.
After the connection is established you can share the wallet details with the application.
The iFrame-based approach works similar to the WebExtension approach except that the connectionProxy in between isn't needed.
You can take a look into the implementation of the following example to see how it works:
Alternatively, aepp can request wallet to share node url it connected to. If agreed, then aepp can connect to the wallet's node.
It can be used to
improve responsiveness by connecting to the exact node that wallet uses;
allow to connect aepps to private/development networks without changing their configuration;
simplify configuration on aepp side.
Note:
The steps above are snippets taken from the full implementation of the Simple æpp
In some cases, aepp developer may need to send a set of transactions at once. The SDK provides optimizations for this scenario but it also requires additional effort by the developer. This guide covers specific cases with suggestions on how to proceed with them to produce a sequence of requests in an efficient way.
Obviously, multiple spends may be done like:
But this isn't the fastest approach, because on each iteration SDK would:
request the sender data (its type and nonce)
verify the transaction (including additional requests)
wait until the transaction is mined
It can be avoided by making spends as:
This way, SDK would make a single request to get info about the sender account and a transaction post request per each item in the spends array.
Additionally, you may want to set gasPrice and fee to have predictable expenses. By default, SDK sets them based on the current network demand.
If you need to transfer a fixed AE amount from the same account to more than 24 accounts, it is more efficient to do it via a smart contract.
Let's define and deploy a contract
after deployment this contract, it can be called as follows
Pros of this approach:
less fees if more than 24 recipients;
faster to execute because it needs to mine fewer transactions.
Cons:
the amount of recipients in one transaction limited by the maximum gas in a block (about 800 recipients);
harder to implement.
One spend tx takes approximately 0.0000167ae. The above contract deployment is 0.0000815ae. The base contract call price is 0.000182ae. Adding an address to the list costs about 0.0000058ae. So, it is more efficient to use a contract if you have more than 24 recipients. And more than 17 recipients if you use a pre-deployed contract.
Basically, the dry-run endpoint of the node is used to run them. Doing requests one by one, like
will make SDK create a new dry-run request for each static call. It may be not efficient because dry-run supports executing multiple transactions at a single request. It can be done by making all calls at once:
With combine flag SDK would put all of them into a single dry-run request. Also, it is necessary to generate increasing nonces on the aepp side to avoid nonce-already-used errors.
This approach has another limitation: by default, dry-run is limited by 6000000 gas. This is enough to execute only 32 plain contract calls. it can be avoided by:
increasing the default gas limit of restricted dry-run endpoint in node configuration
decreasing the gas limit of each static call
using a debug dry-run endpoint instead of the restricted one
The Hyperchain Bridge enables seamless token transfers between the Aeternity blockchain and its Hyperchains. It ensures secure and efficient scalability and interoperability across these networks. By monitoring Aeternity networks, it indexes and stores bridge transactions, facilitating fast data retrieval for the user interface. Additionally, the application empowers users to integrate new Hyperchain networks, extending bridge capabilities to emerging networks.
⚠ Warning: The Hyperchain Bridge is a work in progress and is not production-ready. Use it with caution and be aware of the risk of losing funds.
Install Bun.js: The bridge application uses Bun.js as its JavaScript runtime. Install Bun.js on the machine that will run the application: .
Setup Supabase:
The bridge application relies on a PostgreSQL database hosted on the Supabase platform. The database should include the following tables: actions and networks. Use the SQL definitions below to create the tables:
After setting up the database:
Before running the application, ensure the following steps are completed:
Add the required environment variables to a .env file:
Update the network constants in src/constants/networks.ts with the deployed bridge contract addresses using the bridge operator account.
Ensure the Hyperchain networks are added to the constants with valid attributes. By default, only Mainnet and Testnet networks are included. Additional chains can be specified in this file or added through the network identification flow.
Install Dependencies:
Run the Development Build: Start the development build with hot module replacement:
Run the Production Build: Start the production build:
The application can be debugged using Visual Studio Code with the Bun for Visual Studio Code extension. After installing the extension, use the debug configurations in launch.json to debug the application.
The Hyperchain Bridge leverages the following technologies:
TypeScript: Ensures type safety and improves developer productivity.
Bun.js: A JavaScript runtime powering backend services for efficient handling of bridge transactions, data processing, and routing.
React: Provides a responsive and user-friendly interface.
Sophia: A functional smart contract language for secure and efficient contracts on the Aeternity blockchain.
The project consists of the following key components:
Smart Contracts: Includes HyperchainBridge and AEX9 FungibleToken Sophia contracts for secure transactions, along with unit tests for critical functionality.
Deployment Scripts: Utility scripts for streamlined deployment of smart contracts.
Backend: Listens for new bridge transactions and stores them in a PostgreSQL database.
Frontend: Enables users to interact with the bridge contracts, perform bridge actions, view transaction history, and monitor ongoing transactions.
The bridge workflow involves transferring tokens between Aeternity blockchains using the HyperchainBridge contract:
A user initiates a bridge action by calling the enter_bridge function on the HyperchainBridge contract with the destination network, token, amount, and other parameters.
After the entry transaction is confirmed, the user connects to the destination network specified in the call.
The user retrieves the necessary parameters (e.g., signature, timestamp) from the bridge API backend.
On the destination network, the user calls the
The application allows users to add new networks by providing details such as nodeURL and mdwURL. The workflow is as follows:
Connect to a network not specified in the networks constants.
Fill out the form with the required network details and submit.
The application verifies the network's connectivity and provides feedback.
Fund the bridge operator's account for contract deployment.
This document defines a standard how arbitrary messages or payload can be signed using an aeternity keypair.
Message signing can be used in a wide variety of scenarios. Common use cases include:
Authentication / Login (Proving you are the owner of an address/pubkey)
Authorization (Giving a user priviliges based on the coins / tokens he owns)
Prove Data Integrity
Voting
This technique has been around for a long time, but with the rise in crypto adoption it becomes more accessible to the average user.
DApp / Website / Wallet prepares a signing request containing a message (challenge) and other parameters (see below)
Signing request is sent to the Wallet / Signer containing the Private Key
User can select an identity (= keypair)
Message will be signed
The signature should be encoded in hex: Buffer.from(signature).toString("hex");
The response can contain an array of signatures and publicKeys, which allows a single message to be signed by multiple identities at once.
Serialization and Transport Layer are not part of this propaosal.
The Serialization is being discussed as part of AEX-7 Data Serialization
In order to prevent malicious DApps from sending a seeminly random message to be signed that actually contains data like a valid transaction, we should add a prefix to the message so this can't be exploited.
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
This document describes the requirements and the process of creating releases of aepp-sdk to npmjs.com.
A user wanting to release a new version needs to be a member of the @aeternity
organization on npmjs.com. An existing member with write access needs to invite
them in order to achieve this. In addition, the user needs to activate any means
of 2-factor authentication because the aepp-sdk package is set up to only
accept new versions if a second factor for authentication is in use.
As new releases should only happen from release branch merges to the master
branch of the repository on GitHub followed by a signed tag push, the user also
needs direct write access to on GitHub. Normally, this can be
achieved by first adding them to the and then to the, which gives automatic write access.
As aepp-sdk follows the for development, the release process is modelled after that strategy accordingly, with a few additions.
Branch out from develop to a dedicated release branch denoting the target
version number, e.g. release/v2.3.4.
If Testnet is not yet targeting the latest Node version, but you're "ready to
release", you can do a pre-release for the latest version, tagging the release
as @next on npmjs.
To do this, You can follow the steps listed below, while keeping the next
portion in both CHANGELOG.md and package.json files.
On the release branch, remove the next portion of the version
string in package.json.
Execute npm run release to automatically
bump version number in package.json and package-lock.json (according to)
output changes to
commit package-lock.json and package.json and CHANGELOG.md
Next, git diff the release, branch a release/vX.X.X (where vX.X.X is your
latest release) against master and validate that all changes are covered in
the changelog. You can find more instructions on how to maintain a CHANGELOG here:
masterCreate a pull request against master and have it peer reviewed thoroughly. As
all changes should've been reviewed before when they were merged to develop,
emphasize on security-related changes and small changes pushed to develop
separately.
Once the integration build has successfully completed (with or without additional
fixes), merge (without squash) the branch into master. This allows master
to be comprised of release commits exclusively, so every commit on master corresponds
to exactly one released (or at least, tagged) version of aepp-sdk, respectively.
Update the local working copy to a local tracking branch of master and
update. Optionally, wait for the CI build to finish and execute a lastnpm run test locally.
Important: Because npm publish will use the local files on disk for
releasing, perform a full clean and build in order to release to npmjs.com!
Cleanup - run git clean -ffdx to completely wipe out your workspace of
files not in the repository. This might wipe out files you still need, so
consider a separate clone of the project!
Execute npm run prepublishOnly to generate Documentation for the API and
the SDK codebase, optionally followed by npm pack and investigate the
resulting tarball's contents. This tarball resembles what
users will actually download from npmjs.com once the release is completed!
Execute npm publish
Important: If you are releasing a Pre-Release (AKA next), make sure to
tag the release as next using the command npm publish --tag next.
At this point, the release should already be in npmjs.com. The final step is to also tag the release on GitHub and push the tag, which requires direct write access.
git tag vX.X.X
git push tag vX.X.X
Recommendation: Use signed tags using the -s option to increase community's trust in the project!
developAt this point, it is important to synchronize develop with any changes that
have happened after branching out to the release branch. Create a new branch
called realign/vX.X.X from master (where vX.X.X is your latest release)
and open a Pull Request towards develop and resolve conflicts, if needed.
This concludes the release process and the development cycle.
JavaScript SDK for the revolutionary æternity blockchain, targeting theæternity node implementation. The aepp-sdk is hosted on GitHub.
Introduction
Usage guides:
(æternity naming system)
There are also that you can directly use and play with.
To quickly test all of æternity's blockchain features from your terminal, you can install and use the by running:
npm i -g @aeternity/aepp-cli to globally install the CLI
aecli --help to get a list of possible commands
For advanced use, to get a deeper understanding of the SDK or to contribute to its development, it is advised to read the section.
We keep our up to date.
In order to have AEproject working you must have installed the following:
Note: on windows WSL 2 must be used
This will create the project scaffold with an example contract including tests as well as a sample deployment script inside the specified folder. If no folder is specified the artifacts will be initialized in the current directory.
Further explained in .
This will run a local æternity network in dev-mode (node, compiler and nginx-proxy).
To stop an already spawned local environment use aeproject env --stop
Further explained in .
This will run the tests located in ./test folder. Further explained in .
Run this command to give you all possible commands of aeproject with help and info
Running this command will give you the current installed aeproject version
Installed automatically with each project initialized with aeproject init, otherwise can be installed using npm i @aeternity/aeproject.
Available imports include helper definitions and utils using:
const { utils, wallets, networks } = require("@aeternity/aeproject");Read the contract source from given path, just a wrapper for fs.readFileSync using utf-8 encoding.
Initialize the æternity SDK, pre-configured for optimal use in an AEproject project using æternity node devmode.
Create and wait for n number of key-blocks with the æternity node devmode, checked using the passed aeSdk.
Create a snapshot of the current chain state using the æternity node devmode, using the passed aeSdk.
Rollback to the latest snapshot using the æternity node devmode, using the passed aeSdk.
Rollback to the specified height using the æternity node devmode, using the passed aeSdk.
Get the pre-funded default accounts as MemoryAccount, so they can be used natively using the aeSdk.
List of configured keypairs that are pre-funded using the æternity node devmode as provided in AEproject.
Exposed URLs for commonly used nodeUrl and compilerUrl, per default local devmode and optionally hosted URLs for mainnet and testnet.
AeMdw is a middleware that acts as a caching and reporting layer for the . It responds to queries more efficiently than the node and supports additional queries.
The middleware runs an Aeternity Node alongside it in the same Docker container and BEAM VM instance, so you don't need to run a standalone one. This node can be configured using the aeternity.yaml file or by passing environment variables, just like configuring the node directly.
aeproject init --updatenpm install -g @aeternity/aeprojectconst { networks, utils, wallets } = require("@aeternity/aeproject");await this.aeSdk.connectToWallet(wallet.getConnection(), {
connectNode: true,
name: 'wallet-node',
select: true,
});AEX: 8
Title: Message Signing
Author: Andreas Gassmann (@AndreasGassmann), Alessandro De Carli (@dcale)
License: BSD-3-Clause
Discussions-To: TBD
Status: Draft
Type: Standards Track
Created: 2019-05-13nodejs >= 18
dockernpm install -g @aeternity/aeprojectutils.getContractContent(contractPath);import * as AeppSdk from "@aeternity/aepp-sdk";
utils.getSdk(AeppSdk, {});local testing network is now devmode instead of local
replace defaultWallets import with const { wallets } = require('@aeternity/aeproject'); for prefunded wallets
replace contractUtils import with const { utils } = require('@aeternity/aeproject'); for utils
consider using the new helpers for initializing an instance of the SDK and creating snapshots similar to test/exampleTest.js
1 000
0.0107ae
100 000
1.07ae
10 000 000
107ae
SUPABASE_URL and SUPABASE_ANON_KEY from the Supabase dashboard and add them to the .env file.Disable Row Level Security (RLS) for these tables.
Add Bridge Operator Private Key:
Add a trusted account's private key to the .env file under the BRIDGE_OWNER_PK variable.
Note: Private keys must be in the old format (128 characters long, base64 string).
Add Networks:
Add your Hyperchain networks to src/constants/networks.ts with the appropriate settings (leave bridge contract addresses empty and fill them once deploy step is done)
Deploy Bridge Contracts: Deploy the HyperchainBridge contracts for each network using deploy scripts:
Note: Before running the deploy command, make sure corresponding network has been added to src/constants/networks.ts and BRIDGE_OWNER_PK environment variable is set.
Supabase: An open-source Firebase alternative for managing PostgreSQL databases.
Docker: Simplifies deployment and management by containerizing components for consistency across environments.
aepp-js-sdk: A JavaScript SDK for interacting with the Aeternity blockchain.
Aeternity Middleware: Indexes and provides access to blockchain data for efficient querying and retrieval.
exit_bridgeThe bridge contract verifies the request and completes the bridge action.
Complete the process by clicking the "Finish" button after funding the account.
User is either being redirected to the provided callback URL, or the signed message is displayed (eg. QR code)
utils.awaitKeyBlocks(aeSdk, n);To properly configure your middleware for Aeternity Hyperchains, start by generating the necessary configuration files from init.hyperchains.ae.
Access the Hyperchains Initialization Tool:
Visit init.hyperchains.ae in your web browser.
Input Node Information and Generate the Configuration Files:
Click on the 'Get Started' button.
Follow the on-screen instructions to enter details about your Hyperchain node and select a pinning chain.
Download the init.yaml file.
Follow the 'Next Steps' to generate additional configuration files:
aeternity.yaml
${NAME}_accounts.json
${NAME}_contracts.json
Once you have the necessary configuration files, you can run the middleware using Docker:
Make sure you have enough account balance on the pinning chain for all of the accounts
The command assumes the configuration files are in the ${NAME}/nodeConfig directory in your current working directory, where ${NAME} is the name of your Hyperchain.
This command uses the middleware image, which differs from the node image.
You can pass the -d flag to run the container in detached mode.
To ensure data persistence across container restarts:
Create the Data Directory (if it doesn’t already exist):
In your working directory, create a data folder to store the node and middleware databases:
Run the Docker Container with Volumes:
-v ${PWD}/data/mnesia:/home/aeternity/node/data/mnesia: Persists the node database.
-v ${PWD}/data/mdw.db:/home/aeternity/node/data/mdw.db: Persists the middleware database.
With this setup, the middleware will retain its state even after the container is stopped or restarted.
You can also pass the -d flag to run the container in detached mode.
Once the container is running, you can access the middleware at http://localhost:4000 and the node at http://localhost:3013.
To check the logs, run the following command:
To check the status of the container, run the following command:
To stop the container, run the following command:
To restart the container, run the following command:
You can use the same configuration options available for the Aeternity node to further customize your setup. For more information on available options and how to modify the aeternity.yaml file, refer to the Aeternity node documentation.
Let's assume we got a JWT as string. Firstly we need to ensure that it has the right format.
After that we can pass JWT to other SDK's methods, for example to get JWT payload and signer address
in case JWT has the signer public key included in "sub_jwk".
unpackJwt will also check the JWT signature in this case.
Alternatively, if "sub_jwk" is not included then we can provide signer address to unpackJwt.
If we need to a get signer address based on JWT payload then we need to unpack it without checking
the signature. Don't forget to check signature after that using verifyJwt.
import { AccountMemory, signJwt } from '@aeternity/aepp-sdk';
const account = AccountMemory.generate();
const payload = { test: 'data' };
const jwt = await signJwt(payload, account);const jwt = await signJwt({ test: 'data', sub_jwk: undefined }, account);for (const { address, amount } of spends) {
await aeSdk.spend(amount, address);
}const base = (await aeSdk.api.getAccountNextNonce(aeSdk.address)).nextNonce;
await Promise.all(
spends.map(({ amount, address }, idx) =>
aeSdk.spend(amount, address, { nonce: base + idx, verify: false, waitMined: false }),
),
);include "List.aes"
contract MultipleSpends =
payable stateful entrypoint spend(addresses : list(address), amount: int) =
List.foreach(addresses, (address) => Chain.spend(address, amount))await contract.spend(addresses, amount, { amount: amount * addresses.length });const results = [];
for (const d of data) {
results.push(await contract.foo(d));
}const base = (await aeSdk.api.getAccountNextNonce(aeSdk.address)).nextNonce;
const results = await Promise.all(
data.map((d, idx) => contract.foo(d, { nonce: base + idx, combine: true })),
);bun deploy-bridge --network $NETWORK_ID# Bridge operator account's private key
BRIDGE_OWNER_PK=
# Bridge user account's private key (for testing purposes)
BRIDGE_USER_PK=
# Supabase URL and Anonymous key from the Supabase dashboard
SUPABASE_URL=
SUPABASE_ANON_KEY=bun installbun devbun start
const signingRequest = {
message: string // Message to be signed
publicKey?: string // OPTIONAL: allows wallet to pre-select signing identity
ttl?: string // OPTIONAL: Blockheight or timestamp to prevent replay attacks
origin?: string // OPTIONAL: eg. aeternity.com
callbackURL?: string // OPTIONAL: eg. https://aeternity.com/?signedMessage=
}
const signingResponse = {
message: string // Message to be signed
signature: string[] // Signature of the message
publicKey: string[] // allows wallet to pre-select signing identity
ttl?: string // Blockheight or timestamp to prevent replay attacks
origin?: string // OPTIONAL: eg. aeternity.com
}// TODO: How do we fit TTL and hostname into the message?
import * as sodium from "libsodium-wrappers";
const signMessage = async (
message: string,
privateKey: Buffer
): Promise<string> => {
await sodium.ready;
const signature = sodium.crypto_sign_detached(
sodium.from_string(message),
privateKey
);
const hexSignature = Buffer.from(signature).toString("hex");
return hexSignature;
};import * as sodium from "libsodium-wrappers";
const verifyMessage = async (
message: string,
hexSignature: string,
publicKey: Buffer
): Promise<boolean> => {
await sodium.ready;
const signature = new Uint8Array(Buffer.from(hexSignature, "hex"));
const isValidSignature = sodium.crypto_sign_verify_detached(
signature,
message,
publicKey
);
return isValidSignature;
};// risk monitor path sick coconut cube ecology brief table adapt evil oven
const privateKey = Buffer.from(
"7f192bc4b5d6e828b6aeed3958f791f2d4d0f69e9b34a164df41f0f325c48ceb7d29631b2cc36eb4931a2ebe8b0a1bd95a29825ec21430b9e472146c851d2cfd",
"hex"
);
const publicKey = Buffer.from(
"7d29631b2cc36eb4931a2ebe8b0a1bd95a29825ec21430b9e472146c851d2cfd",
"hex"
);
const message = "This message will be signed.";
const signature = await signMessage(message, publicKey);
// e650110d48b42cf07f577b886f852b36945da4b175cb1629528b705799d1565799802c7fbb7d07685f8b22185db7ce5bd03f7e0e754b904b80b4fe4fda4f1802
const isValidSignature = await verifyMessage(message, signature, publicKey);
// trueaeproject init [folder]aeproject envaeproject testaeproject helpaeproject --versionutils.createSnapshot(aeSdk);utils.rollbackSnapshot(aeSdk);utils.rollbackHeight(aeSdk, height);utils.getDefaultAccounts();mkdir -p ${PWD}/datadocker run -it --name ae_mdw_${NAME} \
-p 4000:4000 \
-p 4001:4001 \
-p 3113:3113 \
-p 3013:3013 \
-p 3014:3014 \
-v ${PWD}/${NAME}/nodeConfig/aeternity.yaml:/home/aeternity/.aeternity/aeternity/aeternity.yaml \
-v ${PWD}/${NAME}/nodeConfig/${NAME}_accounts.json:/home/aeternity/node/data/aecore/${NAME}_accounts.json \
-v ${PWD}/${NAME}/nodeConfig/${NAME}_contracts.json:/home/aeternity/node/data/aecore/${NAME}_contracts.json \
aeternity/ae_mdwdocker run -it --name ae_mdw_${NAME} \
-p 4000:4000 \
-p 4001:4001 \
-p 3113:3113 \
-p 3013:3013 \
-p 3014:3014 \
-v ${PWD}/${NAME}/nodeConfig/aeternity.yaml:/home/aeternity/.aeternity/aeternity/aeternity.yaml \
-v ${PWD}/${NAME}/nodeConfig/${NAME}_accounts.json:/home/aeternity/node/data/mnesia/${NAME}_accounts.json \
-v ${PWD}/${NAME}/nodeConfig/${NAME}_contracts.json:/home/aeternity/node/data/mnesia/${NAME}_contracts.json \
-v ${PWD}/data/mnesia:/home/aeternity/node/data/mnesia \
-v ${PWD}/data/mdw.db:/home/aeternity/node/data/mdw.db \
aeternity/ae_mdwdocker logs ae_mdw_${NAME}docker ps -adocker stop ae_mdw_${NAME}docker start ae_mdw_${NAME}const payload = {
test: 'data',
sub_jwk: undefined,
address: 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E',
};
const jwt = await signJwt(payload, account);import { isJwt, ensureJwt } from '@aeternity/aepp-sdk';
if (!isJwt(jwt)) throw new Error('Invalid JWT');
// alternatively,
ensureJwt(jwt);import { unpackJwt } from '@aeternity/aepp-sdk';
const { payload, signer } = unpackJwt(jwt);
console.log(payload); // { test: 'data', sub_jwk: { ... } }
console.log(signer); // 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E'const knownSigner = 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E';
const { payload, signer } = unpackJwt(jwt, knownSigner);
console.log(payload); // { test: 'data' }
console.log(signer); // 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E'import { verifyJwt } from '@aeternity/aepp-sdk';
const { payload, signer } = unpackJwt(jwt);
console.log(payload); // { address: 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E' }
console.log(signer); // undefined
if (!verifyJwt(jwt, payload.address)) throw new Error('JWT signature is invalid');PayingForTx (Meta-Transactions)
Wallet Interaction
merge the release please PR
as @aeternity/aeproject has a dependency on itself as library, the CI run before publishing to npm after merging might fail
build locally and publish
checkout latest origin/main including the merged release please PR, ensure no local changes
publish to npm using npm publish (does automatically clean-build, may require login if not already)
A short (~200 word) description of the technical issue being addressed.
The following describes standard functions a token contract and contract working with specified token can implement to prevent accidentally sends of tokens to contracts and make token transactions behave like ether transactions.
Moreover, where designing the tokens we looked carfully at compliance work and wanted to make it easier for integrating compliance workflow. With this respect token transactions contains data field to be used freely to pass additional information (eg: reference) from a holder or an operator.
The goal is to make this specification useful with Native Tokens.
The token contract MUST implement the above interface. The implementation MUST follow the specifications described below.
An operator is an address which is allowed to send and burn tokens on behalf of some holder.
NOTE: A holder MAY have multiple operators at the same time.
A default operator is an implicitly authorized operator for all holders. The rules below apply to default operators:
The token contract MUST define default operators at creation time. The default operators set MAY be empty.
The token contract MUST NOT add or remove default operators after contract instantiation.
AuthorizedOperator events MUST NOT be emitted when defining default operators.
A holder MUST be allowed to revoke a default operator (unless the holder is the default operator).
The following rules apply to any operator:
An address MUST always be an operator for itself. Hence an address MUST NOT ever be revoked as its own operator.
NOTE: A holder MAY authorize an already authorized operator. An AuthorizedOperator MUST be emitted each time.
NOTE: A holder MAY revoke an already revoked operator. A RevokedOperator MUST be emitted each time.
meta() : meta_infReturns information about token as a meta_inf record.
total_supply() : intReturns: Total supply of tokens currently in circulation.
NOTE: MUST be equal to the sum of the balances of all addresses—as returned by the balance_of function.
NOTE: MUST be equal to the sum of all the minted tokens as defined in all the Minted events minus the sum of all the burned tokens as defined in all the Burned events.
balance_of(holder: address) : option(int)Get the balance of the holder account. If the account is not registered (didn't use any token) then it MUST return None. Oherwise it MUST return non negative integer.
default_operators() : list(address)List of addresses of all the default operators.
is_operator_for(operator: address, holder: address) : boolMUST return true if the operator address is an operator for the holder. Otherwise MUST return false.
authorize_operator(operator: address)Set a third party operator address as an operator of Call.caller to transfer and burn tokens on its behalf.
NOTE: The holder (Call.caller) is always an operator for itself. This right SHALL NOT be revoked.
revoke_operator(operator: address)Remove the right of the operator address to be an operator for Call.caller and to send and burn tokens on its behalf.
NOTE: The holder (Call.caller) is always an operator for itself. This right SHALL NOT be revoked.
transfer(to: address, amount: int, data: string)Send the amount of tokens from the Call.caller (holder) to the to address. data an information provided by the holder.
In the Transfer event, the operator and the holder MUST both be Call.caller.
op_transfer(from: address, to: address, amount: int, data: string, op_data: string)Send the amount of tokens on behalf of the from address to the to address.
Reminder: If the operator address (Call.caller) is not an authorized operator of the from address, then the send process MUST abort.
burn(amount: int, data: string)Burn the amount of tokens from the Call.caller address.
In the Burned event, the operator and the holder MUST both be Call.caller.
op_burn(from: address, amount: int, data: string, op_data: string)Burn the amount of tokens on behalf of the from address.
Reminder: If the operator address (Call.caller) is not an authorized operator of the from address, then the burn process MUST abort.
AuthorizedOperator eventIndicates the authorization of operator as an _operator for holder.
The token contract MUST emit an AuthorizedOperator event with the correct values when a holder authorizes an address as its operator (even if it's already authorized or it's defined as a default oprator).
RevokeOperator eventIndicates the revokation of operator as an _operator for holder.
The token contract MUST emit an RevokeOperator event with the correct values when a holder revokes an address as its operator (even if it's already revoked or it's defined as a default oprator).
tokensToTransfer hookThe tokensToSend hook notifies of any request to decrement the balance (transfer and burn) for a given holder. Any address (regular or contract) wishing to be notified of token debits from their address MAY register for receiving this hooks
Interface:
Notify a request to transfer or burn (if to is 0x0) an amount tokens from the from address to the to address by the operator address. The holder MAY block a send or burn process by aborting. (I.e., reject the withdrawal of tokens from its account.)
to MUST be 0x0 for a burn.
amount MUST be the number of tokens the holder sent or burned. MUST be non negative integer (0 is possible).
data MUST contain the extra information (if any) provided to the send or the burn process.
NOTE: A regular address MAY register a different address—the address of a contract—implementing the interface on its behalf. A contract MAY register either its address or the address of another contract but said address MUST implement the interface on its behalf.
TODO
tokensReceived hookThe tokensToSend hook notifies of any request to increment the balance (transfer and mint) for a given holder. Any address (regular or contract) wishing to be notified of token credits from their address MAY register for receiving this hooks
Interface:
Notify a send or mint (if from is 0x0) of amount tokens from the from address to the to address by the operator address.
TOOD
This token provides a foundation for compliance tokens. Because of the need for refence field (data), and introduction of operators (often required in the industry and interoperability with other smart contracts), the interface is not backward compatible with proposed AEX-9 simple token standard.
TODO
register token interfaces Probably we don't need it because Sophia is strong static typed language.
For every transaction it is possible to provide an options object with one or multiple of the following attributes to the respective function that builds and broadcasts the transaction.
Some of these are common and can be provided for each transaction type. Others are transaction specific and only relevant for a specific tx-type.
The options object can be optionally passed to the respective function behind the last parameter, example:
Note:
Without the options object the sender would be some other account selected in the instance of AeSdk and the recipient would receive 1 aetto instead of 1 AE.
These options are common and can be provided to every tx-type:
onAccount (default: the first account defined in the account array of the SDK instance)
You can specify the account that should be used to sign a transaction.
Note:
The following options are sepcific for each tx-type.
amount (default: 0)
To be used for providing aettos (or AE with respective denomination) to a contract related transaction.
denomination
nameFee (default: calculated based on the length of the name)
The fee in aettos that will be payed to claim the name.
For bids in an auction you need to explicitely calculate the required nameFee based on the last bid
clientTtl (default: 3600, one hour)
This option is an indicator for indexing tools to know how long (in seconds) they could or should cache the name information.
nameTtl (default: 180000)
queryFee (default: 0)
The fee in aettos that the oracle requests in order to provide a response.
oracleTtlValue (default: 500
queryFee (default: 0)
The fee in aettos that will be payed to the oracle.
queryTtlValue (default: 10
denomination (default: aettos)
You can specify the denomination of the amount that will be provided to the contract related transaction.
As æpp developer, it is reasonable to estimate the gas consumption for a contract call using the dry-run feature of the node once and provide a specific offset (e.g. multiplied by 1.5 or 2) as default in the æpp to ensure that contract calls are mined. Depending on the logic of the contract the gas consumption of a specific contract call can vary and therefore you should monitor the gas consumption and increase the default for the respective contract call accordingly over time.
By default, SDK estimates gasLimit using dry-run endpoint. This means an extra request that makes contract iterations slower, but it is more developer friendly (support of heavy requests without adjustments, and verbose error messages).
This proposal has been withdrawn because of overlap with AEX-2. A new AEX will be created at a later stage that is compatible with AEX-2 and focuses on the transport layer only.
This document defines a serialization standard to facilitate data transfer between DApps, Wallets and devices.
Data needs to be transferred between different apps and devices. Those apps may or may not be located on the same device. The transport layer used by those apps is unknown and will not be part of this AEX. However, since many of the transport layers can only transfer a limited amount of data (eg. QR codes, Bluetooth, NFC, URLs), the data should always be encoded in a standardized and space efficient way.
The data serialization protocol in this AEX aims to provide a solution with the following goals in mind:
Easy understand and implement
Space efficient
Make sure to not transmit redundant information, send only what is necessary
Allow airgapped Apps such as AirGap Vault to properly display all necessary information when signing a transaction
Basic description of .
We use RLP for the following reasons:
RLP is being used throughout the crypto space, with Aeternity adapting RLP as well after Ethereum
It is able to serialize and deserialize data in a predictable way
Easy to understand and implement
Encoded Data as Binary, size-efficient
The resulting string will be encoded with base58 because it is URL-safe, which is important for some transport layers.
The different transport layers are not part of this AEX, but we should keep the following transport layers in mind:
QR Codes
Deeplinking / URLs
Clipboard copy/paste
Push Notifications
This example would result in the following, base58 encoded, string:
The payload can be another RLP array, depending on the MessageType.
While the transport layer is not part of this AEX, we have to think about how we can split up a request if it doesn't fit into one "packet", depending on the transport layer.
The protocol should offer a "chunking" functionality where the user can pass a maximum size per chunk.
This standard allows for new message types to be added by every application. But ideally, we should provide a set of commonly used types so they can be re-used between different apps. Some of the default types could be:
MetadataRequest (Information about the app, like name, version, url)
MetadataResponse
AccountShareRequest
AccountShareResponse
The numbers 0 to 999 of the message type are reserved for official/default messages, other numbers can be used for user defined types (for which they have to provide their own serialization / deserialization methods.)
There are 2 different kinds of versions:
Protocol Version: Defines the version of the sync protocol. If this does not match, then the request most likely cannot be processed.
Message Version: This version is specific to a currency and message type. This allows us to add additional functionality (new message types), without breaking existing (unchanged) message types.
Looking at the MessageVersion, MessageType and ProtcolIdentifier together, we can determine if we can handle that specific request or not.
We use RLP over more commonly used standards like JSON or XML because it's more space efficient.
We encode the resulting string with base58 so it will be compatible with URLs.
In some situations it makes sense to include context to a request, which is then also sent back with the response.
This could for example be used to attach IDs to requests to track their state.
The context should be used with caution because:
It will increase the size of both the request and response QR.
You cannot be sure that the response is received on the same device that created the original request. (eg. prepare in chrome extension > signing on offline device > broadcasting with mobile phone)
This context will be added as an optional parameter to all the default message types.
There is currently one working implementation inside the , which uses this scheme to facilitate communication between online and offline devices.
This guide shows you how to perform all the operations that you need within the lifecycle of oracles using the SDK.
Let's register an oracle that responds with the temperature of the city that is included in the query.
Firstly, you need to create an instance of Oracle class. This class requires an account that would be used to sign operations on behalf of the oracle. So one account can host only one oracle, and this oracle address would be the same as the corresponding account address except for a different prefix (ok_ instead of ak_). This means that it's not possible to manage multiple oracles using the same account.
To register an oracle on-chain you need to provide a queryFormat and a responseFormat to the register function of Oracle class. In addition to the common transaction options you can provide the oracle specific options queryFee and oracleTtlValue, see .
Note:
By default the oracle will exist for the next 500 key blocks.
If you intend to keep your oracle running longer you should increase the oracleTtlValue and/or set up a service that automatically extends the TTL before it expires.
After the oracle has been registered and as long as it isn't expired, everybody that knows the oracleId can query it.
Note:
Again, take a look into the to see what (other) options you can provide.
Alternatively, you can post query and poll for response using separate methods from below.
To post a query without waiting for a response do the below.
Now you have query ID that can be used to poll for the response:
Typically, the oracle itself polls for its own queries and responds as soon as possible:
This way, the oracle would respond with the temperature in a requested city. It needs to be done before the query's TTL expires.
Note:
Of course, the oracle itself would either use an API to get the current temperature for a certain city or ideally directly communicate with measuring devices located in that specific city.
As far as Oracle class is bound to a specific account provided while creation, it is not necessary to pass the onAccount option.
The above is the simplest way to respond to queries, though you can manually subscribe for new queries and respond to them.
To subscribe to new queries without responding to them:
If the oracle recognizes that it has been queried it can respond to the query.
As mentioned above an Oracle has a certain TTL that can be specified when registering it. You might want to extend the TTL of the oracle before it expires. You can do that as follows:
Both Oracle and OracleClient have methods to get their state from the node.
Oracle:getState, OracleClient:getState returns the same value as Node:getOracleByPubkey, but without arguments (it uses the oracle address provided in the constructor).
Oracle:getQuery, OracleClient:getQuery corresponds to Node:getOracleQueryByPubkeyAndQueryId, adding decodedQuery, decodedResponse based on the oracle type. In the same way Oracle:getQueries, OracleClient:getQueries corresponds to Node:getOracleQueriesByPubkey.
NodeJS example that registers an oracle, extends it if required and responds to queries automatically.
application that registers an oracle to check the presence of an AE address at a specific page
The Javascript SDK wraps the æternity API exposed byNode's Swagger file. It aims to abstract the API, while still providing low-level access to it's endpoints, when necessary.
It uses the following Javascript technologies and principles:
JavaScript the Good Parts (because Crockford is always right)
, using export and import
using ES7 syntax, where applicable
Statelessness wherever possible
and the
Loose coupling of modules to enable
Convention over configuration
"Easy things should be easy, and hard things should be possible." --
Support for
module access, enabling tree-shaking
direct use in node scripts through bundling
direct use in browser <script> tags through bundling
aepp-sdk is transpiled to EcmaScript 5 through , using and is expected to work in any sufficiently new version of or modern web browser.
Clone the application
Make sure your editor/IDE can read and use the .editorconfig file
Start hacking (and don't forget to add for whatever you'll be building).
Apart from documenting features and code, there is also documentation automatically generated using for documenting TS files and for documenting examples and code partials.
aepp-sdk is built using npm. In order to build a production version, launch the build command.
Note: If you experience errors during the building, you might need to install build tools for your OS.
Windows: Windows Build Tools
Ubuntu / Debian: Build Essential
Mac
Download from AppStore, then run
To test, launch the test command. This will run 's tests locally.
This repository also includes a docker-compose file, to allow you to run your own æternity node locally. If you want to do so, from the root of the project:
Run docker-compose up node
Congrats! you're now running your own æternity node locally.
The WebPack compilation provides two different build artifacts in dist/, one
for Node.js and one for browsers. When referencing aepp-sdk through any modern
build tooling, it should pick the right one automatically through the entry
points defined in package.json.
In order to add a local development version of aepp-sdk to a project, npm link can be used.
<script> include via CDNIn case you're not using any JS bundling/compilation technique, the SDK can also be loaded with the traditional <script> tag, as follows:
...where VERSION is the version number of the SDK you want to use (eg. 14.1.0).
<script> tagThe bundle will assign the SDK to a global variable called Aeternity that makes all functionalities of the SDK accessible.
Usage:
To install a Pre-Release (latest beta or alpha version) you have to install the package appending the @next tag reference.
You can also install a version coming from a specific branch. In this case you would install the SDK version of the develop branch.
To work properly, sdk requires to enable allowSyntheticDefaultImports flag and register folder
that contains type definitions for third-party packages sdk depends on.
This may be done in tsconfig.json:
Ensure that you have strictFunctionTypes option not enabled (as it is in VS code and ts-node by default), otherwise some of SDK types won't work correctly (see ).
In some environments, TypeScript fails to check types of sdk's dependencies (@metamask/json-rpc-engine, @ledgerhq/hw-transport), if so you may find useful.
SDK checks are not working correctly because CLI picks both ESM and CJS versions of autorest
dependencies. To fix this, you need to specify aliases in vue.config.js.
Reactivity in Vue@3 Proxy class. Proxy is with private fields of ES classes. AeSdk, Contract and AccountMemory classes uses private fields, so if you make an instance of these classes reactive then the app may fail with
TypeError: attempted to get private field on non-instance
AeSdk and Contract classes doesn’t have a state intended to be tracked using reactivity. Therefore to solve this issue we suggest to avoid making their instances reactive using Vue's integrated utility: . The idea is to make reactive only the instance value, to don't make it reactive in deep.
Alternatively, can unwrap the proxy object, returning an unmodified instance and allowing access to its private properties by its methods. It can be useful if you need a reactive array of AccountMemory.
You can find both approaches used in the .
If you don't need to include specific functionality into your application and just want to use or play around with features the SDK provides you can make use of the and follow the instructions mentioned there.
npm install -g @aeternity/aeprojectAEX: 11
Title: Fungible Token Standard
Author: Robert Zaremba (@robert-zaremba)
License: BSD-3-Clause
Discussions-To: <URL>
Status: Draft
Type: Interface
Created: 2019-09-19const sender = 'ak_...';
const recipient = 'ak_...';
const options = { onAccount: sender, denomination: 'ae' }; // optional options object
// aeSdk is an instance of the AeSdk class
await aeSdk.spend(1, recipient, options); // amount, recipient and (optional) optionsAEX: 7
Title: Data Serialization
Author: Andreas Gassmann (@AndreasGassmann), Alessandro De Carli (@dcale)
License: BSD-3-Clause
Discussions-To: TBD
Status: Withdrawn
Type: Standards Track
Created: 2019-05-13nonce (default: obtain nonce of the account via node API)
The default behavior might cause problems if you perform many transactions in a short period of time.
You might want to implement your own nonce management and provide the nonce "manually".
2 different strategies to use in order to determine the next nonce, See option strategy to learn more.
strategy (default: max)
The strategy to obtain next nonce for an account via node API
If set to max, then the greatest nonce seen in the account or currently in the transaction pool is incremented with 1 and returned.
If the strategy is set to continuity, then transactions in the mempool are checked if there are gaps - missing nonces that prevent transactions with greater nonces to get included
ttl (default: 0 if buildTx used, current height + 3 otherwise)
Should be set if you want the transaction to be only valid until a certain block height is reached.
fee (default: calculated for each tx-type, based on network demand)
The minimum fee is dependent on the tx-type.
You can provide a higher fee to additionally reward the miners.
innerTx (default: false)
Should be used for signing an inner transaction that will be wrapped in a PayingForTx.
verify (default: false)
If set to true the transaction will be verified prior to broadcasting it.
waitMined (default: true)
Wait for transactions to be mined.
You can get the tx object that contains the tx-hash immediately by setting to false and should implement your own logic to watch for mined transactions.
aettosYou can specify the denomination of the amount that will be provided to the contract related transaction.
gasLimit
Maximum amount of gas to be consumed by the transaction. Learn more on How to estimate gas?
gasPrice (default: based on network demand, minimum: 1e9)
To increase chances to get your transaction included quickly you can use a higher gasPrice.
This option tells the protocol the relative TTL based on the current block height.
180000 is the maximum possible value
The TTL of the oracle that defines its expiration.
oracleTtlType (default: ORACLE_TTL_TYPES.delta)
ORACLE_TTL_TYPES.delta: TTL value treated relative to a current block height
ORACLE_TTL_TYPES.block: TTL value treated as absolute block height
The TTL of the query that defines its expiration. The oracle needs to respond before the queryTtl expires.
queryTtlType (default: ORACLE_TTL_TYPES.delta)
ORACLE_TTL_TYPES.delta: TTL value treated relative to a current block height
ORACLE_TTL_TYPES.block: TTL value treated as absolute block height
responseTtlValue (default 10)
The TTL of the response that defines its expiration. The response of the oracle will be garbage collected after its expiration.
responseTtlType (default ORACLE_TTL_TYPES.delta)
ORACLE_TTL_TYPES.delta: TTL value treated relative to a current block height
ORACLE_TTL_TYPES.block: TTL value treated as absolute block height
A holder MUST be allowed to re-authorize a previously revoked default operator.
op_data MUST contain the extra information provided by the address which triggered the decrease of the balance (if any).
Webhooks
Bluetooth
NFC
TransactionSignResponse
MessageSignRequest
MessageSignResponse
bundling through webpack
contract AEX11Token {
record meta_info = { name : string
symbol : string
decimals : int}
entrypoint meta(): meta_info
entrypoint total_supply() external : int
entrypoint balance_of(holder: address) : option(int)
external default_operators() : list(address)
external is_operator_for(operator: address, holder: address) : bool
stateful external authorize_operator(operator: address)
stateful external revoke_operator(operator: address)
entrypoint stateful transfer(to: address, amount: int, data: string)
entrypoint stateful op_transfer(from: address, to: address, amount: int, data: string, op_data: string)
entrypoint stateful burn(amount: int, data: string)
entrypoint stateful op_burn(from: address, amount: int, data: string, op_data: string)
datetype event =
// operator, from, to, amount ,data, op_data
Transfer(indexed address, // operator
indexed address, // from
address, // to
int, // amount
string, // data
string) // op_data
| Mint(indexed address, // operator
indexed address, // to
int, // amount
string, // data
string) // op_data
| Burned(indexed address, // operator
indexed address, // from
int, // amount
string, // data
string) // op_data
| AuthorizedOperator(indexed address, // operator
indexed address) // holder
| RevokedOperator(indexed address, // oprator
indexed address) // holder
}stateful entrypoint tokensToTransfer(
operator: address,
from: address,
to: address,
amount: int,
data: string,
op_data: string
)function tokensReceived(
operator: address,
from: address,
to: address,
amount: int,
data: string,
op_data: string
)[
1, // ProtocolVersion
1, // SerializationType: Full or Chunked
[
// Array of Messages
[
1, // MessageVersion
2, // MessageType
"ae", // Protocol
"payload" // Payload depending on the MessageType
],
[
1, // MessageVersion
3, // MessageType
"ae", // Protocol
"payload" // Payload depending on the MessageType
]
]
];2hDLW1FiwvQs5ofPUgi5CgAJKDWiNncCoETXf7DGdkkDmrhN3zfunction serialize(rlp, maxChunkSizeInByte): string[] {}
function deserialize(chunks): any[] {}
const chunks = serialize(rlp, 1024);
const deserializedRlp = deserialize(chunks);[
1, // Protocol Version
1, // SerializationType: Full or Chunked
[
1, // Current Page
4, // Number of pages
"payload of current chunk as string"
]
];import { AeSdk, Oracle } from '@aeternity/aepp-sdk'
// init an instance of the SDK using the AeSdk class
const aeSdk = new AeSdk({ ... })
// it should be an instance of AccountBase with non-zero balance
const oracleAccount = new AccountMemory(...)
const oracle = new Oracle(oracleAccount, aeSdk.getContext())// set TTL with a delta of 1000 blocks
const oracleTtlOptions = { oracleTtlType: ORACLE_TTL_TYPES.delta, oracleTtlValue: 1000 };
// OR set a specific block height to expire
const oracleTtlOptions = { oracleTtlType: ORACLE_TTL_TYPES.block, oracleTtlValue: 555555 };
// queryFee is optional and defaults to 0
// oracleTtlValue is optional and defaults to 500
// oracleTtlType is optional and defaults to ORACLE_TTL_TYPES.delta
const options = { queryFee: 1337, ...oracleTtlOptions };
// the first argument is the queryFormat and the second is the responseFormat
await oracle.register('{"city": "str"}', '{"temperature": "int"}', options);import { OracleClient } from '@aeternity/aepp-sdk';
const oracleId = 'ok_...';
const options = {
queryFee: 1337, // should cover the requested fee of the oracle and defaults to 0
queryTtlType: ORACLE_TTL_TYPES.delta, // optional and defaults to ORACLE_TTL_TYPES.delta
queryTtlValue: 20, // optional and defaults to 10
responseTtlType: ORACLE_TTL_TYPES.delta, // optional and defaults to ORACLE_TTL_TYPES.delta
responseTtlValue: 50, // optional and defaults to 10
interval: 6000, // response polling interval
};
// to query an oracle you need to instantiate the OracleClient object first
const oracleClient = new OracleClient(oracleId, aeSdk.getContext());
const response = await oracleClient.query('{"city": "Berlin"}', options);
console.log('Decoded oracle response', response);const { queryId } = await oracleClient.postQuery('{"city": "Berlin"}'); // oq_...
console.log('Oracle query ID', queryId);const response = await oracleClient.pollForResponse(queryId);
console.log('Decoded oracle response', response);const stopHandling = await oracle.handleQueries(
(query) => {
if (query.decodedQuery === '{"city": "Berlin"}') {
return '{"temperature": 27.5}';
}
return '{"error": "Unknown request"}';
},
{ interval: 1000 }, // polling interval in milliseconds
);
stopHandling();const stopPolling = await oracle.pollQueries(
(query) => {
console.log(query); // log a new query
},
{ interval: 1000 }, // polling interval in milliseconds
);
stopPolling();const oracleId = 'ok_...';
const queryId = 'oq_...';
const options = { onAccount: 'ak_...' }; // only the account of the oracle can respond to the query
await oracle.respondToQuery(queryId, '{"temperature": 27.5}', options);// extend TTL by additional 500 blocks (based on current expiration height of the oracle)
const options = { oracleTtlType: ORACLE_TTL_TYPES.delta, oracleTtlValue: 500 };
// using the Oracle instance
await oracle.extend(options);#generate examples and api documentation
npm run docs:examples && npm run docs:apinpm install
npm run buildnpm install -g windows-build-toolssudo apt-get update
sudo apt-get install build-essentialxcode-select --installnpx webpack --env REPORTnpm test<script src="https://unpkg.com/@aeternity/aepp-sdk/dist/aepp-sdk.browser-script.cjs"></script><script src="https://unpkg.com/@aeternity/aepp-sdk@VERSION/dist/aepp-sdk.browser-script.cjs"></script><!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<!-- include latest SDK version -->
<script src="https://unpkg.com/@aeternity/aepp-sdk/dist/aepp-sdk.browser-script.cjs"></script>
<script type="text/javascript">
const { AeSdk, Node } = Aeternity;
const node = new Node('https://testnet.aeternity.io');
const aeSdk = new AeSdk({
nodes: [{ name: 'testnet', instance: node }],
});
aeSdk.getHeight().then((height) => {
console.log('Current Block Height:' + height);
});
</script>
</body>
</html>npm i @aeternity/aepp-sdknpm i @aeternity/aepp-sdk@nextnpm i github:aeternity/aepp-sdk-js#develop{
"compilerOptions": {
...
+ "typeRoots": [
+ "node_modules/@types",
+ "node_modules/@aeternity/aepp-sdk/src/typings"
+ ],
+ "allowSyntheticDefaultImports": true
}
}module.exports = {
configureWebpack: {
resolve: {
alias: {
+ '@azure/core-client': '@azure/core-client/dist-esm/src/index.js',
+ '@azure/core-rest-pipeline': '@azure/core-rest-pipeline/dist-esm/src/index.js',
},
},
},
};Currently, if a wallet wants to talk to another wallet then each wallet has to implement its own set of messages that the wallet on the other end will understand and this gets limited to communication between the wallets of a single vendor. Although, this single vendor implementation eases the transaction and message signing part when having multiple devices but it binds users to a single wallet and single experience.
By standardization of the set of messages that should be used for inter-wallet communication this AEX will to open the communication between different types of wallet (mobile, web, extensions) from different vendors.
SDK connects with a wallet
Wallet shares the account address with the SDK
When the SDK needs the wallet to sign the transaction it asks the wallet
Wallet signs and returns the signed transaction.
SDK connects with a wallet
Wallet returns its current address and other account addresses it may help the SDK in getting signature for.
When the SDK needs the wallet to sign the transaction it asks the wallet
Wallet performs steps in the below order
checks if it can sign the transaction.
else it checks if it holds a direct link to the wallet that can sign the transaction and forwards the request to it.
and at last it checks if there is an indirect link to the signing address i.e. via another connected wallet and forwards the request to it.
Once the transaction is signed, it is returned back to the requesting SDK for further processing.
error: Used to communicate any error occurred. Error code 1 to 9 are reserved and reused here from AEX-2.
ping/pong: general ping/pong messages to check liveness. Implementation of this method is not mandatory for wallets communicating over a transport layer that have native support for liveness check.
Parameters
Object
id - A unique identifier, must conform to the
Returns
Object
id - same id as in the corresponding request
data - Value will always be equal to pong
wallet.channel.initiate: Initiate request to open a communication channel. The request contains an identifier that will be used by either party to recognize and process incoming messages. The id should match the subsequent incoming or outgoing messages between the two wallets. The generated identifier must be unique and must conform to the UUID v4 standards.
Parameters
Object
id - A unique identifier, must conform to the
name - human readable wallet name
version - protocol version. Currently defaults to 1.
Returns
Object
id - same id as in the corresponding request
name - human readable wallet name
wallet.channel.close: Close the channel
Parameters
Object
id - A unique identifier, must conform to the
Returns
Object
wallet.channel.close_incoming: Close channel only for signing requests i.e. closing wallet can still ask the wallet on another end to sign or forward the transactions.
Parameters
Object
id - A unique identifier, must conform to the
Returns
wallet.get.address: Ask the connected wallet for its address
Parameters
Object
id - A unique identifier, must conform to the UUID v4 standards
wallet.update.address: Issued by connected wallets for returning addresses incl. from the connected wallets. The connected field is optional and contains the list of address of the wallets it is further connected to.
Parameters
Object
id - A unique identifier, must conform to the
address - Object containing two objects named current and connected.
current
wallet.sign.tx: Ask the connected wallet to sign the transaction.
Parameters
Object
id - A unique identifier, must conform to the UUID v4 standards
tx - raw unsigned transaction
Returns
Object
id - same id as in the corresponding request
tx - signed tx returned by the wallet
wallet.request.broadcast: Ask connected wallet to broadcast the transaction. The connected wallet can try to broadcast the transaction itself or forward it to the SDK. If the wallet is unable to broadcast it returns the error with code 3.
Parameters
Object
id - A unique identifier, must conform to the
[WIP]
This guide assumes that you have aecli installed and you checked the Quick start.
The account (wallet) are those which create and report on key pairs, and sign transactions, messages. To within aeternity, you need to have at least two wallets with some coins on their accounts.
Use to create a new wallet. You can specify a password for accessing your wallet or just press Enter if you do not want to set a password. The wallet is created at the specified path.
Alternatively, you can pass the secret key in [secretKey] argument to generate a corresponding wallet.
View the address (public key) of your wallet using command. Also, it can be used to reveal your secret key.
With the aeternity naming system (AENS), you can assign and register a name to your account or oracle. This way, instead of a complex hash, you can use a name you choose. These names have an expiration period, after which the name will no longer belong to anyone, so it can be claimed again. For more information, see docs.
The name group consists of the .
Use to create and register a name for your account.
After that, you can use command to set a name pointer. You can assign the name to another account via pointers, you will still have the right to do other operations with this name.
Don't forget to run from time to time to don't lose access to your name. By default name TTL gets extended to one year, it can't be extended for a longer period.
You can a name to another account or contract, just indicate another account's address. You will pass all rights regarding the name to another account.
At last, you can revoke your name using . The revoked name can be claimed again after a fixed timeout of 2016 blocks (~ 4 days).
A smart contract is a computer protocol intended to digitally facilitate, verify, or enforce the negotiation or performance of a contract. Smart contracts allow the performance of credible transactions without third parties. These transactions are trackable and irreversible. Smart contracts aim to provide security that is superior to traditional contract law and to reduce other transaction costs associated with contracting.
The contracts group consists of the .
deploy
Here is an example contract that we will deploy
To deploy a contract, run adding a file that should be compiled.
call
To execute a function of the contract, run command. sum is a function which is executed by this contract, [1, 2] are arguments of this function:
In the above, the "Return value (decoded)" is a result of contract execution — it is a sum of values 1 and 2.
display basic information about the blockchain and require little explanation. moves backward through the blockchain displaying blocks and transactions.
The command allows you to see inside various æternity types. Because each æternity type starts with two letters identifying what sort of thing it is, you can throw anything you like at inspect, and it will bravely try to do the right thing.
inspect account by address
inspect transaction
inspect block
One of aecli use cases is offline signing. It requires the below steps.
prepare a transaction using on any device;
optionally run to verify the generated transaction before signing on offline device;
sign the transaction by on offline device;
broadcast signed transaction using on a device connected to the internet.
This guide describes all breaking changes introduced with v14.0.0.
Minimum supported versions:
aeternity node 7.1.0
aesophia@8
Stick to a previous sdk version if it is required.
If you are importing files explicitly from dist folder then you need to update the extension
recover, dump removed (AEX-3 keystore implementation)Copy the removed implementation to your project or add a previous sdk as a separate dependency
It is made to don't break caching. If you need to change a server URL, create a new server instance instead.
Because it is not thrown by wallet as well.
Use signDelegation api instead.
onAskToSelectNetwork constructor optionProvide a function throwing RpcMethodNotFoundError if you don't want to support network change by
aepp.
ChannelClientReconnectTx removedYou couldn't use it because it is not supported on the node side.
ORACLE_TTL, QUERY_TTL, RESPONSE_TTL not exported anymoreThese values provided by default in buildTx, if necessary define them as
buildTx/unpackTx works only with transactionsIf you need to work with node's entry use packEntry/unpackEntry.
Tag include only transactionsNode entries tags moved to EntryTag.
buildTx doesn't accept prefix anymoreUse decode/encode to convert payload to desired format.
NAME_*TTL, CLIENT_TTL not exported anymoreThese values provided by default in buildTx, if necessary define them as
Apply a change
Namely: deriveChild, derivePathFromKey, getMasterKeyFromSeed,derivePathFromSeed, getKeyPair, generateSaveHDWalletFromSeed,getSaveHDWalletAccounts, getHdWalletAccountFromSeed.
Use AccountMnemonicFactory instead.
sign, signMessage removedUse MemoryAccount:sign, MemoryAccount:signMessage instead.
isValidKeypair removedCreate a MemoryAccount by a secret key and compare it's address with an address in the key pair instead.
getAddressFromPriv removedUse MemoryAccount instead.
Use SDK page to convert secret keys.
generateKeyPair removedUse MemoryAccount::generate instead.
Optionally add decode if you need raw keys.
Obtain the secret key via MemoryAccount:secretKey.
generateKeyPairFromSecret removedUse MemoryAccount instead.
Convert secret key as hex to new format as
Use SDK page to convert secret keys.
signTypedData, signDelegationYou can throw an exception if the account operation is not doable.
Use Name class instead.
Accordingly for other methods:
NAME_BID_MAX_LENGTH not exported anymoreUse isAuctionName function instead.
Use Oracle, OracleClient classes instead.
Accordingly for other methods:
pollQueries don't return responded queries by defaultUse includeResponded option to restore the previous behavior.
Use CompilerCli instead.
encodeFateValue, decodeFateValue not exported anymoreUse ContractByteArrayEncoder:encodeWithType, decodeWithType from @aeternity/aepp-calldata.
AeSdk:initializeContract removedUse Contract.initialize instead:
createDelegationSignature removedUse packDelegation and AccountBase::signDelegation instead.
Namely:
signDelegationToContract,
signNameDelegationToContract,
signAllNamesDelegationToContract,
Use signDelegation instead.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
The issue of large build size by setting include_src to false for prod
build, and removing unnecessary dependencies.
Compilation error due to a bug in enacl library.
format generic server call for formatting outputs as renderables
version generic server call
set_account generic server call for setting balance of arbitrary account
Generic server now returns structured data and errors which have to be
formatted manually using format call
location display has been improved
display_gas is renamed to print_gas for consistency
In-repl Sophia functions
Option to return rendered results
Option to return raw erlang values for successful calls to the gen server
Several options to configure printing format
Themed rendering now returns bytestrings
print is renamed to lookup
aere_repl more often returns a tuple {Result, repl_state()}
In-repl functions
Command print_vars to list all values of all variables at a breakpoint
File system cache
Debugger integration
REPL meta-states: normal, break, abort
Rendering of colored messages
Reworked file loading and including to resemble GHCi's behaviour
Disassembling features
Fixed parsing errors
Fixed bugs in printing outputs
Dockerfile
help instruction
print instruction
Refactored the project structure
Fixed command parsing
Massively refactored and cleaned code
The REPL operates directly on the FATE engine
Most of inline definitions such as types, functions, variables
Added
Updated to
AEX: 5
Title: Inter-Wallet Communication
Author: Shubhendu Shekhar <@shekhar-shubhendu>
License: BSD-3-Clause
Discussions-To: https://forum.aeternity.com/t/aex-5-inter-wallet-communication/3371
Status: Withdrawn
Type: Standards Track
Created: 2019-04-29stop command to quit debugging state and revert the callOption call_gas_price to set result of Call.gas_price
Option call_origin to set the account to execute the repl query (affectsCall.origin and Call.caller)
Option call_contract_creator to set result of Contract.creator
Option call_fee to set result of Call.fee
Option call_height to set result of Chain.block_height
Startup parameter accounts to specify initial account balances
CLI arguments to set the newly added accounts parameter
Fixed numerous bugs and crashes
Adjusted output of :location
CLI uses REPL supervisor directly
Run npm link for linking aecli executable to src/aecli.js
Start a new terminal session and try aecli command to see if everything is okay.
If you have any issue, open an issue in github
If you have problems linking, try also npm install and then npm link.
Instead of using npm link you can also execute ./src/aecli.js directly.
id - same id as in the corresponding request
status - Value will always be equal to ack
Objectid - same id as in the corresponding request
status - Value will always be equal to ack
connected(optional) - Object containing multiple connected accounts.
Example Account Format
tx - signed transaction to be broadcasted
verify - Boolean. Perform verification before broadcasting or not.
Returns
Object
id - same id as in the corresponding request
tx_id - transaction id of the broadcasted transaction
signOracleQueryDelegationToContract.{
"current": {
"ak_2iBPH7HUz3cSDVEUWiHg76MZJ6tZooVNBmmxcgVK6VV8KAE688": {
"name": "this property is optional"
}
}
}contract Example =
entrypoint sum(a: int, b: int) = a + b$ aecli contract deploy --contractSource ./contract.aes ./wallet.json
Contract was successfully deployed
Contract address ct_5MbRKEb77pJVZrjVrQYHu2nzr2EKojuthotio1vZ2Q23dkYkV
Transaction hash th_5M77avjrPKezyBrUfkn19C79MnVh9SSoX4Euz4nY75kn9Fxto
Deploy descriptor /path/to/contract.aes.deploy.5MbRKEb77pJVZrjVrQYHu2nzr2EKojuthotio1vZ2Q23dkYkV.json$ aecli contract call --descrPath contract.aes.deploy.5MbRKEb77pJVZrjVrQYHu2nzr2EKojuthotio1vZ2Q23dkYkV.json sum '[1, 2]' ./wallet.json
Transaction hash th_urgozuZRooNXrZxuvNDdT4BiApcGKsf6ZRpffargXcoZNHQ4C
Block hash mh_dnoULQWpiRtcrntd5yJPUxcu7YrTu18xZ1e9EC2b8prKdShME
Block height 4 (about now)
Signatures ["sg_Vn2cCsMk8RvBKyNTKTbq8V4vm6beuHxfYA7vLBNLnRF3x9hoydWWAtNkaiix8KhyEFSLmsmTy6jz9Lps2TQqVdmH6qmCG"]
Transaction type ContractCallTx (ver. 1)
Caller address ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E
Contract address ct_5MbRKEb77pJVZrjVrQYHu2nzr2EKojuthotio1vZ2Q23dkYkV
Gas 31 (0.000000031ae)
Gas price 0.000000001ae
Call data cb_KxHrtMsKKwIE32Kmfg==
ABI version 3 (Fate)
Amount 0ae
Fee 0.00018198ae
Nonce 3
TTL 7 (in 6 minutes)
----------------------Call info-----------------------
Gas used 25 (0.000000025ae)
Return value (encoded) cb_BvMDXHk=
Return value (decoded) 3$ aecli inspect ak_22xzfNRfgYWJmsB1nFAGF3kmabuaGFTzWRobNdpturBgHF83Cx
Account ID ak_22xzfNRfgYWJmsB1nFAGF3kmabuaGFTzWRobNdpturBgHF83Cx
Account balance 52.1342501ae
Account nonce 3
No pending transactions$ aecli inspect th_iirV7mw49NfFY8NbBhbXGBLv9PPT3h1ou11oKtPsJVHGVpWVC
Transaction hash th_iirV7mw49NfFY8NbBhbXGBLv9PPT3h1ou11oKtPsJVHGVpWVC
Block hash mh_2RojH44UtAjf8pRQekPp7o78CmCqMQJkRdxmfXvVmWg9M6ymcr
Block height 99005 (5 years ago)
Signatures ["sg_MjwB8zrhqGTqYWY2c5jLrikuCcwppnhNhjXg9TcdFbCkSvGhPL6Hf4iu81eoxWWJFSgRSFQ3h3qMv6vVNqYfo5NNBNDFK"]
Transaction type NameClaimTx (ver. 2)
Account address ak_2i74vkHbdciAdr7Bw3ogdTHsLykPf4ii1DQEGLh6RpySyhtA9H
Name yanislav.test
Name salt 6632125367082877
Fee 0.00001638ae
Nonce 2$ aecli inspect mh_2DhgyD4np6n3JMsNWVXdtWZE2rAx74sgxL6nb2GsCKB1VnbLxN
<<--------------- MicroBlock --------------->>
Block hash mh_2DhgyD4np6n3JMsNWVXdtWZE2rAx74sgxL6nb2GsCKB1VnbLxN
Block height 762850
State hash bs_9vEQ2hkjJLFoqbmUq2YB3PyZN4TGV6Viv686wgX3i4t21PUK3
Nonce N/A
Miner N/A
Time 17/04/2023, 05:54:40
Previous block hash mh_2VaToyVbe8joVts9SjzdGJZqK7nk6w4MfvGC32Nfwp9KnTa7Z6
Previous key block hash kh_2gVG4vzZwWJfzMe5Ug2jwwDcgcpmjEd1umsWqKA9CkSPidCYuw
Version 5
Target N/A
Transactions 1
<<--------------- Transaction --------------->>
Transaction hash th_2uc2RDDQnDV2BsyVLHA36GP3UZJNn16utV6uivWjLAQoTVBA3u
Block hash mh_2DhgyD4np6n3JMsNWVXdtWZE2rAx74sgxL6nb2GsCKB1VnbLxN
Block height 762850
Signatures ["sg_4UUxNZhGLXWjGsfAMEddccjQ1wpZfwUkZ9qMczjRUNFGAWAS3fahHWqgwxLf79RQ3J3ZRnEaazz259dPzUjj5J3EHcNYj"]
Transaction type SpendTx (ver. 1)
Sender address ak_2swhLkgBPeeADxVTAVCJnZLY5NZtCFiM93JxsEaMuC59euuFRQ
Recipient address ak_22xzfNRfgYWJmsB1nFAGF3kmabuaGFTzWRobNdpturBgHF83Cx
Amount 50ae
Payload ba_Xfbg4g==
Fee 0.00001688ae
Nonce 1513- https://unpkg.com/@aeternity/aepp-sdk/dist/aepp-sdk.browser-script.js
+ https://unpkg.com/@aeternity/aepp-sdk/dist/aepp-sdk.browser-script.cjs "dependencies": {
"@aeternity/aepp-sdk": "^14.0.0",
"@aeternity/aepp-sdk-13": "npm:@aeternity/aepp-sdk@^13.3.3"
}- node.$host = 'http://example.com';
+ node = new Node('http://example.com');const ORACLE_TTL = { type: ORACLE_TTL_TYPES.delta, value: 500 };
const QUERY_TTL = { type: ORACLE_TTL_TYPES.delta, value: 10 };
const RESPONSE_TTL = { type: ORACLE_TTL_TYPES.delta, value: 10 };const NAME_TTL = 180000;
const NAME_MAX_TTL = 36000;
const NAME_MAX_CLIENT_TTL = 86400;
const CLIENT_TTL = 86400;-const time = new Date(
- (await node.getTopHeader()).time,
-);
+const time = (await node.getTopHeader()).time;- address = getAddressFromPriv(secretKeyOldFormat)
+ address = new MemoryAccount(secretKeyNewFormat).address- const keyPair = generateKeyPairFromSecret(rawSecretKey)
+ const secretKey = encode(rawSecretKey.subarray(0, 32), Encoding.AccountSecretKey)
+ const account = new MemoryAccount(secretKey)
+ const keyPair = {
+ publicKey: decode(account.address),
+ secretKey: rawSecretKey,
+ }const oldSk =
'9ebd7beda0c79af72a42ece3821a56eff16359b6df376cf049aee995565f022f840c974b97164776454ba119d84edc4d6058a8dec92b6edc578ab2d30b4c4200';
const newSk = encode(Buffer.from(oldSk, 'hex').subarray(0, 32), Encoding.AccountSecretKey);
// 'sk_2CuofqWZHrABCrM7GY95YSQn8PyFvKQadnvFnpwhjUnDCFAWmf'-await aeSdk.aensPreclaim('example.chain')
+const name = new Name('example.chain', aeSdk.getContext())
+await name.preclaim()aensRevoke => Name:revoke
aensUpdate => Name:update
aensTransfer => Name:transfer
aensQuery => Name:getState
aensClaim => Name:claim
aensBid => Name:bid-aeSdk.pollForQueries(queryHandler)
+const oracle = new Oracle(account, aeSdk.getContext());
+oracle.pollQueries(queryHandler)extendOracleTtl => Oracle:extendTtl
respondToQuery => Oracle:respondToQuery
getOracleObject => Oracle:getState
registerOracle => Oracle:register
getQueryObject => Oracle:getQuery, OracleClient:getQuery
postQueryToOracle => OracleClient:postQuery
pollForQueryResponse => OracleClient:pollForResponse- aeSdk.initializeContract(options)
+ Contract.initialize({ ...aeSdk.getContext(), ...options })-const dlg = await aeSdk.createDelegationSignature(contractAddress, [name]);
+const dlg = await aeSdk.signDelegation(
+ packDelegation({
+ tag: DelegationTag.AensName,
+ accountAddress: aeSdk.address,
+ contractAddress,
+ nameId: name,
+ }),
+);Command Line Interface for the æternity blockchain.
You can install aecli using your preferred tool (yarn or npm). Here's an npm example
Let's ensure that CLI installed correctly by running $ aecli. It will show the available commands as below.
To read documentation of other commands and sub-commands, you can append
--help. For example, typeaecli account --helpto get a list of commands available inaccountmodule.
The next step is to create a wallet to use in other commands:
You need to send some coins to the created wallet.
On testnet you can do that using . Switch to testnet using
$ aecli select-node.
Run $ aecli inspect <wallet address> to ensure that it got coins.
At the last step, we will send our coins to another account:
Find out more in the .
account
— sign a transaction using wallet
— sign a personal message using wallet
— check if message was signed by address
This guide describes all breaking changes introduced with v11.0.0.
decodeEvents methodRemoved decodeEvents from contract ACI methods ().
rewrite
to
Removed raw fields from the decodeEvents response () use processed fields for the same.
Renamed decoded events response field decoded to args
old response
new response
allowUnsynced option of poll method ()poll method now checks if Tx is in the node pool ()5000 is replaced by a method which calculates the default interval using expected mine rate and micro block cycle ()topBlock
use aeSdk.api.getTopHeader() instead
contractCall
rewrite
to
gas of 25000 limit has been dropped. Instead, SDK attempts to estimate the gas using dry-run feature ()See documentation on for detailed explanation.
CompilerApi ()Removed getBytecodeCompilerVersion method.
Removed encodeCall method from contractCompile response.
Removed getCompilerVersion method, use aeSdk. sdk.compilerVersion instead.
rewrite
to
Removed contractEncodeCallDataAPI:
rewrite
to
Removed contractGetACI:
rewrite
to
Removed validateByteCodeAPI:
rewrite
to
name instead of encoded name ()rewrite
to
forceValidation flag from aepp-rpc and wallet-rpc stamps. ()hd-wallet methods ()Renamed generateSaveHDWallet to generateSaveHDWalletFromSeed
Renamed getHdWalletAccountFromMnemonic to getHdWalletAccountFromSeed
This guide explains handling the edge cases that can occur while using aeternity SDK in a TypeScript project.
Firstly, ensure you've set up TypeScript according to the installation guide.
SDK doesn't expose types separately to reduce the number of exports and simplify tracking of breaking changes. But you may need these types to prepare parameters or to hold the return value. In such cases, it is advised to use TypeScript-provided generics Parameters and ReturnType. For example,
The same for ReturnType:
You may need to define an object with parameters to call an sdk method. Obvious to try it as
The problem in this case, is that TypeScript will generalize the type of unpackedEntry.txHash to string instead of th_${string} making it incompatible with arguments of . To fix this you may define gaAuthData's type explicitly, like:
Or to define gaAuthData as immutable:
In the last case, txHash's type will be exactly "th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1", making it compatible with .
Some sdk methods return a of multiple types. For example, returns a union of fields. To work correctly you need to narrow this type to a specific transaction before accessing its fields. For example,
Without checking the tx.tag TypeScript will fail with
Property 'amount' does not exist on type 'TxUnpackedSignedTx1 & { tag: Tag; }'.
The above check is also implemented in itself, instead of checking the tx.tag you can provide Tag in the second argument:
But if you need to get SpendTx properties inside a SignedTx you still need to use the above tag check.
You may find that is a generic function so that it can be executed as
The problem is that JavaScript won't check if the transaction is a SpendTx, so provide Tag.SpendTx as the second argument instead (as the above).
Let's assume we need to receive an address from the user to send some coins to it. The user enters an address in a text box, we can get it as a string. method accepts the address as , it won't accept a general string. We can overcome this restriction by adding a type assertion, like:
The problem is that TypeScript won't check if address is an ak_-encoded string, and the method will fail in this case.
A more accurate solution would be to check the address in advance, providing user feedback if it is incorrect. For example:
Please note that this method doesn't require explicit casting string to because implicitly marks address as ak_${string} in case it returns true.
Additionally, you can use to validate data against other address types:
Or encoding types in general:
The similar way can be used
If you don't need to handle invalid names specially then you can use :
Doing this way, will throw an exception if nameAsString is not a proper AENS name. TypeScript will handle nameAsString as ${string}.chain in lines below invocation.
By default, it is allowed to call any method of the instance. You can enable type-checking by providing a contract interface in a generic parameter of . For example:
If you need to define the contract interface separately then extend :
It is theoretically possible to generate a contract interface by ACI. But unfortunately, it is currently.
$ npm install --global @aeternity/aepp-cliimport { walletDetector } from '@aeternity/aepp-sdk';
type WDCallback = Parameters<typeof walletDetector>[1];
type Wallet = Parameters<WDCallback>[0]['newWallet'];
let wallet: Wallet | null = null;
const stop = walletDetector(connection, ({ newWallet }) => {
wallet = newWallet;
stop();
});import { unpackDelegation } from '@aeternity/aepp-sdk';
type DlgUnpacked = ReturnType<typeof unpackDelegation>;
let delegation: DlgUnpacked | null = null;
delegation = unpackDelegation(
'ba_+EYDAaEBXXFtZp9YqbY4KdW8Nolf9Hjp0VZcNWnQOKjgCb8Br9mhBV1xbWafWKm2OCnVvDaJX/R46dFWXDVp0Dio4Am/Aa/Z2vgCEQ==',
);replace await aeSdk.contractCall(identityContract, contractId, 'getArg', [42])
with (await aeSdk.getContractInstance({ source, contractAddress: contractId })).methods.getArg(42)
contractCompile
replace await aeSdk.contractCompile(CONTRACT_SOURCE)
with (await aeSdk.getContractInstance({ source: CONTRACT_SOURCE })).compile()
contractDeploy
replace await aeSdk.contractDeploy(bytecode, identityContract)
with (await aeSdk.getContractInstance({ bytecode, source: identityContract })).deploy()
contractCallStatic
replace await aeSdk.contractCallStatic(identityContract, null, 'init', [], { bytecode })
with await contract.deploy([], { callStatic: true })
Removed property createdAt from contract.deploy method response
call/callStatic
removed call and callStatic methods from deploy response
Removed contractDecodeCallDataByCodeAPI method.
Removed contractDecodeCallResultAPI method.
Removed getFateAssembler method.
Removed compileContractAPI method.
cInstance.methods.emitEvents.decodeEvents(log);cInstance.decodeEvents(log);// events emitted by contract calls are automatically decoded
const tx = await contractInstance.methods.emitEvents(1337, 'this message is not indexed');
console.log(tx.decodedEvents);
/*
[
{
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh',
data: 'cb_dGhpcyBtZXNzYWdlIGlzIG5vdCBpbmRleGVkdWmUpw==',
topics: [
'101640830366340000167918459210098337687948756568954742276612796897811614700269',
'39519965516565108473327470053407124751867067078530473195651550649472681599133'
],
name: 'AnotherEvent',
decoded: [
'fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk',
'this message is not indexed'
]
},
{
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh',
data: 'cb_Xfbg4g==',
topics: [
'59505622142252318624300825714684802559980671551955787864303522023309554554980',
1337
],
name: 'FirstEvent',
decoded: [ '1337' ]
}
]
*/// events emitted by contract calls are automatically decoded
const tx = await contractInstance.methods.emitEvents(1337, 'this message is not indexed');
console.log(tx.decodedEvents);
/*
[
{
name: 'AnotherEvent',
args: [
'fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk',
'this message is not indexed'
],
contract: {
name: 'EventEmitter',
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh'
}
},
{
name: 'FirstEvent',
args: [1337n],
contract: {
name: 'EventEmitter',
address: 'ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh'
}
}
]
*/deployed = await contract.deploy([], { onAccount });
await deployed.call('getArg', [42]);
await deployed.callStatic('getArg', [42]);await contract.deploy();
await contract.methods.getArg(42, { callStatic: false });
await contract.methods.getArg(42, { callStatic: true });const code = await aeSdk.compileContractAPI(identityContract);
const callData = await aeSdk.contractEncodeCallDataAPI(identityContract, 'init', []);
const result = await initiatorCh.createContract({
code,
callData,
deposit: 1000,
vmVersion: 5,
abiVersion: 3,
amount,
gas,
gasPrice,
});contract = await aeSdk.getContractInstance({ source: contractSource });
await contract.compile();
const result = await aeSdk.createContract({
code: contract.bytecode,
callData: contract.calldata.encode('Identity', 'init', []),
deposit: 1000,
vmVersion: 5,
abiVersion: 3,
amount,
gas,
gasPrice,
});
//or
bytecode = (await aeSdk.compilerApi.compileContract({ code: contractSource })).bytecode;await aeSdk.contractEncodeCallDataAPI(contractSource, 'getArg', ['42']);contract = await aeSdkInitiator.getContractInstance({ source: contractSource });
await contract.compile();
contract.calldata.encode('Identity', 'getArg', [42]);const aci = await aeSdk.contractGetACI(contractSource);const aci = await aeSdk.compilerApi.generateACI({ code: contractSource });aeSdk.validateByteCodeAPI(bytecode, identityContract);await aeSdk.compilerApi.validateByteCode({ bytecode, source: identityContract });const name = 'test123test.chain';
const nameHash = `nm_${encodeBase58Check(Buffer.from(name))}`;
const params = { accountId: senderId, nonce, name: nameHash, nameSalt: _salt, nameFee };
const txFromAPI = await aeSdk.nameClaimTx(params);const name = 'test123test.chain';
const params = { accountId: senderId, nonce, name, nameSalt: _salt, nameFee };
const txFromAPI = await aeSdk.nameClaimTx(params);import { packEntry, EntryTag } from '@aeternity/aepp-sdk';
const gaAuthData = {
tag: EntryTag.GaMetaTxAuthData,
fee: 766e11,
txHash: 'th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1',
};
const gaAuthDataPacked = packEntry(gaAuthData);import { Tag, Encoded } from '@aeternity/aepp-sdk';
interface GaAuthData {
tag: Tag;
fee: number;
txHash: Encoded.TxHash;
}
const gaAuthData: GaAuthData = {
tag: EntryTag.GaMetaTxAuthData,
fee: 766e11,
txHash: 'th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1',
};const gaAuthData = {
tag: EntryTag.GaMetaTxAuthData,
fee: 766e11,
txHash: 'th_2CKnN6EorvNiwwqRjSzXLrPLiHmcwo4Ny22dwCrSYRoD6MVGK1',
} as const;import { unpackTx, Tag } from '@aeternity/aepp-sdk';
const encodedTx =
'tx_+F0MAaEB4TK48d23oE5jt/qWR5pUu8UlpTGn8bwM5JISGQMGf7ChAeEyuPHdt6BOY7f6lkeaVLvFJaUxp/G8DOSSEhkDBn+wiBvBbWdOyAAAhg9e1n8oAAABhHRlc3QLK3OW';
const tx = unpackTx(encodedTx);
if (tx.tag !== Tag.SpendTx) {
throw new Error(`Unknown transaction type: ${Tag[tx.tag]}`);
}
console.log(tx.amount);const tx = unpackTx(encodedTx, Tag.SpendTx);const tx = unpackTx<Tag.SpendTx>(encodedTx);await aeSdk.spend(100, address as Encoded.AccountAddress);import { isEncoded, Encoding } from '@aeternity/aepp-sdk';
if (!isEncoded(address, Encoding.AccountAddress)) {
alert('The address is not valid');
return;
}
await aeSdk.spend(100, address);import { Encoding } from '@aeternity/aepp-sdk';
isEncoded(address, Encoding.ContractAddress, Encoding.OracleAddress);isEncoded(address, Encoding.Transaction);import { isName } from '@aeternity/aepp-sdk';
console.log(isName('name.chain')); // true
console.log(isName('мир.chain')); // true
console.log(isName('🙂.chain')); // falseimport { ensureName, Name } from '@aeternity/aepp-sdk';
const nameAsString: string = readName();
ensureName(nameAsString);
const name = new Name(nameAsString, options);import { Contract } from '@aeternity/aepp-sdk';
const sourceCode = `
include "String.aes"
contract Test =
entrypoint foo(x: int) = x
entrypoint bar(x: map(string, int)) = x
datatype name = FirstName(string) | LastName(string)
entrypoint baz(n: name) =
switch(n)
FirstName(first) => String.length(first)
LastName(_) => abort("Last name not supported yet")
`;
const contract = await Contract.initialize<{
foo: (v: bigint) => bigint;
bar: (x: Map<string, bigint>) => Map<string, bigint>;
baz: (v: { FirstName: [string] } | { LastName: [string] }) => number;
}>({
...aeSdk.getContext(),
sourceCode,
});
await contract.$deploy([]);
console.log((await contract.foo(21n)).decodedResult); // 42
console.log((await contract.bar(new Map([['test', 10n]]))).decodedResult); // Map(1) { 'test' => 10n }
console.log((await contract.baz({ FirstName: ['Nikita'] })).decodedResult); // 6import { ContractMethodsBase } from '@aeternity/aepp-sdk';
interface FooContract extends ContractMethodsBase {
foo: (v: bigint) => bigint;
bar: (x: Map<string, bigint>) => Map<string, bigint>;
baz: (v: { FirstName: [string] } | { LastName: [string] }) => number;
}
const contract = await Contract.initialize<FooContract>({
...aeSdk.getContext(),
sourceCode,
});address — get wallet address and optionally secret key
create — create a wallet by a secret key or generate a new one
spend — send coins to another account or contract
name
full-claim — claim an AENS name in a single command
pre-claim — pre-claim an AENS name
claim — claim an AENS name (requires pre-claim)
— bid on name in auction
— update a name pointer
— extend name TTL
— revoke an AENS name
— transfer a name to another account
contract
compile — compile a contract to get bytecode
encode-calldata — encode calldata for contract call
decode-call-result — decode contract call result
— execute a function of the contract
— deploy a contract on the chain
oracle
create — register current account as oracle
extend — extend oracle's time to leave
create-query — create an oracle query
— respond to an oracle query
inspect — get details of a node entity
tx
spend — build spend transaction
name-preclaim — build name preclaim transaction
name-claim — build name claim transaction
— build name update transaction
— build name transfer transaction
— build name revoke transaction
— build contract deploy transaction
— build contract call transaction
— build oracle register transaction
— build oracle extend transaction
— build oracle post query transaction
— build oracle respond transaction
— verify transaction using node
config — print the current sdk configuration
select-node — specify node to use in other commands
select-compiler — specify compiler to use in other commands
The motivation behind this aexpansion is to improve the user experience of browsing æpps inside æpps browsers, wallets, and listing services. Our goal is to make it easy for users to recognize the purpose of an æpp/what the æpp allows its users to do and whether users would like to open the æpp and give it access to the account data it requests.
Name of aepp
aepp icons
Networks the aepp is available on [mainnet, testnet]
aepp description
Category (select from predermined list)
Author
Author URL
Related applications
Age restrictions/rating
Reference visuals for the result of implementing such metadata format are included below.
We are leveraging the webmanifest format and augmenting it to fit the needs of the blockchain context. The premise is that this format can be universal (used by multiple protocols, with only one field difference).
Consider if aeppsmanifest format applies to both web and non-web contexts.
This proposal does not address whether metadata provided by an aepp is accurate/truthful.
This proposal does not articulate a stance on storage concerns (as aepp metadata can be rendered dynamically or stored locally).
This proposal does not address the concern of aepps sharing aepps data between themselves.
Documentation: https://www.w3.org/TR/appmanifest/#name-member
Documentation: https://www.w3.org/TR/appmanifest/#icons-member
An array of AeternityNetworkIdType items, each item represents id of the network that aepp is compatible with. The persistence of this member means that aepp supports aeternity protocol.
AeternityNetworkIdType is a string, allowed values: ae_mainnet, ae_uat (testnet).
Documentation: https://www.w3.org/TR/appmanifest/#description-member
Documentation: https://www.w3.org/TR/appmanifest/#categories-member List of known values: https://github.com/w3c/manifest/wiki/Categories
The author member is a string that represents the name of author.
The author_url member is a string that represents the URL of the author's website.
Could be used to set age restrictions/ratings. Documentation: https://www.w3.org/TR/appmanifest/#iarc_rating_id-member
http://aeternity.com/aepp-base-example/webmanifest.json
Web App Manifest standard: https://www.w3.org/TR/appmanifest/ Extensions Registry: https://github.com/w3c/manifest/wiki/Extensions-Registry
MDN documentation says
PWA manifests include its name, author, icon(s), version, description, and list of all the necessary resources (among other things).
DD: I can't find a specific way to add author info except for adding it as a part of another member (for example, at the end of description member). Because of this, I am defining the author member in this document.
The smart contract language of the æternity blockchain is Sophia. 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 aepp-sophia-examples and start rapid prototyping using AEstudio.
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.
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 .
Both compiler classes implement the that can be used to generate bytecode and ACI without a Contract instance.
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.
Note:
You can provide multiple accounts to the SDK.
For each transaction you can choose a specific account to use for signing (by default the first account will be used), see .
This is specifically important and useful for writing tests.
To do so, we need to prepare an options object, which can be done in multiple ways.
Note:
If your contract includes external dependencies which are not part of the you should initialize the contract using:
It can be used with both CompilerCli and CompilerHttp. This way contract imports would be handled automatically, with no need to provide fileSystem option.
If you pre-compiled the contracts you can also initialize a contract instance by providing ACI and bytecode:
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:
Do it by Contract::initialize.
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.
Following attributes can be provided via options to Contract::initialize:
aci (default: obtained via onCompiler)
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.
If you have a Sophia contract source code that looks like this:
The contract can be deployed using the contract in two different ways:
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
According to the example above you can call the stateful entrypoint increment by using one of the following lines:
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.
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:
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.
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:
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:
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.
This document describes the process a proposal has to go through in order to be accepted into the AEX repository.
The purpose of AEXs is to provide high quality and accessible specifications to be used when developing applications on top of Aeternity. We intend AEXs to be the primary mechanisms for proposing new standards, for collecting community technical input on an issue, and for documenting the design decisions. Because the AEXs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal.
$ aecli
Usage: aecli [options] [command]
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
account handle wallet operations
spend [options] <wallet> <receiver> <amount> send coins to another account or contract
name manage AENS names
contract contract interactions
oracle interact with oracles
chain make a request to the node
inspect [options] <identifier> get details of a node entity
tx generate transactions to sign and submit manually
config [options] print the current sdk configuration
select-node [nodeUrl] specify node to use in other commands
select-compiler [compilerUrl] specify compiler to use in other commands
help [command] display help for command$ aecli account create ./wallet.json
Address ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E
Path /path/to/wallet.json$ aecli inspect ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E
Account ID ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E
Account balance 10000ae
Account nonce 0
No pending transactions$ aecli spend ./wallet.json ak_AgV756Vfo99juwzNVgnjP1gXX1op1QN3NXTxvkPnHJPUDE8NT 42ae
Transaction mined
Transaction hash th_2muLsbZeFaVJ3tePTnLqobPhxBzwFsm1zUv8sjgMX4LKuevX2T
Block hash mh_dnoULQWpiRtcrntd5yJPUxcu7YrTu18xZ1e9EC2b8prKdShME
Block height 2 (about now)
Signatures ["sg_SG5uW5KEGiy5iG1cCkKq4VEdpyvewcW4NjVf4vj2ZoCiap5iB7UQoknWpyWsD4FkziBuGPE88zwXemq3ZvPrdzNtXtKuD"]
Transaction type SpendTx (ver. 1)
Sender address ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E
Recipient address ak_AgV756Vfo99juwzNVgnjP1gXX1op1QN3NXTxvkPnHJPUDE8NT
Amount 42ae
Payload ba_Xfbg4g==
Fee 0.00001684ae
Nonce 1
TTL 4 (about now)AEX: 130
Title: æpps Meta Information Format
Author: Stoyan Vasilev (@j28), Denis Davidyuk (@davidyuk)
License: BSD-3-Clause
Discussions-To: https://forum.aeternity.com/t/aexpansion-proposal-aepps-metadata-format-specification/3987/9
Status: Draft
Type: Meta
Created: 2019-07-09aeternity Developer Tools
aeternity User Tools
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.
other transaction options which will be provided to every transaction that is initiated using the contract instance. You should be aware that:
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.
increment(value: int)RpcAeppRpcWalletAeUse AeSdk, AeSdkAepp, AeSdkWallet, AeSdbBase accordingly.
For example:
Accessing private fields through Proxy will lead to "TypeError: attempted to set private
field on non-instance" (tc39).
This may be an issue if you are using aepp-sdk with Vue@3, because Vue@3 introduced reactivity based
on Proxy class (Vue docs).
Avoid the above error by not making instances of these classes reactive.
Import the needed utils directly instead of importing a wrapper object firstly. For example:
Use new to create an instance.
Their methods exported instead. Outside of AeSdkBase context, they may accept onAccount,onNode, onCompiler options.
For example:
Don't handle new Node(...) and new Compiler(...) as a Promise.
So, it would throw exception in case networkId is not provided. Use try/catch instead.
Use node.getBalance instead of node.api.getBalance.
Use node.getStatus() or node.getNodeInfo() to get values of version, revision,genesisHash, nodeNetworkId, consensusProtocolVersion.
Node doesn't accepts and stores internalUrl, also internal endpoints are not available anymore.
If necessary, create a wrapper of internal API separately (swagger-client package).
Create a wrapper of internal API by genSwaggerClient and use getPendingTransactions method
instead.
Use compilerApi.aPIVersion() method instead.
Don't handle aeSdk.setCompilerUrl(...) as a Promise.
Use aeSdk.buildTx(txType, params) instead.
Use aeSdk.buildTx(txType, params) instead.
Use gasLimit instead of gas everywhere except for transaction details returned by node.
Use unpackTx(encode(tx, 'tx')) instead.
Use require('rlp').decode(unpackTx(tx).rlpEncoded) instead.
is no more accepted For example:
TX_FEE_BASE_GAS, TX_FEE_OTHER_GAS, calculateFee, DEFAULT_FEE)
Use a general calculateMinFee instead.
Use a general buildTx method instead.
Always use TX_TYPE. To get type name by tag use TX_TYPE[tag].
Use TX_TYPE[tag] instead.
Use TX_SCHEMA[TX_TYPE.*] instead.
Use OBJECT_ID_TX_TYPE to find tag by transaction type.
Use computeAuctionEndBlock function instead.
Use a TypeScript check instead.
Pass an instance of AccountBase to onAccount option instead.
Use oracleTtlType field instead of type, and oracleTtlValue field instead of value.
Use decode function instead.
contractId accepted as the first argument, name should be passed as option to the second one.
contractId accepted as the first argument, queryId should be passed as option to the second one.
Pass an empty array if you need no arguments.
It should be an instance of AccountBase instead.
Use getBalance instead.
Use node.getTransactionByHash/getTransactionInfoByHash instead.
Use node.getTransactionInfoByHash instead.
Use node.getAccountNextNonce instead.
Use aeSdk.addAccount method instead.
It wasn't doing anything, just remove it's usages.
Use AeSdkBase or AeSdk instead.
Use AeSdk instead.
It is intended for internal use only.
In txObject option of onSign handler on wallet side.
In tx field of contract call result.
Rely on TypeScript checks instead.
Use argon2-browser package instead.
Use Crypto.getAddressFromPriv instead.
Use swagger-client package instead.
Create instances using new.
Use connectionProxy, walletDetector accordingly.
Use connection property instead.
Use request or notify instead.
Provide a methods parameter instead of handlers[0].
Provide an onDisconnect parameter instead of handlers[1].
Get aepp info in onConnection callback, and store somehow to use later.
On wallet side: assume that all aepps uses the same network as the wallet connected to.
On aepp side: use networkId that wallet provided.
In case networkId is not compatible ask user to switch wallet to a compatible network.
responseMessage, sendResponseMessage, isValidAccounts)
Use own implementation if needed.
See connect-aepp-to-wallet.md for details.
So, aepp would always send closeConnection notification.
Use connectToWallet instead.
Use connectToWallet method instead.
Detect is aepp connected by persistence of rpcClient property.
Use returnHex option to get the previous behaviour.
Pass require('webextension-polyfill').runtime.connect() to it.
id should be a unique string;type should be one of WALLET_TYPE.window, WALLET_TYPE.extension.
Use webextension-polyfill package instead.
For example:
Just deny the connection if you don't want to share the node url.
If you need this feature, create a custom wallet implementation or fill us an issue.
Use unpackTx(tx) on wallet side instead.
This expected to be used only internally.
Use sdk.rpcClient[clientId] to get the corresponding instance of RpcClient.
If you need this feature, create a custom wallet implementation or fill us an issue.
If you need this feature, create a custom wallet implementation or fill us an issue.
Return the value you passed to accept instead.
Throw instances of RpcRejectedByUserError instead.
new Buffer(newResult)replace oldResult.response with TxBuilderHelper.encode(new Buffer(newResult), 'or').
skipArgsConvert option of contract call and deployment (6d4a599)Convert arguments in intermediate Sophia representation to JavaScript types. For example:
rewrite to
skipTransformDecoded option of contract call and deployment (bb49239)Decoding to JavaScript types is enforced, please use it instead.
Encode addresses as an ak_-prefixed string instead.
contractEncodeCall (a4b303f)Use contractEncodeCallDataAPI instead.
contractDecodeData (5df2285)Use contractDecodeCallResultAPI instead.
setOptions on contract instance (b88e767)Pass them through getContractInstance options instead.
Use getContractInstance instead. Also, these methods will accept JavaScript-type variables instead of
Sophia-encoded. For example:
should be replaced with
Use compiler 6.0.0 and above.
Use validateBytecode when you need to ensure that the source code/bytecode provided togetContractInstance corresponds to the on-chain bytecode.
getConsensusProtocolVersion method (75f0447)Use node.consensusProtocolVersion instead.
Numbers in Sophia are not limited in size. Before they were returned from contract methods as usual JavaScript numbers that have limited accuracy. To fix this, we make it return instances of BigInt.
Variant types are now supported by sdk, so replace "RelativeTTL(50)" with { RelativeTTL: [50] }.
As an exception Some(value) is converted to the exact value in JavaScript and None is converted to undefined
(Sophia's option type).
Contract methods will accept/return instances of JavaScript's Map as variables of Sophia's map
type. Objects are not accepted as maps any longer.
Sophia's hash, signature, bytes types return values as Uint8Array instead of a hex-encoded
string.
Check the documentation of calldata package for additional info.
Use .decodedResult instead of .decode() to get the result of method call.
Most of the errors thrown by contract iterations will be different due to doing validation using
calldata package instead of joi.
sdk.getContractInstance (5c690d2)For example:
rewrite to
Contract instance can be generated by ACI and bytecode:
SDK won't use hosted compiler in this case.
Also, contract.compiled was renamed to contract.bytecode.
getContractInstance accepted as usual ones (10fb7ba)For example, replace
with
To support old environments, you need to set up transpilation of SDK package while building your
app. In Webpack it can be done by excludingnode_modules folder except for this package in babe-loader rule. In @vue/cli you can usetranspileDependencies option.
Use third-party cryptographic packages instead of Crypto.encryptData, Crypto.decryptData
methods.
aensUpdate accepts pointers as object (f6b8999)For example, replace
with
Additionally, getDefaultPointerKey (was named classify before) helper function can be used
// 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 CompilerHttpconst compiler = new CompilerCli();const compiler = new CompilerHttp('https://v8.compiler.aepps.com'); // host your own compilerconst 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
});const sourceCode = ... // source code of the contract
const options = { sourceCode }const fileSystem = ... // key-value map with name of the include as key and source code of the include as value
const options = { sourceCode, fileSystem }const sourceCodePath = './example.aes';
const options = { sourceCodePath };const aci = ... // ACI of the contract
const bytecode = ... // bytecode of the contract
const options = { aci, bytecode }const aci = ... // ACI of the contract
const address = ... // the address of the contract
const options = { aci, address }const contract = await Contract.initialize({ ...aeSdk.getContext(), ...options });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.countconst 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 }const tx = await contract.increment(3); // recommended
// or
const tx = await contract.increment(3, { callStatic: false });
// or
const tx = await contract.$call('increment', [3]);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);payable stateful entrypoint fund_project(project_id: int) =
require(Call.value >= 50, 'at least 50 aettos need to be provided')
// further logic ...const tx = await contract.fund_project(1, { amount: 50 }); // recommended
// or
const tx = await contract.$call('fund_project', [1], { amount: 50 });-import { Universal } from '@aeternity/aepp-sdk'
+import { AeSdk } from '@aeternity/aepp-sdk'
-const aeSdk = await Universal(options)
+const aeSdk = new AeSdk(options)-import { Crypto } from '@aeternity/aepp-sdk'
+import { generateKeyPair } from '@aeternity/aepp-sdk'
-console.log(Crypto.generateKeyPair())
+console.log(generateKeyPair())import { Node } from '@aeternity/aepp-sdk'
-const node = await Node({ url, ignoreVersion: false })
+const node = new Node(url, { ignoreVersion: false })-decode('cb_DA6sWJo=', 'cb')
+decode('cb_DA6sWJo=')const connection = new BrowserRuntimeConnection({ port })
-aeSdk.addRpcClient(connection)
-aeSdk.shareWalletInfo(port.postMessage.bind(port))
+const rpcClientId = aeSdk.addRpcClient(connection)
+aeSdk.shareWalletInfo(rpcClientId)contract.methods.listFn('[1, 2]', { skipArgsConvert: false });contract.methods.listFn([1, 2]);sdk.contractCallStatic(source, address, methodName, ['42']);sdk.contractCallStatic(source, address, methodName, [42]);sdk.getContractInstance(contractSource, { contractAddress: '...' });sdk.getContractInstance({ source: contractSource, contractAddress: '...' });sdk.getContractInstance({ aci, bytecode });sdk.getContractInstance({ source, opt: { ttl: 1 } });sdk.getContractInstance({ source, ttl: 1 });sdk.aensUpdate('test.chain', ['ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk']);sdk.aensUpdate('test.chain', {
account_pubkey: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
});import { getDefaultPointerKey } from '@aeternity/aepp-sdk';
const address = 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk';
sdk.aensUpdate('test.chain', { [getDefaultPointerKey(address)]: address });There are three types of AEXs:
A Standards Track AEX describes any change or addition that affects the interoperability of applications using Aeternity. Standards Track AEXs consist of two parts: a design document and a reference implementation.
An Informational AEX describes a design issue, or provides general guidelines or information to the Aeternity community, but does not propose a new feature. Informational AEXs do not necessarily represent an Aeternity community consensus or recommendation, so users and implementors are free to ignore Informational AEXs or follow their advice.
A Meta AEX describes a process surrounding AEXs or proposes a change to (or an event in) a process. They often require community consensus; unlike Informational AEXs, they are more than recommendations, and users are typically not free to ignore them. Examples include procedures, guidelines, changes to the decision-making process, and changes to the tools or environment used in Aeternity development.
Parties involved in the process are you, the champion or AEX author and the AEX editors.
⚠️ Before you begin, vet your idea, this will save you time. Ask the Aeternity community first if an idea is original to avoid wasting time on something that will be be rejected based on prior research (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Just because an idea sounds good to the author does not mean it will work for most people in most areas where Aeternity is used. Examples of appropriate public forums to gauge interest around your AEX include the Aeternity forums and the issues section of this repository. In particular, the issues section of this repository is an excellent place to discuss your proposal with the community and start creating more formalised language around your AEX.
Your role as the champion is to write the AEX using the style and format described below, shepherd the discussions in the appropriate forums, and build community consensus around the idea.
Draft
rapid iteration in small/focused working group
none
major
Review
review and feedback from editor and other interested parties
initial specification, editor assigned, template filled, authors and editor consider document to be in a state where the general public can give constructive feedback
no major TODOs left
Last call (yyyy-mm-dd to yyyy-mm-dd)
indicate that authors and editors consider document to be complete; solicit last round of feedback
at least one working implementation (if applicable), authors and editors deem the proposal complete
Each status change is requested by the AEX author and reviewed by the AEX editors. Use a pull request to update the status.
AEXs should be changed from Draft or Review status, to Rejected status,
upon request by any person, if they have not made progress in three years. Such
a AEX may be changed to Draft status if the champion provides revisions that
meaningfully address public criticism of the proposal, or to Review status if
it meets the criteria required as described in the previous paragraph.
The transition from Last Call to either Final or Active happens
automatically if during the last call period, typically 14 days, no
substantiated objections are voiced or left unaddressed.
A Last Call which results in material changes or substantial unaddressed
technical complaints will cause the AEX to revert to Review.
It occasionally becomes necessary to transfer ownership of AEXs to a new champion. In general, we'd like to retain the original author as a co-author of the transferred AEX, but that's really up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the AEX process, or has fallen off the face of the 'net (i.e. is unreachable or isn't responding to email). A bad reason to transfer ownership is because you don't agree with the direction of the AEX. We try to build consensus around an AEX, but if that's not possible, you can always submit a competing AEX.
If you are interested in assuming ownership of an AEX, send a message asking to take over, addressed to both the original author and the AEX editor. If the original author doesn't respond to email in a timely manner, the AEX editor will make a unilateral decision (it's not like such decisions can't be reversed :).
For each new AEX that comes in, an editor does the following:
Read the AEX to check if it is ready: sound and complete. The ideas must make technical sense, even if they don't seem likely to get to final status.
The title should accurately describe the content.
Check the AEX for language (spelling, grammar, sentence structure, etc.), markup (Github flavoured Markdown), code style
If the AEX isn't ready, the editor will send it back to the author for revision, with specific instructions.
Once the AEX is ready for the repository, the editor will:
Assign an AEX number (generally the PR number or, if preferred by the author, the issue # if there was discussion in the issues section of this repository about this AEX)
Merge the corresponding pull request
Send a message back to the AEX author with the next step.
In general, the editors:
Don't pass judgment on AEXs.
Are intended to fulfil administrative and editorial responsibilities.
Monitor AEX changes, and update AEX headers as appropriate.
Sascha Hanse (@knarz)
Philipp Piwowarsky (@thepiwo)
Successful AEXs should contain most of the following sections:
Preamble: RFC 822 style headers containing metadata about the AEX
Simple Summary: a simplified and layman-accessible explanation of the AEX
Abstract: a short (~200 word) description of the (technical) issue being addressed
Motivation: clearly explaining why the existing standards are inadequate to address the problem that the AEX solves
Specification: should describe the syntax and semantics of any new feature and should be detailed enough to allow competing, interoperable implementations
Rationale: fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.
Backwards Compatibility: if a proposal is supposed to supersede another proposal without providing backwards compatibility then it should contain a section describing these incompatibilities and their severity. Further, it should explain how the author proposes to deal with these incompatibilities.
Test Cases: links to test cases if applicable
Implementations: implementation or link to implementations, if applicable
A AEX template can be found under AEX-X.
Each AEX must begin with an RFC 822 style header preamble. The headers must appear in the following order. Headers marked with "*" are optional and are described below. All other headers are required.
Header fields permitting lists must separate elements with commas.
The Discussions-To field should point to a discussion of the proposed
standard. Most of the initial work should happen in small, focused working
groups and only posted once it is in a reasonably stable state.
Please try to refrain from having WIP documents or very early drafts in this
repository as they tend orphan.
Each proposal must start in the Draft state and will move through the
phases in accordance to the criteria defined in this document.
If a proposal depends on another AEX, the Requires field should indicate
so.
Superseded-By, Replaces, Updates and Updated-By fields are required
since standards are in constant flux. Editors and authors should make sure
that old AEXs are update where appropriate.
The following recommended licenses should be used both for code and the specification:
Each submitted proposal needs to list at least one license. If code is
included, a separate license for it can be specified. The licenses should
be included in the header via the License and License-Code fields. If
those fields do not cover the requirements, include a copyright section in
your proposal.
Or with multiple licenses:
Other acceptable licenses:
Apache-2.0: Apache License, version 2.0
FDL-1.3:
GPL-2.0+:
LGPL-2.1+:
Many parts of this document are inspired by or adapted with only minor modifications from many of the already existing standardisation processes.
AEX: 1
Title: AEX process
Author: Sascha Hanse <[email protected]>
License: CC0-1.0
Discussions-To: https://forum.aeternity.com/t/aeternity-best-current-practices-aexpansions/2461
Status: Active
Type: Meta
Created: 2019-02-01+---------------+ +---------------+ +---------------+
| Draft |------------>| Review |<----------->| Last call |
+---------------+ +---------------+ +---------------+
^ | | ^ | | | |
| v | | | | | |
| +---------------+ | | | | | |
| | Withdrawn |<----+-----|-----------------------+ | | |
| +---------------+ | | | |
v | | | |
+---------------+ | | | |
| Rejected |<--------------------+---------------------------+ | |
+---------------+ -----------------+ |
| |
v v
+---------------+ +---------------+ +---------------+
| Updated |<----------->| Final | | Active |
+---------------+ +---------------+ +---------------+
| |
+----------+ +----------+
| |
v v
+---------------+
| Superseded |
+---------------+AEX: <to be assigned by editors>
Title: <AEX title>
Author: <a list of the author's or authors' name(s) and/or username(s), or name(s) and email(s), e.g. (use with the parentheses or triangular brackets): FirstName LastName (@GitHubUsername), FirstName LastName <[email protected]>, FirstName (@GitHubUsername) and GitHubUsername (@GitHubUsername)>
License: <license names, abbreviated>
License-Code (*optional): <license names, abbreviated>
Discussions-To: <URL>
Status: <Draft | Active Review | Last Call (yyyy-mm-dd to yyyy-mm-dd) | Final | Updated | Superseded | Rejected | Withdrawn>
Type: <Standards Track | Informational | Meta>
Created: <date created on, in ISO 8601 (yyyy-mm-dd) format>
Requires (*optional): <AEX number(s)>
Replaces (*optional): <AEX number(s)>
Superseded-By (*optional): <AEX number(s)>
Updates (*optional): <AEX number(s)>
Updated-By (*optional): <AEX number(s)>License: CC0-1.0
License-Code: Apache-2.0License: CC0-1.0
BSD-3-Clause
License-Code: Apache-2.0 aeSdk = new AeSdkAepp({
name: 'Simple æpp',
nodes: [
{ name: 'testnet', instance: new Node(TESTNET_NODE_URL) },
{ name: 'mainnet', instance: new Node(MAINNET_NODE_URL) },
],
compilerUrl: COMPILER_URL,
onNetworkChange: async ({ networkId }) => {
const [{ name }] = (await aeSdk.getNodesInPool())
.filter((node) => node.nodeNetworkId === networkId);
aeSdk.selectNode(name);
commit('setNetworkId', networkId);
},
onAddressChange: ({ current }) => commit('setAddress', Object.keys(current)[0]),
onDisconnect: () => alert('Aepp is disconnected'),
});minor
Final
proposal is considered to be completed
no unaddressed substantiated objections are left
crucial or cosmetic updates only
Active
proposal can be in constant flux
no unaddressed substantiated objections are left
crucial or cosmetic updates only
Updated
signalling that an updating standard might have to be considered
an updating proposal entered the Final state
crucial or cosmetic updates only
Superseded
standard should no longer be used
community consensus around a superseding proposal
none
Rejected
editors deemed this proposal to be unworkable
proposal was rejected before, authors were unwilling to respond to feedback, too unfocused, too broad, duplication of effort, being technically unsound, not providing proper motivation or addressing backwards compatibility
none
Withdrawn
signalling that the proposal is no longer relevant
withdrawn by original authors
none
The following standard allows for the implementation of a standard API for tokens within smart contracts. This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.
This standard will allow decentralized applications and wallets to handle fungible tokens in a standardized way. A standard interface allows any tokens to be re-used by other applications, e.g. from wallets to decentralized exchanges.
The provided specification is following the ERC20 standard introduced in Ethereum for fungible tokens. This standard is proven to be working, it will help with interoperability and easier developer onboarding as the main differences will be Sophia syntax related. Another goal with following the ERC20 standard, is to learn from its mistakes and not repeat them.
The newly proposed standard should be easy to use but extendable with more functionality, both first and third party as shown by splitting allowance, minting, burning and swapping into optional extensions.
This function returns a hardcoded list of all implemented extensions on the deployed contract.
This function returns meta information associated with the token contract.
meta_info
meta_info
This function returns the total token supply.
total_supply
int
This function returns the full balance state for static calls, e.g. by a blockchain explorer.
balances
map(address, int)
This function returns the account balance of another account with address owner, if the account exists. If the owner address is unknown to the contract None will be returned. Using option type as a return value allows us to determine if the account has balance of 0, more than 0, or the account has never had balance and is still unknown to the contract.
owner
address
balance
option(int)
This function allows transfer of value amount of tokens to to_account address and MUST fire the Transfer event. The function SHOULD abort if the Call.caller's account balance does not have enough tokens to spend.
Note: Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event.
to_account
address
value
int
This event MUST be triggered and emitted when tokens are transferred, including zero value transfers.
The transfer event arguments should be as follows: (from_account, to_account, value)
from_account
address
to_account
address
value
int
Mint (optional if token creation happens) - MUST trigger when tokens are minted and thus are newly available in the given token contract, this also applies to tokens created using the init method on contract creation.
The mint event arguments should be as follows: (account, value)
account
address
value
int
This section covers the extendability of the basic token - e.g. mintable, burnable and allowances.
When a token contract implements an extension its name should be included in the aex9_extensions array, in order for third party software or contracts to know the interface.
Any extensions should be implementable without permission. Developers of extensions MUST choose a name for aex9_extensions that is not yet used. Developers CAN make a pull request to the reference implementation for general purpose extensions and maintainers choose to eventually include them.
This function mints value new tokens to account. The function SHOULD abort if Call.caller is not the owner of the contract state.owner.
account
address
value
int
Mint - MUST trigger when tokens are minted and thus are newly available in the given token contract, this also applies to tokens created using the init method on contract creation.
The mint event arguments should be as follows: (account, value)
account
address
value
int
This function burns value of tokens from Call.caller.
value
int
Burn - MUST trigger when tokens are burned and thus are no longer available in the given token contact.
The burn event arguments should be as follows: (account, value)
account
address
value
int
Allows for_account to withdraw from your account multiple times, up to the value amount. If this function is called again it overwrites the current allowance with value.
Note: To prevent attack vectors (like the ones possible in ERC20) clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH the contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before.
for_account
address
value
int
Transfers value amount of tokens from address from_account to address to_account, and MUST fire the Transfer event.
The transfer_allowance method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD abort unless the from_account account has deliberately authorized the sender of the message via some mechanism.
Note: Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event.
from_account
address
to_account
address
value
int
This function returns the amount which for_account is still allowed to withdraw from from_account, where record allowance_accounts = { from_account: address, for_account: address }. If no allowance for this combination of accounts exists, None is returned.
allowance_accounts
allowance_accounts
This function returns all allowances stored in state.allowances record.
allowances
map(allowance_accounts, int)
This function will look up the allowances and return the allowed spendable amount from from_account for the transaction sender Call.caller. If there is no such allowance present result is None, otherwise Some(int) is returned with the allowance amount.
from_account
address
option(int)
This function allows the Call.caller to change the allowed spendable value for for_account with value_change. This adds the value_change to the current allowance value. If used for increasing allowance amount a positive value should be passed, if the desired outcome is to lower the value of the allowed spendable value a negative value_change should be passed.
for_account
address
value_change
int
unit
Resets the allowance given for_account to zero.
for_account
address
unit
Allowance - MUST trigger on any successful allowance creation or change.
The approval event arguments should be as follows: (from_account, for_account, value)
from_account
address
for_account
address
value
int
This function burns the whole balance of the Call.caller and stores the same amount in the swapped map.
value
int
()
unit
This function returns the amount of tokens that were burned trough swap for the provided account.
account
address
int
int
This function returns all swapped tokens that are stored in contract state.
swapped
map(address, int)
Swap - MUST trigger when tokens are swapped and thus are no longer available in the given token contact.
The swap event arguments should be as follows: (account, value)
account
address
value
int
There are several implementations available at the moment, but they lack a thing or two (that is why this standard is being proposed).
Example implementations:
AEX: 9
Title: Fungible Token Standard
Author: @mradkov, @thepiwo
License: ISC
Discussions-To: https://forum.aeternity.com/t/aex-9-fungible-token/3565
Status: Review
Type: Standards Track
Created: 2019-05-11contract interface FungibleTokenInterface =
record meta_info =
{ name : string
, symbol : string
, decimals : int }
datatype event =
Transfer(address, address, int)
entrypoint aex9_extensions : () => list(string)
entrypoint meta_info : () => meta_info
entrypoint total_supply : () => int
entrypoint owner : () => address
entrypoint balances : () => map(address, int)
entrypoint balance : (address) => option(int)
entrypoint transfer : (address, int) => unitentrypoint aex9_extensions() : list(string)entrypoint meta_info() : meta_inforecord meta_info =
{ name : string
, symbol : string
, decimals : int }entrypoint total_supply() : intentrypoint balances() : map(address, int)entrypoint balance(owner: address) : option(int)stateful entrypoint transfer(to_account: address, value: int) : unitTransfer(address, address, int)Mint(address, int)stateful entrypoint mint(account: address, value: int) : unitMint(address, int)stateful entrypoint burn(value: int) : unitBurn(address, int)stateful entrypoint create_allowance(for_account: address, value: int) : unitstateful entrypoint transfer_allowance(from_account: address, to_account: address, value: int)entrypoint allowance(allowance_accounts : allowance_accounts) : option(int)record allowance_accounts =
{ from_account: address
, for_account: address }entrypoint allowances() : allowancesentrypoint allowance_for_caller(from_account: address) : option(int)stateful entrypoint change_allowance(for_account: address, value_change: int)stateful entrypoint reset_allowance(for_account: address)Allowance(address, address, int)stateful entrypoint swap() : unitstateful entrypoint check_swap(account: address) : intstateful entrypoint swapped() : map(address, int)Swap(address, int)add package version to footer ()
enhance signature verification ()
integrate routing and add documentation and FAQ pages ()
hydration error ()
undefined event definition errors ()
extract walletNodes initialization to improve network handling in wallet-sdk ()
enhance network change handling to validate nodes in pool before selection ()
increase security on request verification & add cleanup, pause, resume functions ()
improve network fetching logic and connection status handling in WalletProvider ()
update bridge contract addresses and operator account in network configurations ()
update string concatenation to use semicolons ()
update operator account address and improve balance fetching logic ()
add warning message to prevent incorrect token bridging between networks ()
conditionally render action history based on network support ()
increase retry limit for fetching bridge transaction ()
improve transaction processing & fixes ()
update condition to check for data length ()
add Aeternity SDK integration and update project configuration ()
add assets folder which includes global styles, logos, favicon, and font ()
add bridge configuration script and enhance deployment scripts with save option for ACI ()
add currency support to wallet management and update balance display ()
adjust legend class names for consistent styling in form components ()
change ClockIcon stroke color ()
correct amount handling in create_token_link_and_mint function ()
include current network in bridge form component ()
adjust margin and padding in bridge and connected view components for better layout consistency ()
bridge contract and tests ()
improve table layout and alert visibility in BridgeActionDetailsModal ()
monorepo ()
add Dockerfile for application containerization and remove build script ()
This guide shows you how to perform all the operations that you need within the lifecycle of æternity naming system (AENS) using the SDK.
If you successfully claimed a name it will expire after 180000 key blocks (~375 days). You will need to update your name before it expires!
Claiming an AENS name requires you (at least) 2 transactions:
First you need to perform a pre-claim by providing a commitmentId (hash).
The commitmentId is calculated with a random salt and the provided name. The SDK automatically generates the random salt, calculates the commitmentId and includes it into the NamePreclaimTx
Note:
After transaction is included, you have 300 key blocks to broadcast claim transaction with
the same salt and it should be signed with the same private key as pre-claim. - As the pre-claim is required to avoid front running it is recommended to wait with the actual claim until at least 1 key block has been mined so that nobody knows which name you aim to claim. - The corresponding claim cannot be included in the same key block anyway. The protocol doesn't allow that.
This example assumes that you did a pre-claim before and kept an instance of Name.
Depending on the length of the name in punycode the actual claim will result in direct ownership of the AENS name or start an auction:
Name length > 12: ownership of the name is immediately transferred to your account
Name length <= 12: an auction is started
Note:
The nameFee that is required will be correctly calculated automatically for the initial claim.
It's still possible to pass it as additional param, see .
In case the claim triggers an auction the required nameFee is locked by the protocol.
In case there is an auction running for a name you want to claim you need to place a bid.
Note:
It is required to provide a nameFee that is at least 5% higher than the current bid.
The node doesn't expose an API to request the nameFee of the last bid. You need to receive that information from the that you ideally host yourself.
Now that you own your AENS name you might want to update it in order to:
Set pointers to accounts, oracles, contracts, channels, or store binary data.
Extend the TTL before it expires.
By default a name will have a TTL of 180000 key blocks (~375 days). It cannot be extended longer than 180000 key blocks.
Note:
If you provide an empty pointers object and don't set extendPointers to true all of your current pointers will be removed.
If you provide a non-empty object of pointers to that function while using extendPointers the SDK will merge the existing pointers with those provided.
In case there already exists an account pointer and you provide an accounts address in the array the old account pointer will be overwritten
In case you want to extend a name using a custom TTL and keep the current pointers you can do this as follows:
In some cases you might want to transfer the ownership of a name to another account. Of course this is also possible and you can do that as follows:
In case you want to revoke a name prior to its expiration for whatever reason you can do that as follows:
Note:
On revocation the name enters in a revoked state.
After a timeout of 2016 key blocks the name will be available for claiming again.
It is possible to authorize a Sophia contract to manage an AENS name on behalf of your account. In order to achieve that you need to provide a delegation signature to the contract. The contract will then be able to use the and perform AENS related actions on behalf of your account.
This functionality could for example be used to build an AENS marketplace.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in .
This document describes the technical specification and methods that the wallet provider (ex. Base æpp, Wællet, MetaMask) MUST use to interact with Aeternity based applications (hereinafter referred to as 'aepp' or 'aepps').
import { AeSdk, Node, AccountMemory, encode, Encoding } from '@aeternity/aepp-sdk';
const aeSdk = new AeSdk({
nodes: [
{
name: 'testnet',
instance: new Node('https://testnet.aeternity.io'), // host your node for better decentralization
},
],
accounts: [new AccountMemory('sk_2CuofqWZHrABCrM7GY95YSQn8PyFvKQadnvFnpwhjUnDCFAWmf')],
});
const transactionInfo = await aeSdk.spend(
100, // aettos
'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E',
{ payload: encode(Buffer.from('spend tx payload'), Encoding.Bytearray) },
);
console.log(transactionInfo); async scanForWallets () {
return new Promise((resolve) => {
const handleWallets = async ({ wallets, newWallet }) => {
newWallet = newWallet || Object.values(wallets)[0]
if (confirm(`Do you want to connect to wallet ${newWallet.info.name} with id ${newWallet.info.id}`)) {
console.log('newWallet', newWallet)
stopScan()
this.walletInfo = await this.aeSdk.connectToWallet(newWallet.getConnection())
this.walletConnected = true
const { address: { current } } = await this.aeSdk.subscribeAddress('subscribe', 'connected')
this.$store.commit('aeSdk/setAddress', Object.keys(current)[0])
resolve()
}
}
const scannerConnection = new BrowserWindowMessageConnection()
const stopScan = walletDetector(scannerConnection, handleWallets)
})
},add daisyUI for enhanced styling, improve token and network selection UI, and update balance formatting (b4dcd0e)
add disconnect icon and enhance wallet management UI with address copy functionality (eda4504)
add footer component, update button components to outlined style, and enhance color variables in global CSS (9ad1e65)
add initial project configuration with NextJS (b4cfbfa)
add launch configuration for debugging and refactor network configurations (a9dce6e)
add network and address validation before fetching balance in wallet provider (d707b3d)
add network configs (a1b2e35)
add periodic sync for events every 10 seconds in backend index (aa7a011)
add reusable Button component and enhance wallet management with detection status handling (1443086)
add SQLite database, update backend server configuration, and enhance script commands (499c12b)
add tests and improve testing utility (fcf0098)
add TTL option to deposit function in useBridgeActions hook (ca69829)
add usage instructions for deploy-token script (2934416)
add wallet and contract types, enhance bridge state management, and update network/token selection components (020e807)
adjust transaction history layout for better responsiveness (e42f174)
clean up imports in bridge configuration and deploy-token scripts (292d9a4)
complete bridge action (491c4e5)
docs: intro updated (c116983)
enhance bridge action components with history visibility and update date formatting (ec93d26)
enhance bridge action provider with transaction detail fetching and error handling (c8ef520)
enhance bridge form layout with fieldset and improve error message display (ad7dc7f)
enhance bridge form with error handling, validation logic, and improved input components (8060691)
enhance bridge functionality with improved wallet connection handling, UI adjustments, and new contract state utilities (8dedaa3)
enhance deposit function to return deposit index and improve test coverage (eb98a63)
enhance layout and add bridge component for asset management (e543f38)
enhance transaction handling with new Deposit interface, add explorer URLs, and refactor components (1620b05)
enhance transaction list display, fixes, improvements (bfece2f)
extend contracts with more getters, add data sync, fixes (f8ea8af)
handle token balance retrieval gracefully by returning "0" for undefined results (c0e9527)
implement bridge action context and notification system; refactor network handling and API routes (2efec3b)
implement bridge action verification and refactor SDK instance creation (abd05c5)
implement bridge context and provider (21e62cb)
implement Hyperchain bridge form with token and network selection, add token constants, and update deployment scripts (a53e4d0)
implement input components for amount and token selection, enhance bridge form functionality, and improve state management (9563d7a)
implement network constants and SDK initialization for Aeternity (d50f267)
implement network verification and deployment functionality (63c235b)
implement wallet management components (2d4e857)
improve amount input validation and integrate wallet context in bridge form (63769fd)
integrate notistack for notifications, enhance bridge form validation, and refactor network selection component (7451bec)
integrate Supabase for network data retrieval and refactor related components (fe9502b)
refactor bridge fe components and remove unused NetworkDisplay (7309a25)
Refactor bridge transaction handling and introduce new APIs (a749404)
refactor header component (e597bb0)
rewrite bridge contract (ae41a22)
simplify network and token selection components by removing unused props (6f2e4ff)
update cache deployments (2458d95)
update deployment file references and enhance HyperchainBridge contract with index handling (c4dd778)
update frontend structure by adding index and render files, and refactor package.json scripts (f13b053)
Update HyperchainBridge contract and related components (6087099)
update layout and styling, replace SVG icons, and enhance bridge form components (bec76f0)
update package.json to support concurrent frontend and backend development (5207fe2)
update TTL for allowance and deposit functions, enhance bridge page styling with background img (e0232cd)
update usage instructions in configure-bridge script to support multiple token and network registrations (8b495fc)
remove default values for network URLs in NetworkForm component (19633e9)
remove status code from error response in byUserAddress API (b02c660)
update AE_TESTNET bridge contract address and include in DEFAULT_NETWORKS (dc24459)
update bridge contract address for AE_MAINNET (0ed9668)
update bridge contract addresses and improve bridge action handling (a40d2a5)
update bridge contract addresses for AE_TESTNET and AE_MAINNET (3107947)
update Dockerfile and package.json for consistency and production environment setup (fedc618)
update token transfer logic in HyperchainBridge (30d3478)
use environment variable for server port configuration (f5eed97)
remove unused network display logic and clean up component structure (134f356)
replace app.ts with server.ts for improved server handling and update package scripts (62e5a6c)
replace useNetworks hook with WalletContext for network management and introduce NetworkBalanceProvider (05c4fa8)
restructure project by removing web package and consolidating frontend and backend components (b74b1e6)
smart contracts and packages (0fed5cc)
update bridge contract handling and improve token balance fetching logic (e0bf16f)
update font weight in connected view for improved emphasis on balance display (3caf71d)
update styling in bridge form title and alert message for improved readability (3f9269d)
update useBridgeContract hook to return loading state and adjust usage in components (1dc9ab1)
update variable declarations to use const, improve code readability, and clean up unused functions (bb6d25a)
After the NamePreclaimTx transaction has been mined you will be able to perform the actual claim of the name. When performing the actual claim via a NameClaimTx you will, depending on the length of the name:
immediately become owner of that name
initiate an auction
pre-claim. The protocol itself doesn't reject a pre-claim transaction if the name isn't available anymore.If you win the auction the nameFee is permanently deducted from your accounts balance and effectively burned.
It will be credited to ak_11111111111111111111111111111111273Yts which nobody can access. This reduces the total supply of AE over time.
If somebody else outbids you the provided nameFee is immediately released and returned to your account.
It's also possible to pass additional transaction options here, too.
import { AeSdk, Name } from '@aeternity/aepp-sdk'
const aeSdk = new AeSdk({ ... }) // init the SDK instance with AeSdk class
// `getContext` is used to bind AeSdk to Name instance
// e.g. if you change the node in AeSdk it also would be changed in Name.
// Alternatively, you need to provide `onAccount`, `onNode` options.
const name = new Name('testNameForTheGuide.chain', aeSdk.getContext())
const preClaimTx = await name.preclaim()
console.log(preClaimTx)
/*
{
blockHash: 'mh_2UsggiUaQQmEPjxLnXkXHpm1WawTWqZb1jBx6UzsQNHgirWAwd',
blockHeight: 449499,
hash: 'th_48RktjEutZC8TCubaq9YhjaF1cKLV9D3VRCJyzJLs7oSp4Ry6',
signatures: [
'sg_Da98k2EKMun1TkE7ytonRypvJwaKg9iBjp8rNcYuodFXqzRqwjQyuFQP5DhxWUpTYRzSTurrNtDmUft8eyTStjCyNqFf8'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
commitmentId: 'cm_2igvW9egddKh77gDdE8mjotmL8PzE7Tf2Q639Q5stUqWQoEfap',
fee: 16620000000000n,
nonce: 18,
type: 'NamePreclaimTx',
version: 1
},
rawTx: 'tx_+JkLAfhCuEBgFzAL0bPDufmzDq0558vaKtrIyRpNxCYVtkgnJjBrxDpQZHkfbwG+oRuBUAfgfrAKF0lO9mRI1zq0H6bXIq8KuFH4TyEBoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAhKhA+Jawe/spFaw823K+U59CWx+xD1i34gngUPiAAKJqv/fhg8dpTI4AAAGc20E',
height: 449499
}
*/// the minimum `nameFee` will be automatically generated by sdk
// in case you want to provide a custom `nameFee` you can so so by providing it in an options object
// in case of starting the auction `nameFee` will be the starting bid
const claimTx = await name.claim();
console.log(claimTx);
/*
{
blockHash: 'mh_UvtuVNvK7k29G3anF48W4hgUMaFFLc1wKir55FFifgT49Egk',
blockHeight: 449507,
hash: 'th_2sWNusGUf2wuRn7d453wPWTAe8pKVbtNF4DqakvippsxjvF8g1',
signatures: [
'sg_LYsVj9zUoKFPDiSvFUWG5QaRhnqQ525YA314xMVzRhApYuPnFyMWgAQGpChKHHWyMbykBwVRrmoQtTENTFCaCoMj17CBK'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
fee: 16800000000000n,
name: 'testNameForTheGuide.chain',
nameFee: 2865700000000000000n,
nameSalt: 7595805618692717,
nonce: 19,
type: 'NameClaimTx',
version: 2
},
rawTx: 'tx_+KILAfhCuECVba2mm3Un3nrN9U+LpuB2wzqDDmAzXwvc+9sVkpkcALzqm14p7kGqyt8pwjGTyKeLM9lp+KgXWF4PHmHz0WAPuFr4WCACoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAhOZdGVzdE5hbWVGb3JUaGVHdWlkZS5jaGFpboca/FhPr2JtiCfFAveE1kAAhg9HjghAAADilhgr'
}
*/import { computeBidFee, computeAuctionEndBlock } from '@aeternity/aepp-sdk'
const name = new Name('auctiontest1.chain', aeSdk.getContext())
const startFee = ... // request from middleware, e.g. https://testnet.aeternity.io/mdw/name/auctiontest1.chain
const increment = 0.05 // 5%, the minimum required increment
// startFee is OPTIONAL and defaults to minimum calculated fee for the name in general
// startFee MUST be at least the nameFee of the last bid
// increment is OPTIONAL and defaults to 0.05
// `name.value` is a name as string
const nameFee = computeBidFee(name.value, { startFee, increment })
const bidTx = await name.bid(nameFee)
console.log(bidTx)
console.log(`BID PLACED AT ${bidTx.blockHeight} WILL END AT ${computeAuctionEndBlock(name, bidTx.blockHeight)}`)
/*
{
blockHash: 'mh_Y5LDYPtPWzcop2FCbxnwTSwjWo9d3rYcBBcChCEHfzHo2YZpm',
blockHeight: 449693,
hash: 'th_2nZshewM7FtKSsDEP4zXPsGCe9cdxaFTRrcNjJyE22ktjGidZR',
signatures: [
'sg_7G49bziWjjZAjayBhFffRyfLbmFczs2foJgXcx1n1Vo7iGELQqggdH4w72MqWbNUbM9Jv2EBJnd2LFjv6LJhqTmvJBWyr'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
fee: 16520000000000n,
name: 'auctiontest1.chain',
nameFee: 3159434250000000000n,
nameSalt: 0,
nonce: 24,
type: 'NameClaimTx',
version: 2
},
rawTx: 'tx_+JQLAfhCuEAv2HQoyLa7krHpcQAsPpWdP+6PJYzdPSifmwNIgpWZtyrdgVD+IGMzzAqxkOQEDeAwc/Oh+dfXPBZpNslCNFgBuEz4SiACoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAhiSYXVjdGlvbnRlc3QxLmNoYWluAIgr2JC2AnPkAIYPBly7UAAAm/NY1g=='
}
BID PLACED AT 449693 WILL END AT 479453
*/import { getDefaultPointerKey, encode, Encoding } from '@aeternity/aepp-sdk';
const oracle = 'ok_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk';
const pointers = {
account_pubkey: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
customKey: encode(Buffer.from('example data'), Encoding.Bytearray),
[getDefaultPointerKey(oracle)]: oracle, // the same as `oracle_pubkey: oracle,`
contract_pubkey: 'ct_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
channel: 'ch_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
};
const nameUpdateTx = await name.update(pointers);
console.log(nameUpdateTx);
/*
{
blockHash: 'mh_AiaGtTWBRys7EX5apAidShyCw1kefocuWt49DgLE2fWNCgKvq',
blockHeight: 449855,
hash: 'th_LLef19g2mLWQfG7Ds1XZNGyb3SGvi8PGvk7mJczpD9iToBcqL',
signatures: [
'sg_Zm7kp1oBnXGnHwdzsim9nTXtrGoV4bWJhcC1nkw9f3eMPibVaYQRoM829iNrPandAfs8TK7ogEkYByxQx11xCAFMpwUBz'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
clientTtl: 3600,
fee: 17800000000000n,
nameId: 'nm_1Cz5HGY8PMWZxNrM6s51CtsJZDU3DDT1LdmpEipa3DRghyGz5',
nameTtl: 180000,
nonce: 27,
pointers: [ [Object] ],
type: 'NameUpdateTx',
version: 1
},
rawTx: 'tx_+NQLAfhCuED6aLVAlIfcqczlZ4XzOjG3U23l5+egPFDVEKTSMuL0Zj18jUG6ctJxGGQubNoANFcwQl79T7w0dG4+FV7Qn3AKuIz4iiIBoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAhuhAgB4Gsn+dalOdWvHXJd+3LBBiO9HsZoHIF2/aQ4n/bbagwK/IPLxjmFjY291bnRfcHVia2V5oQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAoMBSniGEDBirVAAAJ7I9GA='
}
*/const nameUpdateTx = await name.extendTtl(100000);
console.log(nameUpdateTx);
/*
{
blockHash: 'mh_2mbAuBtyPp7wN6hrcvkYD7LZRSegwZZKYnLcNQkGVGRZ3uVxW6',
blockHeight: 449860,
hash: 'th_2wXE8i5BUFCUPuioKwAuwNysm6RPQo8STf5m91CuT3LTh7q4ko',
signatures: [
'sg_E69tfR3STWi5Dg6yUHQj5D5waTCEhoFmb1LYWGU2bsCnuLkMgH1KqhRKrCZaatDMyg5szgABDuU1r6ZD5K74qXWW5pMJ'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
clientTtl: 100000,
fee: 17800000000000n,
nameId: 'nm_1Cz5HGY8PMWZxNrM6s51CtsJZDU3DDT1LdmpEipa3DRghyGz5',
nameTtl: 100000,
nonce: 28,
pointers: [ [Object] ],
type: 'NameUpdateTx',
version: 1
},
rawTx: 'tx_+NQLAfhCuEABuZTyU+W5xmBpQn5GCJiSpK6fI0pYoMIQ5IqD2bs6pJ+oyU7HDGoSU0Mn6tsfYOn+MVRsxLR6yM1Vyv0c4JQNuIz4iiIBoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAhyhAgB4Gsn+dalOdWvHXJd+3LBBiO9HsZoHIF2/aQ4n/bbagwGGoPLxjmFjY291bnRfcHVia2V5oQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAoMBhqCGEDBirVAAANKYAm0='
}
*/const recipient = 'ak_...';
const nameTransferTx = await name.transfer(recipient);
console.log(nameTransferTx);
/*
{
blockHash: 'mh_ZuYV5tmJM4PhrfxzXfo9e37uqPcYpCiAoEC2uRcqbUXeMSmLH',
blockHeight: 449982,
hash: 'th_xXqmZxR7WJDe6YTz1GnHWgNjtcZjpTPA5bVuiQstmd8o6Gg7x',
signatures: [
'sg_72fiMzprywNmFtuf1i1FFfhBBXcPHpHDfi1Uv2bDnYayoCRWe1yyzvwLmhM6cfA3TR6pBF9Kj3iyYm3mrC46rvNCpchyi'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
fee: 17300000000000n,
nameId: 'nm_1Cz5HGY8PMWZxNrM6s51CtsJZDU3DDT1LdmpEipa3DRghyGz5',
nonce: 33,
recipientId: 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E',
type: 'NameTransferTx',
version: 1
},
rawTx: 'tx_+LsLAfhCuEAuFNHG4gniZjJDQtbm5cIfJACkU/NI96mZpwMvdyuxxOYWYxSxUF2NF5oxjmsYLdXWfSrdmgWj40JzZU/TRA4DuHP4cSQBoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAiGhAgB4Gsn+dalOdWvHXJd+3LBBiO9HsZoHIF2/aQ4n/bbaoQHVzwhADpiCIvJutLAsj4kHdFdGchGm5tlV7bcHScajO4YPu/hayAAABhgUgg=='
}
*/const nameRevokeTx = await name.revoke();
console.log(nameRevokeTx);
/*
{
blockHash: 'mh_2Q5Xqd4vrmwkS98SBkN79k1t9VLNmDX4wk8xnUJYTEvkK3YoH4',
blockHeight: 450018,
hash: 'th_2XhJradAVKN2jR2tgNYdKNWikMc8XunqTdUhRPh2TyhAwMqijJ',
signatures: [
'sg_Tjbf8SJDQXgBhaYk7AzTTr7d1RF3bDcMp6BMgRoHcHcgBp13HjcMYmZJ8vvqrZ94An9gvQD4NegYrR7eaBLt6jEy99xyM'
],
tx: {
accountId: 'ak_2519mBsgjJEVEFoRgno1ryDsn3BEaCZGRbXPEjThWYLX9MTpmk',
fee: 16620000000000,
nameId: 'nm_1Cz5HGY8PMWZxNrM6s51CtsJZDU3DDT1LdmpEipa3DRghyGz5',
nonce: 34,
type: 'NameRevokeTx',
version: 1
},
rawTx: 'tx_+JkLAfhCuEDMWOZac70tEHQ4AHGBIedZepwTvsBjIHk36vhTd5yBepmTemTQcUVrAtbNO3jZVZD4GUOhN+DfXm2lNrpZu+8FuFH4TyMBoQGMyNToF1flcYDSVsPl5DZ9ZY3FJWRpDRQYD32quWBEAiKhAgB4Gsn+dalOdWvHXJd+3LBBiO9HsZoHIF2/aQ4n/bbahg8dpTI4AAB44bma'
}
*/const contractAddress = 'ct_asd2ks...';
// AENS name
const nameId = 'example.chain';
const commonParams = {
contractAddress,
accountAddress: aeSdk.address,
};
let delegation;
// this signature will allow the contract to perform a pre-claim on your behalf
delegation = packDelegation({ tag: DelegationTag.AensPreclaim, ...commonParams });
// this signature will allow the contract to perform
// any name related transaction for a specific name that you own
delegation = packDelegation({ tag: DelegationTag.AensName, nameId, ...commonParams });
// alternatively, you can generate a delegation signature suitable for every name you own
delegation = packDelegation({ tag: DelegationTag.AensWildcard, ...commonParams });
const delegationSignature = await aeSdk.signDelegation(delegation);import { Node, AccountMemory, buildTxAsync, Tag, encode, Encoding } from '@aeternity/aepp-sdk';
const onNode = new Node('https://testnet.aeternity.io'); // host your node for better decentralization
const account = new AccountMemory('sk_2CuofqWZHrABCrM7GY95YSQn8PyFvKQadnvFnpwhjUnDCFAWmf');
const spendTx = await buildTxAsync({
tag: Tag.SpendTx,
senderId: account.address,
recipientId: 'ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E',
amount: 100, // aettos
payload: encode(Buffer.from('spend tx payload'), Encoding.Bytearray),
onNode,
});
const signedTx = await account.signTransaction(spendTx, { networkId: await onNode.getNetworkId() });
// broadcast the signed tx to the node
const { txHash } = await onNode.postTransaction({ tx: signedTx });
console.log(txHash);import { AeSdkAepp, Node } from '@aeternity/aepp-sdk';
const TESTNET_NODE_URL = 'https://testnet.aeternity.io';
const MAINNET_NODE_URL = 'https://mainnet.aeternity.io';
const COMPILER_URL = 'https://compiler.aepps.com';Tools:
git
OTP 25 or 26
C++ compiler
Libraries:
Clone the repo:
Set up the environment:
Build the project (the make step may need to be executed twice, see this issue):
Launch the REPL
For a consistent setup, a docker image can be created:
Then to start the dockerized REPL:
Use make podman for a podman build.
æREPL usage patterns are highly inspired byGHCi. Most of the syntax is a direct adaptation of it to the needs of Sophia and FATE. This section shall provide an overview of the most fundamental features and typical workflows. If you find navigation clunky, please consider usingrlwrap.
Main functionality of æREPL is to evaluate Sophia expressions:
Aside from that, values can be assigned to REPL-local variables (pattern matching is supported)
Functions and types are supported as well
NOTE: in-REPL functions cannot use in-REPL variables and other functions yet.
A common query is to ask about the type of an expression. This is done using the:type command:
æREPL allows loading files to call their code and deploy contracts defined in
them. To load a file, the :load command may be used:
If multiple files are loaded, only the most recent one is brought to the scope.
To include other loaded files into the working scope, Sophia's include should
be used:
Note that :load reloads all listed files and unloads those skipped. Yet
another useful command is :reload, which reloads all loaded files, preserving
the included scope.
:load and :reload clear out the scope, meaning that they will clean
User defined variables
User defined functions
User defined types
Includes
Deployed contracts
In-REPL state
æREPL maintains its own Sophia state which can be accessed using standard
operations put and state, as well as stateful functions. By default, the
state is set to () : unit. In order to change it to some other type, :state
command should be used:
Note that :state is parameterized by value, not by type. The value has to have
a fully instantiated, non-functional type. Changing the state using the :state
commands clears out all user-defined variables and functions --- if that is not
desired, put should be used to modify the state if possible.
æREPL can be configured interactively using the :set command. The syntax for
this command is :set OPTION [ARGS], for example
Currently the supported options are:
call_gas
non-neg int
Determines the amount of gas to be supplied to each query.
-------------------------
--------------------
:--------------------------------------------------------------------
call_value
non-neg int
The value, the amount of tokens supplied with the query.
-------------------------
--------------------
:--------------------------------------------------------------------
By default, the REPL shall display values preserving compatibility with Sophia
syntax. An exception from that rule are values containing functions which
in FATE are represented as pairs of function name and closure. In that case,
the output will take a form of "<fun $FUNHASH>" : $TYPE where $TYPE is
the type of the function (according to the Sophia code, not FATE bytecode), and$FUNHASH is a hex-encoded shortcut of the original function's name hashed with
BLAKE2B (as it is stored in the bytecode). For example
If print_format is set to fate, the value shall be displayed as an Erlang
term that describes the exact representation of the value in the runtime.
If set to json, the values will be encoded in JSON format. Information about
record fields and datatype constructor names shall not be dropped. Function
values are represented as strings in the same manner as in the sophia format.
To type in a multiline block of code, surround it with :{ and :}:
If REPL is used as a library for a different tool, its generic server can be
used for more structured interface. The server is located insrc/aere_gen_server.erl and implements the standard gen_server Erlang
behaviour.
Use aere_gen_server:start/1 to start up the server. aere_gen_server:start/2
allows to start a server under a custom name. The argument is property list with
the following fields:
options --- parameter map for the repl configuration. See "Configuration"
for more details.
accounts :: list(#{pubkey() => integer()}) --- list of initial accounts and
their balances
quit --- terminates the server
skip --- does nothing
bump_nonce --- bumps internal REPL nonce (used in naming internal variables)
blockchain_state --- returns the chain state for the current session
theme --- returns the current display theme
{type, string()} --- parses the expression and returns its type in the
session context
{state, string()} --- parses the expression and evaluates it in the session
context. The restult is then assigned to the session's contract store. All
locally defined functions, variables and types are pruned.
{eval, string()} --- parses the expression and evaluates it in the session
context
{load, list(string())} --- Loads files from the file system. Includes the
first one in the list.
reload --- Reloads the currently loaded files.
{set, Option :: atom(), Value :: list(term())} --- changes REPL's
configuration (see {help, "set"} for more details)
help --- lists all available commands
{help, string()} --- returns the help text for the given command
{lookup, atom()} --- prints information about REPL's state or configuration
{disas, string()} --- parses a reference to a function and prints its FATE
code
stop --- if at breakpoint, cancels the execution and rolls back all changes
{break, FileName :: string(), Line :: integer()} --- adds a breakpoint
{delete_break, integer()} --- removes a breakpoint with a given id
{delete_break_loc, string(), integer()} --- removes all breakpoints from the
given file at the given line
continue --- resumes execution after a breakpoint stop
stepover --- proceeds to the next line in the current execution
stepin --- proceeds to the next line, or enters the function body if there
is a function call upcoming
stepout --- resumes execution until the next breakpoint or current function
return
location --- returns in-code location of current execution
{print_var, string()} --- returns in-code location of where the variable was introduced
print_vars --- returns values of all variables in scope
stacktrace --- returns the current stacktrace
{set_account, pubkey(), integer()} --- sets balance for an in-repl account
version --- returns version information
banner --- returns an ASCII "banner" presenting the REPL's logo and various
version information
{update_filesystem_cache, #{string() => binary()}} --- updates REPL's
perception of the file system to the provided map. If this is set, all include
and file load instructions will ignore system's file system, and will use this
map instead.
All above calls and casts are exposed as function calls for convenience. Additionally, the following are offered:
format --- formats outputs of other commands into renderable texts to be
used by the render function
render --- renders a renderable output to a string using REPL's theme
banner --- returns a nicely rendered banner for CLI interfaces
input --- parses a text command and interprets it as one of the calls
above. Useful for CLI-like interfaces.
prompt --- proposes prompt to display in the CLI based on the REPL's
state. For example, the default is AESO> .
Currently, there exists no standard way for wallets and aepps to communicate and everything developed on the SDK side is developed only keeping the Base æpp in mind and rest of the wallet providers need to follow the same path. By defining the standard way of communication between aepps and Wallet we will not only reduce the dependency that other wallet providers have on the Base æpp as well as we'll have a clear standard method of communication on the SDK side that can be further extended upon whenever required.
Wherever possible, this document tries to closely follow the who.what.how naming convention for JSON-RPC methods.
JSON-RPC 2.0 response error object that is used to communicate any error occurred while processing the request.
Types of errors
Code
Message
Meaning
1
Invalid transaction
MUST be returned whenever the transaction validity check fails and the node returns a similar error
2
Broadcast failed
MUST be returned by the aepp or wallet if it has been unable to broadcast the transaction.
3
Rejected by user
MUST be returned by the wallet when user denies the action request by aepp.
4
Unsupported protocol version
MUST be returned by wallet when it does not support protocol version the aepp wants to connect through.
Aepp Invokable Methods
This section defines the methods that the aepps MUST invoke to either get information from the wallet or request the wallet to perform an action.
connection.open: connection request sent by the aepp to the wallet.
Parameters
Object
version: protocol version. Currently defaults to 1.
Returns
Object
networkId: Network id used by the wallet
Returns errors
Unsupported protocol version
Unsupported network
address.subscribe: request the wallet to get or subscribe to address changes. This method MUST return only if the aepp is successfully subscribed else it MUST throw the appropriate error.
Parameters
Object
type: payload indicating the type of update i.e. subscription or un-subscription. This supports two options:
transaction.sign: request wallet for signature
Parameters
Object
tx: unsigned encoded transaction (Datatype: String).
return
Wallet Invokable Notifications
connection.announcePresence: MAY be used by the wallets to announce their presence wherever required (e.g. postMessage API). This message SHOULD NOT be used by the wallets where a 1-to-1 connection with the aepp is already established but instead wait for the aepp to initiate the connection using connection.open message.
Note: This is a helper message for the aepp to identify the presence of a wallet.
Parameters
Object
networkId: Network id used by the wallet
networkId.update: MUST be used by Wallet for informing Aepp about the change of network id.
Parameters
Object
networkId: Updated network id.
address.update: MUST be used by the wallet to notify subscribed aepps about the address change.
Parameters
Object
address: JSON Object. This MAY contain 1 or more keys but only of the below types. The values in the object completely depend on the aepp's subscription.
Subscription Type:
Invokable by Wallet and Aepp
connection.close: SHOULD be used by Aepp or Wallet for informing the other party that it is disconnecting and further requests will either be denied or not acknowledged.
Aepp: https://github.com/aeternity/aepp-sdk-js/tree/feature/aex-2/examples/browser/vuejs/connect-two-ae
Extension Wallet: https://github.com/aeternity/aepp-sdk-js/tree/feature/aex-2/examples/browser/extension
Transaction Encoding and Serialization https://github.com/aeternity/protocol/blob/master/node/api/api_encoding.md https://github.com/aeternity/protocol/blob/master/serializations.md
JSON-RPC 2.0 Specification https://www.jsonrpc.org/specification
git clone https://github.com/aeternity/aerepl.gitexport ERLANG_ROCKSDB_OPTS="-DWITH_SYSTEM_ROCKSDB=ON -DWITH_LZ4=ON -DWITH_SNAPPY=ON -DWITH_BZ2=ON -DWITH_ZSTD=ON"
export CXXFLAGS="-Wno-error=shadow -Wno-deprecated-copy -Wno-redundant-move -Wno-pessimizing-move"cd aerepl
make./aereplmake dockerdocker run -i aeternity/aerepl:localAESO> 2 + 2
4AESO> let x = 2
AESO> let (q, w) = (x + 1, x - 1)
AESO> q
3
AESO> w
1AESO> record point = {x : int, y : int}
AESO> function get_x(p : point) = p.x
AESO> get_x({x = 100, y = 42})
100AESO> :type Oracle.query
(oracle('a, 'b), 'a, int, Chain.ttl, Chain.ttl) => oracle_query('a, 'b)// File: Test.aes
namespace N =
function f() = 100
contract C =
entrypoint f() = N.f() + 23AESO> :load Test.aes
AESO> N.f()
100
AESO> let c = Chain.create() : C
AESO> c.f()
123AESO> include "List.aes"AESO> :load X.aes Y.aes
AESO> Y.y() // defined in Y.aes
"y"
AESO> X.x() // defined in X.aes
1:1 Unbound variable: X.x
AESO> include "X.aes"
AESO> X.x() // Now it works
"x"AESO> :set print_unit true
AESO> state
()
AESO> :state 1000
AESO> state + 1
1001
AESO> put(state / 2)
()
AESO> state
500AESO> :set print_unit trueAESO> () => ()
"<fun E3472E14>" : () => unitAESO> :set print_format fate
AESO> record r = {x : int, y : int}
AESO> {y = 100, x = 7}
{tuple,{7,100}}
AESO> Some(1)
{variant,[0,1],1,{1}}
AESO> () => ()
{tuple,{<<227,71,46,20>>,{tuple,{}}}}AESO> :set print_format json
AESO> record r = {x: int, y : int}
AESO> ({x = 3, y = 4}, "STRING")
[
{
"x": 3,
"y": 4
},
"STRING"
]AESO> :{
| let x = 123
| x
| :}
123AEX: 2
Title: Third-party Wallet Provider Support
Author: Shubhendu Shekhar (@shekhar-shubhendu), Andrea Giacobino (@noandrea), Enrico Icardi (@ricricucit) & Nazar Duchak (@nduchak)
License: BSD-3-Clause
Discussions-To: https://forum.aeternity.com/t/aex-2-js-sdk-interfaces-for-wallets/2715
License-Code: Apache-2.0
Status: Withdrawn
Type: Standards Track
Created: 2019-03-04import browser from 'webextension-polyfill';
import {
BrowserRuntimeConnection,
BrowserWindowMessageConnection,
MESSAGE_DIRECTION,
connectionProxy,
} from '@aeternity/aepp-sdk';
(async () => {
console.log('Waiting until document is ready');
await new Promise((resolve) => {
const interval = setInterval(() => {
// TODO: ensure that there is no corresponding event
if (document.readyState !== 'complete') return;
clearInterval(interval);
resolve();
}, 100);
});
console.log('Document is ready');
const port = browser.runtime.connect();
const extConnection = new BrowserRuntimeConnection({ port });
const pageConnection = new BrowserWindowMessageConnection({
target: window,
...(window.origin !== 'null' && { origin: window.origin }),
sendDirection: MESSAGE_DIRECTION.to_aepp,
receiveDirection: MESSAGE_DIRECTION.to_waellet,
});
connectionProxy(pageConnection, extConnection);
})();call_gas_price
non-neg int
The result of Call.gas_price
-------------------------
--------------------
:--------------------------------------------------------------------
call_origin
pubkey
The account to initiate execution of in-REPL code.
Defines Call.origin and initial Call.caller.
-------------------------
--------------------
:--------------------------------------------------------------------
call_contract_creator
pubkey
The result of Contract.creator.
-------------------------
--------------------
:--------------------------------------------------------------------
call_fee
non-neg int
The result of Call.fee.
-------------------------
--------------------
:--------------------------------------------------------------------
call_height
non-neg int
The result of Chain.block_height.
-------------------------
--------------------
:--------------------------------------------------------------------
print_gas
true/false
If true, REPL will print gas used for evaluating each expression.
-------------------------
--------------------
:--------------------------------------------------------------------
print_format
sophia/fate/json
Determines the syntax used to display values.
-------------------------
--------------------
:--------------------------------------------------------------------
print_unit
true/false
Whether to display unit (()).
-------------------------
--------------------
:--------------------------------------------------------------------
print_type
true/false
Whether to display the type after each eval.
-------------------------
--------------------
:--------------------------------------------------------------------
loc_backwards
non-neg int
Number of previous lines to be displayed when using location.
-------------------------
--------------------
:--------------------------------------------------------------------
loc_forwards
non-neg int
Number of further lines to be displayed when using location.
import browser from 'webextension-polyfill';
import {
AeSdkWallet,
CompilerHttp,
Node,
AccountMemory,
BrowserRuntimeConnection,
WALLET_TYPE,
RpcConnectionDenyError,
RpcRejectedByUserError,
RpcNoNetworkById,
unpackTx,
unpackDelegation,
} from '@aeternity/aepp-sdk';
import { TypeResolver, ContractByteArrayEncoder } from '@aeternity/aepp-calldata';
function stringifyBigint(value) {
return JSON.stringify(value, (k, v) => (typeof v === 'bigint' ? `${v} (as BigInt)` : v), 2);
}
let popupCounter = 0;
async function confirmInPopup(parameters) {
const popupUrl = new URL(browser.runtime.getURL('./popup.html'));
const popupId = popupCounter;
popupCounter += 1;
popupUrl.searchParams.set('data', stringifyBigint({ ...parameters, popupId }));
await browser.windows.create({
url: popupUrl.toString(),
type: 'popup',
height: 600,
width: 600,
});
return new Promise((resolve) => {
const handler = (message, sender, sendResponse) => {
if (message.popupId !== popupId) return;
resolve(message.response);
sendResponse();
browser.runtime.onMessage.removeListener(handler);
};
browser.runtime.onMessage.addListener(handler);
});
}
const aeppInfo = {};
const genConfirmCallback = (action) => async (aeppId, parameters, aeppOrigin) => {
const isConfirmed = await confirmInPopup({
...parameters,
action,
aeppId,
aeppInfo: aeppInfo[aeppId],
aeppOrigin,
});
if (!isConfirmed) throw new RpcRejectedByUserError();
};
class AccountMemoryProtected extends AccountMemory {
async signTransaction(transaction, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) {
if (id != null) {
const opt = { ...options, transaction, unpackedTx: unpackTx(transaction) };
if (opt.onCompiler) opt.onCompiler = '<Compiler>';
if (opt.onNode) opt.onNode = '<Node>';
await genConfirmCallback('sign transaction')(id, opt, aeppOrigin);
}
return super.signTransaction(transaction, options);
}
async signMessage(message, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) {
if (id != null) {
await genConfirmCallback('sign message')(id, { ...options, message }, aeppOrigin);
}
return super.signMessage(message, options);
}
async signTypedData(data, aci, { aeppRpcClientId: id, aeppOrigin, ...options }) {
if (id != null) {
const dataType = new TypeResolver().resolveType(aci);
const decodedData = new ContractByteArrayEncoder().decodeWithType(data, dataType);
const opt = {
...options,
aci,
data,
decodedData,
};
await genConfirmCallback('sign typed data')(id, opt, aeppOrigin);
}
return super.signTypedData(data, aci, options);
}
async unsafeSign(data, { aeppRpcClientId: id, aeppOrigin, ...options } = {}) {
if (id != null) {
await genConfirmCallback(`sign raw data ${data}`)(id, options, aeppOrigin);
}
return super.unsafeSign(data, options);
}
async signDelegation(delegation, { aeppRpcClientId: id, aeppOrigin, ...options }) {
if (id != null) {
const opt = { ...options, ...unpackDelegation(delegation) };
await genConfirmCallback('sign delegation')(id, opt, aeppOrigin);
}
return super.signDelegation(delegation, options);
}
static generate() {
return new AccountMemoryProtected(super.generate().secretKey);
}
}
const aeSdk = new AeSdkWallet({
onCompiler: new CompilerHttp('https://v8.compiler.aepps.com'),
nodes: [
{ name: 'ae_uat', instance: new Node('https://testnet.aeternity.io') },
{ name: 'ae_mainnet', instance: new Node('https://mainnet.aeternity.io') },
],
accounts: [
new AccountMemoryProtected('sk_2CuofqWZHrABCrM7GY95YSQn8PyFvKQadnvFnpwhjUnDCFAWmf'),
AccountMemoryProtected.generate(),
],
id: browser.runtime.id,
type: WALLET_TYPE.extension,
name: 'Wallet WebExtension',
async onConnection(aeppId, params, aeppOrigin) {
const isConfirmed = await confirmInPopup({
action: 'connect',
aeppId,
aeppInfo: params,
aeppOrigin,
});
if (!isConfirmed) throw new RpcConnectionDenyError();
aeppInfo[aeppId] = params;
},
onDisconnect(aeppId, payload) {
console.log('Client disconnected:', aeppId, payload);
},
onSubscription: genConfirmCallback('subscription'),
onAskAccounts: genConfirmCallback('get accounts'),
async onAskToSelectNetwork(aeppId, parameters, origin) {
await genConfirmCallback('select network')(aeppId, parameters, origin);
if (parameters.networkId) {
if (!this.pool.has(parameters.networkId)) throw new RpcNoNetworkById(parameters.networkId);
await this.selectNode(parameters.networkId);
} else {
this.pool.delete('by-aepp');
this.addNode('by-aepp', new Node(parameters.nodeUrl));
await this.selectNode('by-aepp');
}
},
});
// The `ExtensionProvider` uses the first account by default.
// You can change active account using `selectAccount(address)` function
browser.runtime.onConnect.addListener((port) => {
// create connection
const connection = new BrowserRuntimeConnection({ port });
// add new aepp to wallet
const clientId = aeSdk.addRpcClient(connection);
// share wallet details
aeSdk.shareWalletInfo(clientId);
const interval = setInterval(() => aeSdk.shareWalletInfo(clientId), 3000);
port.onDisconnect.addListener(() => clearInterval(interval));
});
console.log('Wallet initialized!');subscribe (datatype: string): MUST be used by the aepp to request a subscription.
unsubscribe (datatype: string): MUST be used by the aepp to request an un-subscription.
value: indicating the subscription/un-subscription that needs to be handled Currently supported options:
current (datatype: string): MUST be used to for current user account
connected (datatype: string): MUST be used for connected wallet accounts.
Returns
Object
subscription: Array of string indicating the current subscriptions. Example: ['current', 'connected']
address: This is a nested JSON Object containing the subscribed addresses in the below defined format. Same as address.update notification, please refer for more details.
This field MUST be included in the response when the wallet receives a subscription request i.e. when type == 'subscribe'.
This field is OPTIONAL in the response when the wallet receives an un-subscription request i.e. when type == 'unsubscribe'.
Returns errors
Rejected by user
Account Format:
falsetrue: the aepp is indicating that it is expecting a signed transaction back in return and do not want the wallet to perform a transaction broadcast.
false: the aepp wants the wallet to sign and broadcast the transaction and return only the transaction id.
Returns
Object
result: this can be either of two values depending on the request (as mentioned in the above description of return):
signed transaction: signed encoded transaction (Datatype: String).
transaction hash: encoded transaction hash (Datatype: String).
Returns errors
Invalid transaction
Rejected by user
Broadcast failed
current: Object containing only a single account currently in use by the wallet. The account MAY also have an embedded name key which is a human-readable name for the account.
connected: Object containing multiple connected accounts. The accounts MAY also have an embedded name key which is a human-readable name for the account.
Account Format:
{
"<subscription_type>": {
"<account_public_key>": {
"name": "<optional_human_readable_account_name>"
}
}
} {
"<subscription_type>": {
"<account_public_key>": {
"name": "<optional_human_readable_account_name>"
}
}
}The new Aeternity Middleware is a complete rewrite of the legacy middleware.
Versioned API: Implement a versioning strategy for the API to ensure backward compatibility and allow for future updates without breaking existing integrations. This helps to manage changes and provide a stable interface for clients.
Rapid Sync Speed: Optimize the sync process to achieve faster data synchronization. This can involve improving algorithms, utilizing parallel processing, optimizing database queries, or implementing efficient caching mechanisms. By reducing sync times, you can provide real-time or near real-time data updates to users.
Lean, Fast, and Easy Development and Deployment: Focus on improving the middleware's performance, reducing resource consumption, and enhancing its development and deployment process. Employ efficient coding practices, utilize lightweight frameworks, and automate deployment pipelines to streamline development and ensure faster, hassle-free deployments.
Reliable Paginated Retrieval: Enhance the API endpoints to support reliable paginated retrieval of information. Implement mechanisms such as cursor-based pagination or offset-based pagination to allow clients to retrieve data in manageable chunks, improving performance and preventing overwhelming large result sets.
Complex Search Queries: Enable the ability to perform complex search queries across multiple endpoints. Implement advanced search capabilities, such as filtering, sorting, and aggregations, to empower users to retrieve specific and relevant information from the middleware. This can be achieved by integrating powerful search engines or implementing custom search functionalities.
Implementation keeping these goals in mind should result in a middleware usable as a data source for the frontend, as well as a generic service component in any other setup working with Aeternity chain.
The design decision with the greatest impact was to run the middleware logic in the same BEAM process where AE node runs.
By using Elixir for implementation, we can understand middleware as an application running alongside the AE node, via.
The extension of this decision is using the same database as AE node does (RocksDB).
The benefits of these decisions were:
No network transfers between middleware and AE node
No network transfers between middleware and datastore
Much simpler and cheaper flow of data
Significant speedup in syncing (approx 100 times faster)
Middleware could be understood as an application running inside of Aeternity node OS process, along with Aecore application which implements the Aeternity node logic.
Image below depicts how these two large blocks fit together.
By merging the database types of AE node and Middleware, we can save a significant amount of space and work with both datasets in the same way - using RocksDB transactions and working with similar data model - sets of records.
The Middleware keeps track of several distinct types of information:
Plain data indices - blocks, transactions and ids (public keys) inside transactions - keyed by integers or tuples of integers
Objects with lifecycle - names, oracles and channels - keyed by strings or hashes
Supporting information - origin of objects and data, valency of public keys, name ownership and pointers
Feature specific information - contract logs, events and calls, AEx9 and AEx141 (token) support
All DB tables used by Middleware are of type ordered_set. All keys of the
tables (except - oracle identifiers which are public keys) are then meaningfully
ordered - either by history (blocks, transactions) or lexicographically (names).
Plain data indices don't evolve - change their state - as the chain progresses. A spend transaction (for example) is still the same transaction, 1 or 100K generations after it was executed.
Objects with the lifecycle are different. As the chain progresses, each object changes its state at specific heights. The state of the object and height when the state is changed depends on the sequence of transactions related to the object.
For each new generation, the sync process needs to check if some objects expired.
The lifecycle model of names, oracles and channels have the following states:
active - after claim/create/register transaction, extended by update/extend
transaction
inactive - happens automatically after time period (or, for names via revoke
or close transactions)
Supporting information is needed for quick resolving of the origin (of name, oracle, contract or channel) or database invalidations in case of chain fork event. Another example of supporting information is tracking of the counts of public keys in transaction fields. These counts are used for optimization of transaction queries.
When constructing detailed replies to the requests, Middleware often looks into data belonging to the AE node's Merkle-Patricia Tries.
The key and micro blocks are identified by hash, but for usable investigation of history or specifying the scope we want to look into, integer indices are very useful. From the hash of the block only, we can't know which generation the block belongs to, and by extension, we don't know which block precedes it or succeeds it.
The block index solves this by indexing the block hash with tuple in the format:{key_block_index, micro_block_index}
key_block_index identifies the generation (or height) of the block,micro_block_index identifies the position of the micro block in the
generation.
Both indices start from 0, but since we are mapping two different types of block
to the same set, we need a special value of micro_block_index for the key
block. Since the key block starts the generation, and is followed by micro
blocks with micro block index from 0, the special micro block index for key
block has always the value -1.
This ensures ordering of both key and micro blocks as per Erlang's term order.
The database model of the table record is defined as:
Table holding these records is Model.Block.
Transaction index is a non-negative, always increasing integer, uniquely identifying the transaction.
It is a fundamental piece of information used as a reference to transactions in all other, specialized indices in the Middleware.
Specialized indices like time, type or field are not unique on their own, so for the purpose of ensuring uniqueness of specialized index entries, transaction index is part of the key. The database model of the table record is defined as:
The table holding these records is Model.Tx.
The id/hash of the transaction is used for fetching the transaction details.
Since the transaction index is an integer, it's easy to see which transaction
precedes or succeeds another transaction. Transaction index also allows us to
specify a scope (start_index..end_index) in the queries to state what we are
interested in.
Specialized index - time
The time index is useful for mapping time to the transaction. While the public endpoints don't support time based queries, the internal query language supports it.
The database model of the table record is defined as:
Stored in table Model.Time.
The time (in milliseconds) marks when the whole micro block is added to the DB. Since there can be many transactions in one micro block, the transaction index is used in the key to keep uniqueness of the time entry.
Specialized index - type
The type index is mapping transaction type to the transactions. It allows us to quickly filter transactions per transaction type, and are also used for queries with multiple types or type groups.
The database model of the table record is defined as:
Stored in table Model.Type.
Similarly as in time record key, the transaction index serves the purpose of keeping uniqueness of the type record.
Representing objects with a lifecycle is a lot more challenging than plain data. While plain data like blocks or transactions are inserted once during syncing, objects with lifecycles need to be actively managed and potentially updated every time a new generation starts.
The simplified model of objects has states:
in auction (some names only (*))
active
inactive
(*) names (without domain) shorter than 12 ascii characters and claimed after Lima hard-fork
After objects expire, they are in an inactive state, and can be moved to an active (or "in auction") state again. The periods during which the objects are in an active state are called "epochs".
The state changes are tracked via manipulating of expiration table records stored in object specific tables, defined as:
The states are mapped to DB tables - e.g. if some object is stored in it's active table, we know the object is in active state. Changing states means removing the object from one table, and inserting it into another. This way we can conveniently list objects of specific state, and have them sorted lexicographically where it makes sense (e.g. names).
A lot of information in objects takes the shape named as bi_txi_idx, composed of{block_index, txi_idx} where the block index is {key block index, micro block index}
and the txi_idx is composed of {transaction index, contract call index} where the
contract call index is -1 is the raw transaction (no contract call) is being referenced.
Names
Names use following expiration tables for tracking generations when are the states changed:
Model.AuctionExpiration
Model.ActiveNameExpiration
Model.InactiveNameExpiration
The auction table record has following definition:
The name table records represent both active and inactive names, depending on the table there are stored:
Tables below store the actual objects:
Model.AuctionBid (auction)
Model.ActiveName (name)
Model.InactiveName (name)
Oracles
Oracles use following expiration tables for tracking generations when are the states changed:
Model.ActiveOracleExpiration
Model.InactiveOracleExpiration
The oracle table records represent both active and inactive oracles, depending on the table there are stored in:
Tables below store the actual objects:
Model.ActiveOracle
Model.InactiveOracle
Tables for keeping supporting information are needed for several reasons:
Tracking origin of objects
When objects (with or without lifecycle) like contracts, channels, oracles and names are created via their creation transaction, the identifier of such objects is not part of the creation transaction. It is useful to maintain the mapping between transactions and the created objects.
The origin table record has the following definition:
Rev origin records are kept in the Model.RevOrigin table.
In both origin and rev_origin models, ideally we could represent the
necessary information without storing the transaction type. The reason why we
need transaction type here, is because oracles are identified with the same
public key as the account which created the oracle. Since we don't keep tags
(e.g.: account_pubkey, contract, oracle, ...) in our identifiers - just
public key binaries - the transaction type allows us to differentiate between
spend transactions and oracle transactions.
Tracking public keys inside transaction fields and their valency
The query language supports constructs where we can provide identifiers in the transaction fields to match.
For illustration, a typical spend transaction looks as follows:
Here, the identifiers in transaction fields we index would be sender_id (at
position 1) and recipient_id (at position 2) - extracted from the AE node
spend transaction representation, having the fields: [sender_id,recipient_id, amount, fee, ttl, nonce, payload].
The field table record allowing us to quickly operate on this information is defined as:
Records of this shape are stored in the Model.Field table.
When the query contains more than one transaction field to match, we have several ways to search for the result. The role of the query optimizer is to select the optimal way to traverse the tables. For this selection, the query optimizer uses the counts of the occurrences of the public keys in the transaction fields.
Below is the definition of the table records keeping this information:
Records of this shape are stored in table Model.IdCount.
Tracking name ownership and pointees
The data stored by the AE node name system doesn't provide all the information we want to be able to query. Due to this reason, we need to maintain separate tables.
Tables Model.AuctionOwner and Model.ActiveNameOwner hold answers to the
query which names (in auction, or currently active) belong to a given owner
public key.
The table record is defined as:
Another table - Model.Pointee - holds answers to queries on who (which account
public key) points to a name. The table record are defined as:
On the latest version, a new concept called has been introduced. This concept serves as a declarative representation of the Middleware state, encompassing all the models and their key-value records in a sorted manner.
The State is defined alongside its internal component called. The purpose of the Store is to provide an
interface for getting, putting, and deleting values. This abstraction allows
for flexibility in defining various types of storage that may be needed. Here
are some examples:
: This implementation directly interacts with RocksDb, performing queries and storing data without relying on a transaction.
: This implementation
encapsulates all operations within a RocksDb transaction.
: This implementation stores operations in memory using a Map data structure.
By utilizing this functional abstraction, it becomes easier to perform in-memory syncing for a specific range (e.g., the last 10 generations) while retaining the rest of the data in a persistent storage system like RocksDb. This approach allows for efficient data management and synchronization, leveraging the benefits of both in-memory and persistent storage solutions.
The goal of the syncing process is to translate AE node data to actionable middleware data which allows querying.
The syncing process (AeMdw.Sync.Watcher) listens to the AE node top_changed
event which references a new block added on the main chain. For every block
added, a new message is sent to the syncing server process
(AeMdw.Sync.Server) for it to be processed accordingly.
Synchronization happens in two steps:
First, the top state of the chain is compared to the top state of the middleware to decide on which blocks to synchronize next. Once decided which generations are going to be synced next mutations are built for each of the key/micro blocks of these generations. Secondly, the mutations are then executed.
In order to be able to synchronize and invalidate forks data fast, the middleware stores the output of the sync data in two separate places:
All data generated from the genesis up to 10 generations before the top block
is stored in RocksDb tables (this is done using AeMdw.Db.TxnDbStore).
Data from the last 10 generations is stored in memory using theAeMdw.Db.MemStore, this occurs almost instantly.
Every time any of the last 10 generations change (via forks or new blocks added), the new generations needed to be added onto the database are first processed (if any), and then the new in-memory generations are processed.
When retrieving data through the endpoints, the MemStore is first queried,
and the results are merged with the data stored on the DbStore.
Mutations are meant to be a single, atomic database change. The most basic
mutation would be the WriteMutation, which simply writes a new record on a
table. More complex use cases are needed when you need to read from the
database to calculate the changes needed to be performed.
Here's an example of a WriteMutation usage:
The Sync.Server was built to be a GenStateMachine, which has the following
states:
:idle - There's nothing to process yet.
:stopped - The server failed too many times, it is now in a stopped state
and will retry later.
{:syncing_db, ref} - There's a new Task with reference ref which is
syncing changes and writing them to the database.
While in any state, if any new updates to the node change arrives
(new_height) the internal state of the Server is updated, and acheck_sync event is triggered.
While in idle state, if a check_sync event arrives, it is processed
accordingly:
If there's at least 1 generation which should belong to the database but has
not yet been synced, it spawns an new Task to store these changes and
enters into {:syncing_db, ref} state. When the task is done, it triggers
a :done event.
If there's at least 1 key or micro block that is not yet part of the memory,
it spawns a new Task to store these changes and enters into{:syncing_mem, ref} state. When the task is done it triggers a :done
event.
Visualization of the different Server states:
All the functionality described above - database design, syncing - has one goal, to keep database records in a shape usable for performing queries over transactions and additionally over lifecycle objects - names, channels and oracles.
Name, oracle and channels querying works conceptually in the same way. These objects can be in several states - "inactive", "active", and in case of name also "in auction". Objects in the same state are represented by these tables:
Object table, keyed by identifier of the object (plain name for names and
public key for oracles), e.g. Model.InactiveName, Model.InactiveOracle,Model.ActiveName, Model.ActiveOracle, Model.AuctionBid,Model.ActiveChannel, Model.InactiveChannel.
Expiration table, keyed by tuple {expiration height, identifier}
All these types of tables are sorted. This allows listing of names in any state either by expiration date or plain name. Since listing of oracles by sorted public keys doesn't make much sense, although technically possible, oracles are listed by their expiration only. Since there aren't any filtering or selection criteria needed for listing these objects (just state represented by a pair of tables), no query planner is needed.
The transaction query engine is a core functionality of the Middleware.
The query engine runs is several steps:
utilize the indices in Model.Type, Model.Time, Model.Field andModel.Tx to construct all variants how to traverse and pull the matching
records from the tables
use Model.IdCount table to pick the optimal variant which would generate the
stream of results
The query engine doesn't provide collecting or counting or additional processing of the results - it's only goal is to return a stream of results, which can be suspended and it's continuation stored and resumed later.
Without clauses, the query engine returns transactions in requested scope and direction. With clauses, the engine selects only results matching the clauses.
The clauses are key value pairs, where the keys can be:
type constraints: :type, :type_group
generic ids: :account, :contract, :channel, :oracle, :name
The values are either transaction types (for :type and :type_group), plain
names (for :name) or identifiers - encoded public keys of accounts, contracts,
oracles and channels (for fields).
Middleware acts as an indexing tool of the Node to provide users more useful and friendlier information. This is done mostly by indexing data that can then be queried through endpoints that provide a list of results.
Since the amount of results for these endpoints is unlimited and can ultimately
be a large number, all endpoints (since v2) are paginated by using cursors. Acursor is a reference to the next record that should be returned on the
paginated list, and it should contain any information needed to reference it
(numbers, string, etc). This cursor is included as a query parameter and
returned on the prev and next URL of any paginated endpoint. The result
of the endpoint should end up looking like this:
Internally, for all paginated endpoints, a stream is built that would then be
accesed to return the list of results. This is done by using regular, usually built
by using the Collection.stream/3 or Collection.stream/5 functions.
Collection.stream(state, table, direction, scope, cursor) iterates over the
keys provided by the state on that specific table, where:
state is the object which requires a to be initialized.
table is the atom specifying the table name.
direction is either forward or backward.
An example of its usage is the following:
In the first example, it iterates over the table Model.Tx where the keys are
a consecutive list of txi values. It begins at txi 300, iterating over values
up until 400.
Collection.stream(state, table, cursor) is a shorthand forCollection.stream(state, table, :forward, nil, cursor).
All endpoints that are paginated allow you to specify query parameters to scope
and order the results presented. This is done via the direction and scope
query parameter.
Direction determines the order of the results, and it can be eitherdirection=forward or direction=backward.
Scope allows to specify a range of generations endpoint points. The following values are supported:
scope=gen:<a>-<b> - from generation a to b (forward if a < b,
backward otherwise). This is represented as {:gen, a..b} internally.
scope=txi:<a>-<b> - from transaction index a to b (forward if a < b,
backward otherwise). Represented as {:txi, a..b}
We will summarize the main defects of previous middleware and the need for the rewrite.
The legacy middleware consisted of several hosts:
Aeternity Node for synchronization and sourcing the chain data
PostgreSQL for keeping denormalized chain data
Server in Rust for business logic and managing requests
Optional NodeJS for server side rendering
The main defects are summarized below.
Splitting the functionality between logic, data and presentation parts is a common industry practice. However, it doesn't mean that this architecture should be used everywhere, especially when we want a lean, simple and fast software stack.
Old middleware has 3-4 diverse components, where data is stored in 2 locations - AE node, and SQL host.
New middleware has 2 components which are operationally just one OS process - the AE node with Middleware extensions, with additional middleware data in the same DB used by AE node as well.
The instability stems from breaking down the functionality into several components which must communicate via network. Synchronization step requires 2 network requests (4 transmissions, as request/reply) - fetching data from the node and then inserting data to the SQL.
Client reply requires either DB network request or AE node network request, sometimes both. Network performance varies, connections between different parts of the service sometimes break.
Another large source of service breakage is when a fork happens in the chain, resulting in crashes of the Rust server.
Once the legacy Middleware synchronizes, the performance is tolerable, sans occasional response time spikes.
The main problem is synchronization performance. In a hosted environment, with 400K+ generations, synchronization from scratch would take several months. Asking for data via a public AE Node endpoint, with necessary JSON encoding/decoding for network transfer is simply way too slow.
New Middleware completely removed intra service network traffic. By placing Middleware into the AE node, we can synchronize Middleware data in less than a day.
Legacy middleware has severely broken support for paginations. Many endpoints return just the first page and rely on retrieving older data via paginations. There are two major issues.
Requesting a page doesn't remember the starting position - e.g. page 2 can return the same transactions as page 1 if the top of the chain changed between requests.
Fetching data for pages from SQL doesn't use SQL cursors - it collects all entries up to those which should be in the reply, and discards all except those in the requested page. Pagination is then progressively slower with each subsequent page.
Besides pagination being incorrect, wasteful and slow, they also allow DDOSing of the service. Malicious user just needs to send a request to a paginable endpoint, asking for a very high numbered page. This way the legacy Middleware can be tricked to collect millions of entries and trash the DB.
While legacy Middleware uses the SQL for storing the denormalized data model of the chain, public endpoints don't provide any means for more flexible searching of the transaction history. The endpoints were designed only for a single purpose - to support frontend application. Another large use case, using Middleware as part of the stack for other, non-frontend related logic, is not possible with legacy Middleware.
update to sdk 14
drop custom get function, require node >= 18
drop cjs support
use sdk provided filesystem util, remove aeproject util implementation
build artifact files ()
sdk import usage ()
drop cjs support ()
drop custom get function, require node >= 18 ()
update to sdk 14 ()
use sdk provided filesystem util, remove aeproject util implementation ()
update dependencies ()
update eslint ()
upgrade to chai@5 for new projects ()
use npm pack in tests ()
publish ()
update dependencies ()
replace chai/mocha with vitest ()
update compatible node version ()
update dependencies ()
update dependency versions, temp fix ci ()
default to use ceres ()
optimize docker healthcheck ()
upgrade sdk and docker for next versions ()
add ceres initializer and docs ()
add debug await key block after creating snapshot ()
check for actually supported node >= 16 requirement ()
rollback to correct height ()
fix workflow for incompatible versions ()
skip certain tests for aux ci runs ()
add library usage tests ()
improve library typescript defs ()
init command to take current aeproject library version ()
add chai as promised test rejection example ()
document and improve release process ()
improve env initialisation and test setup ()
introduce prettier ()
add matrix for compiler/node versions ()
use matrix test suite ()
improve env command ()
update default compiler tag ()
update dependencies ()
remove unneeded await ()
update sdk ()
update to latest compiler ()
upgrade to latest sdk ()
add back wait additional block workaround ()
prepare for fix release 4.8.1 ()
allow rollback to specific height ()
prepare for release 4.8.0 ()
upgrade dependencies ()
upgrade node to v6.11.0 with devmode timout fix ()
upgrade to compiler 7.4.0 ()
upgrade dependencies ()
fix scripts, prepare for 4.6.3 ()
use typescript to build project, migrate lib to ts ()
rollback unintended code-style changes ()
upgrade dependencies ()
minor fixes, adjust docs ()
upgrade to compiler image 7.3.0 for ARM64/Apple Silicon support ()
upgrade to sdk 13 beta and compiler 7 ()
prepare for release 4.6.0 ()
upgrade to final release sdk ()
update dependencies ()
update to node v6.8.1 ()
add support for node v6.8.0 ()
deps: mkdocs version update ()
generate .gitignore ()
use specific version of node to fix tests ()
update dependencies ()
remove the need for axios ()
simplify getFilesystem regexes ()
add image versions in env --info ()
add missing stdlib includes in getFilesystem ()
allow usage of native docker-compose without specifying env ()
correct escaping to use - in filesystem contracts ()
use fixed compiler version as latest is not supported by sdk ()
remove log for docker compose checks ()
fix support for docker compose without minus ()
add support for docker compose without minus ()
fix dependencies upgrade, prepare for 4.1.1 release ()
adjust for sdk 12 usage ()
upgrade to sdk 12 ()
fix breaking changes for sdk 12 usage ()
prepare for 4.1.0 release ()
improve update from previous aeproject version
use calldata lib sdk, use snapshotting in tests
tx-inspector: refactor inspector command
cleanup code
env: abort tests if env is not running ()
init: add optional folder parameter to init ()
init: check for up-to-date nodejs version ()
lib: add all accounts to default client ()
consider env running check if any container is up ()
docker-compose v2 up/running check ()
incorrect default includes regex fix (resolves ) ()
improve update from previous aeproject version ()
init: init command adjustments ()
prepare for new project structure ()
tx-inspector: refactor inspector command ()
improved exec env, assert env and test results ()
improved exec env, assert file existence ()
link to use local aeproject utils ()
adapt to naming convention of sdk examples ()
beta 5 release ()
beta 6 release ()
clean unused code and formatting ()
use the same sdk (a90943e)
update dependencies (5faaf66)
upgrade support latest aeternity node (afd36a5)
init: init command adjustments
prepare for new project structure
test: better example test and contract (f98e1df)
use updated sdk and rollback http usage (1dc45f2)
use calldata lib sdk, use snapshotting in tests (0c6d010)
cleanup code (2244394)
cleanup folders (46d73f3)
deps: bump mkdocs version from 1.2.3 to 1.2.4 (59bbded)
deps: sdk v11.0.1 (90d9cf6)
prepare for 4.0.0 release (9da6a85)
repo: add commitlint and release-please (00d08ba)
repo: add issue template and action docs generation (7fc04cc)
repo: re-add license (85f29c9)
tests: happy path tests (without assertions) (f8e3e3f)
tests: improved env to wait for node to come up (0992920)
tests: more test cases (28e0859)
update dependencies (5650a31)
update dependencies (397c3c5)
update dependencies (c42c2e4)
update dependencies, add lint check (adc54a4)
update node, sdk & compiler version (c625c38)
update release please ci action (aa56ac6)
update to lockfile v2 (0e3e3ee)
update version, use fixed node image (bf92a20)
update version, use latest bundle image (3b5cc81)
Significant speedup when serving requests
Greater stability (network isn't a variable factor anymore, all data are local)
Easier deployment and upgrading
Model.ActiveOracleExpirationModel.InactiveOracleExpiration
Model.OracleQueryExpiration
NullStore: This implementation
does not return any results or store anything, primarily used for testing
purposes.{:syncing_mem, ref} - There's a new Task with reference ref which is
syncing changes and writing them to memory.
Model.InactiveNameExpirationModel.InactiveOracleExpirationModel.ActiveNameExpirationModel.ActiveOracleExpirationModel.AuctionExpirationActivation tables, keyed by the tuple {activation height, identifier}, e.g.Model.ActiveNameActivation, Model.InactiveNameActivation,Model.ActiveChannelActivation.
freestanding fields: :sender_id, :from_id, :contract_id, ...
typed fields: :'spend.sender_id', :'name_transfer.recipient_id', ...
scope is either nil or a tuple of two values {first_key, last_key}, this
has to be provided in forward order (e.g. first_key <= last_key always).
cursor is the initial key to start iterating from. If nil it will begin
from the first element of the scope.
txiThis guide describes all breaking changes introduced with v13.0.0.
onSign, onMessageSign callbacks were removed on the wallet sideCheck allowance to sign on the account side instead, using aeppOrigin, aeppRpcClientId options.
Specified in name option of connectToWallet.
If you are using connectNode then the current node would always be the same as wallet provides.
aesophia_http old format
aesophia_cli format
params argument in $deploy and $call is requiredApply a patch:
contract.methods.<name>.get,send removedUse callStatic option instead.
contract.bytecode,sourceCode moved to contract.$optionscontract.calldata renamed to contract._calldataUse contract._calldata (considered to be a private field) or aepp-calldata package directly.
contract.options renamed to contract.$optionscontract.deployInfo removedUse the return value of contract.$deploy instead.contract.deployInfo.address moved to contract.$options.address.
contract.decodeEvents renamed to contract.$decodeEventscontract.call renamed to contract.$callcontract.compile renamed to contract.$compilecontract.deploy renamed to contract.$deploycreateAensDelegationSignature, createOracleDelegationSignature removedUse createDelegationSignature instead.
sourceCode instead of sourceIt is related to getContractInstance and signing using Generalized accounts. Apply a change:
getContractInstance accepts address instead of contractAddressApply a change:
getContractInstance function replaced with Contract classApply a patch:
AeSdk.getContractInstance renamed to AeSdk.initializeContractprepareTxParams, getVmVersion are not exported anymoreUse buildTx instead.
isGA method removedUse (await aeSdk.getAccount(<address>)).kind === 'generalized' instead.
writeInt function removedUse toBytes util instead.
returnType of contract call result structure is a value of CallReturnType enumApply a patch:
writeId, readId functions removedUse transaction builder instead.
readPointers, buildPointers functions removedUse transaction builder instead.
formatSalt function removedUse Buffer.from(<salt>.toString(16).padStart(64, '0'), 'hex') instead.
validateParams, unpackRawTx functions removedUse transaction builder instead.
AMOUNT constant removedIf necessary, use 0 instead.
payload fieldTX_TTL is not exported anymoreUse 0 instead.
FIELD_TYPES is not exported anymorePROTOCOL_VM_ABI, interface CtVersion not exported anymoreVM_VERSIONS, ABI_VERSIONS, PROTOCOL_VERSIONS renamedThey are exported as VmVersion, AbiVersion, ConsensusProtocolVersion.
stateHash of Channel entry decoded as st_-prefixed string instead of hexpayload doesn't accept arbitrary strings anymoreProvide a ba_-encoded string instead.
verifyTransaction doesn't accept parent tx types anymorebuildTx doesn't accept excludeKeys option anymoreConsider opening an issue, if you need this functionality.
version instead of VSN, vsn in unpackTx, buildTxbuildTx accepts transaction type and version in the first argumentApply a change:
tag in optionsReplace aeSdk.buildTx(Tag.SpendTx, { ... }) with aeSdk.buildTx({ ..., tag: Tag.SpendTx }).
buildTx accepts denomination in the first argumentunpackTx return an object of transaction parametersUse unpackTx(...) instead of unpackTx(...).tx.
unpackTx doesn't return rlpEncoded anymoreUse decode(buildTx(unpackTx(...))) instead.
unpackTx doesn't return txType anymoreUse unpackTx(...).tag instead.
buildTx return string instead of objectUse just buildTx(...) instead of buildTx(...).tx.
buildTx doesn't return txObject anymoreUse unpackTx(buildTx(...)) instead.
buildTx doesn't return binary anymoreUse require('rlp').decode(decode(buildTx(...))) instead.
buildTx doesn't return rlpEncoded anymoreUse decode(buildTx(...)) instead.
key of MtreeValue entry decoded as a buffer instead of a hexpoi field unpacked as TreesPoiget method of MPTree accepts and returns typed valuesApply a change:
Compiler export renamed to CompilerHttpA compiler instance needs to be passed explicitly in onCompiler option:
CompilerHttp moved to api propertyApply a patch:
createGeneralizedAccount accepts sourceCode in optionsApply a patch:
createMetaTx removedUse AccountGeneralized.signTransaction instead.
AccountRpc constructor accepts arguments one by oneApply a change:
AccountMemory requires networkId in signTransactionAccountBase simplifiednetworkId removed
getNetworkId method removed
signTransaction, signMessage made abstract
address in AccountBase is a propertyApply a change:
Apply a change:
Apply a change:
url property of Node removedUse autorest's $host property instead.
QUERY_FEE is not exported anymoreUse 30000 instead if necessary.
Specify queryFee in registerOracle if needed.
Remove the first argument.
onQuery callback of pollForQueries, oracle.pollQueries accepts a single queryIt was accepting an array before. Apply a patch:
send inlined into sendTransactionPass not signed transaction to sendTransaction.
If you need to post signed transaction use Node:postTransaction.
height removed from the output of aensPreclaimUse blockHeight instead:
Use buildTx to pack them back if needed.
Affected events: 'own_withdraw_locked', 'withdraw_locked', 'own_deposit_locked', 'deposit_locked', 'peer_disconnected', 'channel_reestablished'.
Use just await channel.poi(...) instead of unpackTx(await channel.poi(...)).
onAccount doesn't accept keypairApply a change:
bigNumberToByteArray removedUse toBytes instead.
str2buf function removedUse Buffer.from(<data>, <encoding>) instead.
getAddressFromPriv doesn't accept private key as base64-encoded or raw stringisValidKeypair doesn't accept public key as base64-encoded stringbytesToHex function removedUse Buffer.from(<bytes>).toString('hex') instead.
hexToBytes function removedUse Buffer.from(<hex string>, 'hex') instead.
AeternitySDK does versioning only for the API provided in the root export. Replace subpaths imports with imports of the package root.
getNetworkId from AeSdkBaseUse Node.getNetworkId instead.
address a getter in AeSdkBaseApply a change:
addAccount is a sync functionverifyMessage removed from accounts and AeSdkBaseUse verifyMessage exported in the root instead.
verify and verifyMessage accepts address instead of hex string or Uint8ArrayConvert public key in Uint8Array to address using encode(pk, 'ak').
Convert public key in hex to address using encode(Buffer.from(pk, 'hex'), 'ak').
Use [email protected] or newer.
removeAccount throws an error if the account is not foundsignMessage always returns Uint8ArrayUse Buffer.from(signature).toString('hex') to convert it to hex.
encryptKey, decryptKey are not exported anymoreUse 'sha.js' and 'aes-js' packages directly instead.
sha256hash is not exported anymoreUse SubtleCrypto.digest or sha.js package instead.
height method removedUse getHeight instead.
signUsingGA method removedUse AccountGeneralized.signTransaction instead.
POINTER_KEY_BY_PREFIX removedUse getDefaultPointerKey instead.
ID_TAG_PREFIX, PREFIX_ID_TAG, ID_TAG removedUse transaction builder instead.
TX_TYPE removed.Use Tag instead.
GAS_MAX removedThe maximum gas limit depends on transaction size, this value is outdated, sdk check/provides gasLimit by itself while building a transaction.
calculateMinFee removedUse buildTx to generate a transaction, unpack it and refer to fee field.
salt, createSalt removedUse genSalt instead.
Pointer removedUse NamePointer from apis/node instead.
defrecord :block,
[index: {-1, -1}, # {key_block_index, micro_block_index}
tx_index: nil, # first transaction index in this block
hash: <<>>] # block hash for lookup into AE node DBdefrecord :tx,
[index: -1, # transaction index value
id: <<>>, # transaction hash for lookup into AE node DB
block_index: {-1, -1}, # in which block the tx resides
time: -1] # micro block time in millisecondsdefrecord :time,
[index: {-1, -1}, # as {micro block milliseconds, transaction index}
unused: nil # unused as RocksDB valuedefrecord :type,
[index: {nil, -1}, # as {transaction type, transaction index}
unused: nil] # unused as RocksDB valuedefrecord :expiration,
[index: {nil, nil}, # {expiration height, object identifier}
value: nil] # possible metadatadefrecord :auction_bid,
# ame, bi_txi, expire height, owner, previous bids [bi_txi, ..]}
[index: plain_name(),
block_index_txi_idx: bi_txi_idx(),
expire_height: height(),
owner: pubkey(),
bids: [bi_txi_idx()]]defrecord :name,
[index: nil, # plain name
active: nil, # height from which name became active
expire: nil, # height when the name expires (expired)
claims: [], # claims (auction bids) as [bi_txi]
updates: [], # updates as [bi_txi]
transfers: [], # transfers as [bi_txi]
revoke: nil, # revoke transaction as bi_txi or nil
auction_timeout: 0, # if 0, name wasn't auctioned
owner: nil, # owner's public key
previous: nil] # previous version of the name as #name{}defrecord :oracle,
[index: nil, # public key of the oracle
active: nil, # height from which the oracle became active
expire: nil, # height when the oracle expires (expired)
register: nil, # registration bi_txi
extends: [], # extensions a [bi_txi]
previous: nil] # previous version of the oracle as #oracle{}defrecord :origin,
[index: {nil, nil, nil}, # {tx type, object pubkey, tx index}
tx_id: nil] # transaction hash
# The records are stored in the Model.Origin table.
# For the query execution logic and invalidations, rev_origin table record is needed:
defrecord :rev_origin,
[index: {nil, nil, nil}, # {tx index, tx type, object pubkey}
unused: nil]%{
block_hash: <<201, 228, 14t6, …>>,
block_height: 322515,
hash: <<72, 94, 35, …>>,
micro_index: 57,
micro_time: 1601651331156,
signatures: [<<1, 120, 56, ...>>],
tx: %{
amount: 20000,
fee: 19320000000000,
nonce: 3287310,
payload: "322515:kh_2m...iH:1601651331",
recipient_id: {:id, :account, <<123, 165, 128, ...>>},
sender_id: {:id, :account, <<123, 165, 128, ...>>},
ttl: 322525,
type: :spend_tx
},
tx_index: 16284706
}defrecord :field,
# {tx_type, tx_field_pos, object_pubkey, tx_index}
[index: {nil, -1, nil, -1},
unused: nil]defrecord :id_count,
[index: {nil, nil, nil}, # {tx type, field position, object pubkey}
count: 0] # valencydefrecord :owner,
[index: {pubkey, object}, # {owner pubkey, object pubkey}
unused: nil]defrecord :pointee,
# {pointer value (name), {block index, tx index}, pointer key}
[index: {nil, {{nil, nil}, nil}, nil},
unused: nil]...---- First n - 10 gens -----> <-------------- Top 10 gens ----------------->
+-----+----+----+---------+-----+---------+----+----+----+-----+------+----+---
| ... K(n-11) | M0 | M1 | | ... | K(n-10) | M0 | M1 | M2 | ... | K(n) | M0 | M1
+-----+----+----+---------+-----+---------+----+----+----+-----+------+----+---
...--- Synced into Rocksdb ----> <----------- Synced into memory ------------->tx = Model.tx(index: 1, id: <<0, 21, 30>>, block_index: {1, 10}, time: 1_000_000)
mutation = WriteMutation.new(Model.Tx, tx)
state = State.new()
State.commit(state, [mutation]){
"data": [
record1,
record2,
...
],
"next": "/v2/...?cursor=<cursor-next>"
"prev": "/v2/...?cursor=<cursor-prev>"
}state = State.new()
stream = Collection.stream(state, Model.Tx, :forward, {200, 400}, 300)
Enum.take(stream, 4) # => [200, 201, 202, 203]
stream = Collection.stream(state, Model.ActiveName, :backward, nil, "c.chain")
Enum.take(stream, 4) # => ["c.chain", "ba.chain", "b.chain"]{
"encoded_aci": { contract: <1> },
"external_encoded_aci": [<2>]
}[<2>, { contract: <1> }]-const contract = aeSdk.getContractInstance(<contract args>);
+const contract = aeSdk.getContractInstance<{ foo: (a: bigint) => bigint }>(<contract args>);
-await contract.methods.foo(<arguments>);
+await contract.foo(<arguments>);-aeSdk.getContractInstance({ source: <contract source code>, ... })
+aeSdk.getContractInstance({ sourceCode: <contract source code>, ... })
-aeSdk.spend(..., { authData: { source: <contract source code>, args: [...] } })
+aeSdk.spend(..., { authData: { sourceCode: <contract source code>, args: [...] } })-aeSdk.getContractInstance({ contractAddress: <contract address>, ... })
+aeSdk.getContractInstance({ address: <contract address>, ... })-contract = await getContractInstance(<options>);
+contract = await Contract.initialize(<options>);-contractCall.returnType === "error"
+contractCall.returnType === CallReturnType.Error-payload: 'test',
+payload: encode(Buffer.from('test'), Encoding.Bytearray),-buildTx({ ... }, Tag.SpendTx, { version: 2 })
+buildTx({ ..., tag: Tag.SpendTx, version: 2 })-buildTx({ ... }, { denomination: AE_AMOUNT_FORMATS.AETTOS })
+buildTx({ ..., denomination: AE_AMOUNT_FORMATS.AETTOS })-unpackTx(tree.get(decode('ak_97...')))
+tree.get('ak_97...')-import { AeSdk } from '@aeternity/aepp-sdk';
+import { AeSdk, CompilerHttp } from '@aeternity/aepp-sdk';
const aeSdk = new AeSdk({
- compilerUrl: <compiler url>,
+ onCompiler: new CompilerHttp(<compiler url>),
});-compilerHttp.generateACI({ code: sourceCode });
+compilerHttp.api.generateACI({ code: sourceCode });-aeSdk.createGeneralizedAccount('authorize', sourceCode, ['arg-1']);
+aeSdk.createGeneralizedAccount('authorize', ['arg-1'], { sourceCode });-new AccountRpc({ rpcClient: <rpc client>, address: <address> })
+new AccountRpc(<rpc client>, <address>)-await accountMemory.address(options)
+accountMemory.address-new MemoryAccount({ keypair: { publicKey: 'ak_..', secretKey: <secret key> } })
+new MemoryAccount(<secret key>)-new MemoryAccount({ gaId: <address> })
+new AccountGeneralized(<address>)-aeSdk.pollForQueries(oracleId, (queries) => queries.forEach(handleQuery));
+aeSdk.pollForQueries(oracleId, handleQuery);const res = aeSdk.aensPreclaim('name.chain');
-res.height
+res.blockHeight - 1-aeSdk.<metnod name>(..., { onAccount: <keypair> })
+aeSdk.<metnod name>(..., { onAccount: new MemoryAccount(<keypair>.secretKey) })-import MemoryAccount from '@aeternity/aepp-sdk/es/account/Memory.mjs';
+import { MemoryAccount } from '@aeternity/aepp-sdk';-await aeSdk.address()
+aeSdk.addressAll notable changes to this project will be documented in this file. See standard-version for commit guidelines.
aecli migrates to a new secret key format. Use SDK's page to convert secret keys.
account: aecli account address accepts --secretKey instead --privateKey
contract: uses v8 compiler by default
contract: not compatible with v7 compiler
narrow first column and remove _ in tables ()
oracle: make oracleTtl optional ()
contract: print details of static call ()
name keystore as filename instead of full path ()
race condition while setting options ()
account: consistently use secret key instead private key ()
deps: update sdk to 14.0.0 ()
don't show stacktrace for ACI-not-match error ()
update sdk to 13.3.2 ()
Check out the new documentation at
oracle: aecli oracle get removed
Use aecli inspect instead.
oracle: aecli don't accept already known account address in oracles
Remove extra argument:
account: aecli account verify-message accepts signer address instead wallet
chain: aecli chain network_id removed
Use aecli chain status instead.
Commands don't accept --no-waitMined anymore
In the most cases transactions gets mined immediately. In case of NameClaim, tx needs to be
submitted in the next keyblock after preclaim. In that case it would be mined also immediately,
with no early name revealing.
If still needed, use aecli chain broadcast tx_... --no-waitMined instead.
account: account save removed
Use account create instead:
account: aecli account spend renamed to aecli spend
chain: aecli connects to mainnet by default
Use the below to switch back to testnet.
require nodejs@18 or newer
Because nodejs@16 is not maintained currently.
name: name lookup command removed
Use inspect instead.
account: account generate command removed
Use account create in a cycle instead.
crypto: crypto sign command removed
Use account sign instead.
crypto: crypto unpack command removed
Use inspect instead.
crypto: crypto decode removed
Use another base58 decoder if necessary.
account: account balance, account nonce commands removed
Use inspect <ak-address> instead.
account: remove useless output option
account: account spend returns unwrapped JSON
account: account transfer command removed
Use spend instead.
account: accept password in env variable, notice password recorded ()
account: show approximate tx execution cost before asking password ()
account: verify message by address instead wallet ()
aens: don't require name ttl in
account: don't ask for password if it is empty ()
account: don't ask password if it is not required ()
aens: handle revoked names, refactor docs ()
chain: use mainnet instead testnet by default ()
Other commits with breaking changes
account: combine account create and account save ()
account: combine spend and transfer commands ()
account: move aecli account spend to aecli spend
The format of contract descriptor file changed
Contract descriptors needs to be regenerated.
contract: contract call accepts wallet_path as the last argument
For example, replace
with
account spend doesn't accept denomination parameter
accept amount suffixed with ae instead of denomination option ()
add select-node, select-compiler commands ()
add update-notifier to ask user to switch to the latest version ()
account: show network id in sign call output ()
contract: allow to static calls without wallet ()
contract: stringify maps as arrays ()
don't show stack trace when entered an invalid password to wallet ()
don't print stack traces for cli errors ()
commands in crypto module ()
contract: always store aci in descriptor, override descr by options ()
contract: clear error when can't parse call arguments ()
contract: create file descriptor at not existing path ()
contract deploy: accept args and bytecode, custom descrPath
Run aecli contract deploy --help to get the latest documentation.
contract call: accept arguments as JSON-encoded array
Affected commands: contract deploy, contract call.
contract: decode call result, make args flexible
Removed commands: contract encodeData, contract decodeCallData.
Added commands: contract encode-calldata, contract decode-call-result.
contract deploy: accept args and bytecode, custom descrPath ()
account transfer: remove unimplemented excludeFee option ()
account transfer: remove unused denomination option ()
contract call: accept arguments as JSON-encoded array ()
name full-claim: key of created pointer (
docker: enable dry-run endpoints ()
test: aens suite ()
test: contract suite ()
test: oracle suite lint ()
ci: add github actions workflow ()
env: bump node and compiler version ()
oracle: implement Oracle Test's ()
oracle: Implement Oracle Test's ()
AENS: Change tld from aet to chain () ()
Contract: Fix compiler test's ()
tests: Regenerate lock files to fix build on CI () ()
Account: Add verify-message command to account module ()
Account: Add message sign command ()
Account: Adjust printing and json serialization for sign-message result ()
Lima: Add support for lima () ()
Compiler: Add backend option to compiler(Can be fate or aevm. fate by default)
AENS: Add
Node Node 5.0.0-rc1 compatibility
ACCOUNT: Add command for generating and printing bulk of Key Pairs () ()
Account: Fix --json for account commands. Add proper error code to AENS commands. () ()
CLI: Fix exit codes around the CLI () ()
sdk: Update sdk version to 4.3.0 () ()
Node: Compatibility for node 4.0.0
Inspect Ability to unpack transaction using inspect command
CLI: Fix exit codes around the CLI () ()
README: Adjust readme () ()
Fortuna: Add Fortune(3.0.0) compatibility
Account: Feature/allow to spend percentage of balance (#68)
Commitizen: Configurte commitizen () ()
CI: Configure Jenkins pipeline
Account: Add option to get balance on specific heigh/hash
Remove contract call and deploy commands. Remove aens claim, revoke andupdate commands.
Contract: Add contract inspect command
CLI Improve error printing
TX: Add --networkId flag to each command which build a tx
CLI: Remove default fee for each command's (SDK calculate fee by itself)
Default node url changed to


aens: commitmentId removed from the JSON output of aecli name pre-claim
Use tx.commitmentId instead.
some fields in node responses returned as numbers instead of strings Namely:
abiVersion
vmVersion
callerNonce
senderNonce
oracleTtl.value
responseTtl.value
queryTtl.value
endsAt
tabbed data aligned without underscores
width of the first column in tabbed data depends on the content
name extendaens: print missed name details, be human-friendly (91c7731)
aens: show auction details (75217c3)
chain: show protocol version in config (35496fb)
contract: accept amount in contract and tx builder commands (1dbd195)
show extra info in tx details, consistent fields naming (5a9f4cc)
contract: don't show stacktrace if static contract call failed (694d400)
contract: don't use -G flag for both gas and gas price (047cf8e)
don't accept --networkId in commands where node is required (cfd7ac5)
don't print contract deposit because it can't be used (47e0306)
don't show stacktraces for RestErrors (e7f2e58)
oracle: don't require extra arguments, refactor examples (4fada6e)
oracle: remove extra arguments in tx builder, refactor, fix examples (e3be365)
account: remove extra object wrapping json output (b1d4585)
account: remove unnecessary account generate command (1c6abd8)
account: remove unnecessary balance, nonce commands (b4792e6)
account: remove useless output option (74a8a37)
chain: remove network_id command (4d4adce)
crypto: remove duplicate crypto sign command (bb39f07)
crypto: remove duplicate crypto unpack command (37b9965)
crypto: remove unnecessary crypto decode command (a0d9b05)
name: remove duplicate name lookup command (e4f9b50)
oracle: remove oracle get (6db5dc2)
remove --no-waitMined option (5fe7dc4)
require nodejs@18 (5fd3bfa)
aesophia_cli support (a74fc2b)
contract: includes support (818f375)
get urls from AECLI_NODE_URL, AECLI_COMPILER_URL env variables (78a9953)
specify and check contract descriptor file version (ea17f80)
tx: remove missed deposit field in contract call tx (a1aa7c7)
tx: show bytecode and call data instead of missed payload (75f5eee)
tx: show name of transaction type (18ee736)
chain: calculation of relative ttl (651ba1a)
chain: height calculation, improve markup, remove confusing timeout (4f5329d)
chain: padding of top output (ca661d7)
chain: show correctly consensus protocol version (a5fa358)
don't override files by default (d09eabe)
inspect: encoded tx, plain contract output, oracle queries in json (dae4df9)
oracle: decoding of oracle query (fa2764b)
oracle: providing oracleTtl, queryTtl, responseTtl (a0cc66c)
show name pointers line by line (9dbcf41)
contract: fall if descriptor file specified but not exists (37b490f)
remove broken crypto decrypt command (03c645c)
remove broken crypto genkey command (32e5b0f)
config command (27a1169)
usage show correct command name (223f05d)
contract: decode call result, make args flexible (b0a5cdc)
test: tx suite (64993ba)
exit code of get address command (fddd2b0)
remove compiler decodeData commend that depends on unsupported api (e198ea2)
typo in gasPrice (347e733)
oracle: Implement Oracle Test's (854ce61)
Fix test for AENS (fae6ce8)
AENS: Add bid, transfer, revoke and fullClaim commands (a5eb23a)
AENS: Add test for auction (9f4f6b2)
AENS: extend name ttl command (63c99ae)
AENS: Fix transfer command. Add more test for transfer AENS names (547af5a)
AENS: Fix BC for all of AENS commands. (77d2d3c)
AENS: Implement name update command (b65c5e6)
CLI: Refactor constant(Use constant from sdk). Refactor error handling in AENS module. Add pre-claim command. Refactor claim command (7038629)
Contract: Add test for calling contract using cointract descriptor file or source code and address (3f77138)
Contract: contract call command (ae723d5)
Contract: Enable test's for contract (ed48a83)
nameFeeclaimContract: Implement standalone compiler commands
DOCS add command for auto generating CHANGELOG
AENS: Add AENS transaction's build commands for offline mode to tx module
Contract: Add contract transaction's build commands for offline mode to tx module
Oracle: Add oracle transaction's build commands for offline mode to tx module
TX: tx root command, which allow to build transaction's in offline-mode
TX: Add broadcast sub-command to tx
Account: Add 'sign' sub-command to account
- $ aecli oracle extend ./wallet.json ok_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi 200
+ $ aecli oracle extend ./wallet.json 200
- $ aecli oracle respond-query ./wallet.json ok_2a1j2Mk9YSmC1gi... oq_6y3N9KqQb74QsvR... +16Degree
+ $ aecli oracle respond-query ./wallet.json oq_6y3N9KqQb74QsvR... +16Degree-$ aecli account save ./my-wallet.json <hex secret key>
+$ aecli account create ./my-wallet.json <hex secret key>$ aecli select-node https://testnet.aeternity.io- aecli name lookup <name.chain>
+ aecli inspect <name.chain>- aecli crypto unpack <tx-prefixed transaction>
+ aecli inspect <tx-prefixed transaction>- aecli account balance wallet.json --password=123
- aecli account nonce wallet.json --password=123
+ address=$(aecli account address wallet.json --json | jq -r .publicKey)
+ aecli inspect $address- aecli account spend ... | jq .tx.tx.amount
+ aecli spend ... | jq .tx.amount- aecli account transfer 0.42 <recipient>
+ aecli spend 42% <recipient>$ aecli contract call ./wallet.json foo '[1, 2]'$ aecli contract call foo '[1, 2]' ./wallet.jsonsign-message — sign a personal message using wallet
verify-message — check if message was signed by address
address — get wallet address and optionally secret key
create — create a wallet by a secret key or generate a new one
spend — send coins to another account or contract
name
full-claim — claim an AENS name in a single command
pre-claim — pre-claim an AENS name
claim — claim an AENS name (requires pre-claim)
— bid on name in auction
— update a name pointer
— extend name TTL
— revoke an AENS name
— transfer a name to another account
contract
compile — compile a contract to get bytecode
encode-calldata — encode calldata for contract call
decode-call-result — decode contract call result
— execute a function of the contract
— deploy a contract on the chain
oracle
create — register current account as oracle
extend — extend oracle's time to leave
create-query — create an oracle query
— respond to an oracle query
inspect — get details of a node entity
tx
spend — build spend transaction
name-preclaim — build name preclaim transaction
name-claim — build name claim transaction
— build name update transaction
— build name transfer transaction
— build name revoke transaction
— build contract deploy transaction
— build contract call transaction
— build oracle register transaction
— build oracle extend transaction
— build oracle post query transaction
— build oracle respond transaction
— verify transaction using node
config — print the current sdk configuration
select-node — specify node to use in other commands
select-compiler — specify compiler to use in other commands
Sign a transaction using wallet. Useful in offline signing scheme.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--networkId [networkId]
Network id.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
--json
Print result in json format.
Example calls
Sign a personal message using wallet.
Options
--filePath [path]
Specify the path to the file for signing (ignore "data" argument and use file instead).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
--json
Print result in json format.
Example calls
Check if message was signed by address.
Options
--filePath [path]
Specify the path to the file (ignore "data" argument and use file instead).
--json
Print result in json format.
Example calls
Get wallet address and optionally secret key.
Options
--secretKey
Print secret key.
--forcePrompt
Force prompting.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
--json
Print result in json format.
Example calls
Create a password-encrypted wallet by a secret key. Secret key can be provided in options, or cli will generate one. This command creates ethereum-like keyfile.
Arguments
wallet_path
secretKey
Secret key in sk_ or hex encoding.
Options
--overwrite
Overwrite if exist.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
--json
Print result in json format.
Example calls
Sends coins to another account or contract.
Arguments
wallet
A path to wallet file.
receiver
Address or name of recipient account.
amount
Amount of coins to send in aettos/ae (example: 1.2ae), or percent of sender balance (example: 42%).
Options
--payload [payload]
Transaction payload as text (default: "").
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-N, --nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Claim an AENS name in a single command. This command signs and sends a pre-claim transaction and waits until one block gets mined. After that, it sends a claim transaction. At the end, the update transaction is submitted, making a name point to the current account.
A name in arguments should end with ".chain". Be careful, shorter names are more expensive. If the name is shorter than 13 characters (without ".chain") then it won't be claimed immediately but would start an auction instead.
Options
--nameFee [nameFee]
Amount of coins to pay for name.
--nameTtl [nameTtl]
A number of blocks until name expires (default: 180000 (1 year)).
--clientTtl [clientTtl]
A suggestion measured in seconds on how long clients should cache name pointers (default: 3600 (1 hour)).
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Pre-claim an AENS name. The name should be claimed after one key block since the pre-claim gets mined. This command sends a pre-claim transaction, and outputs a salt that needs to be provided to aecli name claim.
A name in arguments should end with ".chain". Be careful, shorter names are more expensive. If the name is shorter than 13 characters (without ".chain") then it won't be claimed immediately but would start an auction instead.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Claim an AENS name, it requires a salt provided by aecli name pre-claim.
A name in arguments should end with ".chain". Be careful, shorter names are more expensive. If the name is shorter than 13 characters (without ".chain") then it won't be claimed immediately but would start an auction instead.
Options
--nameFee [nameFee]
Amount of coins to pay for name.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Bid on name in auction.
Arguments
wallet_path
name
nameFee
Amount of coins to pay for name.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Update a name pointer.
Options
--extendPointers
Extend pointers (default: false).
--nameTtl [nameTtl]
A number of blocks until name expires (default: 180000 (1 year)).
--clientTtl [clientTtl]
A suggestion measured in seconds on how long clients should cache name pointers (default: 3600 (1 hour)).
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Extend name TTL.
Arguments
wallet_path
name
nameTtl
A number of blocks until name expires (default: 180000 (1 year)).
Options
--clientTtl [clientTtl]
A suggestion measured in seconds on how long clients should cache name pointers (default: 3600 (1 hour)).
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Revoke an AENS name. After that nobody will be able to claim it again. This action is irreversible!
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Transfer a name to another account.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Compile a contract to get bytecode.
Options
--compilerUrl [compilerUrl]
Compiler to connect to (default: stable compiler, env: AECLI_COMPILER_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Encode calldata for contract call.
Arguments
fn
args
JSON-encoded arguments array of contract call (default: []).
Options
-d, --descrPath [descrPath]
Path to contract descriptor file.
--contractSource [contractSource]
Contract source code file name.
--contractAci [contractAci]
Contract ACI file name.
--compilerUrl [compilerUrl]
Compiler to connect to (default: stable compiler, env: AECLI_COMPILER_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Decode contract call result.
Options
-d, --descrPath [descrPath]
Path to contract descriptor file.
--contractSource [contractSource]
Contract source code file name.
--contractAci [contractAci]
Contract ACI file name.
--compilerUrl [compilerUrl]
Compiler to connect to (default: stable compiler, env: AECLI_COMPILER_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Execute a function of the contract.
Arguments
fn
Name of contract entrypoint to call.
args
JSON-encoded arguments array of contract call (default: []).
wallet_path
Path to secret storage file, not needed to make a static call.
Options
--contractAddress [contractAddress]
Contract address to call.
-s, --callStatic
Estimate the return value, without making a transaction on chain.
-t, --topHash
Hash of block to make call.
-d, --descrPath [descrPath]
Path to contract descriptor file.
--contractSource [contractSource]
Contract source code file name.
--contractAci [contractAci]
Contract ACI file name.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-G, --gas [gas]
Amount of gas to call/deploy the contract.
--gasPrice [gasPrice]
Gas price to call/deploy the contract (default: based on network demand).
-N, --nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-a, --amount [amount]
Amount of coins to send (default: 0ae).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
--compilerUrl [compilerUrl]
Compiler to connect to (default: stable compiler, env: AECLI_COMPILER_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Deploy a contract on the chain and create a deployment descriptor with the contract information that can be used to invoke the contract later on. The generated descriptor will be made in the same folder of the contract source file or at the location provided in descrPath. Multiple deploys of the same contract file will generate different deploy descriptors.
Arguments
wallet_path
args
JSON-encoded arguments array of contract call (default: []).
Options
--contractBytecode [contractBytecode]
Contract bytecode file name.
-d, --descrPath [descrPath]
Path to contract descriptor file.
--contractSource [contractSource]
Contract source code file name.
--contractAci [contractAci]
Contract ACI file name.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-G, --gas [gas]
Amount of gas to call/deploy the contract.
--gasPrice [gasPrice]
Gas price to call/deploy the contract (default: based on network demand).
-N, --nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-a, --amount [amount]
Amount of coins to send (default: 0ae).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
--compilerUrl [compilerUrl]
Compiler to connect to (default: stable compiler, env: AECLI_COMPILER_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Register current account as oracle.
Options
--oracleTtl [oracleTtl]
A number of blocks until oracle expires (default: 500 (1 day)).
--queryFee [queryFee]
Oracle query fee (default: 0ae).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Extend oracle's time to leave.
Arguments
wallet_path
oracleTtl
A number of blocks until oracle expires (default: 500 (1 day)).
Options
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Create an oracle query.
Options
--queryTtl [queryTtl]
A number of blocks while oracle can respond (default: 10 (30 minutes)).
--responseTtl [responseTtl]
A number of blocks while response available (default: 10 (30 minutes)).
--queryFee [queryFee]
Oracle query fee (default: provided by oracle).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Respond to an oracle query.
Options
--responseTtl [responseTtl]
A number of blocks while response available (default: 10 (30 minutes)).
-P, --password [password]
Wallet Password, may be recorded to shell history (env: AECLI_WALLET_PASSWORD).
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: 3).
-F, --fee [fee]
Override the transaction fee.
--nonce [nonce]
Override the nonce that the transaction is going to be sent with.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Query the top key/micro block of the chain.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Query node version, network id, and related details of the selected node.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Get relative TTL by absolute TTL.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Prints blocks from top until condition.
Options
-L, --limit [playLimit]
Amount of blocks to print (default: 10).
-P, --height [playToHeight]
Print blocks till the height.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Send signed transaction to the chain. Useful in offline signing scheme.
Options
-W, --no-waitMined
Don't wait until transaction gets mined.
--verify
Verify Transaction before broadcasting.
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Prints details of:
account (ak_-prefixed string),
name (string ending with '.chain'),
contract (ct_-prefixed string),
oracle (ok_-prefixed string),
keyblock or microblock (prefixed with kh_, mh_),
keyblock by height (integer),
transaction (by th_-string or tx_).
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Build spend transaction.
Arguments
senderId
receiverId
amount
Amount of coins to send.
nonce
Unique number that is required to sign transaction securely.
Options
--payload [payload]
Transaction payload (default: "").
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build name preclaim transaction.
Arguments
accountId
name
nonce
Unique number that is required to sign transaction securely.
Options
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build name claim transaction.
Arguments
accountId
salt
name
nonce
Unique number that is required to sign transaction securely.
Options
--nameFee [nameFee]
Amount of coins to pay for name.
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build name update transaction.
Arguments
accountId
nameId
nonce
Unique number that is required to sign transaction securely.
pointers
Options
--nameTtl [nameTtl]
A number of blocks until name expires (default: 180000 (1 year)).
--clientTtl [clientTtl]
A suggestion measured in seconds on how long clients should cache name pointers (default: 3600 (1 hour)).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build name transfer transaction.
Arguments
accountId
recipientId
name
nonce
Unique number that is required to sign transaction securely.
Options
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build name revoke transaction.
Arguments
accountId
name
nonce
Unique number that is required to sign transaction securely.
Options
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build contract deploy transaction.
Arguments
ownerId
contractBytecode
initCallData
nonce
Unique number that is required to sign transaction securely.
Options
-G, --gas [gas]
Amount of gas to call/deploy the contract.
--gasPrice [gasPrice]
Gas price to call/deploy the contract (default: 1000000000).
-a, --amount [amount]
Amount of coins to send (default: 0ae).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build contract call transaction.
Arguments
callerId
contractId
callData
nonce
Unique number that is required to sign transaction securely.
Options
-G, --gas [gas]
Amount of gas to call/deploy the contract.
--gasPrice [gasPrice]
Gas price to call/deploy the contract (default: 1000000000).
-a, --amount [amount]
Amount of coins to send (default: 0ae).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build oracle register transaction.
Arguments
accountId
queryFormat
responseFormat
nonce
Unique number that is required to sign transaction securely.
Options
--queryFee [queryFee]
Oracle query fee (default: 0ae).
--oracleTtl [oracleTtl]
A number of blocks until oracle expires (default: 500 (1 day)).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build oracle extend transaction.
Arguments
oracleId
oracleTtl
nonce
Unique number that is required to sign transaction securely.
Options
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build oracle post query transaction.
Arguments
accountId
oracleId
query
nonce
Unique number that is required to sign transaction securely.
Options
--queryFee [queryFee]
Oracle query fee (default: provided by oracle).
--queryTtl [queryTtl]
A number of blocks while oracle can respond (default: 10 (30 minutes)).
--responseTtl [responseTtl]
A number of blocks while response available (default: 10 (30 minutes)).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Build oracle respond transaction.
Arguments
oracleId
queryId
response
nonce
Unique number that is required to sign transaction securely.
Options
--responseTtl [responseTtl]
A number of blocks while response available (default: 10 (30 minutes)).
-F, --fee [fee]
Override the transaction fee.
-T, --ttl [ttl]
Validity of the transaction in number of keyblocks, or without this limit if 0 (default: undefined).
--json
Print result in json format.
Example calls
Verify transaction using node.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
-f, --force
Ignore node version compatibility check.
--json
Print result in json format.
Example calls
Print the current sdk configuration.
Options
-u, --url [nodeUrl]
Node to connect to (default: mainnet, env: AECLI_NODE_URL).
--compilerUrl [compilerUrl]
Compiler to connect to (default: stable compiler, env: AECLI_COMPILER_URL).
Specify node to use in other commands.
Arguments
nodeUrl
Node URL.
Specify compiler to use in other commands.
Arguments
compilerUrl
Compiler URL.
aecli account sign [options] <wallet_path> <tx>$ aecli account sign ./wallet.json tx_+FoMAaEBzqet5HDJ+Z2dTkAIgKhvHUm7REti8Rqeu2S7z+tz/vOhARX7Ovvi4N8rfRN/Dsvb2ei7AJ3ysIkBrG5pnY6qW3W7iQVrx14tYxAAAIYPUN430AAAKoBebL57aecli account sign-message [options] <wallet_path> [data...]$ aecli account sign-message ./wallet.json 'message to sign'aecli account verify-message [options] <address> <hexSignature> [data...]$ aecli account verify-message ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E f2f268f195d4747568f38f9efd36e72606dc356c0b8db9fdfae5f1f9c207dbc354c57c29397837d911516aef184b0ddbed7d16d77caf9ffb3f42fe2bcc15c30e 'message to sign'aecli account address [options] <wallet_path>$ aecli account address ./wallet.json # show only public key
$ aecli account address ./wallet.json --secretKey # show public key and secret keyaecli account create [options] <wallet_path> [secretKey]$ aecli account create ./wallet.json
$ aecli account create ./wallet.json sk_2CuofqWZHrABCrM7GY95YSQn8PyFvKQadnvFnpwhjUnDCFAWmfaecli spend [options] <wallet> <receiver> <amount>$ aecli spend ./wallet.json ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E 100
$ aecli spend ./wallet.json example-name.chain 1.23ae
$ aecli spend ./wallet.json ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E 20% --ttl 20aecli name full-claim [options] <wallet_path> <name>$ aecli name full-claim ./wallet.json example-name.chainaecli name pre-claim [options] <wallet_path> <name>$ aecli name pre-claim ./wallet.json example-name.chainaecli name claim [options] <wallet_path> <name> <salt>$ aecli name claim ./wallet.json example-name.chain 12327389123aecli name bid [options] <wallet_path> <name> <nameFee>$ aecli name bid ./wallet.json example-name.chain 4.2aeaecli name update [options] <wallet_path> <name> [addresses...]$ aecli name update ./wallet.json example-name.chain ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzhaecli name extend [options] <wallet_path> <name> [nameTtl]$ aecli name extend ./wallet.json example-name.chain 180000aecli name revoke [options] <wallet_path> <name>$ aecli name revoke ./wallet.json example-name.chainaecli name transfer [options] <wallet_path> <name> <address>$ aecli name transfer ./wallet.json example-name.chain ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7Eaecli contract compile [options] <file>$ aecli contract compile ./contract.aesaecli contract encode-calldata [options] <fn> [args]$ aecli contract encode-calldata --descrPath ./contract.aes.deploy.229e.json sum '[1, 2]'
$ aecli contract encode-calldata --contractSource ./contract.aes sum '[1, 2]'
$ aecli contract encode-calldata --contractAci ./contract.json sum '[1, 2]'aecli contract decode-call-result [options] <fn> <encoded_result>$ aecli contract decode-call-result --descrPath ./contract.aes.deploy.229e.json test cb_DA6sWJo=
$ aecli contract decode-call-result --contractSource ./contract.aes test cb_DA6sWJo=
$ aecli contract decode-call-result --contractAci ./contract.json test cb_DA6sWJo=aecli contract call [options] <fn> [args] [wallet_path]$ aecli contract call ./wallet.json sum '[1, 2]' --descrPath ./contract.aes.deploy.229e.json
$ aecli contract call ./wallet.json sum '[1, 2]' --contractAddress ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh --callStatic
$ aecli contract call ./wallet.json sum '[1, 2]' --descrPath ./contract.aes.deploy.229e.json --gas 2222222 --nonce 4 --ttl 1243aecli contract deploy [options] <wallet_path> [args]$ aecli contract deploy ./wallet.json --contractSource ./contract.aes '[1, 2]'
$ aecli contract deploy ./wallet.json --descrPath ./contract.aes.deploy.229e.json --gas 2222222
$ aecli contract deploy ./wallet.json --contractBytecode ./contract.txt --contractAci ./contract.jsonaecli oracle create [options] <wallet_path> <queryFormat> <responseFormat>$ aecli oracle create ./wallet.json string stringaecli oracle extend [options] <wallet_path> [oracleTtl]$ aecli oracle extend ./wallet.json 200aecli oracle create-query [options] <wallet_path> <oracleId> <query>$ aecli oracle create-query ./wallet.json ok_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi WhatTheWeatherIs?aecli oracle respond-query [options] <wallet_path> <queryId> <response>$ aecli oracle respond-query ./wallet.json oq_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh +16Degreeaecli chain top [options]$ aecli chain topaecli chain status [options]$ aecli chain statusaecli chain ttl [options] <absoluteTtl>$ aecli chain ttlaecli chain play [options]$ aecli chain play --limit 3 # print 3 blocks from top
$ aecli chain play --height 929796 # print blocks from top until reach heightaecli chain broadcast [options] <tx>$ aecli chain broadcast tx_+FoMAaEBzqet5HDJ+Z2dTkAIgKhvHUm7REti8Rqeu2S7z+tz/vOhARX7Ovvi4N8rfRN/Dsvb2ei7AJ3ysIkBrG5pnY6qW3W7iQVrx14tYxAAAIYPUN430AAAKoBebL57aecli inspect [options] <identifier>$ aecli inspect ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E # get account details
$ aecli inspect example-name.chain # get details of AENS name
$ aecli inspect ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh # get contract details
$ aecli inspect ok_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi # get contract details
$ aecli inspect kh_CF37tA4KiiZTFqbQ6JFCU7kDt6CBZucBrvineVUGC7svA9vK7 # get key block details by hash
$ aecli inspect mh_k1K9gLLtdikJhCdKfBbhYGveQs7osSNwceEJZb1jD6AmraNdr # get micro block details by hash
$ aecli inspect 929796 # get key block details by height
$ aecli inspect th_2nZshewM7FtKSsDEP4zXPsGCe9cdxaFTRrcNjJyE22ktjGidZR # get transaction details by hash
$ aecli inspect tx_+FoMAaEBzqet5HDJ+Z2dTkAIgKhvHUm7REti8Rqeu2S7z+tz/vOhARX7Ovvi4N8rfRN/Dsvb2ei7AJ3ysIkBrG5pnY6qW3W7iQVrx14tYxAAAIYPUN430AAAKoBebL57 # get transaction detailsaecli tx spend [options] <senderId> <receiverId> <amount> <nonce>$ aecli tx spend ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E ak_AgV756Vfo99juwzNVgnjP1gXX1op1QN3NXTxvkPnHJPUDE8NT 100ae 42aecli tx name-preclaim [options] <accountId> <name> <nonce>$ aecli tx name-preclaim ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E example-name.chain 42aecli tx name-claim [options] <accountId> <salt> <name> <nonce>$ aecli tx name-claim ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E 12327389123 example-name.chain 42aecli tx name-update [options] <accountId> <nameId> <nonce> [pointers...]$ aecli tx name-update ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E example-name.chain 42 ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzhaecli tx name-transfer [options] <accountId> <recipientId> <name> <nonce>$ aecli tx name-transfer ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E ak_AgV756Vfo99juwzNVgnjP1gXX1op1QN3NXTxvkPnHJPUDE8NT example-name.chain 42aecli tx name-revoke [options] <accountId> <name> <nonce>$ aecli tx name-revoke ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E example-name.chain 42aecli tx contract-deploy [options] <ownerId> <contractBytecode> <initCallData> <nonce>$ aecli tx contract-deploy ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E cb_dGhpcyBtZXNzYWdlIGlzIG5vdCBpbmRleGVkdWmUpw== cb_DA6sWJo= 42aecli tx contract-call [options] <callerId> <contractId> <callData> <nonce>$ aecli tx contract-call ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E ct_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh cb_DA6sWJo= 42aecli tx oracle-register [options] <accountId> <queryFormat> <responseFormat> <nonce>$ aecli tx oracle-register ak_21A27UVVt3hDkBE5J7rhhqnH5YNb4Y1dqo4PnSybrH85pnWo7E '{"city": "string"}' '{"tmp": "number"}' 42aecli tx oracle-extend [options] <oracleId> <oracleTtl> <nonce>$ aecli tx oracle-extend ok_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi 100 42aecli tx oracle-post-query [options] <accountId> <oracleId> <query> <nonce>$ aecli tx oracle-post-query ak_AgV756Vfo99juwzNVgnjP1gXX1op1QN3NXTxvkPnHJPUDE8NT ok_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi '{"city": "Berlin"}' 42aecli tx oracle-respond [options] <oracleId> <queryId> <response> <nonce>$ aecli tx oracle-respond ok_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi oq_6y3N9KqQb74QsvR9NrESyhWeLNiA9aJgJ7ua8CvsTuGot6uzh '{"tmp": 1}' 42aecli tx verify [options] <tx>$ aecli tx verify tx_+FoMAaEBzqet5HDJ+Z2dTkAIgKhvHUm7REti8Rqeu2S7z+tz/vOhARX7Ovvi4N8rfRN/Dsvb2ei7AJ3ysIkBrG5pnY6qW3W7iQVrx14tYxAAAIYPUN430AAAKoBebL57aecli config [options]aecli select-node [options] [nodeUrl]aecli select-compiler [options] [compilerUrl]
All notable changes to this project will be documented in this file. See standard-version for commit guidelines.
Update AE GHA to latest ()
show correct icons for ETH and WAE () ()
update metadata ()
add bridge contracts ()
readme: add title ()
update ethers package and adjust related code for compatibility ()
trigger testing docs updater ()
trigger testing docs updater ()
AE wallet select prompting issue ()
remove persistance show of wallet extension missing error ()
support aeternity MM snap ()
update ae sdk package & adapt changes ()
remove redundant context prop ()
scientific notation issue ()
validations for amount's new type ()
add PageContainer style prop ()
adjust content height for page container component ()
set smaller paddings for smaller screens ()
headings & margins across pages ()
supported token list heading ()
transaction history box metrics ()
transaction page mobile screen text positions ()
page components to create reusable PageContainer ()
wallet connection flow improvements ()
auto wallet connect & display message ()
only fetch bridge info when wallets detected ()
only try to connect to aeternity wallet when wallet detected ()
added sub menu to left bar & reorganized menus ()
left sub menu responsiveness ()
wording updates ()
added view customization features to WalletConnection component ()
connect wallet view in transaction history ()
transaction page ()
add react node keys to wallet connect buttons ()
console warning for nth-child ()
wording, half button issue ()
WalletConnection component ()
update material icons package ()
improve left menu navigation ()
left menu component with responsiveness updates () ()
left menu styling ()
transaction history route fundamentals ()
code formatting ()
update blockchain name with proper spelling and symbols ()
typo ()
update wording in FAQ ()
Added "what's next?" entry to faq & created a token list page ()
typo ()
Fix formatting issue in summary view ()
further information about bridge action & bug fixes/improvements ()
remove unused import ()
Add link to GitHub repository ()
Update ViewContainer footer with Acurast's link ()
typo ()
Update README with deployment instructions ()
Update sponsorship information in terms and conditions ()
update terms and conditions ()
remove powered by aeternity remark ()
update AE address in bridge form ()
update bridge transaction link to use correct blockchain explorer ()
improve destination token value display in Bridge form ()
checkAeAccountHasEligibleBridgeUse function's transactions call ()
add "How To" link to the top menu ()
header and footer for small screens ()
restrict bridge usage to once in every 12 hours ()
snack message display function & restriction interval var ()
check for AE bridging to EVM ()
refactor bridge info object and adjust views accordingly to the bridge operator fund account balance ()
setup snack notificator lib ()
dialogs & display bridge action summary ()
Add check for sufficient balance in Ethereum bridge contract ()
Disable bridge usage depending on the contract flag ()
replace error dialogs with snack alerts ()
nginx config and Dockerfile ()
remove nginx config ()
Update Dockerfile to remove unnecessary file copy and nginx configuration ()
Update Dockerfile to copy files and directories for nginx deployment ()
Update nginx.conf to use /index.html as fallback for all routes ()
Add FAQ and Terms and Conditions pages ()
auto connect SH on AE chain selection ()
network switch auto wallet connection issue ()
WAE contract address ()
Add deployment links to README.md ()
remove confusing expressions from the amount input ()
Update AeternityBridgeInfo component to check if AE and EVM bridges are enabled ()
Update default AE and WAE contract addresses ()
Update AeternityBridgeLogo component to use correct icon file name ()
Update ViewContainer to improve readability of the revision information in the footer ()
Update constants.ts to include assets from chainConfig ()
Add version and revision information to footer ()
Update integration.yml to include BUILD_ARGS with revision information ()
Update ViewContainer to conditionally display revision information in the footer ()
update package name to match GH repo ()
use custom GH token to able to trigger releases ()
implement mainnet config and assets ()
Update Aeternity logo in NavigationBar component ()
add complete asset list ()
Add wallet disconnect button to header, copy connected wallet address, and handle account change ()
Update Dockerfile to use multi-stage build for improved performance ()

update mainnet contracts (3d8f7c9)
update testnet contracts and assets (e966f11)
A standard implementation of non-fungible tokens for the æternity ecosystem. Initially, the design goal of the primary interface was to be as compatible with ERC-721 as possible, so that anyone who can work with ERC-721 can work with this interface. However, specifically when it comes to dealing with metadata a decision was taken to provide contract developers as much flexibility as possible.
Core differences to the well-known ERC-721 standard:
Unsafe transactions are not supported. Therefore, all transactions are ought to be safe
Usage of zero-address for minting or burning is avoided. Thus, explicit events for minting and burning have been defined
Token transfers do not require the (owner) address to be passed. Only the recipient address needs to be provided to the entrypoint
High flexibility when it comes to dealing with metadata is provided
The following standard describes standard interfaces for non-fungible tokens. The proposal contains a primary interface and secondary interfaces (extensions) for optional functionality that not everyone might need.
Returns a hardcoded list of all implemented extensions on the deployed contract.
Returns meta information associated with the contract.
Note:
The base_url is optional and is only intended to be used if the metadata_type is URL. As known from ERC-721 this can be used to resolve metadata for a specific NFT which can be fetched from an URL based on the token id
The metadata_type MUST be defined on contract level and MUST NOT be mixed across various NFTs in a contract
meta_info
meta_info
Returns metadata associated with an NFT.
Note:
The metadata can be set in the constructor, as well as by implementing extensions like e.g. mintable
The metadata to use depends on the metadata_type defined on contract level and provides certain flexibility:
for URL and OBJECT_ID use MetadataIdentifier
URL can represent any URL and typically the NFT id is used to resolve the metadata using that URL, e.g.
ipfs:// serving as base_url and pointing to a folder stored on IPFS where immutable metadata is stored (recommended)
https:// serving as
for MAP use MetadataMap
MAP provides almost unlimited flexibility and allows any kind of metadata to be represented in a map
token_id
int
data
option(metadata)
Returns the total amount of NFTs in circulation.
total_supply
int
Returns the number of NFTs owned by the account with address owner in the contract. If the owner address is unknown to the contract, None will be returned. Using option type as a return value allows us to determine if the account owns 0, more than 0, or the account has never owned a balance and is still unknown to the contract.
owner
address
balance
option(int)
Returns the owner's address for the provided token_id if the NFT is minted. If the NFT isn't minted, None will be returned.
token_id
int
owner
option(address)
Transfers NFT with ID token_id from the current owner to the to address. Will invoke IAEX141Receiver.on_aex141_received if the to address belongs to a contract. If provided, data will be submitted with the invocation of IAEX141Receiver.on_aex141_received. Emits the Transfer event.
Note: For security reasons reentrancy is not possible. Therefore contracts cannot use this entrypoint to transfer NFTs to itself. Use transfer_to_contract instead to cover this scenario.
Throws if:
Call.caller is NOT the current owner or NOT approved to transfer on behalf of the owner;
token_id is NOT a valid token;
the invocation of IAEX141Receiver.on_aex141_received fails.
token_id
int
data
option(string)
Transfers NFT with ID token_id from the current owner to the contract calling this entrypoint. As reentrancy is not possible for security reasons, this entrypoint MUST be used if a contract (e.g. NFT marketplace) wants to transfer the NFT to itself on behalf of the owner. Emits the Transfer event.
Throws if:
Call.caller is NOT a contract or NOT approved to transfer on behalf of the owner;
token_id is NOT a valid token;
to
address
token_id
int
data
option(string)
Sets the approved address to interact on behalf of an owner for the NFT with ID token_id. If enabled is true the operator address is approved, if false the approval is revoked. Throws unless caller is the current NFT owner, or an authorized operator of the current owner. Emits the Approval event.
approved
address
token_id
int
enabled
bool
Enables or disables approval for an operator address to manage all of the caller's NFTs. If enabled is true, the operator address is approved, if false, the approval is revoked. Emits the ApprovalForAll event.
operator
address
enabled
bool
Returns the address approved to interact with the NFT with ID token_id or returns None if no approval has been set. Throws if NFT with ID token_id does not exist.
token_id
int
approved
option(address)
Returns true if approved address is approved to transact for NFT with ID token_id.
token_id
int
approved
address
approved
bool
Returns true if operator is approved to commit transactions on behalf of owner.
Indicates whether an address is an authorized operator for another address.
owner
address
approved
address
approved
bool
This event MUST be triggered and emitted when tokens are transferred.
The event arguments should be as follows: (from, to, token_id)
from
address
to
address
token_id
int
This event MUST be triggered and emitted upon approval, including revocation of approval.
The event arguments should be as follows: (owner, approved, token_id, enabled).
Enabled is of type string, because of a limit of 3 on indexed values. Since address, int and bool are automatically indexed, having enabled as bool would cause an error, as it would be the 4th indexed item. Use "true" or "false" as return values instead.
owner
address
approved
address
token_id
int
enabled
string
This event MUST be triggered and emitted upon a change of operator status, including revocation of approval for all NFTs in the contract.
The event arguments should be as follows: (owner, operator, approved)
For idiomatic reasons approved is, just as with Approval, of type string
owner
address
operator
address
approved
string
The standard only allows safe transfers of tokens. On transfer a check MUST be performed which checks if the recipient is a contract and if so the transfer MAY ONLY happen if on_aex141_received returns true.
Deals with receiving NFTs on behalf of a contract. Contracts MUST implement this interface to be able to receive NFTs. Mint and transfer transactions will invoke the on_aex141_received function.
Returns true or false to signal whether processing the received NFT was successful or not.
from
option(address)
token_id
int
data
option(string)
This section covers the extendability of the basic token - e.g. mintable, burnable.
When an NFT contract implements an extension its name should be included in the aex141_extensions array, in order for third party software or contracts to know the interface.
Any extensions should be implementable without permission. Developers of extensions MUST choose a name for aex141_extensions that is not yet used. Developers CAN make a pull request to the reference implementation for general purpose extensions and maintainers choose to eventually include them.
The mintable extension SHOULD be used for generic NFT minting without specific requirements in regards to minting.
Note: If you aim to reuse the same metadata across many NFTs you might prefer the mintable_templates extension.
Issues a new token to the provided address. If the owner is a contract, IAEX141Receiver.on_aex141_received will be called with data if provided.
Emits the Mint event.
Throws if the call to IAEX141Receiver.on_aex141_received implementation failed (safe transfer)
owner
address
metadata
option(metadata)
data
option(string)
token_id
int
The mintable_limit extension SHOULD be used if the amount of NFTs to mint should be limited/capped. It MAY ONLY be used in combination with the mintable extension.
The initially defined token limit MUST be greater than or equal to 1.
Emits the TokenLimit event on contract creation.
Returns the limit / max amount of NFTs that can be minted.
token_limit
int
Decreases the NFT limit/cap defined in the collection. An increase of the limit is forbidden.
Emits the TokenLimitDecrease event.
Throws if:
new_limit equals the current token_limit
new_limit is lower than the current total_supply
new_limit
int
The burnable extension SHOULD be used if NFTs within a contract are intended to be burnable.
Burns the NFT with the provided token_id.
Emits the Burn event.
Throws if Call.caller is NOT the current owner or NOT approved to transfer on behalf of the owner.
token_id
int
The mintable_templates extension SHOULD be used if multiple NFTs within a contract should share the same metadata. The extension provides the possbility to create templates. Optionally an edition limit for each template can be defined on template creation. If no edition limit is provided, it's considered to be unlimited. The edition limit can be decreased at any point of time as long as the new value does not exceed the current edition supply. Also, templates can be deleted if no NFT has been created using the template.
Note:
On contract level the MAP MUST be used as metadata_type
the map stores the template_id and edition_serial of each NFT
if mutable_attributes extension is used, it also stores the mutable attributes
The template_metadata_type can either be T_URL (string, e.g. ipfs:// pointing to a JSON stored on IPFS) or T_MAP (map(string, string))
it is defined during contract creation
it is applied to ALL templates created with the contract
Returns the metadata type which is used for templates.
template_metadata_type
template_metadata_type
Returns the template for the provided template_id in case it exists, otherwise None.
template
option(template)
Returns the total amount of templates that currently exist.
template_supply
int
Creates a new template for specific immutable metadata. The immutable_metadata needs to be MetadataIdentifier in case template_metadata_type is T_URL and MetadataMap for T_MAP. The edition limit defines how many NFTs can be minted based on a specific template. If no edition limit is provided, an unlimited amount of NFTs can be created using the template. The edition limit can be decreased at any time.
Emits the TemplateCreation event.
Note: It's recommended to perform a check if immutable_metadata is considered valid according to individual requirements.
Throws in case the wrong variant for metadata is provided:
variant MUST be MetadataIdentifier if template_metadata_type is T_URL
variant MUST be MetadataMap if template_metadata_type is T_MAP
immutable_metadata
metadata
edition_limit
option(int)
template_id
int
Deletes the template with the provided id.
Emits the TemplateDeletion event.
Throws if:
the provided template_id does not exist
an NFT based on this template has already been created
template_id
int
Mints a new NFT for the provided template id. If to is a contract, IAEX141Receiver.on_aex141_received will be called with data if provided.
Emits the TemplateMint event.
Throws if:
the provided template_id does not exist
the mint would exceed the current edition_limit of the template
the call to IAEX141Receiver.on_aex141_received implementation failed (safe transfer)
to
address
template_id
int
data
option(string)
token_id
int
Decreases the edition limit of a specific template. An increase of the edition limit of a template is forbidden.
Emits the EditionLimitDecrease event.
Throws if:
the provided template_id does not exist
the new_limit is equal to or lower than 0
the new_limit is equal to or higher than the current edition limit
the new_limit is lower than the current edition supply
template_id
int
new_limit
int
The mintable_templates_limit extension SHOULD be used to introduce a limit/cap for the amount of templates that may be in existence. It MAY ONLY be used in combination with the mintable_templates extension.
Returns the limit / max amount of templates that can be created.
template_limit
int
Decreases the template limit/cap defined in the contract. An increase of the limit is forbidden.
Emits the TemplateLimitDecrease event.
Throws if:
new_limit equals to or is lower than 0
new_limit equals the current token_limit
new_limit is lower than the current total_supply
new_limit
int
The mutable_attributes extension SHOULD be used if NFTs in the contract should store attributes which can change over time. This can e.g. be beneficial for game assets where users could level up their characters. The mutable attributes are expected to be provided in a JSON string.
Updates the JSON string that contains mutable attributes of the NFT.
Emits the MutableAttributesUpdate event.
Throws if the provided token_id does not exist.
token_id
int
mutable_attributes
string
Mint
This event is defined by the mintable extension and MUST be triggered whenever a new token is minted.
The event arguments should be as follows: (to, token_id)
to
address
token_id
int
TokenLimit
This event is defined by the mintable_limit extension and MUST be triggered in the init entrypoint during contract creation.
The event arguments should be as follows: (limit)
limit
int
TokenLimitDecrease
This event is defined by the mintable_limit extension and MUST be triggered whenever the decrease_token_limit entrypoint is called.
The event arguments should be as follows: (old_limit, new_limit)
old_limit
int
new_limit
int
Burn
This event is defined by the burn extension and MUST be triggered whenever an NFT is burned.
The event arguments should be as follows: (owner, token_id)
owner
address
token_id
int
TemplateCreation
This event is defined by the mintable_templates extension and MUST be triggered whenever a new template is created.
The event arguments should be as follows: (template_id)
template_id
int
TemplateDeletion
This event is defined by the mintable_templates extension and MUST be triggered whenever a template is deleted.
The event arguments should be as follows: (template_id)
template_id
int
TemplateMint
This event is defined by the mintable_templates extension and MUST be triggered whenever a new NFT is minted.
The event arguments should be as follows: (to, template_id, token_id, edition_serial). Sophia does not allow 4 "indexed" values as of writing the standard. For this reason edition_serial defined as type string.
The event arguments should be as follows: (to, template_id, token_id, edition_serial)
to
int
template_id
int
token_id
int
edition_serial
string
EditionLimit
This event is defined by the mintable_templates extension and MUST be triggered whenever a new template is created which specifies an edition limit.
The event arguments should be as follows: (template_id, edition_limit)
template_id
int
edition_limit
int
EditionLimitDecrease
This event is defined by the mintable_templates extension and MUST be triggered whenever the decrease_edition_limit entrypoint is called.
The event arguments should be as follows: (template_id, old_limit, new_limit)
template_id
int
old_limit
int
new_limit
int
TemplateLimit
This event is defined by the mintable_templates_limit extension and MUST be triggered in the init entrypoint during contract creation.
The event arguments should be as follows: (limit)
limit
int
TemplateLimitDecrease
This event is defined by the mintable_templates_limit extension and MUST be triggered whenever the decrease_template_limit entrypoint is called.
The event arguments should be as follows: (old_limit, new_limit)
old_limit
int
new_limit
int
MutableAttributesUpdate
This event is defined by the mutable_attributes extension and MUST be triggered whenever the mutable attributes of an NFT are updated.
The event arguments should be as follows: (token_id, mutable_attributes)
token_id
int
mutable_attributes
string
There are currently following reference implementations available which follows defined standard:
CollectionUniqueNFTs.aes implements the following extensions:
mintable
mintable_limit
burnable
implements the following extensions:
mintable_templates
mintable_templates_limit
mutable_attributes
Additionally there exists following showcase for a simple NFT marketplace using AEX-141:
AEX: 141
Title: Non-Fungible Token Standard
Author: Arjan van Eersel <[email protected]> (@zkvonsnarkenstein), Marco Walz (@marc0olo), Philipp (@thepiwo), Rogerio (@jyeshe)
License: ISC
Discussions-To: https://forum.aeternity.com/t/aeternity-nft-token-standard/9781
Status: Review
Type: Interface
Created: 2021-09-11contract interface IAEX141 =
datatype metadata_type = URL | OBJECT_ID | MAP
datatype metadata = MetadataIdentifier(string) | MetadataMap(map(string, string))
record meta_info =
{ name: string
, symbol: string
, base_url: option(string)
, metadata_type : metadata_type }
datatype event
= Transfer(address, address, int)
| Approval(address, address, int, string)
| ApprovalForAll(address, address, string)
entrypoint aex141_extensions : () => list(string)
entrypoint meta_info : () => meta_info
entrypoint metadata : (int) => option(metadata)
entrypoint total_supply : () => int
entrypoint balance : (address) => option(int)
entrypoint owner : (int) => option(address)
stateful entrypoint transfer : (address, int, option(string)) => unit
stateful entrypoint transfer_to_contract : (int) => unit
stateful entrypoint approve : (address, int, bool) => unit
stateful entrypoint approve_all : (address, bool) => unit
entrypoint get_approved : (int) => option(address)
entrypoint is_approved : (int, address) => bool
entrypoint is_approved_for_all : (address, address) => boolentrypoint aex141_extensions() : list(string)entrypoint meta_info() : meta_infoentrypoint metadata(token_id: int) : option(metadata)entrypoint total_supply() : íntentrypoint balance(owner: address) : option(int)entrypoint owner(token_id: int) : option(address)stateful entrypoint transfer(to: address, token_id: int, data: option(string)) : unitstateful entrypoint transfer(to: address, token_id: int, data: option(string)) : unitstateful entrypoint approve(approved: address, token_id: int, enabled: bool) : unitstateful entrypoint approve_all(operator: address, enabled: bool) : unitentrypoint get_approved(token_id: int) : option(address)entrypoint is_approved(token_id: int, approved: address) : boolentrypoint is_approved_for_all(owner: address, operator: address) : booldatatype event
= Transfer(address, address, int)
| Approval(address, address, int, string)
| ApprovalForAll(address, address, string)Transfer(address, address, int)Approval(address, address, int, string)ApprovalForAll(address, address, string)contract interface IAEX141Receiver =
entrypoint on_aex141_received : (option(address), int, option(string)) => boolentrypoint on_aex141_received(from: option(address), token_id: int, data: option(string)) : boolcontract interface IAEX141Mintable =
datatype event = Mint(address, int)
stateful entrypoint mint : (address, option(metadata), option(string)) => intstateful entrypoint mint(owner: address, metadata: option(metadata), data: option(string)) : intcontract interface IAEX141MintableLimit =
datatype event
= TokenLimit(int)
| TokenLimitDecrease(int, int)
entrypoint token_limit : () => int
stateful entrypoint decrease_token_limit : (int) => unitentrypoint token_limit() : íntstateful entrypoint decrease_token_limit(new_limit: int) : unitcontract interface IAEX141Burnable =
datatype event = Burn(address, int)
stateful entrypoint burn : (int) => unitstateful entrypoint burn(token_id: int) : unitcontract interface IAEX141MintableTemplates =
datatype template_metadata_type = T_URL | T_MAP
datatype event
= TemplateCreation(int)
| TemplateDeletion(int)
| TemplateMint(address, int, int, string)
| EditionLimit(int, int)
| EditionLimitDecrease(int, int, int)
record template =
{ immutable_metadata: metadata
, edition_limit: option(int)
, edition_supply: int }
entrypoint template_metadata_type : () => template_metadata_type
entrypoint template : (int) => option(template)
entrypoint template_supply : () => int
stateful entrypoint create_template : (metadata, option(int)) => int
stateful entrypoint delete_template : (int) => unit
stateful entrypoint template_mint : (address, int, option(string)) => int
stateful entrypoint decrease_edition_limit : (int, int) => unitentrypoint template_metadata_type() : template_metadata_typeentrypoint template(template_id: int) : option(template)entrypoint template_supply() : íntstateful entrypoint create_template(immutable_metadata: metadata, edition_limit: option(int)) : intstateful entrypoint delete_template(template_id: int) : unitstateful entrypoint template_mint(to: address, template_id: int, data: option(string)) : intstateful entrypoint decrease_edition_limit(template_id: int, new_limit: int) : unitcontract interface IAEX141MintableTemplatesLimit =
datatype event
= TemplateLimit(int)
| TemplateLimitDecrease(int, int)
entrypoint template_limit : () => int
stateful entrypoint decrease_template_limit : (int) => unitentrypoint template_limit() : íntstateful entrypoint decrease_template_limit(new_limit: int) : unitcontract interface IAEX141MutableAttributes =
datatype event = MutableAttributesUpdate(int, string)
stateful entrypoint update_mutable_attributes : (int, string) => unitstateful entrypoint update_mutable_attributes(token_id: int, mutable_attributes: string) : unitMint(address, int)TokenLimit(int)TokenLimitDecrease(int, int)Burn(address, int)TemplateCreation(int)TemplateMint(address, int, int, string)EditionLimit(int, int)EditionLimitDecrease(int, int, int)TemplateLimit(int)TemplateLimitDecrease(int, int)MutableAttributesUpdate(token_id, string)base_url...
OBJECT_ID can be used to refer to any kind of item which typically already exists (e.g. the VIN of a car)
burnable

Table of Contents
The middleware is a caching and reporting layer which sits in front of the nodes of the . Its purpose is to respond to queries faster than the node can do, and to support queries that for reasons of efficiency the node cannot or will not support itself.
The architecture of the app is explained .
For running it without Docker, ensure that you have installed, using Erlang 26 or newer.
If using Docker, make sure you have or newer.
Firstly, clone the middleware repo:
git clone https://github.com/aeternity/ae_mdw && cd ae_mdw
Before running it, it's recommended to use a Node database snapshot for faster syncing.
Download one of the full backups from https://downloads.aeternity.io
Create a 'data' directory under the root repo dir and extract the backup to it (it creates a mnesia directory).
To start a docker container on mainnet, simply run: docker compose up.
You can check on /status page that the node_height is higher than 600000.
In case you want to use it on testnet or for development purposes please follow the instructions below.
The middleware runs along with an Aeternity Node on the same docker container and BEAM VM instance.
Its configuration file is found at docker/aeternity.yaml. Under fork_management key, the network_id options are: ae_mainnet and ae_uat (testnet).
If you are running your own build, on dev environment, with docker-compose-dev.yml the docker/aeternity.yaml is copied when the container is started and it is used as a node configuration file.
For docker hub images, you can create a volume to copy your local /home/aeternity/aeternity.yaml by uncommenting it on docker-compose.yml.
You may also redefine other Aeternity node configurations. More information regarding configuration can be found
The aeternity/ae_mdw docker image runs with unprivileged user (uid=1000).
Therefore permissions should be given when mapping the data/mnesia and/or data/mdw.db volumes:
In case you want to setup different accounts on testnet with initial balance you can add this volume to docker-compose-dev.yml:
- ${PWD}/accounts_test.json:/home/aeternity/node/data/aecore/.genesis/accounts_test.json
An example of accounts_test.json is:
Starting the middleware with docker is described , to start the middleware as a hyperchain you can follow guide.
The project comes with a two docker compose files:
docker-compose.yml: to run the middleware as is
docker-compose-dev.yml: for development env that includes dev tools
A helper script might be used to get a docker shell on dev env: ./scripts/do.sh docker-shell
You should now be able to navigate through the project having the /app as working directory.
When inside the docker container shell, some useful commands that you might want to run are:
We currently provide hosted infrastructure at https://mainnet.aeternity.io/mdw/ , all examples here are based on it.
NOTE: Local deploy with default configuration endpoints will not contain /mdw/ segment on the path.
The routes and respective responses are:
The swagger specification of the endpoints can be downloaded from:
https://testnet.aeternity.io/mdw/v3/api/
It can be visualized on a swagger UI at:
https://testnet.aeternity.io/mdw/swagger
This npm package can be also used for a self-hosted app to visualize these specs: https://www.npmjs.com/package/swagger-ui
The application does not support paginated page-based endpoints. Instead, a
cursor-based pagination is offered. This means that in order to traverse through
a list of pages for any of the paginated endpoints, either the next or prev
field from the current page has to be used instead.
Asking for an arbitrary page, without first retrieving it from the next orprev field is not supported.
The paginated endpoints return JSON in the following format:
The continuation-URL, when concatenated with host, has to be used to
retrieve a new page of results.
Examples
Getting the first transaction:
Getting the next transaction by prepending host (https://mainnet.aeternity.io/mdw) to the continuation-URL from last request:
Once there are no more transactions for a query, the next and/or prev key is set to null.
The client can set limit explicitly if he wishes to receive different number
of transactions in the reply than 10 (max 100).
The scope parameter specifies the time period to look for results matching the criteria:
gen:A-B - from generation A to B (forward if A < B, backward otherwise)
Not all paginated endpoints support all scopes.
All paginated endpoints support a direction parameter that specifies the order in which results are expected to be returned.
It can be either forward or backward (default).
In many of the endpoints there's some additional query parameters that can be sent to change the endpoint behavior.
topWhen top=true, it displays the latest state of the changes by querying the node directly. This is allowed on some of the AEx9 endpoints to obtain the latest balances state for a given contract.
int-as-stringIf this flag is set to true, the response will have all integers set as strings
/v3/transactionsQuerying for transactions via /v3/transactions endpoint supports 3 kinds of parameters specifying which transactions should be part of the reply:
types
generic ids
transaction fields
Types of transactions in the resulting set can be constrained by providing type and/or type_group parameter.
The query allows providing of multiple type & type_group parameters - they form a union of admissible types.
(In other words - they are combined with OR.)
Supported types:
channel_close_mutual, channel_close_solo, channel_create, channel_deposit, channel_force_progress, channel_offchain, channel_settle, channel_slash, channel_snapshot_solo, channel_withdraw.
Supported type groups:
channel
contract
ga
name
Examples:
type parameter:
type_group parameter:
Generic ids allow selecting of transactions related to the provided id in any way.
With generic ids, it is possible to select also create/register transactions of particular AEternity object (like contract, channel or oracle), despite the fact that these transactions don't have the ID of the created object among its transaction fields.
Supported generic IDs:
account
contract
channel
oracle
Examples
Every transaction record has one or more fields with identifier, represented by public key. Middleware is indexing these fields and allows them to be used in the query.
Supported fields with provided transaction type:
The syntax of the field with provided type is: type.field - for example: spend.sender_id
The fields for transaction types are:
channel_close_mutual - channel_id, from_id
channel_close_solo - channel_id, from_id
channel_create - initiator_id, responder_id
channel_deposit - channel_id, from_id
Supported freestanding fields:
In case a freestanding field (without transaction type) is part of the query, it deduces the admissible set of types to those which have this field.
The types for freestanding fields are:
account_id - name_claim, name_preclaim, name_revoke, name_transfer, name_update, oracle_register
caller_id - contract_call
channel_id - channel_close_mutual, channel_close_solo, channel_deposit, channel_force_progress, channel_offchain, channel_settle, channel_slash, channel_snapshot_solo, channel_withdraw
commitment_id - name_preclaim
Supported inner transactions fields:
The ga_meta and paying_for transactions have inner transactions which might be filtered as if they were not inner.
For example, for a GAMetaTx with inner SpendTx, one might request with the following query params:
spend.recipient_id or
spend.sender_id or
spend.recipient_id and spend.sender_id
Examples
with provided transaction type (name_transfer):
freestanding field from_id, and via jq extracting only hash and transaction type:
The query string can mix types, global ids and transaction fields.
The resulting set of transactions must meet all constraints specified by parameters denoting ID (global ids and transaction fields) - the parameters are combined with AND.
If type or type_group is provided, the transaction in the result set must be of some type specified by these parameters.
transactions where each transaction contains both accounts, no matter in which field:
spend transactions between sender and recipient (transaction type = spend is deduced from the fields):
name related transactions for account:
/v3/transactions/:hashSingle transactions can be obtained by either the identifying hash or transaction index.
/txs/countCounting all transactions
It can also be scoped by generations:
Or by address:
Or by type:
NOTE: It cannot be filtered by more than one of these filters.
/v3/key-blocksThere are several endpoints for querying block(s) or generation(s). A generation can be understood as key block and micro blocks containing transactions.
Since we are returning whole generations, replies can be very large.
Examples below are trimmed heavily.
With /v3/key-blocks endpoint:
Numeric range:
/v3/key-blocks/:hash_or_kbiRetrieves a single key block including the micro_blocks_count and transactions_count counters.
Or alternatively, by kbi:
/v3/key-blocksReturns a paginated list of key-blocks together with the amount of micro blocks and transactions each key-block generation has.
/v3/key-blocks/:hash_or_kbi/micro-blocks/v3/micro-blocks/:hash/v3/micro-blocks/:hash/txsThere are several endpoints for querying of the Naming System.
Name objects in Aeternity blockchain have a lifecycle formed by several types of transactions. Names can become claimed (directly or via name auction), updated the lifespan or pointers, transferred the ownership and revoked when not needed.
Information about the name returned from the name endpoints summarizes this lifecycle in vectors of transaction indices, under keys claims, updates, transfers and optional transaction index in revoke.
Transaction index is useful for retrieving detailed information about the transaction via txi/:index endpoint.
Using transactions/:hash endpoint is flexible, on-demand way to get detailed transaction information, but in some situations leads to multiple round trips to the server.
Due to this reason, all name endpoints except name/pointers and name/pointees support expand parameter (either set to true or without value), which will replace the transaction indices with the JSON body of the transaction detail.
/v3/namesNames can be filtered by state, which can contain the following values:
inactive - for listing inactive names (expired or revoked)
active - for listing active names
auction - for listing auctions
They support ordering via parameters by (with value activation, deactivation or name).
Using the by=activation requires state=active and includes only successfully claimed names (those in auction won't appear yet).
Using the by=deactivation means for inactive names that they are sorted by the height of deactivation, whether the name had expired or had been revoked.
For active names it means they are sorted by expiration height.
Without these parameters, the endpoints return results ordered as if by=deactivation were provided.
Active names
Additionally, this endpoint allows you to filter by name owner using the query param owned_by:
An example of by usage:
Names can also be filtered by prefix, as long as they are NOT filtered by owner and ordered by name (e.g. ?prefix=somenam&by=name).
/v3/names/auctionsTo show auctions ordered by name, from the beginning:
/v3/names/:name_or_hashIt's possible to use encoded hash as well:
If the name is currently in auction, the reply has different shape:
/v3/names/auctions/:nameAuction specific name resolution is available behind this endpoint:
/v3/accounts/:account_id/names/pointeesReturns names pointing to a particular pubkey. Can be scoped by gen using scope=gen:100-200 query parameter.
/v3/names/:name/claimsReturns the name claims, paginated.
/v3/names/:name/transfersReturns the name transfers, paginated.
/v3/names/:name/updatesReturns the name updates, paginated.
/v3/contractsPaginatable list of all non-preset contracts, filterable by scope.
/v3/contracts/:idGet a single contract.
/v3/contracts/logsA paginable contract log endpoint allows querying of the contract logs using several querying parameters, including:
contract_id - listing only logs emitted by given contract
event - listing only logs emitted by particular event constructor (base32hex encoded blake2b hash)
data - listing only logs which have data field matching the provided prefix
The attributes returned on each object are the following:
args - a list of event constructor arguments as big integers. Contract bytecode doesn't contain metadata describing the types of the contract events. As a result, we can only report the binary blobs to the user, which can be either an integer (probably denoting an amount or counter), or public key.
The integer can be converted to public key (256-bits) binary in Elixir (or Erlang) shell:
call_tx_hash - hash of contract call transaction which emitted the event log
contract_id - contract identifier
Note for contract writers
From the above, it is obvious that due to the lack of useful metadata in the contract bytecode, browsing contract logs isn't user friendly.
However, logs are still useful for people writing the contracts since they have source code of the contract.
With access to the contract's source code, the developer can:
identify the event log constructor from the event_hash field
with the constructor, the developer knows the types of args for a particular event log
integer arguments are then understandable literally, while hashes need one more step:
Listing the last (to date) contract log in the chain:
Listing contract logs in range between generations 200000 and 210000:
Listing contract logs in generation 250109 only:
Listing latest logs for given contract
Listing first logs where data field points to aeternity.com:
(The value of data parameter needs to be URL encoded, which is not visible in this example)
Listing the last "TipReceived" event:
/v3/contracts/callsA running contract can call other functions during execution. These calls are recorded and can be queried later.
The query accepts following filters:
fname - The prefix of the name of the function
contract - The contract for the calls
ID field - Any field belonging to the contract call transaction
Using function prefix
Using ID field
Following ID fields are recognized: account_id, caller_id, channel_id, commitment_id, from_id, ga_id, initiator_id, name_id, oracle_id, owner_id, payer_id, recipient_id, responder_id, sender_id
Contract_id field is inaccessible via this lookup, as when present in query, it filters only contracts with given contract id and doesn't look into internal transaction's fields.
/v3/transfersDuring the operation of the node, several kinds of internal transfers happen which are not visible on general transaction ledger.
Besides specifying of scope and direction as with other streaming endpoints (via forward/backward or gen), the query accepts following filters:
kind. At the moment, following kinds of transfers can be queried:
fee_spend_name (fee for placing bid to the name auction)
fee_refund_name (returned fee when the new name bid outbids the previous one in the name auction)
Listing internal transfers in range
Listing internal transfers of a specific kind
Listing internal transfers related to specific account
There are several endpoints for fetching information about the oracles.
Oracles in Aeternity blockchain have a lifecycle formed by several types of transactions, similar to the Name objects.
/v3/oraclesThere is only paginable endpoint for listing oracles, which can be filtered by scope (e.g. gen:100-200) or state (active or inactive).
Inactive oracles
Active oracles
/v3/oracles/:id/v3/oracles/:id/queriesPaginated list of an oracle's queries.
/v3/oracles/:id/responsesPaginated list of an oracle's responses to queries.
/v3/channelsReturns active channels ordered by the txi of the last update.
These can also be filtered by state=active or state=inactive.
Besides the participants balances it includes some fields intrinsic to the channel such as:
the reserve deposited in the channel for paying fees and assuring refunds;
lock parameters, in case of individual actions; and
delegates allowed to represent participants
/v3/channels/:idReturns the state of an active/inactive channel.
Optionally a block_hash parameter might be used to query for the state on a specific block.
In this example it retrieves the ChannelDepositTx as the last udpate for a block prior to the last update that was a ChannelCloseMutualTx.
/v3/channels/:id/updatesReturns a paginated list of updates done to a channel.
AEx9 tokens standard is defined by AEX9 (https://github.com/aeternity/AEXs/blob/master/AEXS/aex-9.md).
/v3/aex9Returns paginated list of AEx9 contracts. Can be sorted with the by query parameter by name (default), symbol or creation.
These endpoints accepts an optiona parameter of prefix OR exact for listing tokens with the name or symbol, which are matching either by prefix, or exactly.
/v3/aex9/:contract_id/v3/aex9/:contract_id/balances/v3/aex9/:contract_id/balances/:account_id/v3/aex9/:contract_id/transfersAEX-141 NFT contracts might organize the access and storage of NFTs metadata in flexible ways. This behaviour is declared during contract creation with the metadata_type field. This and other meta_info fields like name and symbol can be accessed by /aex141 endpoint that displays information about NFT contracts.
/v3/aex141Returns creation and stats information in default paginated way for all NFT collections.
/v3/aex141/:contract_idReturns creation and stats information for a specific NFT collection.
/v3/aex141/:contract_id/tokensReturns the tokens of a collection in paginated way.
/v3/aex141/:contract_id/tokens/:token_idReturns the owner wallet address of a NFT.
/v3/aex141/:contract_id/templatesReturns the NFT templates of a collection in paginated way.
/v3/aex141/:contract_id/templates/:template_id/tokensReturns the NFTs from a collection template in paginated way.
/v3/accounts/:account_id/aex141/tokensReturns each NFT owned by a wallet in paginated way.
/v3/aex141/:contract_id/transfersReturns all NFT transfers involving a NFT collection in paginated way.
/v3/aex141/transfersReturns paginated NFT transfers where you can filter by an account being the sender, recpient or both.
/v3/stats/deltaTo show a statistics for a given height, we can use "stats" endpoint:
/v3/stats/totalAggregated (summarized) statistics are also available, showing the total sum of rewards and the token supply:
These endpoints allow pagination, with typical forward/backward direction or scope denoted by gen/from-to.
/v3/stats/minersTotal reward given to each chain miner.
/v3/stats/blocksRetrieve the total count of blocks over time, with an optional filter by block type (key or micro). By default, this will count all blocks.
You can adjust the time granularity of the results using the interval_by query parameter, which supports day (default), week, or month.
Additionally, filter results by specifying a date range with the min_start_date and/or max_start_date parameters. Dates should be provided in ISO 8601 format.
/v3/stats/namesRetrieve the count of names over time.
Similar to block stats, interval_by, min_start_date and max_start_date can be used.
/v3/stats/transactionsRetrieve the count of transactions over time, with an optional filter by transaction type. By default, this will count all transactions.
Similar to blocks stats, interval_by, min_start_date and max_start_date can be used.
/v3/statsGlobal statistics.
Intended for being able to display all events in which a specific account is related to in any way.
An activity event occurs when there's any change in the blockchain related to a specific account. It is not the same as the log events which occur when executing a contract.
/v3/accounts/:id/activitiesPaginated list of events related to the :id account.
Each activity contains 3 values:
height - The height in which the event occurred
type - The type of event.
payload - An object whose structure depends on the type of event.
For transaction events the activity type will be <TxType>Event, and the payload will contain a single transaction object as displayed in the /v3/transactions endpoint.
Transaction events can also be InternalContractCallEvent which represent transactions that happen internally during a contract call.
Optionally the owned_only=true parameter might be used to return only activities initiated by the account.
Additionally, activities can be filtered by any of these types using ?type=<type> query parameter:
transactions - Transactions containing the account in any of the transaction fields
aexn - AExN (aex9 and aex141) activities
aex9 - AEx9 activities
The websocket interface, which listens by default on port 4001, gives asynchronous notifications when various events occur.
Each event is notified twice: firstly when the Node has synced the block or transaction and after when AeMdw indexation is done.
In order to differentiate, please check the "source" field on .
Subscribe
Unsubscribe
KeyBlocks
MicroBlocks
Transactions
Object, which takes a further field, target - can be any æternity entity. So you may subscribe to any æternity object type, and be sent all transactions which reference the object. For instance, if you have an oracle ok_JcUaMCu9FzTwonCZkFE5BXsgxueagub9fVzywuQRDiCogTzse
/websocketThe V1 websocket interface accepts JSON - encoded commands to subscribe and unsubscribe, and answers these with the list of subscriptions. A session will look like this:
Actual chain data is wrapped in a JSON structure identifying the subscription to which it relates.
When the source is "node" it means that the Node is synching the block or transaction (not yet indexed by AeMdw).
If it's "mdw", it indicates that it's already available through AeMdw Api.
/v3/websocketThe V3 websocket interface behaves the same way as the V1 interface, but when the published message has source mdw it returns the rendered representation of the object as it would be rendered by the middleware (e.g. the returned object for the Transactions subscription will be the same object as returned by the /v3/transactions endpoint).
Running unit tests will not sync the database. To run them:
The database has to be fully synced. Then, run the tests with:
These tests allow you to create your own transactions using the devmode (plus the JS SDK). To add newer tests you need to:
Add the transactions creation on node_sdk/index.js.
Run the JavaScript file using docker compose -f docker-compose-dev.yml run node_sdk node index.js.
Add new devmode tests under the test/devmode/ directory.
On push:
Commit linter for conventional commit messages
Elixir code formatting
Credo
Dialyzer
On merge to master:
Release with notes based on git history
In order to anticipate some of these checks one might run mix git_hooks.install.
This installs pre_commit and pre_push checks as defined by config :git_hooks in dev.tools.exs.
If sure about the change, if it was for example in an integration test case and it was already tested and formatted,
one can use git push --no-verify to bypass the hook.
Every time an endpoint is changed, the swagger v2 file should be changed as well.
contract_call, contract_create
ga_attach, ga_meta
name_claim, name_preclaim, name_revoke, name_transfer, name_update
oracle_extend, oracle_query, oracle_register, oracle_response
paying_for
spend
oracle
paying
spend
channel_force_progress - channel_id, from_id
channel_offchain - channel_id
channel_settle - channel_id, from_id
channel_slash - channel_id, from_id
channel_snapshot_solo - channel_id, from_id
channel_withdraw - channel_id, to_id
contract_call - caller_id, contract_id
contract_create - owner_id, contract_id
ga_attach - owner_id, contract_id
ga_meta - ga_id
name_claim - account_id
name_preclaim - account_id, commitment_id
name_revoke - account_id, name_id
name_transfer - account_id, name_id, recipient_id
name_update - account_id, name_id
oracle_extend - oracle_id
oracle_query - oracle_id, sender_id
oracle_register - account_id
oracle_response - oracle_id
paying_for - payer_id
spend - recipient_id, sender_id
contract_id - contract_call
entrypoint - contract_call
from_id - channel_close_mutual, channel_close_solo, channel_deposit, channel_force_progress, channel_settle, channel_slash, channel_snapshot_solo
ga_id - ga_meta
initiator_id - channel_create
name_id - name_revoke, name_transfer, name_update
oracle_id - oracle_extend, oracle_query, oracle_response
owner_id - contract_create, ga_attach
payer_id - paying_for
recipient_id - name_transfer, spend
responder_id - channel_create
sender_id - oracle_query, spend
to_id - channel_withdraw
function - the name of the function called
aexn-args- formats the args topics according to the event type
data - decoded (human readable) data field of event log (if any)
event_hash - base32hex encoded blake2b hash of the name of the event constructor
The source of the contract in question has one of the event log constructors named "TipReceived".
Its encoded hash can be retrieved as:
ext_caller_contract_id - caller contract id, potentially different to contract_id, if the contract which emitted the event was called from other contract
log_idx - contract call can emit many events. Log idx uniquely identifies the event log inside the contract call.
after extracting the binary of the argument, this binary should be then passed to:
where the <id-type> can be one of: :account_pubkey, :contract_pubkey, :oracle_pubkey
and others, the full list of known types is here (in Erlang syntax):
https://github.com/aeternity/aeserialization/blob/master/src/aeser_api_encoder.erl#L16
to_idfee_lock_name (locked fee of the name auction winning)
reward_oracle (reward for the operator of the oracle (on transaction basis))
reward_block (reward for the miner (on block basis))
reward_dev (reward for funding of the development (on block basis))
accounts_minerva, accounts_fortuna and accounts_lima (added on hardforks including migrated ERC20 amounts)
It it possible to provide just a prefix of the kind in interest, e.g.: "reward" will return all rewards, "fee" will return all fees, "accounts" will return credits after hardforks.
account - account which received rewards or that was charged fees or that received tokens after a hardfork migration.
aex141 - AEx141 activitiescontract - Internal and external contract calls
transfers - Internal (both gen-based and tx-based) transfers
claims - Name claims related to the name hash
./scripts/test-devmode.sh.ExCoveralls
iex(aeternity@localhost)11> Base.hex_encode32(:aec_hash.blake2b_256_hash("TipReceived"))
"MVGUQ861EKRNBCGUC35711P9M2HSVQHG5N39CE5CCIUQ7AGK7UU0====":aeser_api_encoder.encode(<id-type>, extracted-binary)mkdir -p data/mnesia data/mdw.db
chown -R 1000 data{
"ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi": 10000000000000000000000000000000
}iex --sname aeternity@localhost -S mix # IEx shell
elixir --sname aeternity@localhost -S mix phx.server # Start the server
elixir --sname aeternity@localhost -S mix test # Unit tests
INTEGRATION_TEST=1 elixir --sname aeternity@localhost -S mix test.integration # Integration tests
mix format # Run formatting tool
mix credo # Run `credo` tool
mix dialyzer # Run `dialyzer` toolGET /v3/key-blocks - key blocks with micro blocks and transaction counts
GET /v3/key-blocks/:hash_or_kbi - key block by hash or height
GET /v3/key-blocks/:hash_or_kbi/micro-blocks - micro block belonging to key block
GET /v3/micro-blocks/:hash - micro block with transaction count
GET /v3/micro-blocks/:hash/transactions - micro block transactions
GET /v3/transactions - transactions in any direction
GET /v3/transactions/:hash - transaction by hash
GET /v3/transactions/count - total number of transactions (last transaction index + 1)
GET /v3/accounts/:id/activities - transactions, internal contract calls, AEX-N and internal transfers involving an account
GET /v3/accounts/:account_id/aex9/balances - aex9 account balances
GET /v3/accounts/:account_id/names/pointees - AENS names that point to the account
GET /v3/contracts - contracts
GET /v3/contracts/:id - contract by id
GET /v3/contracts/logs - contract logs
GET /v3/contracts/calls - contract calls
GET /v3/names - AENS names
GET /v3/names/:id/auction - AENS name auction
GET /v3/names/:id/pointers - AENS name pointer
GET /v3/names/auctions - all AENS name auctions
GET /v3/names/:id - AENS name state and transaction history
GET /v3/names/:id/claims - AENS name claims history
GET /v3/names/:id/updates - AENS name update history
GET /v3/names/:id/transfers - AENS name transfer history
GET /v3/oracles - expired oracles ordered by expiration height, filtered by active/inactive state and scope
GET /v3/oracles/:id - oracle information by hash
GET /v3/oracles/:id/queries - oracle queries
GET /v3/oracles/:id/responses - oracle responses
GET /v3/channels - active channels ordered by activation height
GET /v3/channels/:id - active or inactive channel
GET /v3/channels/:id/updates - displays all updates done to a channel
GET /v3/transfers - internal transfers from the top of the chain
GET /v3/aex9 - aex9 contracts
GET /v3/aex9/:contract_id - aex9 contract tokens
GET /v3/aex9/:contract_id/balances - aex9 contract balances
GET /v3/aex9/:contract_id/balances/:account_id - aex9 contract account balance
GET /v3/aex9/transfers - aex9 transfers that can be filtered by sender/recipient
GET /v3/aex9/:contract_id/balances/:account_id/history - aex9 contract account balances history
GET /v3/aex141 - nft contracts meta info and stats
GET /v3/aex141/:contract_id - nft contract meta info and stats
GET /v3/aex141/owned-nfts/:account_id - nfts owned by a wallet
GET /v3/aex141/:contract_id/owner/:token_id - the owner wallet address of a NFT
GET /v3/aex141/:contract_id/owners - the owners wallets of NFTs from a collection
GET /v3/aex141/:contract_id/templates - nft templates
GET /v3/aex141/:contract_id/templates/:id/tokens - nft supply from a template
GET /v3/aex141/transfers - nft transfers that can be filtered by sender/recipient
GET /v3/stats/delta - statistics for generations from tip of the chain
GET /v3/stats/total - aggregated statistics for generations from tip of the chain
GET /v3/stats/miners - total rewards for each miner
GET /v3/stats/transactions - statistics over time of transactions count
GET /v3/stats/blocks - statistics over time of blocks count
GET /v3/stats/names - statistics over time of names count
GET /v3/stats - global statistics
GET /v3/status - middleware status{
"data": [...objects...],
"next": continuation-URL or null,
"prev": continuation-URL or null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2Rkmk15VeTVWTHt9bVBFcQRuvseKCkuHpm1RexsMcpAdZpFCLx",
"block_height": 77216,
"hash": "th_MutYY63TMfYQ7z4rWrQd8WGJqszz1h3FdAGHYLVYJBquHoG2V",
"micro_index": 0,
"micro_time": 1557275476873,
"signatures": [
"sg_SKC9yVm59qNh3HrpRdqfbkYnoH1ksypECnPxe67iuPadF3KN7HjR4D7qs4gYkeAhbgno2yUjHfZMcTxrF6CKFZQPaGfdq"
],
"tx": {
"amount": 1e+18,
"fee": 16840000000000,
"nonce": 7,
"payload": "ba_Xfbg4g==",
"recipient_id": "ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD",
"sender_id": "ak_2cLJfLQPhkTiz7RCVQ9ii8mVPJu8gHLy6qpafmTcHYrFYWBHCG",
"type": "SpendTx",
"version": 1
},
"tx_index": 1776073
}
],
"next": "/v3/transactions?direction=forward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&cursor=1779354&limit=1",
"prev": "/v3/transactions?direction=forward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&cursor=19813844&limit=1&rev=1"
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&cursor=1779354&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_SDfdhTd3zfTpAqHMUJsX8RjAm6QyrZYgtqNf3y6EdMMSppEgd",
"block_height": 77865,
"hash": "th_2RfB4NrPNyAr8gkm5vTQimVo6uBcZMQfmqdY8LZkuRJfhcs3HA",
"micro_index": 0,
"micro_time": 1557391780018,
"signatures": [
"sg_XjVTnUbvytX3pAbQQvwYFYXETCqDKzyen7kXqoEqRm5hr6m72k3RzKBHP4GWTHup51ZnxQuDf8R8Rxu5fUwAQGeQMHmh1"
],
"tx": {
"amount": 1e+18,
"fee": 16840000000000,
"nonce": 6,
"payload": "ba_Xfbg4g==",
"recipient_id": "ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD",
"sender_id": "ak_2iK7D3t5xyN8GHxQktvBnfoC3tpq1eVMzTpABQY72FXRfg3HMW",
"type": "SpendTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&cursor=1779356&limit=1",
"prev": "/v3/transactions?direction=backward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&cursor=1776073&limit=1&rev=1"
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&type=channel_create&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2aw4KGSWLq7opXT796a5QZx8Hd7BDaGRSwEcyqzNQMii7MrGrv",
"block_height": 1208,
"hash": "th_25ofE3Ah8Fm3PV8oo5Trh5rMMiU4E8uqFfncu9EjJHvubumkij",
"micro_index": 0,
"micro_time": 1543584946527,
"signatures": [
"sg_2NjzKD4ZKNQiqjAYLVFfVL4ZMCXUhVUEXCmoAZkhAZxsJQmPfzWj3Dq6QnRiXmJDByCPc33qYdwTAaiXDHwpdjFuuxwCT",
"sg_Wpm8j6ZhRzo6SLnaqWUb24KwFZ7YLws9zHiUKvWrf89cV2RAYGqftXBAzS6Pj7AVWKQLwSjL384yzG7hK4rHB8dn2d67g"
],
"tx": {
"channel_id": "ch_22usvXSjYaDPdhecyhub7tZnYpHeCEZdscEEyhb2M4rHb58RyD",
"channel_reserve": 10,
"delegate_ids": [],
"fee": 20000,
"initiator_amount": 50000,
"initiator_id": "ak_ozzwBYeatmuN818LjDDDwRSiBSvrqt4WU7WvbGsZGVre72LTS",
"lock_period": 3,
"nonce": 1,
"responder_amount": 50000,
"responder_id": "ak_26xYuZJnxpjuBqkvXQ4EKb4Ludt8w3rGWREvEwm68qdtJLyLwq",
"state_hash": "st_MHb9b2dXovoWyhDf12kVJPwXNLCWuSzpwPBvMFbNizRJttaZ",
"type": "ChannelCreateTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&cursor=73270&limit=1&type=channel_create"
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&type_group=oracle&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2G7DgcE1f9QJQNkYnLyTYTq4vjR47G4qUQHkwkXpNiT2J6hm5T",
"block_height": 4165,
"hash": "th_iECkSToLNWJ77Fiehi39zxJwLjPfstsAtYFC8rbCsEStEy1xv",
"micro_index": 0,
"micro_time": 1544106799973,
"signatures": [
"sg_XoYmhU7J6XzJazUvo48ijUKRj5DweV8rBuwBwgdZUiUEeYLe1h4pdJ7jbBWGHC8M7diMA2AFrH1AL739XNChX4wrH58Ng"
],
"tx": {
"abi_version": 0,
"account_id": "ak_g5vQK6beY3vsTJHH7KBusesyzq9WMdEYorF8VyvZURXTjLnxT",
"fee": 20000,
"nonce": 1,
"oracle_id": "ok_g5vQK6beY3vsTJHH7KBusesyzq9WMdEYorF8VyvZURXTjLnxT",
"oracle_ttl": {
"type": "delta",
"value": 1234
},
"query_fee": 20000,
"query_format": "the query spec",
"response_format": "the response spec",
"type": "OracleRegisterTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&cursor=8892&limit=1&type_group=oracle",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&contract=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&limit=2" | jq '.'
{
"data": [
{
"block_hash": "mh_ZwPrtCMWMPF5e4RLoaY8cb6HUGadSKknpy5gp8nrDes3eSKyZ",
"block_height": 218938,
"hash": "th_6memqAr5S3UQp1pc4FWXT8xUotfdrdUFgBd8VPmjM2ZRuojTF",
"micro_index": 2,
"micro_time": 1582898946277,
"signatures": [
"sg_LiNE1DtiFkUH19WtJ1p9tX9Zy9fuGaW3bAop1mLCe5jJktQ3XiAu2Bop6JPBrkHyi1eQ2xCyPXQxZmiyqroMwaL7BrqWN"
],
"tx": {
"abi_version": 3,
"amount": 0,
"call_data": "cb_KxFE1kQfK58CoImYHijBOQaROWmeJkniQvuQjKtkbE5UZnXQ+sB9eLb1nwCgkRvEABX1lZmfsIGIeFuXiHMZfg6eGt4RXdqdu+P8EZ1cfiCj",
"code": "cb_+QdxRgOgfRB0ofOTJwMaz73GwgUNX4rSsqh81yEyoDCgyFqUs63AuQdDuQXM/ir6YP4ENwEHNwAvGIgABwwE+wNBVElQX05PVF9FWElTVElORxoKBogrGggGABoKCoQoLAgIKwoMCiguDgAMKC4QAgwaChKKMQoUElUACwAUOA4CDAEAJwwIDwIcCwAUCi4QDAIODAIuJwwEKCwICC0KhIQtqoqKFBwaCkCGVQALACgsCAgrCEBE/DMGBgYCBgQDEWWl4A/+PR6JaAA3ADcHZ3cHZwc3AgcHZwd3Zwc3BkcAdwcHBwdnBzcERwAHBwdHAEcCDAKCDAKEDAKGDAKIDAKKDAKMDAKOJwwOAP5E1kQfADcCRwJHADcAGg6CLwAaDoQvABoOhi8AGg6ILwAaDoovABoGjAIaBo4AAQM//liqK7MANwF3JzcGRwB3BwcHBy8YggAHDAT7A0FVUkxfTk9UX0VYSVNUSU5HGgoGghoKCogyCAoMAxFkJuW0KxgGACcMBAQDEWh21t/+W1GPJgA3AXcHLxiCAAcMBPsDQVVSTF9OT1RfRVhJU1RJTkcaCgaCKxoIBgAaCgqEKyoMCggoLAIMAP5kJuW0AjcC9/f3KB4CAgIoLAgCIBAABwwEAQMDNDgCAwD+ZOFddAA3AUcCNwACAxFsZXWrDwJvgibPGgaOAAEDP/5lpeAPAjcBhwM3A0cAB3c3A0cAB3c3A0cAB3c3AAn9AAIEBkY2AAAARjYCAAJGNgQABGOuBJ8Bgbfh7SDBdTd1sh5gynCHKbCjz+owLcaWOKxkvaOqFD+8AAIBAz9GNgAAAEY2AgACRjYEAARjrgSfAYFroODuqDgz06d0bgFzLA3+WX8iEYX/NjmzrNC0Dn7DPgACAQM/RjYAAABGNgIAAkY2BAAEY64EnwGBV3MM/1lAjn9BBvAm1QmZfTQXiQoofqgl4BJQMzPBlBAAAgEDP/5nCp0GBDcCd0cANwAMAQIMAQALAAwCjgMA/BHCC+urNwJ3RwA3AAD+aHbW3wI3AjcCd/cn5wAn5wEzBAIHDAg2BAIMAQACAxFodtbfNQQCKBwCACgcAAACADkAAAEDA/5sZXWrAjcANwBVACAgjAcMBPsDOU9XTkVSX1JFUVVJUkVEAQM//pLx5vMANwJ3RwA3AxdHAAcMA38MAQIMAQAMAwAMAo4DAPwRJz2AQTcDd0cAFzcDF0cABwD+lMr4XwI3Avf39ygeAgICKCwGAiAQAAcMBAEDAzQ4AgMA/pWEerICNwF3BxoKAIIvGIIABwwIDAOvggABAD8PAgQIPgQEBhoKBoIxCggGLWqGhggALZqCggAIAQIIRjgEAAArGAAARPwjAAICAg8CBAg+BAQG/qSV6n0ANwFHADcAAgMRbGV1qw8Cb4Imz1MAZQEAAQM//rOIgD8ANwN3RwAXNwAMAQQMAQIMAQACAxHUfYQwDwJvgibPLxiCAAcMBvsDQVVSTF9OT1RfRVhJU1RJTkcaCgiCKxoKCAAaCgyEKyoODAooLhAADiguEgIOIzgSAAcMCvsDVU5PX1pFUk9fQU1PVU5UX1BBWU9VVGUJAhIMAQIMAhIMAQBE/DMGBgYEBgIDEWWl4A8PAm+CJs8UOBACDAMAJwwELSqEhAoBAz/+zeehTgA3AQcnNwRHAAcHBy8YiAAHDAT7A0FUSVBfTk9UX0VYSVNUSU5HGgoGijIIBgwDEZTK+F8MAQAnDAQEAxFodtbf/tR9hDACNwN3RwAXNwAMAQQMAQIMAQAMAwAMAo4DAPwRJz2AQTcDd0cAFzcDF0cABygMAAcMBvsDgU9SQUNMRV9TRVZJQ0VfQ0hFQ0tfQ0xBSU1fRkFJTEVEAQM//u3Sa0YENwJ3dzcADAEAAgMRlYR6sg8CABoKAoQs6gQCACsAACguBgAEKC4IAgQaCgqIMQoMClUADAECFDgGAlgADAIACwAnDAwPAhYLABQKKAgMAgYMAignDAQtKoSEAC2qiIgMFlUACwAMAQBE/DMGBgYABgQDEWWl4A+5AW4vExEq+mD+FXJldGlwET0eiWglZ2V0X3N0YXRlEUTWRB8RaW5pdBFYqiuzMXRpcHNfZm9yX3VybBFbUY8mRXVuY2xhaW1lZF9mb3JfdXJsEWQm5bQZLl4xMDU2EWThXXRVY2hhbmdlX29yYWNsZV9zZXJ2aWNlEWWl4A8tQ2hhaW4uZXZlbnQRZwqdBiVwcmVfY2xhaW0RaHbW31kuTGlzdEludGVybmFsLmZsYXRfbWFwEWxldatZLlRpcHBpbmcucmVxdWlyZV9vd25lchGS8ebzLWNoZWNrX2NsYWltEZTK+F8ZLl4xMDU1EZWEerJNLlRpcHBpbmcuZ2V0X3VybF9pZBGklep9PW1pZ3JhdGVfYmFsYW5jZRGziIA/FWNsYWltEc3noU45cmV0aXBzX2Zvcl90aXAR1H2EMJ0uVGlwcGluZy5yZXF1aXJlX2FsbG93ZWRfb3JhY2xlX3NlcnZpY2UR7dJrRg10aXCCLwCFNC4yLjAAQNBRMA==",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"deposit": 0,
"fee": 116060000000000,
"gas": 1000000,
"gas_price": 1000000000,
"nonce": 2,
"owner_id": "ak_26ubrEL8sBqYNp4kvKb1t4Cg7XsCciYq4HdznrvfUkW359gf17",
"type": "ContractCreateTx",
"version": 1,
"vm_version": 5
}
},
{
"block_hash": "mh_233z34seMczJE7XtGLJN6ZrvJG9eQXG6fdTFymyzYyUyQbt2tY",
"block_height": 218968,
"hash": "th_2JLGkWhXbEQxMuEYTxazPurKiwGvo5R6vgqjSBw3R8z9F6b4rv",
"micro_index": 1,
"micro_time": 1582904578154,
"signatures": [
"sg_HKk9C1vCuHcZRj9zAdh2WvjvwVJwzNkXgPLsqy2SdR3L3hNkc1oMHjNnQxB558mdRWNPP711DMun3KEy9ZYyvo2QgR8B"
],
"tx": {
"abi_version": 3,
"amount": 1e+16,
"arguments": [
{
"type": "string",
"value": "https://github.com/thepiwo"
},
{
"type": "string",
"value": "Cool projects!"
}
],
"call_data": "cb_KxHt0mtGK2lodHRwczovL2dpdGh1Yi5jb20vdGhlcGl3bzlDb29sIHByb2plY3RzIZ01af4=",
"caller_id": "ak_YCwfWaW5ER6cRsG9Jg4KMyVU59bQkt45WvcnJJctQojCqBeG2",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"fee": 182980000000000,
"function": "tip",
"gas": 1579000,
"gas_price": 1000000000,
"gas_used": 3600,
"log": [
{
"address": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "cb_aHR0cHM6Ly9naXRodWIuY29tL3RoZXBpd2+QKOcm",
"topics": [
"83172428477288860679626635256348428097419935810558542860159024775388982427580",
"32049452134983951870486158652299990269658301415986031571975774292043131948665",
"10000000000000000"
]
}
],
"nonce": 80,
"result": "ok",
"return": {
"type": "unit",
"value": ""
},
"return_type": "ok",
"type": "ContractCallTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&contract=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&cursor=8401663&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&oracle=ok_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2kSWEwFPPMXSjCx3r1nxi3vnpnXAYB7TEVZuEJsSkGjnsewTBF",
"block_height": 34421,
"hash": "th_MRDMpanm3UqgNtAtpEsM59LkyX3TL2wXgeXnx4T9Yn8w1f9L1",
"micro_index": 0,
"micro_time": 1549551115213,
"signatures": [
"sg_LdVk6F8PPMDPW9ZGkAX653GgaSpjRrfgRByKGAjvxUaBAqjgdG7t6NyLs5UPYBWk7xVEfXgyTNgyrjpvfqaFz7DA9L9ZV"
],
"tx": {
"abi_version": 0,
"account_id": "ak_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR",
"fee": 20000,
"nonce": 18442,
"oracle_id": "ok_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR",
"oracle_ttl": {
"type": "delta",
"value": 1000
},
"query_fee": 20000,
"query_format": "string",
"response_format": "int",
"ttl": 50000,
"type": "OracleRegisterTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&cursor=600286&limit=1&oracle=ok_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&channel=ch_22usvXSjYaDPdhecyhub7tZnYpHeCEZdscEEyhb2M4rHb58RyD&limit=2" | jq '.'
{
"data": [
{
"block_hash": "mh_2aw4KGSWLq7opXT796a5QZx8Hd7BDaGRSwEcyqzNQMii7MrGrv",
"block_height": 1208,
"hash": "th_25ofE3Ah8Fm3PV8oo5Trh5rMMiU4E8uqFfncu9EjJHvubumkij",
"micro_index": 0,
"micro_time": 1543584946527,
"signatures": [
"sg_2NjzKD4ZKNQiqjAYLVFfVL4ZMCXUhVUEXCmoAZkhAZxsJQmPfzWj3Dq6QnRiXmJDByCPc33qYdwTAaiXDHwpdjFuuxwCT",
"sg_Wpm8j6ZhRzo6SLnaqWUb24KwFZ7YLws9zHiUKvWrf89cV2RAYGqftXBAzS6Pj7AVWKQLwSjL384yzG7hK4rHB8dn2d67g"
],
"tx": {
"channel_id": "ch_22usvXSjYaDPdhecyhub7tZnYpHeCEZdscEEyhb2M4rHb58RyD",
"channel_reserve": 10,
"delegate_ids": [],
"fee": 20000,
"initiator_amount": 50000,
"initiator_id": "ak_ozzwBYeatmuN818LjDDDwRSiBSvrqt4WU7WvbGsZGVre72LTS",
"lock_period": 3,
"nonce": 1,
"responder_amount": 50000,
"responder_id": "ak_26xYuZJnxpjuBqkvXQ4EKb4Ludt8w3rGWREvEwm68qdtJLyLwq",
"state_hash": "st_MHb9b2dXovoWyhDf12kVJPwXNLCWuSzpwPBvMFbNizRJttaZ",
"type": "ChannelCreateTx",
"version": 1
}
},
{
"block_hash": "mh_joVBtAVakCpGWqesP4S8HpDTs6tUuwq2hjpGHwN4aGP1shfFx",
"block_height": 14258,
"hash": "th_meBfq6EWuUXExBRkbi618RVkQ8nFMz7uo26HkxFXwko9NjF9L",
"micro_index": 0,
"micro_time": 1545910910104,
"signatures": [
"sg_GnbScdeBzkXhj9DR1GQcb2LFxHmuL1eNYrScRCPVp2XKt26BoinsrAbdMBWZimqrY36sF5PzAiA4Vqfx6yfGtRtMGXPuQ",
"sg_VoH1jw5de6wtpzdDsZnA1ATgqV22Rkq2YN2SsphiwqCbY9nipjm3CcwkbKWhAkrud6MnY9biJHVDAzu5UjMf8c691fEcA"
],
"tx": {
"amount": 10,
"channel_id": "ch_22usvXSjYaDPdhecyhub7tZnYpHeCEZdscEEyhb2M4rHb58RyD",
"fee": 17240,
"nonce": 16,
"round": 5,
"state_hash": "st_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACr8s/aY",
"to_id": "ak_ozzwBYeatmuN818LjDDDwRSiBSvrqt4WU7WvbGsZGVre72LTS",
"type": "ChannelWithdrawTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&channel=ch_22usvXSjYaDPdhecyhub7tZnYpHeCEZdscEEyhb2M4rHb58RyD&cursor=94617&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&name_transfer.recipient_id=ak_idkx6m3bgRr7WiKXuB8EBYBoRqVsaSc6qo4dsd23HKgj3qiCF&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2aLMAszzEf3ZS2Xkn8JRrzU4ogWBzxiDYYFqmUKz1r3XJ7nvEF",
"block_height": 262368,
"hash": "th_ssPMQvMPgRgUdbYJXzwxCBugz9J8fgP37MoVdqiBHR71Cm2nM",
"micro_index": 80,
"micro_time": 1590759423839,
"signatures": [
"sg_DBJnw22QJ7gcfhMMvYdkDqgf3LstHLivZjVdPSXz2LuUHedhQwfrpEEdwvebcqwxdNsrRv7FnzbG8f7oEex3muv7ZayZ5"
],
"tx": {
"account_id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"fee": 17380000000000,
"name_id": "nm_2t5eU4gLBmMaw4xn3Xb6LZwoJjB5qh6YxT39jKyCq4dvVh8nwf",
"nonce": 190,
"recipient_id": "ak_idkx6m3bgRr7WiKXuB8EBYBoRqVsaSc6qo4dsd23HKgj3qiCF",
"ttl": 262868,
"type": "NameTransferTx",
"version": 1
},
"tx_index": 11700056
}
],
"next": "/v3/transactions?direction=forward&cursor=11734834&limit=1&name_transfer.recipient_id=ak_idkx6m3bgRr7WiKXuB8EBYBoRqVsaSc6qo4dsd23HKgj3qiCF"
}curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?from_id=ak_ozzwBYeatmuN818LjDDDwRSiBSvrqt4WU7WvbGsZGVre72LTS&limit=5" | jq '.data | .[] | [.hash, .tx.type]'
[
"th_s1C1VC1nwWR4WB8qqJ7o9VokTTPQkAmKQ4aEfQf2GnVa4GKqw",
"ChannelForceProgressTx"
]
[
"th_2donST82cDa4trBqE4d2m7kPoTe56cvQVZ52aSoNG8V4UnV8vX",
"ChannelSettleTx"
]
[
"th_2wevgEPtCdRMpPaoHRQjyaApXK9FbErnM3UtqN7KDmbxjEeiAQ",
"ChannelSlashTx"
]
[
"th_YcFkm7qTgEe5zFhCB21td6f68u1WTH8qArZZwsNqhJCSzhJ3L",
"ChannelSnapshotSoloTx"
]
[
"th_qT9SvwhKZaUeVJLvr4e24gBYCwXaszdMPgRAZismKK2oecFAi",
"ChannelDepositTx"
]$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?account=ak_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR&account=ak_zUQikTiUMNxfKwuAfQVMPkaxdPsXP8uAxnfn6TkZKZCtmRcUD&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_vCizDmxFrwMFCjBFDWfe8husZ4i8d7K2hFKfmQHhau3DkK9Ka",
"block_height": 68234,
"hash": "th_2HvqS7RjoWvBFMGr6WsUsXRhDEcfs3DotZXFm5rRNg7TVZUmnu",
"micro_index": 0,
"micro_time": 1555651193447,
"signatures": [
"sg_Rimi7QJoHfuFTG79iuZ92GTrmzPcjBxRDe4DniXX9SveAQWcZx9D3FMHUhc7fzfSgJ8vcykGrGpdUXtM3gkFM1pMy4AVL"
],
"tx": {
"amount": 1,
"fee": 30000000000000,
"nonce": 19223,
"payload": "ba_dGVzdJVNWkk=",
"recipient_id": "ak_zUQikTiUMNxfKwuAfQVMPkaxdPsXP8uAxnfn6TkZKZCtmRcUD",
"sender_id": "ak_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR",
"ttl": 70000,
"type": "SpendTx",
"version": 1
}
}
],
"next": "/v3/transactions?account=ak_zUQikTiUMNxfKwuAfQVMPkaxdPsXP8uAxnfn6TkZKZCtmRcUD&cursor=17022424&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&sender_id=ak_26dopN3U2zgfJG4Ao4J4ZvLTf5mqr7WAgLAq6WxjxuSapZhQg5&recipient_id=ak_r7wvMxmhnJ3cMp75D8DUnxNiAvXs8qcdfbJ1gUWfH8Ufrx2A2&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_88NN1Y5rmofQ5SUkQNcuBnLMyQucdrCXXcqBduYjLygDmSuSz",
"block_height": 172,
"hash": "th_LnKAy1SDEwQjn9kvVmZ8woCExEX7g29UBvZthWnugKAF2ZBhf",
"micro_index": 1,
"micro_time": 1543404316091,
"signatures": [
"sg_7wbXjsJLYy3gxGpLsi62s9j7nd4Qm3uppPFsNXLw7WdqZE6b1mPyUqkiMvDTJMD3zQCYy2BNgzpdyLAZJuNmkKKhmFUL3"
],
"tx": {
"amount": 1000000,
"fee": 20000,
"nonce": 10,
"payload": "ba_SGFucyBkb25hdGVzs/BHFA==",
"recipient_id": "ak_r7wvMxmhnJ3cMp75D8DUnxNiAvXs8qcdfbJ1gUWfH8Ufrx2A2",
"sender_id": "ak_26dopN3U2zgfJG4Ao4J4ZvLTf5mqr7WAgLAq6WxjxuSapZhQg5",
"type": "SpendTx",
"version": 1
}
}
],
"next": "/v3/transactions?direction=forward&cursor=41&limit=1&recipient_id=ak_r7wvMxmhnJ3cMp75D8DUnxNiAvXs8qcdfbJ1gUWfH8Ufrx2A2&sender_id=ak_26dopN3U2zgfJG4Ao4J4ZvLTf5mqr7WAgLAq6WxjxuSapZhQg5",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions?direction=forward&account=ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD&type_group=name" | jq '.'
{
"data": [
{
"block_hash": "mh_JRADbFAfMf4JJApALLc3JuJgmQtRsQ91WHQvyGZzGJiCuLBFV",
"block_height": 141695,
"hash": "th_vNPVyhuUTWkdvU9hTC6vRK52Hevt5Lbv3ZjVV67KoghE1Vake",
"micro_index": 17,
"micro_time": 1568931464420,
"signatures": [
"sg_C81dBwSTehaPDuz23PDAeZZAgTQYeTGcpYXabkTQiQa7YBzvwwK9us7dxSd6FsqZ2wpzmsM72QYwoUJzKtsY75BG8Eu9i"
],
"tx": {
"account_id": "ak_AiQGnvEgsbLQixVJABpTc9h7hXtP4Lt3sorCa9FbtvYfiBH6a",
"fee": 17300000000000,
"name_id": "nm_2fzt9CmGxe1GgKs42xM95h8nvgXqTECCKqjSZQinQUiwBooGid",
"nonce": 6,
"recipient_id": "ak_E64bTuWTVj9Hu5EQSgyTGZp27diFKohTQWw3AYnmgVSWCnfnD",
"type": "NameTransferTx",
"version": 1
}
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions/th_zATv7B4RHS45GamShnWgjkvcrQfZUWQkZ8gk1RD4m2uWLJKnq" | jq '.'
{
"block_hash": "mh_2kE3N7GCaeAiowu1a7dopJygxQfxvRXYCNy7Pc657arjCa8PPe",
"block_height": 257058,
"hash": "th_zATv7B4RHS45GamShnWgjkvcrQfZUWQkZ8gk1RD4m2uWLJKnq",
"micro_index": 19,
"micro_time": 1589801584978,
"signatures": [
"sg_Z7bbM2a8tDZchtpAkQuMrw5S3cf3yvVizx5qb6hB58KJBBTqhCcpgq2adwNz9SneSQgzD6QQSToiKn3XosS7qybacLpiG"
],
"tx": {
"amount": 20000,
"fee": 19300000000000,
"nonce": 2129052,
"payload": "ba_MjU3MDU4OmtoXzhVdnp6am9tZG9ZakdMNURic2hhN1RuMnYzYzNXWWNCVlg4cWFQV0JyZjcyVHhSeWQ6bWhfald1dnhrWTZReXBzb25RZVpwM1B2cHNLaG9ZMkp4cHIzOHhhaWR2aWozeVRGaTF4UDoxNTg5ODAxNTkxQa+0cQ==",
"recipient_id": "ak_zvU8YQLagjcfng7Tg8yCdiZ1rpiWNp1PBn3vtUs44utSvbJVR",
"sender_id": "ak_zvU8YQLagjcfng7Tg8yCdiZ1rpiWNp1PBn3vtUs44utSvbJVR",
"ttl": 257068,
"type": "SpendTx",
"version": 1
}
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions/count" | jq '.'
11921825$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions/count?scope=gen:123-456" | jq '.'
23$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions/count?id=ak_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR" | jq '.'
19323$ curl -s "https://mainnet.aeternity.io/mdw/v3/transactions/count?tx_type=oracle_register" | jq '.'
286$ curl -s "https://mainnet.aeternity.io/mdw/v3/key-blocks?scope=gen:101125-101125" | jq '.'
{
"data": [
{
"beneficiary" : "ak_2MR38Zf355m6JtP13T3WEcUcSLVLCxjGvjk6zG95S2mfKohcSS",
"hash" : "kh_2MK98WvTtAMzvNNJSi62iConXWshwDM49pfyQi2uVPXE73vv7p",
"height" : 101125,
"info" : "cb_AAAAAfy4hFE=",
"micro_blocks_count" : 1,
"miner" : "ak_2HToRDUsCuBqdGsFqCCE19chrRQ7hhYE5Ebd3LETfwnk3gGnzX",
"nonce" : 9256408633249849368,
"pow" : [5377241, ..., 514753955],
"prev_hash" : "kh_tPiapdedaKhT8egWrtLWsvACbEzTbpECdWg9P8dTtK8P8w48s",
"prev_key_hash" : "kh_tPiapdedaKhT8egWrtLWsvACbEzTbpECdWg9P8dTtK8P8w48s",
"state_hash" : "bs_2SF46f1xU4uxiKKVmeT9jqFWJenftFzXTVse9GGLwtit78zHQP",
"target" : 504458445,
"time" : 1561595666398,
"transactions_count" : 4,
"version" : 3
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/key-blocks?scope=gen:100000-100100&limit=3" | jq '.'
{
"data": [
{
"beneficiary" : "ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv",
"hash" : "kh_foi6pMgz1zi17tYy5eBMQMzCLf7jaAYQTL9WtoJiqR5bk38hg",
"height" : 100000,
"info" : "cb_AAAAAfy4hFE=",
"micro_blocks_count" : 1,
"miner" : "ak_2K5fAjna26t2U2V6v2LwNBUZpT9puriPdvxifDmGRoqG1a7R3Z",
"nonce" : 14620604494251230255,
"pow" : [8664748, ..., 485310990],
"prev_hash" : "mh_2EFE1CxvXM2dKtu4Jt4yLAbW8gS5MkpDtNmGKHP4bPXDvtubKJ",
"prev_key_hash" : "kh_B18SQZmResYV5yqxbFUizKPqrtrjky3LESGUvRECDp9N2kNmA",
"state_hash" : "bs_185cZMdvy6wJXjCZDwGnLJ4TCrU18yxGSVkbtQh4DyCm2yPaV",
"target" : 504047608,
"time" : 1561390154570,
"transactions_count" : 1,
"version" : 3
},
{
"beneficiary" : "ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv",
"hash" : "kh_2gJqm1zmvpMGLMiViwwiHE2EhvdzWjm6KBVthRouHM71rCnUuN",
"height" : 100001,
"info" : "cb_AAAAAfy4hFE=",
"micro_blocks_count" : 2,
"miner" : "ak_2AT33FPB7DSvd3XU2nKPh4sUbBjb6jHWtKh6CF2b1eK2y3daA3",
"nonce" : 8862664339569827477,
"pow" : [7438320, ..., 519071892],
"prev_hash" : "mh_zpiiJYsHZZ9ibKSF1fGLcossdgFjHNaN2Yu6cEF9KSNLqQLbS",
"prev_key_hash" : "kh_foi6pMgz1zi17tYy5eBMQMzCLf7jaAYQTL9WtoJiqR5bk38hg",
"state_hash" : "bs_Wqv4So3wfCV2eyJMnjfiGsrb1D7nrUk2r6K9ufgnX22J5wVPA",
"target" : 504063592,
"time" : 1561390309740,
"transactions_count" : 2,
"version" : 3
},
{
"beneficiary" : "ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv",
"hash" : "kh_2BXy8tftXFVj859j4YpkTyf7Ld5AXrvPqUSbYwGoWZpKQ9VNVB",
"height" : 100002,
"info" : "cb_AAAAAfy4hFE=",
"micro_blocks_count" : 1,
"miner" : "ak_2VJtWGt45q8w9Aj7gYJPz9kZG3EU45xi6YZ4wgXSb25MeYGdfM",
"nonce" : 5829762670850390403,
"pow" : [1917903, ..., 530252456],
"prev_hash" : "mh_NxwB3r43rT4ghZscfuXhHNKNouuVQmU1Lkrf4sgCTPYy3Szdr",
"prev_key_hash" : "kh_2gJqm1zmvpMGLMiViwwiHE2EhvdzWjm6KBVthRouHM71rCnUuN",
"state_hash" : "bs_2E75ChNX5EZo42xek6K64i5MZfQNxDUo5M9DwAufFRqQRqx3Z5",
"target" : 504062474,
"time" : 1561390340812,
"transactions_count" : 1,
"version" : 3
}
],
"next" : "/v3/key-blocks?cursor=100003&limit=3&scope=gen%3A100000-100100",
"prev" : null
}$ curl -s https://mainnet.aeternity.io/mdw/v3/key-blocks/kh_2oKCXoTcm7rSxxAHaEcoUe6JV7Xs9Nmk3TNXHSEQcs9NwE8o6W
{
"micro_blocks_count": 204,
"transactions_count": 273,
"beneficiary": "ak_wM8yFU8eSETXU7VSN48HMDmevGoCMiuveQZgkPuRn1nTiRqyv",
"hash": "kh_2oKCXoTcm7rSxxAHaEcoUe6JV7Xs9Nmk3TNXHSEQcs9NwE8o6W",
"height": 653413,
"info": "cb_AAACjBq0Xcc=",
"miner": "ak_2XTwJ1uqopnb6swmNCA35AuzgZJ8cqJqT1jtGi1j3pKzrsnXGL",
"nonce": 11146303448381,
"pow": [
470518102,
470786769,
472378123,
477583630,
477907327,
488321757,
491143869,
493744235,
505396477,
518355451,
531366816
],
"prev_hash": "mh_StyRqEViVt5z4pvFu6LeJXjy3eh9He7w83UUPsp2gfxnHMrqb",
"prev_key_hash": "kh_2mkrqWnKFBhEdX5B27pmvd1LN6FqQfHm2XzXo2uc5ZGAqkrwRf",
"state_hash": "bs_2pgQNoRYU32wCv3ESvHg6RYpSgsXX9NjkKJ2TuaZnxW6qqVtsN",
"target": 520136850,
"time": 1662676277823,
"version": 5
}$ curl -s https://mainnet.aeternity.io/mdw/v3/key-blocks/123
{
"micro_blocks_count": 0,
"transactions_count": 0,
"beneficiary": "ak_TFm6MPeRXz4oiy5rQ9QRsFpaQb27GCc5ZEXCDhCFPYvYWxV5v",
"hash": "kh_c1F1ZfcqhLMqPNoTzgNKAp3n18kPMCrWvuH9j2Dc2kdiUteRZ",
"height": 123,
"info": "cb_Xfbg4g==",
"miner": "ak_2W4cmcpJQZ4JeBF1kPoe5UsEZCS4gzbCWtoDsVDr7EzF65bmkf",
"nonce": 2384355247607917600,
"pow": [
28236516,
37891637,
39568937,
41751636,
53905843,
77440491,
77746610,
80023552,
85642112,
89247851,
105135109
],
"prev_hash": "kh_MD6dBz1sk6n4P4HZUjzwfiLHSMxzmFk5ZVjcG5cF7PqBCgT9b",
"prev_key_hash": "kh_MD6dBz1sk6n4P4HZUjzwfiLHSMxzmFk5ZVjcG5cF7PqBCgT9b",
"state_hash": "bs_2pAUexcNWE9HFruXUugY28yfUifWDh449JK1dDgdeMix5uk8Q",
"target": 521613269,
"time": 1543395219643,
"version": 1
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/key-blocks?limit=1" | jq '.'
{
"data": [
{
"micro_blocks_count": 180,
"transactions_count": 244,
"beneficiary": "ak_wM8yFU8eSETXU7VSN48HMDmevGoCMiuveQZgkPuRn1nTiRqyv",
"hash": "kh_2w8M2XGQaEhrf5AQwKyibgskKshCeFNsmGCxjHUDbUMm8BdzaV",
"height": 652730,
"info": "cb_AAACjBq0Xcc=",
"miner": "ak_2fh4U3GaZGV2PFy7x7UDPNZN9F4gi1sryKCP4VtJawjJbQVsGR",
"nonce": 28361498886552,
"pow": [
8004426,
25304189,
41033042,
48739301,
55650278,
69208239,
78837065
],
"prev_hash": "mh_2f4TgYysCB6x1N9KtUNbQDUjcDJkq4hNrCkMcLxutBb6ydsfa1",
"prev_key_hash": "kh_Bfip7MNDMJGEe1PqCsPggUkuSQCAQFKAmWAM42jezSmUB3Zfm",
"state_hash": "bs_kyyX1ujxAJm6orwxPghVJK8ZqxKMXuVUp5hUfnpjaJWnRgx3T",
"target": 520137938,
"time": 1662549337009,
"version": 5
}
],
"next": "/v3/key-blocks?cursor=652729&limit=1",
"prev": null
}$ curl https://mainnet.aeternity.io/v3/key-blocks/kh_2HvzkfTvRjfwbim8YZ2q2ETKLhuYK125JGpisr1Cc9m2VSa5iC/micro-blocks?limit=1
{
"data": [
{
"micro_block_index": 39,
"transactions_count": 0,
"hash": "mh_HqJKqWdJ1vaPcr82zYNue99GXcKfjpYbmrEcZ7kmUHAzQoeZv",
"height": 654915,
"pof_hash": "no_fraud",
"prev_hash": "mh_G2gtKvDAkoi3HZDe5TmWYzGX2pD2AL2DrFXACTch57QEWi1Bo",
"prev_key_hash": "kh_2HvzkfTvRjfwbim8YZ2q2ETKLhuYK125JGpisr1Cc9m2VSa5iC",
"signature": "sg_Eyv2nWKwMbxga4XDHH2oCtnSCWhtD87qUjvFLqKvzt9kq2yVPMkcHSv51kr9fmHQk6TGxBHjRjm74pVZtNuHpZkvybsXX",
"state_hash": "bs_2WNN8aZ15a7pd68wWDZkTqpGUTPezUV6KTN2ra5m3v1x5vVJGC",
"time": 1662950429203,
"txs_hash": "bx_AK5hwnJdG3KAEHEvzs4gwjkRDZP5sw5sbtqgHsgJT2fp1PJka",
"version": 5
}
],
"next": "/v3/key-blocks/kh_2HvzkfTvRjfwbim8YZ2q2ETKLhuYK125JGpisr1Cc9m2VSa5iC/micro-blocks?cursor=38&limit=1",
"prev": null
}$ curl https://mainnet.aeternity.io/mdw/v3/micro-blocks/mh_HqJKqWdJ1vaPcr82zYNue99GXcKfjpYbmrEcZ7kmUHAzQoeZv
{
"micro_block_index": 39,
"transactions_count": 0,
"hash": "mh_HqJKqWdJ1vaPcr82zYNue99GXcKfjpYbmrEcZ7kmUHAzQoeZv",
"height": 654915,
"pof_hash": "no_fraud",
"prev_hash": "mh_G2gtKvDAkoi3HZDe5TmWYzGX2pD2AL2DrFXACTch57QEWi1Bo",
"prev_key_hash": "kh_2HvzkfTvRjfwbim8YZ2q2ETKLhuYK125JGpisr1Cc9m2VSa5iC",
"signature": "sg_Eyv2nWKwMbxga4XDHH2oCtnSCWhtD87qUjvFLqKvzt9kq2yVPMkcHSv51kr9fmHQk6TGxBHjRjm74pVZtNuHpZkvybsXX",
"state_hash": "bs_2WNN8aZ15a7pd68wWDZkTqpGUTPezUV6KTN2ra5m3v1x5vVJGC",
"time": 1662950429203,
"txs_hash": "bx_AK5hwnJdG3KAEHEvzs4gwjkRDZP5sw5sbtqgHsgJT2fp1PJka",
"version": 5
}$ curl https://mainnet.aeternity.io/mdw/v3/micro-blocks/mh_3TzzPsMhgnJBYAtSJ6c4SdbQppZi64mxP61b1u1E8g3stDQwk/txs?limit=1
{
"data": [
{
"block_hash": "mh_3TzzPsMhgnJBYAtSJ6c4SdbQppZi64mxP61b1u1E8g3stDQwk",
"block_height": 14085,
"hash": "th_2Eo84A8gYkaNnRXkkEe9gPg5jcbKGdPVkZvK9XUSEQhDD6kmqm",
"micro_index": 59,
"micro_time": 1545877257605,
"signatures": [
"sg_E6tbrssPGL4a1mXyN5EW9d3UwRfYN9pSsBDtDEQVyQqTQjhQVBPKNJV6qyc43M5zY2tLE8VQa8Jb3q1XGYKJYaHM5Q3T4"
],
"tx": {
"amount": 43734300000000000000,
"fee": 21000,
"nonce": 19631,
"payload": "ba_SGVsbG8sIE1pbmVyISAvWW91cnMgQmVlcG9vbC4vKXcQag==",
"recipient_id": "ak_2gD9eHc6AaLSgUKne5vVLrsnG4acTCDE7KPetE4PqA8MYvz8gN",
"sender_id": "ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv",
"type": "SpendTx",
"version": 1
}
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names?limit=2" | jq '.'
{
"data": [
{
"active": true,
"hash": "nm_qock4y2xnYdyy779vayFfu7YUBTwy9bTfoJeH4pM5EpRyJU3A",
"active_from": 205194,
"auction_timeout": 14880,
"expire_height": 349080,
"ownership": {
"current": "ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN",
"original": "ak_pMwUuWtqDoPxVtyAmWT45JvbCF2pGTmbCMB4U5yQHi37XF9is"
},
"pointers": {
"account_pubkey": "ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN"
},
"revoke": null,
"auction": null,
"name": "jieyi.chain"
},
{
"active": true,
"hash": "nm_8vYbsvsrBow6jpxPHUtMLKG6EfTKqqwfpu425aJuHKafSxyR6",
"active_from": 253179,
"auction_timeout": 480,
"expire_height": 349071,
"ownership": {
"current": "ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN",
"original": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx"
},
"pointers": {
"account_pubkey": "ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN"
},
"revoke": null,
"auction": null,
"name": "helloword.chain"
}
],
"next": "/v3/names?by=deactivation&cursor=703645-jiangjiajia.chain&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names?state=inactive&by=deactivation&direction=forward&limit=2" | jq '.'
{
"data": [
{
"active": false,
"hash": "nm_PstDX8VxoTutPJG8YrXkWEwAfBoC5ZmoW1j5RZSNNyXa5oJSB",
"active_from": 6089,
"auction_timeout": 0,
"expire_height": 16090,
"ownership": {
"current": "ak_c3LfYDjLqdNdWHUCV8NDv1BELhXqfKxhmKfzh4cBMpwj64CD7",
"original": "ak_c3LfYDjLqdNdWHUCV8NDv1BELhXqfKxhmKfzh4cBMpwj64CD7"
},
"pointers": {
"account_pubkey": "ak_c3LfYDjLqdNdWHUCV8NDv1BELhXqfKxhmKfzh4cBMpwj64CD7"
},
"revoke": null,
"auction": null,
"name": "philippsdk.test"
},
{
"active": false,
"hash": "nm_J9wKEZ1Deo4UAnNo5s5VTRccVCLdZexZBQJgA6YHYy67xDpqy",
"active_from": 6094,
"auction_timeout": 0,
"expire_height": 16094,
"ownership": {
"current": "ak_c3LfYDjLqdNdWHUCV8NDv1BELhXqfKxhmKfzh4cBMpwj64CD7",
"original": "ak_c3LfYDjLqdNdWHUCV8NDv1BELhXqfKxhmKfzh4cBMpwj64CD7"
},
"pointers": {
"account_pubkey": "ak_c3LfYDjLqdNdWHUCV8NDv1BELhXqfKxhmKfzh4cBMpwj64CD7"
},
"revoke": null,
"auction": null,
"name": "philippsdk2.test"
}
],
"next": "/v3/names?state=inactive&cursor=16117-philippsdk1.test&direction=forward&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names?state=active&by=name&limit=2" | jq '.'
{
"data": [
{
"active": true,
"hash": "nm_23NKMgfB5igtdWHkY5BPMg75PykVrBTBpPAsE6Y1mYV3kZ8Nbd",
"active_from": 162213,
"auction_timeout": 0,
"expire_height": 309542,
"ownership": {
"current": "ak_2tACpi3fVoP5kGo7aXw4riDNwifU2UR3AxxKzTs7FiCPi4iBa8",
"original": "ak_2tACpi3fVoP5kGo7aXw4riDNwifU2UR3AxxKzTs7FiCPi4iBa8"
},
"pointers": {
"account_pubkey": "ak_2tACpi3fVoP5kGo7aXw4riDNwifU2UR3AxxKzTs7FiCPi4iBa8"
},
"revoke": null,
"auction": null,
"name": "0000000000000.chain"
},
{
"active": true,
"hash": "nm_2q5bUSTcibKsuRfGnXSFC5JkUSUxiy9UbMuQ2uJn2xiYNZdcbL",
"active_from": 183423,
"auction_timeout": 480,
"expire_height": 336933,
"ownership": {
"current": "ak_id5HJww6GzFBuFeVGX1NNM66fuzuyfvnCQgZmRxzdSnW8WRcv",
"original": "ak_id5HJww6GzFBuFeVGX1NNM66fuzuyfvnCQgZmRxzdSnW8WRcv"
},
"pointers": {
"account_pubkey": "ak_VLkEyJBmvaf6XnqLdknjj7ZMN58G5x1eJhNUkLxPFGmg9JAaJ"
},
"revoke": null,
"auction": null,
"name": "0123456789.chain"
}
],
"next": "/v3/names?state=active&cursor=zz.chain&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names?owned_by=ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN&by=name" | jq '.'
{
"data": [
{
"active": false,
"name": "yedianzhiwang.chain",
"hash": "nm_2akgyVeSqDeynUVTHnHzengLarQyQqC9sHigsrBKnaCtmd3Ca5",
"name_fee": 1771100000000000000,
"revoke": null,
"expire_height": 364002,
"auction_timeout": 0,
"auction": null,
"ownership": {
"current": "ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN",
"original": "ak_2pqYSBpEkykFy11KFZXxDJaB8KugXBi2JxraqZXpTaXzreYb95"
},
"active_from": 163855,
"approximate_expire_time": 1609161570008,
"approximate_activation_time": 1572935113556
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names?state=active&by=activation&direction=forward&limit=2" | jq '.'
{
"data": [
{
"active": true,
"auction": null,
"hash": "nm_2FvtAFr3gPAQtNutEnjcPDQSqbhxDHBg9j8LE5WESPCJjzFmuU",
"active_from": 161313,
"auction_timeout": 0,
"expire_height": 653635,
"ownership": {
"current": "ak_5z1fmzTKR1GA1P7qiLDCC1s3V7AK2RRpNbXqUhfHQbUeg7mmV",
"original": "ak_5z1fmzTKR1GA1P7qiLDCC1s3V7AK2RRpNbXqUhfHQbUeg7mmV"
},
"pointers": {
"account_pubkey": "ak_2QGAAqDXK7g8zCbck7zm25TGAW1hRuVCET2SRCCFCMSMjrVCrF"
},
"revoke": null,
"name": "batchpayments.chain"
},
{
"active": true,
"auction": null,
"hash": "nm_E5JeB8xLS9UR5qN65kDuAhRCHDno5B9pLwoXCm5DEKVpmWrUN",
"active_from": 161349,
"auction_timeout": 0,
"expire_height": 653635,
"ownership": {
"current": "ak_5z1fmzTKR1GA1P7qiLDCC1s3V7AK2RRpNbXqUhfHQbUeg7mmV",
"original": "ak_5z1fmzTKR1GA1P7qiLDCC1s3V7AK2RRpNbXqUhfHQbUeg7mmV"
},
"pointers": {
"account_pubkey": "ak_2QGAAqDXK7g8zCbck7zm25TGAW1hRuVCET2SRCCFCMSMjrVCrF"
},
"revoke": null,
"name": "internetofmoney.chain"
}
],
"next": "/v3/names?by=activation&cursor=161350-internetofvalue.chain&direction=forward&limit=2&state=active",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names?prefix=aaa&by=name&limit=2" | jq '.'
{
"data": [
{
"active": false,
"name": "aaaz.test",
"hash": "nm_28ZLaroYYUQ1B5MDa7FiKz2F7mSvrtPXSEfavbqXbg2y1ia28j",
"revoke": null,
"name_fee": 134626900000000000000,
"auction_timeout": 0,
"pointers": {},
"auction": null,
"expire_height": 130718,
"active_from": 80718,
"approximate_activation_time": 1557907284835,
"approximate_expire_time": 1566948271337,
"ownership": {
"current": "ak_pANDBzM259a9UgZFeiCJyWjXSeRhqrBQ6UCBBeXfbCQyP33Tf",
"original": "ak_pANDBzM259a9UgZFeiCJyWjXSeRhqrBQ6UCBBeXfbCQyP33Tf"
}
},
{
"active": false,
"name": "aaay.test",
"hash": "nm_2CtkYRVTtqnK6rf9Tc7AyyiHtcTFaustEzRLArAMiWUzXdAhTT",
"revoke": null,
"name_fee": 134626900000000000000,
"auction_timeout": 0,
"pointers": {},
"auction": null,
"expire_height": 130714,
"active_from": 80714,
"approximate_activation_time": 1557906623769,
"approximate_expire_time": 1566948022162,
"ownership": {
"current": "ak_pANDBzM259a9UgZFeiCJyWjXSeRhqrBQ6UCBBeXfbCQyP33Tf",
"original": "ak_pANDBzM259a9UgZFeiCJyWjXSeRhqrBQ6UCBBeXfbCQyP33Tf"
}
}
],
"next": "/v3/names?by=name&cursor=aaaq.test&prefix=aaa",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/auctions?limit=2" | jq '.'
{
"data": [
{
"name": "meta.chain",
"name_fee": 134626900000000000000,
"auction_end": 968903,
"last_bid": {
"block_hash": "mh_2F3vhNXJ1eXaQiAz6RQHzAUW5dEUTSEvxaBAHDn8ziHjrd9FJK",
"block_height": 939143,
"encoded_tx": "tx_+JYLAfhCuECFZmpTCOnm3v0zZ3g2BVIZApsjxGt4Q4MWck+gEw0j09Jq61XEgQWafn3fP2oesqcsy6wYGpGWT6eFW/iE7IoCuE74TCACoQH7BL4bl7Y/NrliWEMKWaxk9besmKUYp6PkFk7ZZeieHYIyZ4ptZXRhLmNoYWluhwUXe6y8hW+JB0xS1EQgCUAAhg8PrOrgAADImXsf",
"hash": "th_2KpsBbibCN4EwtKNtLLAZzRw3AJ7xMEQw5sfbNZjQKCdP5pc5V",
"micro_index": 0,
"micro_time": 1714619449351,
"signatures": [
"sg_JTFJFCMh84NB9rJiHgzVcCgXsSt5i6njT4E55vLDRVoeXKuB4ETqzt1BB6TtAUrbGoGMYd4iXM7xuwPXXgVoWCPPZu8SS"
],
"tx": {
"account_id": "ak_2uYw22W3KGCCduExjzkBDNUxWt3Akdehm66CFAXDKRt9aoUofX",
"fee": 16560000000000,
"name": "meta.chain",
"name_fee": 134626900000000000000,
"name_id": "nm_2ab7LiFhV5uAzXq6EHmMsPm2cHoKaLdFMnwoTrkVaHSUAAZmx5",
"name_salt": 1433194830005615,
"nonce": 12903,
"ttl": 1148903,
"type": "NameClaimTx",
"version": 2
}
},
"approximate_expire_time": 1719979602317,
"activation_time": 1714619449351
},
{
"name": "tank.chain",
"name_fee": 134626900000000000000,
"auction_end": 965088,
"last_bid": {
"block_hash": "mh_bV9Kq1tCMpRWgTAWy6C6vvQy5r2RjganqjFhQcPoRZmwNxZtN",
"block_height": 935328,
"encoded_tx": "tx_+JQLAfhCuEA+wsY1qqQhRraS487OtyxOqltUkG8KrnrVoMeGj1Db5XRf/cFdyJ3MhMfE5bgoBx57i9zAKC/iMdQsPzzNf3QFuEz4SiACoQFDfNR5+5vHGV9m03tIkBWvRBxUxZg57c17DFoKdfI/bleKdGFuay5jaGFpbocLZSf1Zg0fiQdMUtREIAlAAIYPBly7UAAAdKgDMw==",
"hash": "th_2fpQo1jm3VwHkn4VcDxFxaMnNLWc2PD8KA35WZwGDDSYKxJDkx",
"micro_index": 0,
"micro_time": 1713926446496,
"signatures": [
"sg_9DEUyZZfXQDR7t1QbGod9GztGTeFGCiAuNHzqZaXng6kY9Xbn1hNqbFWVugChgQySzLsNfxhcHRrP7qtjPoCAjaJM57pf"
],
"tx": {
"account_id": "ak_Wit5Lxv9v3QNYiGSTidCM7Ssuagd7cs6fsBnuwZmULLAWBZd2",
"fee": 16520000000000,
"name": "tank.chain",
"name_fee": 134626900000000000000,
"name_id": "nm_CCgyYJEUuyZtfZrAZvFK8tv2k9a9zhKkByxhwHcrc64mVw7EB",
"name_salt": 3207447039053087,
"nonce": 87,
"ttl": 1145088,
"type": "NameClaimTx",
"version": 2
}
},
"approximate_expire_time": 1719292902317,
"activation_time": 1713926446496
}
],
"next": "/v3/names/auctions?cursor=548763-svs.chain&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/auctions?by=name&direction=forward&limit=100" | jq '.data [] .name'
"0.chain"
"5.chain"
"6.chain"
"8.chain"
"AEStudio.chain"
"BTC.chain"
"Facebook.chain"
"Song.chain"
"ant.chain"
"b.chain"
"d.chain"
"help.chain"
"k.chain"
"l.chain"
"m.chain"
"meet.chain"
"o.chain"
"s.chain"
"y.chain"$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/bear.test" | jq '.'
{
"active": false,
"name": "bear.test",
"hash": "nm_2aGpF2uJp1wDpuHoNDhhSztpoQr43dAjzZ5SyvfD2RSKTVmL6X",
"name_fee": 134626900000000000000,
"revoke": null,
"expire_height": 135638,
"auction_timeout": 0,
"auction": null,
"ownership": {
"current": "ak_2CXSVZqVaGuZsmcRs3CN6wb2b9GKtf7Arwej7ahbeAQ1S8qkmM",
"original": "ak_2CXSVZqVaGuZsmcRs3CN6wb2b9GKtf7Arwej7ahbeAQ1S8qkmM"
},
"active_from": 85624,
"approximate_expire_time": 1567835676059,
"approximate_activation_time": 1558792599799
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/nm_MwcgT7ybkVYnKFV6bPqhwYq2mquekhZ2iDNTunJS2Rpz3Njuj" | jq '.'
{
"active": false,
"name": "wwwbeaconoidcom.chain",
"hash": "nm_MwcgT7ybkVYnKFV6bPqhwYq2mquekhZ2iDNTunJS2Rpz3Njuj",
"name_fee": 676500000000000000,
"revoke": null,
"expire_height": 329558,
"auction_timeout": 0,
"auction": null,
"ownership": {
"current": "ak_2HNsyfhFYgByVq8rzn7q4hRbijsa8LP1VN192zZwGm1JRYnB5C",
"original": "ak_2HNsyfhFYgByVq8rzn7q4hRbijsa8LP1VN192zZwGm1JRYnB5C"
},
"active_from": 279555,
"approximate_expire_time": 1602925509746,
"approximate_activation_time": 1593861576848
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/help" | jq '.'
{
"active": false,
"name": "yedianzhiwang.chain",
"hash": "nm_2akgyVeSqDeynUVTHnHzengLarQyQqC9sHigsrBKnaCtmd3Ca5",
"name_fee": 1771100000000000000,
"revoke": null,
"expire_height": 364002,
"auction_timeout": 0,
"auction": {
"name": "yedianzhiwang.chain",
"name_fee": 134626900000000000000,
"auction_end": 965088,
"last_bid": {
"block_hash": "mh_bV9Kq1tCMpRWgTAWy6C6vvQy5r2RjganqjFhQcPoRZmwNxZtN",
"block_height": 935328,
"encoded_tx": "tx_+JQLAfhCuEA+wsY1qqQhRraS487OtyxOqltUkG8KrnrVoMeGj1Db5XRf/cFdyJ3MhMfE5bgoBx57i9zAKC/iMdQsPzzNf3QFuEz4SiACoQFDfNR5+5vHGV9m03tIkBWvRBxUxZg57c17DFoKdfI/bleKdGFuay5jaGFpbocLZSf1Zg0fiQdMUtREIAlAAIYPBly7UAAAdKgDMw==",
"hash": "th_2fpQo1jm3VwHkn4VcDxFxaMnNLWc2PD8KA35WZwGDDSYKxJDkx",
"micro_index": 0,
"micro_time": 1713926446496,
"signatures": [
"sg_9DEUyZZfXQDR7t1QbGod9GztGTeFGCiAuNHzqZaXng6kY9Xbn1hNqbFWVugChgQySzLsNfxhcHRrP7qtjPoCAjaJM57pf"
],
"tx": {
"account_id": "ak_Wit5Lxv9v3QNYiGSTidCM7Ssuagd7cs6fsBnuwZmULLAWBZd2",
"fee": 16520000000000,
"name": "tank.chain",
"name_fee": 134626900000000000000,
"name_id": "nm_CCgyYJEUuyZtfZrAZvFK8tv2k9a9zhKkByxhwHcrc64mVw7EB",
"name_salt": 3207447039053087,
"nonce": 87,
"ttl": 1145088,
"type": "NameClaimTx",
"version": 2
}
},
"approximate_expire_time": 1719295566979,
"activation_time": 1713926446496
},
"ownership": {
"current": "ak_25BWMx4An9mmQJNPSwJisiENek3bAGadze31Eetj4K4JJC8VQN",
"original": "ak_2pqYSBpEkykFy11KFZXxDJaB8KugXBi2JxraqZXpTaXzreYb95"
},
"active_from": 163855,
"approximate_expire_time": 1609161570008,
"approximate_activation_time": 1572935113556
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/auctions/meta.chain" | jq '.'
{
"name": "meta.chain",
"name_fee": 134626900000000000000,
"auction_end": 968903,
"last_bid": {
"block_hash": "mh_2F3vhNXJ1eXaQiAz6RQHzAUW5dEUTSEvxaBAHDn8ziHjrd9FJK",
"block_height": 939143,
"encoded_tx": "tx_+JYLAfhCuECFZmpTCOnm3v0zZ3g2BVIZApsjxGt4Q4MWck+gEw0j09Jq61XEgQWafn3fP2oesqcsy6wYGpGWT6eFW/iE7IoCuE74TCACoQH7BL4bl7Y/NrliWEMKWaxk9besmKUYp6PkFk7ZZeieHYIyZ4ptZXRhLmNoYWluhwUXe6y8hW+JB0xS1EQgCUAAhg8PrOrgAADImXsf",
"hash": "th_2KpsBbibCN4EwtKNtLLAZzRw3AJ7xMEQw5sfbNZjQKCdP5pc5V",
"micro_index": 0,
"micro_time": 1714619449351,
"signatures": [
"sg_JTFJFCMh84NB9rJiHgzVcCgXsSt5i6njT4E55vLDRVoeXKuB4ETqzt1BB6TtAUrbGoGMYd4iXM7xuwPXXgVoWCPPZu8SS"
],
"tx": {
"account_id": "ak_2uYw22W3KGCCduExjzkBDNUxWt3Akdehm66CFAXDKRt9aoUofX",
"fee": 16560000000000,
"name": "meta.chain",
"name_fee": 134626900000000000000,
"name_id": "nm_2ab7LiFhV5uAzXq6EHmMsPm2cHoKaLdFMnwoTrkVaHSUAAZmx5",
"name_salt": 1433194830005615,
"nonce": 12903,
"ttl": 1148903,
"type": "NameClaimTx",
"version": 2
}
},
"approximate_expire_time": 1719978527794,
"activation_time": 1714619449351
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/accounts/ak_2HNsyfhFYgByVq8rzn7q4hRbijsa8LP1VN192zZwGm1JRYnB5C/names/pointees?limit=3" | jq '.'
{
"data": [
{
"name": "star.chain",
"key": "account_pubkey",
"tx": {
"account_id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"client_ttl": 10500,
"fee": 17860000000000,
"name_id": "nm_dRChkcZn62toYnPZVjgpi5UsnyMZdHH3zw9ah2JR9ESFga5qK",
"name_ttl": 50000,
"nonce": 245,
"pointers": [
{
"id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"key": "account_pubkey"
}
],
"ttl": 272285
},
"block_hash": "mh_2ksi3YAh6oYviVooxn93F6vMrYoGhBuX4LgZnBUHszYJSPx5eT",
"source_tx_type": "NameUpdateTx",
"source_tx_hash": "th_YfXgjU5LPonGzZRSNedHtzqZLtSLbuorbBV9T2iCPQVcATRNM",
"block_time": 1592458627198,
"block_height": 271786
},
{
"name": "store.chain",
"key": "account_pubkey",
"tx": {
"account_id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"client_ttl": 10500,
"fee": 17860000000000,
"name_id": "nm_2PMNtzqTk38rEMmoVAuFNSJtWQgdtREDWDau497ofQW4XvRydC",
"name_ttl": 50000,
"nonce": 244,
"pointers": [
{
"id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"key": "account_pubkey"
}
],
"ttl": 272285
},
"block_hash": "mh_jKTG4ThGE2dFyoKDBi2AUgkHrBi8LQEF5NuD2WDuX5jJmpT8n",
"source_tx_type": "NameUpdateTx",
"source_tx_hash": "th_2ccvwv8sd4f7UgjCETvmG8wEx5ZSa7wnYzuU3yUyVSJkjhz3Lq",
"block_time": 1592458574738,
"block_height": 271785
},
{
"name": "aepps.chain",
"key": "account_pubkey",
"tx": {
"account_id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"client_ttl": 10500,
"fee": 17860000000000,
"name_id": "nm_zJVQvLaC3DPVKTdrYXvrB8YpQpQFqN6drxUmGbyvTQQWjAcAf",
"name_ttl": 50000,
"nonce": 241,
"pointers": [
{
"id": "ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx",
"key": "account_pubkey"
}
],
"ttl": 271240
},
"block_hash": "mh_SG6qWMrJEtbjfFiUJLeR7KaU5q3GNMMrMCLM1MYEQcafLF3jU",
"source_tx_type": "NameUpdateTx",
"source_tx_hash": "th_25nTyhVyLWRwgnkh3VJZnBcNvWpQgEDq1azv3RFyRJXs5eqauV",
"block_time": 1592269558743,
"block_height": 270740
}
],
"next": "/v3/accounts/ak_QyFYYpgJ1vUGk1Lnk8d79WJEVcAtcfuNHqquuP2ADfxsL6yKx/names/pointees?cursor=276059-0-12703951-0-YWNjb3VudF9wdWJrZXk&limit=3",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/vlsl.test/claims" | jq '.'
{
"data": [
{
"block_hash": "mh_2Nr1oj3Z3D9sYnEDrNk4SXjboT3otCXQafsNukRcRDg25URKrR",
"height": 45784,
"tx": {
"account_id": "ak_2T42t9vpy56kKfZuX74SHuYGsETi1YegJ1KjBbieBwJswt1QVN",
"fee": 21000000000000,
"name": "vlsl.test",
"name_salt": 123,
"nonce": 67,
"ttl": 45882,
"type": "NameClaimTx",
"version": 2
}
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/test.test/transfers" | jq '.'
{
"data": [
{
"block_hash": "mh_2wWv1cwnC2purbtZqXiNcZDpX9SAmEUc5YaMKZmSR9p1pEm9rE",
"height": 42320,
"tx": {
"account_id": "ak_24jcHLTZQfsou7NvomRJ1hKEnjyNqbYSq2Az7DmyrAyUHPq8uR",
"fee": 30000,
"name_id": "nm_en1mSKcVPb9gY8UGxPfABw3JouEGZ4ZvdfcBWetmn6czUuVG1",
"nonce": 18550,
"recipient_id": "ak_2WZoa13VKHCamt2zL9Wid8ovmyvTEUzqBjDNGDNwuqwUQJZG4t",
"ttl": 42420,
"type": "NameTransferTx",
"version": 1
}
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/names/ssup.test/updates?limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_qZM3VVCHynY1AG4Pgwcdobg42oGAxhY7c1LrUzqvgJSFLLbPU",
"height": 45706,
"tx": {
"account_id": "ak_2CXSVZqVaGuZsmcRs3CN6wb2b9GKtf7Arwej7ahbeAQ1S8qkmM",
"client_ttl": 36000,
"fee": 20000000000000,
"name_id": "nm_2tokSd7X5zeYzAr5icomaVLBYC3TGeCypsPjZALcQcxYZb4YdP",
"name_ttl": 50000,
"nonce": 3544,
"pointers": [
{
"id": "ak_M6MNwGLtMQ4j3m8pzQz9uF38nMfjCCVaiQ8fvTAU6DEsCocD5",
"key": "account_pubkey"
}
],
"ttl": 60000,
"type": "NameUpdateTx",
"version": 1
}
}
],
"next": "/v3/names/ssup.test/updates?cursor=45706-20-1132300&limit=1",
"prev": null
}curl -s "https://mainnet.aeternity.io/mdw/v3/contracts?limit=1" | jq '.'
{
"data" : [
{
"block_hash" : "mh_2sEDNcQaZwpU4qUZGPX3zV7BruQvzQ4qnYpo4VWaPU6sQfjDqJ",
"contract" : "ct_D4ZxQD9wXRXYkT7EQd5SiGmySJziEGJSGyDBqH9SwYMsnH4JX",
"create_tx" : {
"abi_version" : 3,
"amount" : 0,
"call_data" : "cb_KxFE1kQfGwphxkNE",
"code" : "cb_+GlGA6ANexG+yJOtFvI0ogpw4uOHJDVScNPobxeyUDr10xHM08C4PKH+RNZEHwA3AQc3ABoGggABAz/+iKBvXwA3AQcHFiQAggCWLwIRRNZEHxFpbml0EYigb18RY2FsY4IvAIU3LjEuMAAZ1+t2",
"deposit" : 0,
"fee" : 78540000000000,
"gas" : 76,
"gas_price" : 1000000000,
"nonce" : 27,
"owner_id" : "ak_2oGsfHFUww8cv7Tsc73FJcKWLFmn25Mk1rF68aTxwhwREecrs8",
"ttl" : 0,
"vm_version" : 7
},
"source_tx_hash" : "th_ZyorKqF8kUac4KFcRcEVeHXsnQ6vfMZei98gekvBwuSdjtEuZ",
"source_tx_type" : "ContractCreateTx"
}
],
"next" : "/v3/contracts?cursor=40835756-0&limit=1",
"prev" : null
}$ curl -s "http://mainnet.aeternity.io/mdw/v3/contracts/ct_D4ZxQD9wXRXYkT7EQd5SiGmySJziEGJSGyDBqH9SwYMsnH4JX" | jq '.'
{
"block_hash" : "mh_2sEDNcQaZwpU4qUZGPX3zV7BruQvzQ4qnYpo4VWaPU6sQfjDqJ",
"contract" : "ct_D4ZxQD9wXRXYkT7EQd5SiGmySJziEGJSGyDBqH9SwYMsnH4JX",
"create_tx" : {
"abi_version" : 3,
"amount" : 0,
"call_data" : "cb_KxFE1kQfGwphxkNE",
"code" : "cb_+GlGA6ANexG+yJOtFvI0ogpw4uOHJDVScNPobxeyUDr10xHM08C4PKH+RNZEHwA3AQc3ABoGggABAz/+iKBvXwA3AQcHFiQAggCWLwIRRNZEHxFpbml0EYigb18RY2FsY4IvAIU3LjEuMAAZ1+t2",
"deposit" : 0,
"fee" : 78540000000000,
"gas" : 76,
"gas_price" : 1000000000,
"nonce" : 27,
"owner_id" : "ak_2oGsfHFUww8cv7Tsc73FJcKWLFmn25Mk1rF68aTxwhwREecrs8",
"ttl" : 0,
"vm_version" : 7
},
"source_tx_hash" : "th_ZyorKqF8kUac4KFcRcEVeHXsnQ6vfMZei98gekvBwuSdjtEuZ",
"source_tx_type" : "ContractCreateTx"
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?direction=forward&contract_id=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&limit=1" | jq '.'
{
"data": [
{
"args": [
"32049452134983951870486158652299990269658301415986031571975774292043131948665",
"10000000000000000"
],
"call_tx_hash": "th_2JLGkWhXbEQxMuEYTxazPurKiwGvo5R6vgqjSBw3R8z9F6b4rv",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "https://github.com/thepiwo",
"event_hash": "MVGUQ861EKRNBCGUC35711P9M2HSVQHG5N39CE5CCIUQ7AGK7UU0====",
"ext_caller_contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"log_idx": 0
}
],
"next": "/v3/contracts/logs?direction=forward&contract_id=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&limit=1"
}iex(aeternity@localhost)3> <<32049452134983951870486158652299990269658301415986031571975774292043131948665 :: 256>>
<<70, 219, 88, 217, 218, 57, 227, 219, 63, 200, 168, 207, 16, 238, 173, 185,
185, 214, 3, 207, 227, 124, 221, 54, 36, 147, 13, 144, 171, 6, 142, 121>>$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?limit=1" | jq '.'
{
"data": [
{
"args": [
"80808227038564992079558295896388926841596253273977977325246416786468530750284",
"23245441236723951035912846601319239080044515685575576534240736154129181748855",
"966628800000000000"
],
"call_tx_hash": "th_2vDNSLGyBdBNPmyfWtfHEAH2PdJh7t39G3a6JtM4ByfYD1LT1V",
"contract_id": "ct_2MgX2e9mdM3epVpmxLQim7SAMF2xTbid4jtyVi4WiLF3Q8ZTRZ",
"data": "",
"event_hash": "48U3JOKTVTI6FVMTK2BLHM8NG72JEBG93VS6MENPSC8E71IM5FNG====",
"ext_caller_contract_id": "ct_2M4mVQCDVxu6mvUrEue1xMafLsoA1bgsfC3uT95F3r1xysaCvE",
"log_idx": 2
}
],
"next": "/v3/contracts/logs?cursor=68PJACHK74O3E91J60QJADHG6OR28HA96P258MAL6KRJAKQ7A0RLEDAL8D65CKIN95C52I23AH7KOKAA8GRJ8HQN9TC5KD2D957KGGIJAT350M2H7KUJQF9460I0&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?scope=gen:200000-210000&limit=1" | jq '.'
{
"data": [
{
"args": [
"48550576960427288418928503238185419255781131458428297160617859112449977313818",
"1000000000000000000"
],
"call_tx_hash": "th_2BjrnHaRHo196AHtpMHV4QUiJqDi6UjfsA5pbPgTGhKpQuB67N",
"contract_id": "ct_cT9mSpx9989Js39ag45fih2daephb7YsicsvNdUdEB156gT5C",
"data": "https://github.com/aeternity",
"event_hash": "MVGUQ861EKRNBCGUC35711P9M2HSVQHG5N39CE5CCIUQ7AGK7UU0====",
"ext_caller_contract_id": "ct_cT9mSpx9989Js39ag45fih2daephb7YsicsvNdUdEB156gT5C",
"log_idx": 0
}
],
"next": "/v3/contracts/logs?cursor=6CS34DHK6KQI8D1G60O38DPP4H2KIDI4AHCLAD9N6L9KEK1NASQLAGQCAP95EIAOA5446L2F9H8KKH1N6H3LEJQOB8Q4QIAF91156LQ6A1C52F9T7KUI8C14&limit=1&scope=gen%3A200000-210000",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?scope=gen:250109&limit=1" | jq '.'
{
"data": [
{
"args": [
"113825637927817399496888947973485901133216730124575464244310341957325543404011",
"100000000000000000"
],
"call_tx_hash": "th_22pciXRFnEieCSMEbcEPEfHdxvJobJt2UoCtXXiQ3pnDn6kvaz",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "https://twitter.com/LeonBlockchain",
"event_hash": "MVGUQ861EKRNBCGUC35711P9M2HSVQHG5N39CE5CCIUQ7AGK7UU0====",
"ext_caller_contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"log_idx": 0
}
],
"next": "/v3/contracts/logs?cursor=6CS34DHK6KQI8D1G60O38DPP4H2KIDI4AHCLAD9N6L9KEK1NASQLAGQCAP95EIAOA5446L2F9H8KKH1N6H3LEJQOB8Q4QIAF91156LQ6A1C52F9T7KUI8C14&limit=1&scope=gen%3A250109",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?contract_id=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&limit=2" | jq '.'
{
"data": [
{
"args": [
"87569133758291964643644139664803946495433064832095920406619813370506210782355",
"120000000000000000"
],
"call_tx_hash": "th_2rQFbvkR2rxvBQLWt4WPUPiSViES8aKDBVDraF4mogdZsVTJSQ",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "https://www.youtube.com/watch?v=iLQzaLr1enE",
"event_hash": "MVGUQ861EKRNBCGUC35711P9M2HSVQHG5N39CE5CCIUQ7AGK7UU0====",
"ext_caller_contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"log_idx": 0
},
{
"args": [
"19315768272296812419334917756530784329195878521494173087129733615253420217233",
"52300000000000000000"
],
"call_tx_hash": "th_JgxLwr7WszXNT5tU1ngc6fJJyxTywcLjWxXy8sqrpX7r7byCQ",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "https://superhero.com/",
"event_hash": "ATPGPVQP8277UG86U0JDA2CPFKQ1F28A51VAG9F029836CU1IG80====",
"ext_caller_contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"log_idx": 0
}
],
"next": "/v3/contracts/logs?contract_id=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&cursor=70PJICHN6OR28CPG6GR3GDHK6OI5AH2MACRKOM9LB58KKD9L9DD3AMIKA92KGM269LCKAL9NA12K4DA69HCKGCQC88PKIDHN6TCLAKA2915LKK9T7KUJQ91G4G&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?direction=forward&data=aeternity.com&limit=2" | jq '.'
{
"data": [
{
"args": [
"69318356919715896655612698359975736845612647472784537635207689589288608801665"
],
"call_tx_hash": "th_29wEBiUVommkJJqtWxczsdTViBSHsCxsQMtyYZb3hju4xW6eFS",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "aeternity.com",
"event_hash": "K3LIVBOTOG9TTAPTPJH47N5CO4KVF41T5BO7RB1R8UVVOKG17APG====",
"ext_caller_contract_id": "ct_7wqP18AHzyoqymwGaqQp8G2UpzBCggYiq7CZdJiB71VUsLpR4",
"log_idx": 0
},
{
"args": [
"69318356919715896655612698359975736845612647472784537635207689589288608801665"
],
"call_tx_hash": "th_nvrmo5YmrWUW9pr2ohiPWB6FHgok9owi5xbLMpV2pHYvECxTD",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "aeternity.com",
"event_hash": "K3LIVBOTOG9TTAPTPJH47N5CO4KVF41T5BO7RB1R8UVVOKG17APG====",
"ext_caller_contract_id": "ct_7wqP18AHzyoqymwGaqQp8G2UpzBCggYiq7CZdJiB71VUsLpR4",
"log_idx": 0
}
],
"next": "/v3/contracts/logs?cursor=70PJICHN6OR28C9K6SQ3IC1L74I5EDQH6OP4IHQ29TAJ6M2C9L8JCJA48P444GIQ99BK6KHK6SP54KA6B124KJAF8P6KQKPM6944MKAL90R3CG9T7KUJQ91G4HGMAT35E9N6IT3P5PHMUR8&data=aeternity.com&direction=forward&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/logs?event=TipReceived&limit=1" | jq '.'
{
"data": [
{
"args": [
"87569133758291964643644139664803946495433064832095920406619813370506210782355",
"120000000000000000"
],
"call_tx_hash": "th_2rQFbvkR2rxvBQLWt4WPUPiSViES8aKDBVDraF4mogdZsVTJSQ",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"data": "https://www.youtube.com/watch?v=iLQzaLr1enE",
"event_hash": "MVGUQ861EKRNBCGUC35711P9M2HSVQHG5N39CE5CCIUQ7AGK7UU0====",
"ext_caller_contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"log_idx": 0
}
],
"next": "/v3/contracts/logs?cursor=70PJICHN6OR28CPG64R3ADHN6CI5EDQH6OP4IHQ29TAJ6M2C9L8JCJA48P444GIQ99BK6KHK6SP54KA6B124KJAF8P6KQKPM6944MKAL90R3CG9T7KUJQ91G4G&event=TipReceived&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/calls?contract_id=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_25eLkLkkMDRg5Sau1ezeNteAXxzAnfECqeN318hTFLifozJkpt",
"call_tx_hash": "th_gTNykxuM2MJ4D2Y7L5EoU7wKprmM6rLmAKe2yaBrjbNudMeSq",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"function": "Call.amount",
"height": 403795,
"internal_tx": {
"amount": 100000000000000,
"fee": 0,
"nonce": 0,
"payload": "ba_Q2FsbC5hbW91bnTau3mT",
"recipient_id": "ak_7wqP18AHzyoqymwGaqQp8G2UpzBCggYiq7CZdJiB71VUsLpR4",
"sender_id": "ak_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"type": "SpendTx",
"version": 1
},
"local_idx": 5,
"micro_index": 9
}
],
"next": "/v3/contracts/calls?contract_id=ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z&cursor=6CO3ACPK6GRJI91J4GS36E9I6SR3C9144GMJ2C1G&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/calls?direction=forward&function=Oracle&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2XAPbotBm5qgkWn165g3J7eRsfV9r5tEwSEqS3rggR6b9fRbW",
"call_tx_hash": "th_4q3cLesnXqSSH3HmecGMSUuZZNKsue8rGMACtCRmFpZtpAXPH",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"function": "Oracle.query",
"height": 219107,
"internal_tx": {
"fee": 0,
"nonce": 0,
"oracle_id": "ok_2ChQprgcW1od3URuRWnRtm1sBLGgoGZCDBwkyXD1U7UYtKUYys",
"query": "ak_y87WkN4C4QevzjTuEYHg6XLqiWx3rjfYDFLBmZiqiro5mkRag;https://github.com/thepiwo",
"query_fee": 20000000000000,
"query_ttl": {
"type": "delta",
"value": 20
},
"response_ttl": {
"type": "delta",
"value": 20
},
"sender_id": "ak_23bfFKQ1vuLeMxyJuCrMHiaGg5wc7bAobKNuDadf8tVZUisKWs",
"type": "OracleQueryTx",
"version": 1
},
"local_idx": 0,
"micro_index": 0
}
],
"next": "/v3/contracts/calls?cursor=70Q30D1N70OI8C945KOJ0C144H53AMI78DCJ6JADALC4GGPL9H34UIHKA4I2QC9G60&direction=forward&function=Oracle&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/contracts/calls?recipient_id=ak_23bfFKQ1vuLeMxyJuCrMHiaGg5wc7bAobKNuDadf8tVZUisKWs&limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2Mp1FfJyEaQUYbBKywWb6kWGm1KoTEyc4SZgt7oA7orz9BpSLD",
"call_tx_hash": "th_XnXh22b9XsXGPEE9ZJwm4E9FuMhv47Z2ogQo6Lgt4npEwVF9W",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"function": "Call.amount",
"height": 224666,
"internal_tx": {
"amount": 80000000000000,
"fee": 0,
"nonce": 0,
"payload": "ba_Q2FsbC5hbW91bnTau3mT",
"recipient_id": "ak_23bfFKQ1vuLeMxyJuCrMHiaGg5wc7bAobKNuDadf8tVZUisKWs",
"sender_id": "ak_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"type": "SpendTx",
"version": 1
},
"local_idx": 4,
"micro_index": 11
}
],
"next": "/v3/contracts/calls?cursor=70S34C1K68S28D145KOJ0C14A93KQGHK9D3K4I258H546JQC99A5IL25AHCL6GPN9T4KIMIB6D2KSKI88P4LKL2M6923AJA16T65ILPJ698I891I&limit=1&recipient_id=ak_23bfFKQ1vuLeMxyJuCrMHiaGg5wc7bAobKNuDadf8tVZUisKWs",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transfers?scope=gen:50002-70000&limit=3" | jq '.'
{
"data": [
{
"kind": "reward_block",
"account_id": "ak_542o93BKHiANzqNaFj6UurrJuDuxU61zCGr9LJCwtTUg34kWt",
"height": 50002,
"amount": 218400000000000,
"ref_tx_type": null,
"ref_tx_hash": null,
"ref_block_hash": null
},
{
"kind": "reward_block",
"account_id": "ak_nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv",
"height": 50002,
"amount": 407000327600000000000,
"ref_tx_type": null,
"ref_tx_hash": null,
"ref_block_hash": null
},
{
"kind": "fee_lock_name",
"account_id": "ak_7myFYvagcqh8AtWEuHL4zKDGfJj5bmacNZS8RoUh5qmam1a3J",
"height": 50002,
"amount": 3,
"ref_tx_type": "mh_2C2KBh8e82yR1TrwrbarNmoNrL1KQG3i29ykooKSTMa7kFJtjF",
"ref_tx_hash": "th_zUk7eWXjqyUK49WU3ZkLinrRRhMHPRSG22CSb4NbqZjmn7xdm",
"ref_block_hash": "NameClaimTx"
}
],
"next": "/v3/transfers?cursor=6KO30C1I5GOJAC9M60S32B1G4HJ6APAVDHNM6QQVDPGMQP948DB54L2FAH356HIN6T84CGHK6GQ4UJ2O6P94ODAM9P248DI69553ECQN899J6KQ4A1CJ6DHN8D7L0GHNA58I8C9L64R30E1H4GO0&limit=3&scope=gen%3A50002-70000",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transfers?direction=forward&kind=reward_dev&limit=2" | jq '.'
{
"data": [
{
"kind": "reward_dev",
"account_id": "ak_2KAcA2Pp1nrR8Wkt3FtCkReGzAi8vJ9Snxa4PcmrthVx8AhPe8",
"height": 90981,
"amount": 37496010998100000000,
"ref_tx_type": null,
"ref_tx_hash": null,
"ref_block_hash": null
},
{
"kind": "reward_dev",
"account_id": "ak_2KAcA2Pp1nrR8Wkt3FtCkReGzAi8vJ9Snxa4PcmrthVx8AhPe8",
"height": 90982,
"amount": 37496003679840000000,
"ref_tx_type": null,
"ref_tx_hash": null,
"ref_block_hash": null
}
],
"next": "/v3/transfers?cursor=74O3IE1J5GO2OC94E9INEOBICHFM8PBM4HB58MAP85B4OLAE88PLIDQI9H542L219T158DI9A9658HI96DD4EJ25A4R3CHIF99BJCD1L8D2LKD2EAT2K291G4GOG&direction=forward&kind=reward_dev&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/transfers?account=ak_7myFYvagcqh8AtWEuHL4zKDGfJj5bmacNZS8RoUh5qmam1a3J&limit=1" | jq '.'
{
"data": [
{
"kind": "fee_lock_name",
"account_id": "ak_7myFYvagcqh8AtWEuHL4zKDGfJj5bmacNZS8RoUh5qmam1a3J",
"height": 51366,
"amount": 3,
"ref_tx_type": "mh_2BMVuVLTbt5rsYn8k1gjmKcSQyPwhCEtydtdSVh6TFZYZt99Z7",
"ref_tx_hash": "th_25CKbSP17N454zjtWdZBmJC4HSyk7USFJfQieyLufXwTKMcwna",
"ref_block_hash": "NameClaimTx"
}
],
"next": "/v3/transfers?account=ak_7myFYvagcqh8AtWEuHL4zKDGfJj5bmacNZS8RoUh5qmam1a3J&cursor=6KOJ4CHH5GOJCDHG70P3GB1G4HJ6APAVDHNM6QQVDPGMQP9488QL4HHJA57K6CIPACR5EIA79T6KKJ9I6L648HQI6LD48LQ4B93KQDPIAD1KIHAIALCK4HPLAL8J8DAKA10I8C9M6OO3GCHO4GO0&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/oracles?direction=forward&limit=1" | jq '.'
{
"data": [
{
"active": false,
"active_from": 4608,
"expire_height": 5851,
"format": {
"query": "the query spec",
"response": "the response spec"
},
"oracle": "ok_2TASQ4QZv584D2ZP7cZxT6sk1L1UyqbWumnWM4g1azGi1qqcR5",
"query_fee": 20000,
"register": {
"block_hash": "mh_uQMxaJ6ajKnMsW2M3QqgH1FchXGNbZriRceVggoTnUEGdgSHq",
"block_height": 4608,
"hash": "th_tboa3XizqaAW3FUx4SxzT2xmuXDYRarQqjZiZ384u4oVDn1EN",
"micro_index": 0,
"micro_time": 1544185806672,
"signatures": [
"sg_A7MGMsQxY9VTCxvBnuStmNsDSADf9H7t57c79hWotFC69e1xpcV78QXJfKoMFSgn1s7RErNksFyKcrihwYifCELnEQFQ3"
],
"tx": {
"abi_version": 0,
"account_id": "ak_2TASQ4QZv584D2ZP7cZxT6sk1L1UyqbWumnWM4g1azGi1qqcR5",
"fee": 20000,
"nonce": 1,
"oracle_id": "ok_2TASQ4QZv584D2ZP7cZxT6sk1L1UyqbWumnWM4g1azGi1qqcR5",
"oracle_ttl": {
"type": "delta",
"value": 1234
},
"query_fee": 20000,
"query_format": "the query spec",
"response_format": "the response spec",
"type": "OracleRegisterTx",
"version": 1
}
}
}
],
"next": "/v3/oracles?cursor=6894-ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM&direction=forward&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/oracles?state=inactive&limit=1" | jq '.'
{
"data": [
{
"active": false,
"active_from": 307850,
"expire_height": 308350,
"format": {
"query": "string",
"response": "string"
},
"oracle": "ok_sezvMRsriPfWdphKmv293hEiyeyUYSoqkWqW7AcAuW9jdkCnT",
"query_fee": 20000000000000,
"register": {
"block_hash": "mh_uQMxaJ6ajKnMsW2M3QqgH1FchXGNbZriRceVggoTnUEGdgSHq",
"block_height": 4608,
"hash": "th_tboa3XizqaAW3FUx4SxzT2xmuXDYRarQqjZiZ384u4oVDn1EN",
"micro_index": 0,
"micro_time": 1544185806672,
"signatures": [
"sg_A7MGMsQxY9VTCxvBnuStmNsDSADf9H7t57c79hWotFC69e1xpcV78QXJfKoMFSgn1s7RErNksFyKcrihwYifCELnEQFQ3"
],
"tx": {
"abi_version": 0,
"account_id": "ak_2TASQ4QZv584D2ZP7cZxT6sk1L1UyqbWumnWM4g1azGi1qqcR5",
"fee": 20000,
"nonce": 1,
"oracle_id": "ok_2TASQ4QZv584D2ZP7cZxT6sk1L1UyqbWumnWM4g1azGi1qqcR5",
"oracle_ttl": {
"type": "delta",
"value": 1234
},
"query_fee": 20000,
"query_format": "the query spec",
"response_format": "the response spec",
"type": "OracleRegisterTx",
"version": 1
}
}
}
],
"next": "/v3/oracles?state=inactive&cursor=507223-ok_26QSujxMBhg67YhbgvjQvsFfGdBrK9ddG4rENEGUq2EdsyfMTC&direction=backward&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/oracles?state=active&limit=1" | jq '.'
{
"data": [
{
"active": true,
"active_from": 289005,
"expire_height": 10289005,
"extends": [],
"format": {
"query": "query",
"response": "response"
},
"oracle": "ok_qJZPXvWPC7G9kFVEqNjj9NAmwMsQcpRu6E3SSCvCQuwfqpMtN",
"query_fee": 0,
"register": {
"block_hash": "mh_2f1gyBmtMMb8Sd3kbSu95cADRMwsYE8171KXP4W8wa2osRp4tZ",
"block_height": 289005,
"hash": "th_K5aPLdEN4H6QduiFtqdkv61gUCvaQpDjX3z9pHKNopD8F65LJ",
"micro_index": 20,
"micro_time": 1595571086808,
"signatures": [
"sg_CW3T2W6Ryi2kcDcSTeuwvL8xGhKYUDnGHygBCPLrF2aqfWA1RiybKqRRafrctK4c9vvL9DS9kCYzWkWSmD8mN9g6yhQPG"
],
"tx": {
"abi_version": 0,
"account_id": "ak_qJZPXvWPC7G9kFVEqNjj9NAmwMsQcpRu6E3SSCvCQuwfqpMtN",
"fee": 1842945000000000,
"nonce": 1,
"oracle_id": "ok_qJZPXvWPC7G9kFVEqNjj9NAmwMsQcpRu6E3SSCvCQuwfqpMtN",
"oracle_ttl": {
"type": "delta",
"value": 10000000
},
"query_fee": 0,
"query_format": "query",
"response_format": "response",
"ttl": 289505,
"type": "OracleRegisterTx",
"version": 1
},
"tx_index": 13749762
}
}
],
"next": "/v3/oracles?state=active&cursor=1289003-ok_f9vDQvr1cFAQAesYA16vjvBX9TFeWUB4Gb7WJkwfYSkL1CpDx&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/oracles/ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM" | jq '.'
{
"active": false,
"active_from": 4660,
"expire_height": 6894,
"approximate_expire_time": 1544587118827,
"register_time": 1544194831238,
"register_tx_hash": "th_2SLFNYk5s5u5tRD4Bqx6pSc1mysZMsCr3szbx55nKgVBQSiZv2",
"format": {
"query": "string",
"response": "string"
},
"oracle": "ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"query_fee": 20000,
"register": 11023
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/oracles/ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM/queries" | jq '.'
{
"data": [
{
"response": {
"height": 4662,
"block_hash": "mh_N2Lg6sLvnHP3eGNp4NB15CiUP3N4TbG5jTjY69HaECs33Z5MS",
"query_id": "oq_fKwkWDh1Ze4iWGaMBjGCu69LKNkzYwndrcnPwLatVDdWe3MF9",
"block_time": 1544195139953,
"source_tx_hash": "th_8Se3Gxt1SYUL7jBAxB33KXDSmp4nh282JqF16CVUmb7wBCvoy",
"source_tx_type": "OracleRespondTx",
"fee": 20000,
"nonce": 198,
"oracle_id": "ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"response": "T3JhY2xlcyBpbiBBZXRlcm5pdHkgYXJlIHdvcmtpbmcu",
"response_ttl": {
"type": "delta",
"value": 1000
},
"ttl": 0
},
"height": 4662,
"block_hash": "mh_vMjtRSPkkkZFhdWcB7Qs2eCWx7deLShL3sW8ANmjijTS5Kmrt",
"query_id": "oq_fKwkWDh1Ze4iWGaMBjGCu69LKNkzYwndrcnPwLatVDdWe3MF9",
"block_time": 1544195030464,
"source_tx_hash": "th_VNYE1rRfjPD66hjgGUBzaqwdGm4PPmzULZAcqnLcWMvrSWehz",
"source_tx_type": "OracleQueryTx",
"fee": 20000,
"nonce": 197,
"oracle_id": "ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"query": "QXJlIG9yYWNsZXMgaW4gYWV0ZXJuaXR5IHdvcmtpbmc/",
"query_fee": 20000,
"query_ttl": {
"type": "delta",
"value": 1000
},
"response_ttl": {
"type": "delta",
"value": 1000
},
"sender_id": "ak_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"ttl": 0
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/oracles/ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM/responses?limit=1" | jq '.'
{
"data": [
{
"height": 4662,
"block_hash": "mh_N2Lg6sLvnHP3eGNp4NB15CiUP3N4TbG5jTjY69HaECs33Z5MS",
"query": {
"height": 4662,
"block_hash": "mh_vMjtRSPkkkZFhdWcB7Qs2eCWx7deLShL3sW8ANmjijTS5Kmrt",
"query_id": "oq_fKwkWDh1Ze4iWGaMBjGCu69LKNkzYwndrcnPwLatVDdWe3MF9",
"block_time": 1544195030464,
"source_tx_hash": "th_VNYE1rRfjPD66hjgGUBzaqwdGm4PPmzULZAcqnLcWMvrSWehz",
"source_tx_type": "OracleQueryTx",
"fee": 20000,
"nonce": 197,
"oracle_id": "ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"query": "QXJlIG9yYWNsZXMgaW4gYWV0ZXJuaXR5IHdvcmtpbmc/",
"query_fee": 20000,
"query_ttl": {
"type": "delta",
"value": 1000
},
"response_ttl": {
"type": "delta",
"value": 1000
},
"sender_id": "ak_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"ttl": 0
},
"query_id": "oq_fKwkWDh1Ze4iWGaMBjGCu69LKNkzYwndrcnPwLatVDdWe3MF9",
"block_time": 1544195139953,
"source_tx_hash": "th_8Se3Gxt1SYUL7jBAxB33KXDSmp4nh282JqF16CVUmb7wBCvoy",
"source_tx_type": "OracleRespondTx",
"fee": 20000,
"nonce": 198,
"oracle_id": "ok_R7cQfVN15F5ek1wBSYaMRjW2XbMRKx7VDQQmbtwxspjZQvmPM",
"response": "T3JhY2xlcyBpbiBBZXRlcm5pdHkgYXJlIHdvcmtpbmcu",
"response_ttl": {
"type": "delta",
"value": 1000
},
"ttl": 0
}
],
"next": null,
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/channels?direction=forward&limit=1" | jq '.'
{
"data": [
{
"active": true,
"amount": 100090,
"channel": "ch_22usvXSjYaDPdhecyhub7tZnYpHeCEZdscEEyhb2M4rHb58RyD",
"initiator": "ak_ozzwBYeatmuN818LjDDDwRSiBSvrqt4WU7WvbGsZGVre72LTS",
"last_updated_height": 14258,
"last_updated_tx_hash": "th_2Ph5XF3VBUNstN5kkVic56NY55xq8vckM3h2TQ5sRVSLGq1kvE",
"last_updated_tx_type": "ChannelDepositTx",
"responder": "ak_26xYuZJnxpjuBqkvXQ4EKb4Ludt8w3rGWREvEwm68qdtJLyLwq",
"state_hash": "st_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACy1gTH9",
"updates_count": 3,
"channel_reserve": 10,
"delegate_ids": [],
"initiator_amount": 50000,
"lock_period": 3,
"locked_until": 0,
"responder_amount": 50000,
"round": 6,
"solo_round": 0
}
],
"next": "/v3/channels?cursor=9155-ch_2tceSwiqxgBcPirX3VYgW3sXgQdJeHjrNWHhLWyfZL7pT4gZF4&direction=forward&limit=1",
"prev": null
}$ curl -s "https://testnet.aeternity.io/mdw/v3/channels/ch_2ZBf9AJ3wr25YzdZb1sQrDALEQ1ZDKwwUhtVXoZiNKbheuesqs?block_hash=mh_245PQCb1gWrJRxUjAmEAv5qSXLQGnksCgHyw9PTHRNGA6PfeD" | jq '.'
{
"active": true,
"amount": 1e+19,
"channel": "ch_2ZBf9AJ3wr25YzdZb1sQrDALEQ1ZDKwwUhtVXoZiNKbheuesqs",
"initiator": "ak_VQbiKWLmFXzamGXeTahL9efE8jMprjM9ZpG2BXyWYmPy3ck9Q",
"last_updated_height": 104024,
"last_updated_tx_hash": "th_2SQMPNd8jdY5nm8YFpitUti8z9qqBfPuzdodQU9FFzpuMxuLYw",
"last_updated_tx_type": "ChannelDepositTx",
"responder": "ak_27c4YpfUuW4s9T6RBNpASNuDRiXSWQ93uZ5WxaUXfx1Lqibv33",
"state_hash": "st_7oYjZ20LNQTH1ICHzQvgmgAKcYgqFP5hiv8ATvu+5y6a4j9h",
"updates_count": 3,
"channel_reserve": 1e+18,
"delegate_ids": [],
"initiator_amount": 2e+18,
"lock_period": 10,
"locked_until": 0,
"responder_amount": 2e+18,
"round": 8,
"solo_round": 0
}$ curl -s "https://testnet.aeternity.io/mdw/v3/channels/ch_2ZBf9AJ3wr25YzdZb1sQrDALEQ1ZDKwwUhtVXoZiNKbheuesqs/updates?limit=1" | jq '.'
{
"data": [
{
"block_hash": "mh_2QuuJR9TC7Pnq2o8myDgEQWnRxbCtYwenLLGrk1Xr1VmjF5ozt",
"source_tx_hash": "th_2YHpkkn9ojgKF8amcJiaLCPR46JZg9He6T73MRHdM21Nj2QSWn",
"source_tx_type": "ChannelCreateTx",
"tx" => {
"channel": "ch_2ZBf9AJ3wr25YzdZb1sQrDALEQ1ZDKwwUhtVXoZiNKbheuesqs",
"tx_type": "ChannelCreateTx",
"channel_reserve": 1,
"delegate_ids": [],
"fee": 17500000000000,
"initiator_amount": 20000000000000,
"initiator_id": "ak_vx8HkCzRHrqpCAyQ7TFBtfTqBimkcTFcJC1amez5vtCzdu2oN",
"lock_period": 1,
"nonce": 7,
"responder_amount": 1,
"responder_id": "ak_2dxvgsogiBDWXvZSzTghv5MoXLfkFGiEynDC5Cn8k2M2s325Ki",
"state_hash": "st_fav83CO2VqFQTOayQE3Z3Xhj1NTbFHNcve7KWjemmES0s7tK",
"ttl": 0
}
}
],
"next": "/v3/channels/ch_2ZBf9AJ3wr25YzdZb1sQrDALEQ1ZDKwwUhtVXoZiNKbheuesqs/updates?cursor=9155-0&limit=1",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/aex9?by=symbol" | jq '.'
{
"data": [
{
"decimals": 18,
"name": "yy",
"extensions": [],
"symbol": "yy",
"contract_id": "ct_ukZe6BBpuSWxT8hxd87z11vdgRnwKnedEWqJ7SyQucbX1C1pc",
"contract_tx_hash": "th_236RbbgokHipFbG5Eu9yZSSgzrBQhkRrkFdhXM7ipsmorbkqgy",
"event_supply": 1e+26,
"holders": 1,
"initial_supply": 1e+26
},
{
"decimals": 18,
"name": "xx",
"extensions": [],
"symbol": "xx",
"contract_id": "ct_vJWj5Z9KPBSE52ZvbZ9cffRhEEX6K6DjRwAZcZ9bArDmrZDuS",
"contract_tx_hash": "th_2B6DM7SLqRkcTRBejLR4fohBpa4k3nR164uUja3k8SKKYvbwdJ",
"event_supply": 2e+25,
"holders": 4,
"initial_supply": 2e+25
}
],
"next": "/v3/aex9?by=symbol&cursor=g2gDdwRhZXg5bQAAAAN4b2ttAAAAIHUgUMyJxcMnebj7f5xFL1tWPOn3pfdez%2FvPSy04W1ws",
"prev": null
}$ curl https://mainnet.aeternity.io/mdw/v3/aex9/ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9
{
"decimals": 18,
"name": "🚀",
"extensions": [
"allowances",
"mintable",
"burnable",
"swappable"
],
"symbol": "🚀",
"contract_id": "ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9",
"contract_tx_hash": "th_rbFNrRDpn6finytCEmHAExtBnRxt14yckvuCWRmXxsRpypHxt",
"event_supply": 99000000000000000000,
"holders": 2,
"initial_supply": 99000000000000000000
}$ curl https://mainnet.aeternity.io/mdw/v3/aex9/ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9/balances
{
"data": [
{
"height": 359828,
"amount": 24000000000000000000,
"contract_id": "ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9",
"block_hash": "mh_22uNd2u5ogsFCua2kU3fSag758fTcwJ4kKJwvHpRVedeKwFRHc",
"account_id": "ak_2KnhztVzfKMBUogdSsCACKVotb6uxjqDLLcLsTk8MdW3266YTL",
"last_tx_hash": "th_2d2Qnx632buohPC6jmu9jwm5m4vbbegcAiwwZevoJJLeru2MVZ",
"last_log_idx": 0
},
{
"height": 359828,
"amount": 75000000000000000000,
"contract_id": "ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9",
"block_hash": "mh_22uNd2u5ogsFCua2kU3fSag758fTcwJ4kKJwvHpRVedeKwFRHc",
"account_id": "ak_YCwfWaW5ER6cRsG9Jg4KMyVU59bQkt45WvcnJJctQojCqBeG2",
"last_tx_hash": "th_2d2Qnx632buohPC6jmu9jwm5m4vbbegcAiwwZevoJJLeru2MVZ",
"last_log_idx": 0
}
],
"next": null,
"prev": null
}$ curl https://mainnet.aeternity.io/mdw/v3/aex9/ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9/balances/ak_2KnhztVzfKMBUogdSsCACKVotb6uxjqDLLcLsTk8MdW3266YTL
{
"contract": "ct_TEt8raHSNKZWHNN8TaCvV2VKDuSGPcxAZhNJcq62M8Gwp6zM9",
"account": "ak_2KnhztVzfKMBUogdSsCACKVotb6uxjqDLLcLsTk8MdW3266YTL",
"amount": 24000000000000000000
}$ TODO$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141?direction=forward&limit=1' | jq '.'
{
"data": [
{
"base_url": null,
"contract_id": "ct_2KsfvrPHwdZb9CkwvgCkzg4o4k7cH7oyfQq4CNPNCHEZ4RTCf",
"contract_txi": 30958504,
"extensions": [
"mintable"
],
"metadata_type": "map",
"name": "Apes stepping into the Metaverse",
"nft_owners": 1,
"nfts_amount": 8,
"symbol": "ASITM"
}
],
"next": "/v3/aex141?cursor=g2gDZAAGYWV4MTQxbQAAACBBcGVzIHN0ZXBwaW5nIGludG8gdGhlIE1ldGF2ZXJzZW0AAAAgD29qcQzT%2FM%2BHEg1uw31I%2BYRUpktYP%2FZ09Dapkl2szkA%3D&direction=forward&limit=1",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8' | jq .
{
"base_url": null,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"contract_txi": 30958726,
"extensions": [
"mintable"
],
"metadata_type": "map",
"name": "Apes stepping into the Metaverse",
"nft_owners": 1,
"nfts_amount": 8,
"symbol": "ASITM"
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8/tokens?direction=forward&limit=2' | jq .
{
"data": [
{
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"owner_id": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"token_id": 1
},
{
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"owner_id": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"token_id": 2
}
],
"next": "/v3/aex141/ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8/tokens?cursor=g2gCbQAAACD5nNNdNGQ3YrwVYeXgdeB%2FFd1jOgwZs1p74F2dVz6zC2ED&direction=forward&limit=2",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8/tokens/2' | jq .
{
"contract_id" : "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"metadata" : {
"map" : {
"description" : "Heaven or metaverse? We don't care!",
"immutable_attributes" : "[object Object]",
"media_type" : "IMAGE",
"media_url" : "ipfs://Qmef7Xrh1YTgQqXbr86o3TrFoya9ZLk1RVdXMga1JjEjnm",
"mutable_attributes" : "[object Object]",
"name" : "The path to heaven"
}
},
"owner" : "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"token_id" : 2
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/ct_2oq4kSd4j1VkkbupueXLdHwYEJdY8Ntzvp1FFkMB1gYyXkYPcV/templates?direction=forward&limit=2' | jq .
{
"data": [
{
"contract_id": "ct_2oq4kSd4j1VkkbupueXLdHwYEJdY8Ntzvp1FFkMB1gYyXkYPcV",
"edition": null,
"log_idx": 0,
"template_id": 1,
"tx_hash": "th_KsfMGhkVf2n5RLY5qh1Bo8HppudiQREq7LMKAYuauLSuYKg4s"
},
{
"contract_id": "ct_2oq4kSd4j1VkkbupueXLdHwYEJdY8Ntzvp1FFkMB1gYyXkYPcV",
"edition": null,
"log_idx": 0,
"template_id": 2,
"tx_hash": "th_Vrk8UGyUpgnvVPK3TknudxPx3Jd3mSCUPnfqcuKbjWZSZivjQ"
}
],
"next": "/v3/aex141/ct_2oq4kSd4j1VkkbupueXLdHwYEJdY8Ntzvp1FFkMB1gYyXkYPcV/templates?cursor=g2gCbQAAACDuBsFrXLJEIAr8CpUxUAJxriYxXg%2BRMhW900GbowEFwWED&direction=forward&limit=2",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/ct_ouWFCU2Qg6v7dgFpjRc3jAfcaRhb9iByPRBDjXSJoA8fRrQ4j/templates/8/tokens?direction=forward&limit=2' | jq .
{
"data": [
{
"log_idx": 0,
"owner_id": "ak_8Ujt76QfpT1DyYsNZKGPGtMZ2C2MFf7CcnpQvJWNsX6szZkYN",
"token_id": 29,
"tx_hash": "th_ZzPmumNtkYCfrGpVGtQP6em9hgkWQqstddB5ynagrJJa7ua9c"
},
{
"log_idx": 0,
"owner_id": "ak_8Ujt76QfpT1DyYsNZKGPGtMZ2C2MFf7CcnpQvJWNsX6szZkYN",
"token_id": 30,
"tx_hash": "th_2UAUi3oYgcYsJ8EGvxR4vurygt7qhYq7tVRNx4g2sZ3quVpym7"
}
],
"next": "/v3/aex141/ct_ouWFCU2Qg6v7dgFpjRc3jAfcaRhb9iByPRBDjXSJoA8fRrQ4j/templates/8/tokens?cursor=g2gDbQAAACBqgQyEWHrcaKnZMsVhZvJdUfhMZjSF4KpvuLx%2FpHpCcmEIYR8%3D&direction=forward&limit=2",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/accounts/ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW/tokens?direction=forward&limit=2' | jq .
{
"data": [
{
"contract_id": "ct_2KsfvrPHwdZb9CkwvgCkzg4o4k7cH7oyfQq4CNPNCHEZ4RTCf",
"owner_id": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"token_id": 1
},
{
"contract_id": "ct_2KsfvrPHwdZb9CkwvgCkzg4o4k7cH7oyfQq4CNPNCHEZ4RTCf",
"owner_id": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"token_id": 2
}
],
"next": "/v3/accounts/ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW/aex141/tokens?cursor=g2gDbQAAACA1VnHPFWKr80aBDnG3tjrWGYMqQpxUJK6dhDlBrJXgEG0AAAAgAwJumVbCVqhk2XF8UnTR8fiNve0Gh9zLEEoZoC55qRdhAw%3D%3D&direction=forward&limit=2",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8/transfers?direction=forward&limit=2' | jq .
{
"data": [
{
"block_height": 651434,
"call_txi": 30958727,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"log_idx": 0,
"micro_index": 5,
"micro_time": 1661491608237,
"recipient": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"sender": "ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"token_id": 1,
"tx_hash": "th_2d5iaRa2DkgJb6ABSt5ea6TcM1FVB2EW6dx7FRU9XMWi1J4n9e"
},
{
"block_height": 651434,
"call_txi": 30958729,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"log_idx": 0,
"micro_index": 6,
"micro_time": 1661491611260,
"recipient": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"sender": "ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"token_id": 2,
"tx_hash": "th_BPiUgq2aqm7rTmhb68DW2vEhReWda3mioxeFBjPfxGtLnkAtg"
}
],
"next": "/v3/aex141/ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8/transfers?cursor=g2gGYgHYZIZtAAAAIPmc0100ZDdivBVh5eB14H8V3WM6DBmzWnvgXZ1XPrMLYgHYZIttAAAAIDVWcc8VYqvzRoEOcbe2OtYZgypCnFQkrp2EOUGsleAQYQNhAA%3D%3D&direction=forward&limit=2",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/transfers?from=ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8&direction=forward&limit=2' | jq .
{
"data": [
{
"block_height": 651434,
"call_txi": 30958727,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"log_idx": 0,
"micro_index": 5,
"micro_time": 1661491608237,
"recipient": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"sender": "ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"token_id": 1,
"tx_hash": "th_2d5iaRa2DkgJb6ABSt5ea6TcM1FVB2EW6dx7FRU9XMWi1J4n9e"
},
{
"block_height": 651434,
"call_txi": 30958729,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"log_idx": 0,
"micro_index": 6,
"micro_time": 1661491611260,
"recipient": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"sender": "ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"token_id": 2,
"tx_hash": "th_BPiUgq2aqm7rTmhb68DW2vEhReWda3mioxeFBjPfxGtLnkAtg"
}
],
"next": "/v3/aex141/transfers?from=ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8&cursor=g2gGYgHYZIZtAAAAIPmc0100ZDdivBVh5eB14H8V3WM6DBmzWnvgXZ1XPrMLYgHYZIttAAAAIDVWcc8VYqvzRoEOcbe2OtYZgypCnFQkrp2EOUGsleAQYQNhAA%3D%3D&direction=forward&limit=2",
"prev": null
}$ curl -s 'https://testnet.aeternity.io/mdw/v3/aex141/transfers?to=ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW&contract_id=ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8&direction=forward&limit=2' | jq .
{
"data": [
{
"block_height": 651434,
"call_txi": 30958727,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"log_idx": 0,
"micro_index": 5,
"micro_time": 1661491608237,
"recipient": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"sender": "ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"token_id": 1,
"tx_hash": "th_2d5iaRa2DkgJb6ABSt5ea6TcM1FVB2EW6dx7FRU9XMWi1J4n9e"
},
{
"block_height": 651434,
"call_txi": 30958729,
"contract_id": "ct_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"log_idx": 0,
"micro_index": 6,
"micro_time": 1661491611260,
"recipient": "ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW",
"sender": "ak_2tw26RwgNADrpuCnrQWKPBH87bPxuRbLR1KLccS9ZJTUMMj4z8",
"token_id": 2,
"tx_hash": "th_BPiUgq2aqm7rTmhb68DW2vEhReWda3mioxeFBjPfxGtLnkAtg"
}
],
"next": "/v3/aex141/transfers?to=ak_QVSUoGrJ31CVxWpvgvwQ7PUPFgnvWQouUgsDBVoGjuT7hjQYW&cursor=g2gGYgHYZIZtAAAAIDVWcc8VYqvzRoEOcbe2OtYZgypCnFQkrp2EOUGsleAQYgHYZIttAAAAIPmc0100ZDdivBVh5eB14H8V3WM6DBmzWnvgXZ1XPrMLYQNhAA%3D%3D&direction=forward&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats/delta?limit=1" | jq '.'
{
"data": [
{
"auctions_started": 0,
"block_reward": 0,
"burned_in_auctions": 0,
"channels_closed": 0,
"channels_opened": 0,
"contracts_created": 0,
"dev_reward": 0,
"height": 1,
"last_tx_hash": "th_2FHxDzpQMRTiRfpYRV3eCcsheHr1sjf9waxk7z6JDTVcgqZRXR",
"locked_in_auctions": 0,
"locked_in_channels": 0,
"names_activated": 0,
"names_expired": 0,
"names_revoked": 0,
"oracles_expired": 0,
"oracles_registered": 0
}
],
"next": "/v3/stats/delta?limit=1&cursor=419208"
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats/total?scope=gen:421454-0&limit=1" | jq '.'
{
"data": [
{
"active_auctions": 0,
"active_names": 0,
"active_oracles": 0,
"burned_in_auctions": 0,
"contracts": 0,
"height": 421454,
"inactive_names": 0,
"inactive_oracles": 0,
"last_tx_hash": "th_2FHxDzpQMRTiRfpYRV3eCcsheHr1sjf9waxk7z6JDTVcgqZRXR",
"locked_in_auctions": 0,
"locked_in_channels": 0,
"open_channels": 0,
"sum_block_reward": 0,
"sum_dev_reward": 0,
"total_token_supply": 8.945137682239798e+25
}
],
"next": "/v3/stats/total?scope=gen:421454-0&limit=1&cursor=42152"
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats/miners?limit=1" | jq '.'
{
"data": [
{
"miner": "ak_2wkBCLxwjfcT3DHoisV7tGVQK8uni8XQwWZ6RUKD9DDwYSz8XN",
"total_reward": 76626041292504000000
}
],
"next": "/v3/stats/miners?cursor=ak_2wk52gAYRWAMi7gWP7A1oMvHEP9kpmp471VJFpvVzWMHnRc47a",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats/blocks?limit=2" | jq '.'
{
"data": [
{
"count": 38150,
"end_date": "2023-07-22",
"start_date": "2023-07-21"
},
{
"count": 117685,
"end_date": "2023-07-21",
"start_date": "2023-07-20"
}
],
"next": "/v3/stats/blocks?cursor=19557&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats/names?limit=2" | jq '.'
{
"data": [
{
"count": 38150,
"end_date": "2023-07-22",
"start_date": "2023-07-21"
},
{
"count": 117685,
"end_date": "2023-07-21",
"start_date": "2023-07-20"
}
],
"next": "/v3/stats/names?cursor=19557&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats/transactions?limit=2" | jq '.'
{
"data": [
{
"count": 38150,
"end_date": "2023-07-22",
"start_date": "2023-07-21"
},
{
"count": 117685,
"end_date": "2023-07-21",
"start_date": "2023-07-20"
}
],
"next": "/v3/stats/transactions?cursor=19557&limit=2",
"prev": null
}$ curl -s "https://mainnet.aeternity.io/mdw/v3/stats" | jq '.'
{
"miners_count": 228,
"fees_trend": -0.86,
"last_24hs_average_transaction_fees": 25816293013087.883,
"last_24hs_transactions": 9606,
"max_transactions_per_second": 147.26,
"max_transactions_per_second_block_hash": "kh_27UooKSFP8qYaymFiUvhrMfAsCUeTon48s52gfdmF8iruoi6cS",
"transactions_trend": -0.12
}$ curl https://mainnet.aeternity.io/mdw/v3/accounts/ak_2nVdbZTBVTbAet8j2hQhLmfNm1N2WKoAGyL7abTAHF1wGMPjzx/activities
{
"data": [
{
"height": 85694,
"type": "NameUpdateTxEvent",
"payload": {
"block_hash": "mh_2tL4tRRnH6WLzzYca7T7vQUbdUCRZEeq58S5giwAtnbkjjb3Vj",
"block_height": 85694,
"hash": "th_2pvhiLSonrEsmJiUf9Q3E3Lkt9ki5MpHGJ9qQsCVt8ACNWpVVc",
"micro_index": 30,
"micro_time": 1558804725247,
"signatures": [
"sg_P7UFr4iySfJpidyitDqVTF86uhnuYjQVJ46c96jC4nYZys5mBDQVbsV4CLxYpCqKU55SySmkcSg3Xg4dcYk4aFJGm3VjF"
],
"tx": {
"account_id": "ak_2nVdbZTBVTbAet8j2hQhLmfNm1N2WKoAGyL7abTAHF1wGMPjzx",
"client_ttl": 84600,
"fee": 30000000000000,
"name": "umpz.test",
"name_id": "nm_t13Kcjan1mRu2sFjdMgeeASSSL8QoxmVhTrFCmji1j1DZ4jhb",
"name_ttl": 50000,
"nonce": 151,
"pointers": [
{
"id": "ak_2nVdbZTBVTbAet8j2hQhLmfNm1N2WKoAGyL7abTAHF1wGMPjzx",
"key": "account_pubkey"
}
],
"type": "NameUpdateTx",
"version": 1
}
}
},
{
"payload": {
"block_hash": "mh_2iWGwtQYYueZ8wLGTBjQ79jYfLnQKNgVcHc1GWuPqMG46UPnHY",
"block_height": 502033,
"hash": "th_29qxc2oEajHPVoGNS6LBe2TbKk2kyECXXR4KtbGHMhfpwdoNzD",
"micro_index": 0,
"micro_time": 1634367215608,
"signatures": [
"sg_DXk5jcdoCgGVHJUqjL2Mnu3tPxFD2mGrPga5TgVH97DZC1oq7aDZKEHgrpBqf24A4v2oBFX3zHQzXC1wj9X4ZqdzsqJqj"
],
"tx": {
"amount": 20000,
"fee": 19320000000000,
"nonce": 5967045,
"payload": "ba_NTAyMDMxOmtoXzJraWtpTms0cnJnV2lNZlBLSmszU2FCdnM5TVVqdHZtNEpLeTdoVnA3Z2k5eW1uaXF1Om1oX01TZ2dxenJINlpXOW9xbmM3eXZDR1dBdGlGRGpaWGFrQWZSVndmeWtteGdWdEd3aVY6MTYzNDM2NzIxMCoV6Eo=",
"recipient_id": "ak_2QkttUgEyPixKzqXkJ4LX7ugbRjwCDWPBT4p4M2r8brjxUxUYd",
"sender_id": "ak_2QkttUgEyPixKzqXkJ4LX7ugbRjwCDWPBT4p4M2r8brjxUxUYd",
"ttl": 502041,
"type": "SpendTx",
"version": 1
}
},
"type": "SpendTxEvent",
"height": 502033
},
{
"height": 659373,
"payload": {
"block_hash": "mh_MXVb7wmE1tqeA2xSPhTTksLy7DE5PvR8nsu5haC2fTGpgxxhR",
"call_tx_hash": "th_Ugtejdn7SkJHXkC3VSdCm2SnXGgPxHgUphBneMqgR3gniZzDN",
"contract_id": "ct_2AfnEfCSZCTEkxL5Yoi4Yfq6fF7YapHRaFKDJK3THMXMBspp5z",
"contract_tx_hash": "th_6memqAr5S3UQp1pc4FWXT8xUotfdrdUFgBd8VPmjM2ZRuojTF",
"function": "Oracle.query",
"height": 659373,
"internal_tx": {
"fee": 0,
"nonce": 0,
"oracle_id": "ok_AFbLSrppnBFgbKPo4GykK5XEwdq15oXgosgcdL7ud6Vo2YPsH",
"query": "YWtfcjNxRWNzWWd5Z2JjYVoxZlhQRFB0YThnZU5FUkV0OHZZaVVKNWtxQnNRNDhXVmp4NztodHRwczovL20ud2VpYm8uY24vNzc1NDY0Njg4Ny80ODE2MjEwNDI2ODYxMjg5",
"query_fee": 20000000000000,
"query_id": "oq_pcJy4ufijeP56LwCaJ47GcRNvJvW5nEUedR4BNeMzSobXXqMx",
"query_ttl": {
"type": "delta",
"value": 20
},
"response_ttl": {
"type": "delta",
"value": 20
},
"sender_id": "ak_7wqP18AHzyoqymwGaqQp8G2UpzBCggYiq7CZdJiB71VUsLpR4",
"type": "OracleQueryTx",
"version": 1
},
"local_idx": 3,
"micro_index": 0
},
"type": "InternalContractCallEvent"
},
{
"height": 653289,
"payload": {
"from": "ak_11111111111111111111111111111111273Yts",
"log_index": 0,
"to": "ak_uTWegpfN6UjA4yz8X4ZVRi9xKEYeXHJDRZcRryTsRHAFoBpLa",
"tx_hash": "th_2FciwUNyT7WRGee35KnNMhuoLFSCyiquVLFP3kATjwrFJh4Cfh",
"value": 1
},
"type": "Aex141TransferEvent"
}
],
"next": "/v3/accounts/ak_2nVdbZTBVTbAet8j2hQhLmfNm1N2WKoAGyL7abTAHF1wGMPjzx/activities?cursor=84328-2002003-0",
"prev": null
}{
"op": <subscription operation>,
"payload": "<message payload>",
}wscat -c wss://mainnet.aeternity.io/mdw/websocket
connected (press CTRL+C to quit)
> {"op":"Subscribe", "payload": "KeyBlocks"}
< ["KeyBlocks"]
> {"op":"Ping"}
< {"subscriptions":["KeyBlocks"],"payload":"Pong"}
> {"op":"Subscribe", "payload": "MicroBlocks"}
< ["KeyBlocks","MicroBlocks"]
> {"op":"Unsubscribe", "payload": "MicroBlocks"}
< ["KeyBlocks"]
> {"op":"Subscribe", "payload": "Transactions"}
< ["KeyBlocks","Transactions"]
> {"op":"Unsubscribe", "payload": "Transactions"}
< ["KeyBlocks"]
> {"op":"Subscribe", "payload": "Object", "target":"ak_KHfXhF2J6VBt3sUgFygdbpEkWi6AKBkr9jNKUCHbpwwagzHUs"}
< ["KeyBlocks","ak_KHfXhF2J6VBt3sUgFygdbpEkWi6AKBkr9jNKUCHbpwwagzHUs"]
< {"subscription":"KeyBlocks","payload":{"version":4,"time":1588935852368,"target":505727522,"state_hash":"bs_6PKt6GXM9Nu3As4XYr3kjmMiuJoTzkHUPDAwm21GBtjbpfWyL","prev_key_hash":"kh_2Dtcpq9ZdB7AJK1aeEwQtoSncDhFejSdzgTTwuNyscFzJrnsnJ","prev_hash":"mh_2H9cAZHHbyMzPwd4vjQHZpxXsrggG54VCryh6k1BTk511At8Bs","pow":[895666,52781556,66367943,73040389,83465124,91957344,137512183,139025150,145635838,147496688,174889700,196453040,223464154,236816295,249867489,251365348,253234990,284153380,309504789,316268731,337440038,348735058,352371122,367534696,378716232,396258628,400918205,407082251,424187867,427465210,430070369,430312387,432729464,438115994,440444207,442136189,473766117,478006149,482575574,489211700,498083855,518253098],"nonce":567855076671752,"miner":"ak_2Go59eRMNcdiq5uUvVAKjSRoxtREtJe6QvNdcAAPh9GiE5ekQi","info":"cb_AAACHMKhM24=","height":252274,"hash":"kh_FProa64FL423f3xok2fKTfbsuEP2QtdUM4idN7GidQ279zgZ1","beneficiary":"ak_2kHmiJN1RzQL6zXZVuoTuFaVLTCeH3BKyDMZKmixCV3QSWs3dd"}}
< {"subscription":"Object","payload":{"tx":{"version":1,"type":"SpendTx","ttl":252284,"sender_id":"ak_KHfXhF2J6VBt3sUgFygdbpEkWi6AKBkr9jNKUCHbpwwagzHUs","recipient_id":"ak_KHfXhF2J6VBt3sUgFygdbpEkWi6AKBkr9jNKUCHbpwwagzHUs","payload":"ba_MjUyMjc0OmtoX0ZQcm9hNjRGTDQyM2YzeG9rMmZLVGZic3VFUDJRdGRVTTRpZE43R2lkUTI3OXpnWjE6bWhfMmJTcFlDRVRzZ3hMZDd3eEx2Rkw5Wlp5V1ZqaEtNQXF6aGc3eVB6ZUNraThySFVTbzI6MTU4ODkzNTkwMjSozR4=","nonce":2044360,"fee":19320000000000,"amount":20000},"signatures":["sg_Kdh2uaoaiDEHoehDZsRHk7LvqUm5kPqyKR3RD71utjkkh5DTqoJeNWqYv4gRePL9FyBcU7oeL8nsT39zQg4ydCmiKUuhN"],"hash":"th_rGmoP9FCJMQMJKmwDE8gCk7i63vX33St3UiqGQsRGG1twHD7R","block_height":252274,"block_hash":"mh_2gYb8Pv1yLpdsPjxkzq8g9zzBVy42ZLDRvWH6aKYXhb8QjxdvU"}}{
"payload": "<sync info payload>",
"source": "node" | "mdw",
"subscription": "KeyBlocks" | "MicroBlocks" | "Transactions" | "Object"
}elixir --sname aeternity@localhost -S mix testelixir --sname aeternity@localhost -S mix test.integrationAll notable changes to this project will be documented in this file. See standard-version for commit guidelines.
account: add sync versions of AccountMnemonicFactory methods ()
account: detect MetaMask over EIP-6963 ()
account: experimental support of Ledger app v1.0.0 ()
account: init AccountMnemonicFactory by seed ()
account: add unsafeSign, deprecate sign ()
add ensureEncoded, isEncoded; deprecate isAddressValid ()
add hashMessage, deprecate messageToHash ()
add verifyMessageSignature, deprecate verifyMessage ()
add verifySignature, deprecate verify ()
aens: add getAuctionState to Name ()
aens: add id getter to Name ()
aens: add isName, deprecate isNameValid ()
aens: allow to pass salt between Name while claiming ()
node: add Hyperchain endpoints ()
node: ignore consensus protocol version if ignoreVersion set ()
node: warn if incompatible version when ignoreVersion set ()
oracle: add getQueries to OracleBase ()
contract: show function name along its hash if missed in bytecode ()
account: implicitly connect to Aeternity snap, clean up flow ()
aens: computeAuctionEndBlock returns value according to Ceres ()
aens: handle highestBid as BigInt in auction details ()
Please check out the and a to convert to convert secret keys.
CommonJS bundles have cjs extension instead js
aepp: AeSdkWallet requires onAskToSelectNetwork constructor option
tx-builder: ChannelClientReconnectTx removed
account: add ensureReady method to AccountLedgerFactory ()
account: add AccountMetamaskFactory ()
account: add AccountMnemonicFactory ()
account: improve Account:publicKey type ()
aens: validate minus chars in name as node does ()
aepp: don't require subscription to request addresses ()
channel: channelId
account: make signTypedData, signDelegation abstract ()
account: remove generateKeyPair ()
account: remove generateKeyPairFromSecret (
account: improve Account:publicKey type ()
aens: validate minus chars in name as node does ()
aepp: don't require subscription to request addresses ()
channel: channelId
contract: detect if ACI doesn't match called contract ()
ttl validation error in dev mode by reducing polling intervals ()
node: mark as compatible with 7.0.0 ()
accept multiple encodings in isAddressValid, add TS asserts ()
add getContext method to AeSdk ()
aens: support update with raw pointers ()
aens: make extendTtl argument optional ()
aens: reduce default client ttl to one hour ()
chain: poll till ttl if defined to ensure tx can't be mined ()
use proper vm version in Ceres ()
aepp,wallet: connect to web-extension if opened over file:/// ()
aepp: use complete type of WalletInfo object ()
contract: don't mark contract as deployed if tx failed ()
use Number instead of unary plus for BigInt ()
account: add methods to generate delegation signatures ()
aepp,wallet: support delegation signatures ()
account: add implementation of signTypedData in AccountBase ()
wallet: don't ask to confirm unsubscription ()
wallet: don't require to be subscribed to request addresses ()
account: support signing typed data ()
aens: add ensureName helper to check names ()
aens: support unicode names claim ()
onAccount option in AeSdkMethods ()
aens: more accurate name check in isNameValid ()
aepp: call onDetected always with newWallet ()
contract: return type of call/deploy on chain ()
export of prefixedAmount helper ()
Please check out , and release notes for the .
aepp: All wallet provided nodes have the same name
Specified in name option of connectToWallet.
aepp: Select option removed from connectToWallet
If you are using connectNode then the current node would always be the same as wallet provides.
aepp: call onNetworkChange after connection ()
export Encoded type ()
aepp: use the same name for all nodes provided by wallet ()
chain: reduce /2 number of blocks to wait before throwing timeout ()
contract: add missed sourceCodePath cases ()
onSign, onMessageSign callbacks were removed on the wallet side
ACI format used the same as returned by aesophia_cli
createAensDelegationSignature, createOracleDelegationSignature replaced with createDelegationSignature
params argument in $deploy and $call
StateTrees fields decoded as objects mapping key to decoded entry instead of internals
The content of Tag.*Mtree entries decoded and moved to payload field
TX_SCHEMA, TxParamsCommon, TxSchema, TxTypeSchemas not exported anymore
AeSdk.buildTx accepts tag
Methods of CompilerHttp moved to api property
Compiler export renamed to CompilerHttp
removed compilerUrl, setCompilerUrl
createGeneralizedAccount accepts sourceCode in options
createMetaTx removed
AccountRpc constructor accepts arguments one by one
url property of Node removed
QUERY_FEE is not exported anymore
Oracles created without queryFee by default
AeSdk:extendOracleTtl, AeSdk:respondToQuery doesn't accept oracleId
onQuery callback of pollForQueries
send inlined into sendTransaction
height removed from the output of aensPreclaim
Channel:state returns unpacked entries
All channel events emitted in snakeCase
Channel:poi returns unpacked TreesPoi
onAccount doesn't accept keypair
bigNumberToByteArray removed
str2buf function removed
account: accept async function in authData of AccountGeneralized ()
account: override fee, gasPrice of GaMetaTx in authData ()
chain:
aepp: don't require connection to wallet to make a static call ()
channel: increase pong timeout 3 times (to 15 seconds) ()
channel: return type of state ()
deps: update calldata to 1.3.0 ()
deps: depend on specific version of @azure/core-client to fix ()
export and implementation of calculateMinFee ()
export Encoding enum ()
ability to use sdk without nodes ()
aepp,wallet: avoid invalid message errors using third-party tools ()
AeSdkBase: don't mutate the options argument ()
awaitHeight: allow to wait for arbitrary number of blocks ()
Universal, RpcAepp, RpcWallet stamps replaced with AeSdk, AeSdkAepp, AeSdkWallet classes
all combined exports are inlined (require('@aeternity/aepp-sdk').generateKeyPair())
Node, Compiler (previously ContractCompilerHttp) are classes instead of a stamps
Node, Compiler doesn't check version on the first request instead of init
getNetworkId
removed methods to generate a transaction of specific type
removed ability to generate transaction on the node side
nonce, ttl, gas decoded and accepted as numbers instead of strings
computeBidFee accepts startFee, increment as options
NAME_BID_TIMEOUTS not exposed anymore
computeAuctionEndBlock accepts and returns height as number
extendOracleTtl accepts oracle ttl in oracleTtlType and oracleTtlValue fields
decode method of getQueryObject removed
createAensDelegationSignature accepts contractId, name, options
createOracleDelegationSignature accepts contractId, queryId as a property of options
removed balance, tx, getTxInfo methods
getAccountNonce removed
AeSdk doesn't accept array of accounts
destroyInstance method removed
BrowserRuntimeConnection, BrowserWindowMessageConnection are classes
ContentScriptBridge, WalletDetector rewrited to plain functions (connectionProxy, walletDetector)
RpcClient: removed origin property
connectToWallet accepts wallet connection as the first argument
disconnectWallet runs in sync and sendDisconnect arg removed
sendConnectRequest removed
BrowserRuntimeConnection requires port parameter
requires id, type in params
getBrowserAPI helper removed
aepp: support external accounts in onAccount ()
ga: implement buildAuthTxHash function ()
NodeInvocationError: store tx-encoded transaction ()
aepp: use networkId in rpc tx signing ()
importing in mjs ()
messageToHash: support messages longer than 252 chars ()
wallet: revert to returning complete tx data instead of just hash in rpc wallet signing ()
generate compiler api in TypeScript using autorest ()
generate node api in TypeScript ()
compiler: init in sync, check version on making request ()
aci: accept onAccount as AccountBase ()
contract: do not check payable if contract call is init ()
importing in mjs ()
oracle: do not include address for oracle respond signature ()
aeSdk.return empty array instead of throwing UnsignedTxError
rpc: remove forceValidation flag
hd-wallet: expect that bip39 used externally
hd-wallet: remove default export
aci: use dry-run to estimate gas and get rich errors ()
calculate default polling intervals depending on node settings ()
chain: combine multiple dry-run requests at one ()
contract events: ability to resolve multiple definitions of event ()
aens helpers: improve naming, add additional validations ()
babel: compatibility with create-react-app ()
babel: depend on buffer package in es build ()
babel: don't rewrite import of rlp package for @vue/[email protected] (
crypto: remove unused asymmetric encode/decode functions
aens: don't limit pointer keys
specify browserlist to better choice of features to transpile
aci: don't require source code
aci: don't require source code ()
aens: don't limit pointer keys ()
aens: enable commitmentHash preclaim in tests ()
decode using calldata package ()
commitlint issue ()
compiler errors: construct error message by server response ()
don't accept ak_ addresses as hash, bytes and signature ()
events: don't require function name for events decoding ()
specify browserlist to better choice of features to transpile
aci: don't require source code
make contractDeploy a wrapper, remove unused code
inline getConsensusProtocolVersion function
aci: don't require source code ()
decode using calldata package ()
encode using calldata package ()
poll-interval: reduce poll interval to be a more sensible default ()
compiler errors: construct error message by server response ()
events: fix event decoding order and address prefix ()
events: fix test for incorrect address return type ()
node errors: construct error message by server response (
Remove channel from universal stamp ()
drop following AENS delegation signature methods over the new common createAensDelegationSignature implementation which accepts an object as param ()
delegateNamePreclaimSignature
delegateNameClaimSignature
payForTransaction method ()
don't check is GA if innerTx ()
don't sent to blockchain if innerTx ()
change default gas limit to 25000 ()
AENS: name length minimum bid fee ()
delegate-signature: stop using the default account in the context of signing ()
mustAccountStamp: process accounts only if supplied ()
swagger https issue ()
swagger file of aeternity's compiler ()
swagger file of aeternity's latest compiler ()
crypto: remove outdated generateSaveWallet function
crypto: remove unused prepareTx, encodeTx, decodeTx functions
crypto: remove unused hexStringToByte function
crypto: rename messageToBinary to messageToHash adding hashing
export aepp-wallet-communication ()
ponyfill Buffer in browser ()
ponyfill process in browser ()
poi-tx schema: use proper type name ()
wait-for-tx-confirm: validate transaction height after awaitHeight ()
support [email protected] and above ()
avoid instanceof between possible not/polyfilled objects ()
revert conversion of case in calls to compiler ()
avoid ts definitions based on broken JsDoc ()
Iris compatibility (compatible with nodes >= 5.2.0 < 7.0.0)
initial TypeScript support (not enough type definitions yet)
documentation is generated using MkDocs on Travis
Drop old aepp-wallet RPC interface ()
refactor: don't retrieve account from process.env ()
refactor(crypto): don't reexport RLP methods ()
refactoring: remove legacy contractDecodeDataAPI compiler method ()
swagger: allow to provide external specification ()
swagger: make compatible with OpenAPI 3 ()
switch to v3 endpoints on Iris ()
traverse-keys: add keysOfValuesToIgnore option as a workaround ()
contract: fix default backend value ()
wallet-iframe: fix disconnect button ()
examples-browser: rearrange files and docs ()
use relative links between docs pages ()
use BigNumber constructor instead of custom wrapper ()
avoid extra object nesting ()
compiler: use swagger file ()
semver-satisfies: remove extra splitting by dash ()
traverse-keys: add missed null check ()
swagger: add workaround to get transaction details of GAAttachTx ()
top-block: use getTopHeader on Iris, mark deprecated ()
nonce-verification: add missed space (
Use ts-standard instead of standard ()
tsconfig: Set target version to es5 ()
Fix eslint errors manually ()
require node below 7.0.0 ()
Optimize height queries ()
simplify GA tests ()
oracle: avoid explicit waiting for 1 second ()
passing of forceCompatibility flag ()
contract: remove extra backend option ()
transferFunds: Accept onAccount option ()
bigNumberToByteArray: Avoid unexpected behaviour by throwing exception ()
example: Add disconnect button on wallet side ()
Use external version of json-bigint ()
Make tests configuration more flexible ()
test-else: Exclude aens tests and speedup jobs ()
Avoid unnecessary eslint-disable ()
Fix typo in Readme.md ()
wallet-detector: allow to connect wallet to aepp between iframes ()
Account: Build signature from transaction hash () ()
ACI: External contract integration () ()
Deps: Clean up repository ()
Env: Simplify Travis and docker-compose ()
Env: Remove unused packages ()
AEX-2: Handler always as Promise () ()
AEX-2: Add debug option for getHandler. Hide unknown message logs () ()
Contract Add AENS name resolver for Contract API
AEX-2: Fix isExtensionContext check () ()
AEX-2: Fix getBrowserAPI helper for cross-browser compatibility () ()
ACI: Event decoding () ()
AEX_2: Handle network switch and update state on both sides. Adjust networkId check for signing request. Add node switcher for example apps ()
example: Regenerate lock () ()
ACI: expose events decoding through Contract ACI stamp () ()
AEX_2: Allow to connect without node () ()
AEX_2: Connect to extension from iframe () ()
Build:
build Remove resolving of minimist using npx
Guide: Adjust guide for RPC Wallet/Aepp usage
RPC: Refactor rpc-related stuff ()
Build: Include amountFormatter and SCHEMA in bundle()
Examples Update examples apps
TX: Introduce new stamp TxObject()
This stamp give more flexibility on transaction serialization/deserialization process
Keystore: Allow to store secret as hex or buffer ()
AEX-2: Add permission layer for account management ()
TxBuilder: Fix fee calculation for Oracles () ()
AEX-2: Broken wallet detection ()
AEX: Simplify message id processing (). Pass AEEP origin to Wallet callback ()
Node: Move getNetworkId to helpers ()
ACI: Minor ACI validation improvement. Move decoding of events to builder. Add ability to decode events without ACI
ACI: Implement Contract Events for ACI()
Contract: Helpers for Oracle and AENS signature delegation()
AmountFormatter: Rework amount formatter. Change formatter units naming. Add more units () ()
TxBuilder:
AEX-2: Fix firefox compatibility issue () ()
Chain: add new method waitFOrTxConfirm. Add new option { confirm: 3 } to all of high lvl SDK API. Add tests. Adjust docs () ()
Compiler: Add new compiler methods API () ()
network: Throw error when can not get networkId () ()
Guide
Guide: Add , and guides
Please check out
This release include all changes from , ,
aens: implement aensExtendTtl function. Refactor aensUpdate () (), closes
aensUpdatenow accept array of pointersaensUpdatehave new optionextendPointers=falsewhich retrieve pointers from the node and merge with provided
Build: update node to 5.4.0 and compiler to 4.2.0
AENS: Change AENS methods arguments
Now all of AENS module methods accept
nameas a first argument instead ofnameId
codecov: Adjust codecov badge. Move @babel/runtime to dev-deps () ()
AEX-2: Fix getBrowserAPI function for firefox ()
Account: Add ability to pass keypair or MemoryAccount as nAccount` option () ()
Test: Increase code coverage () ()
Chain: Extend transaction verification error ()
Guide: Add guide for Contract ACI usage ()
Contract/Chain: Using { waitMined: false } with Contract high lvl API () ()
HdWallet: Fix derive function () ()
Compiler: Filter compiler options
Cross-Node: Remove cross-node compatibility code () ()
Chain: Handle time until tx is not added to mempool ()
Git: Update issue template()
Flavors: Remove deprecated code (
Wallet<->AEPP: Add new Wallet<->Aepp communication API
Add two new stamps
RpcWalletandRpcAeppExample of usage you can find heere: and
Wallet: Use postMessage for communication with extension wall… () ()
Tx: By default sdk make a transaction verification
Node: Change node compatibility range to node >= 5.0.0 && node < 6.0.0
Compiler: Drop compiler version to version >= 4.0.0 && version < 5.0.0
Channel: 5.2.0 compatibility ()
Composition: Chain composition ()
ACI: Disable bytecode check for source and code on-chain. This changes will be included in next major release () ()
KeyStore: Remove argon2 package, use libsodium for both browser and node () ()
AENS: auction end block calculation () ()
AENS: Fix produceNameId function(Make name lowercase). Enable … () ()
state channels: wait for connection to be established before sending generic message () ()
ACI: Add validation for contractAddress () ()
AENS: Add nameFee validation to TxValidator () ()
AENS: Increase default nameTtl () ()
Contract:
name claim: Revert ignoring waitMined from user passed options (#727)
aens: added lower case transformation for aens names () (), closes
SPEND: Add additional validation for recipient () ()
State Channels: make state channels compatible with node v5.0.0… () (), closes
AENS: Change tld for Lima from aet to chain () ()
AENS: Implement name bid
AENS: Change tld for Lima from .aet to .chain
rpc: fix resolution rpc ops () ()
ACI: rework Sophia Option type representation () ()
AENS: Add ability to spend by name () ()
AENS: Add ability to claim contract, oracle, SC () ()
GA: enbale GA () ()
Lima: Lima compatibility (
aci: Change Sophia option type representation in ACI
package: update serialize-javascript to version 2.0.0 () ()
Contract/ACI Add payable feature
Compiler: Compiler 4.0.0 compatibility () ()
Contract/ACI: Add ability to use contract with external namespaces(include "someLib") () ()
Oracle: Add methods for polling queries
Chain: Add getBalance method () ()
state channels: add reconnect method () ()
Compiler: Fix forceCompatibility option ()
Lima: add preliminary support for lima
ACI/Contract: Implement static-call for deploy transaction for ACI methods/Contract low lvl API () ()
GA support has been disabled until further notice due to node compatibility issuesThis version support aeternity node up to 5.0.0-rc.1
Example Add node info to AEPP ()
GA Fix GA account composition ()
Crypto: Fix keypair verification () ()
RPC: Remove NodePool stamp from AE composition () ()
state channels: add missing argument in onOnChainTx callback () ()
MemoryAccount: Add validation of keypair () ()
state channels: handle BigNumbers with json-bigint () ()
state channels: send generic messages immediately () ()
Generalize Account
Package: update commander to version 3.0.0 () ()
Contract: Fix dry-run without account ()
Contract: add ability to use call-static/dry-run without keyPair () ()
AE: Add ability to make operation on specific account using onAccount option.
JSON:: Add serialization to JSON for bigNumbers
State Channels: Fix onChainTx event params () ()
State Channels: Fix websocket url () ()
Swagger: Pass query params in case of get request ()
State Channel: Do not include white space for outgoing websocket messages ()
ACI: Implement sophia variant type () ()
Contract: add ability to use call-static/dry-run without keyPair () ()
NodePool: Implement NodePool stamp () ()
ACI Add some additional clarification to getContractInstance
package: update libsodium-wrappers-sumo to version 0.7.5 () ()
rpc-server: Fix type 'object' check () ()
swagger: Speedup initialisation
AENS: Remove unused param from claim method
AENS: Fix exception if not waiting for mining(claim)
Test: Add test for contract namespaces
Node: Add 4.0.0 node compatibility
Compiler: Add compatibility with compiler 3.2.0
Channel: Implement GA awareness of State Channels
Node: Do not throw error if internalUrl not provided. Instead use url () ()
TXBuilder: Fix payload serialization if you try to unpack and pack tx. () ()
TxValidator: Fix validation of state channel open transaction () ()
ACI: Refactor ACI module. Split to separated files. () ()
Selector: If default account address not provided use the first
ACI: Handle ACI without init function
Usage:: Add instructions about how to include directly the SDK in a html page
RPC: Add contract contractDecodeCallResultAPI to RPC () ()
README: Fix flavor link ()
Compiler: Fix compiler compatibility mechanism () ()
Utils: Move json-bigint implementation to utils () ()
webpack: Add another bundle(dist/aepp-sdk.browser-script.js) for using in <script> tag ()
Ae: Fix exception when it used without Contract stamp
SCM: Update compatibility range for node: 3.0.1 - 4 and compiler 3.1.0 - 4 () ()
Test: Simplify client creation
Docs chore(Docs): new docs ()
Compiler: Add getCompilerVersion to compiler stamp
ACI: Make compatible with compiler 3.1.0 () (), closes
DOCS Restructure and rework sdk documentation
SCM: This change will make the release not compatible with older version of the node and compiler
ACI: Change Contract low lvl API:
change contractDecodeData
Deps: Update axios lib to 0.19.0 due to security issue ()
State Channels: Remove automatic pinging to fix browser compatibility () ()
Transaction Builder: Improve min fee calculation(Reduce the fee) ()
AXIOS: Add ability to intercept error from axios ()
Added additional param to sdk initialization
axiosConfig
Example:
Universal({ axiosConfig: { config: { // axios config object }, errorHandler: (err) => throw err }})
AEP exampe: Fix contract in AEPP example () fix(AEP exampe): Fix contract in AEPP example
Consensus: Add function to get consensus version. () ()
State Channels: Make state channels compatible with aeternity 3.0.0 () ()
Transaction Builder: Add serializations for transactions introd… () ()
NODE Change compatibility from 2.3.0 to 3.0.0
Joi: Add JOI browser comparability
ACI: Add ability to pass zero address as number. () ()
ACI: Fix address type transformation when decoding data () ()
Contract: Add error handling(decoding) in low lvl contract API () ()
KEYSTORE: Add browser compatibility
TX: Handle VM/ABI fields serialization and validation basaed on tx type and node version
ACI: Add contract, address, record types argument/result transformation () ()
State Channels: Endpoint param is removed and no longer defaults to "/channel". This means that "/channel" (or other path) must be appendend to url para
ACI: Fix address type transformation when decoding data () ()
ACI: Add contract, address, record types argument/result transformation () ()
ACI: Update due to compiler API changes () ()
Aepp: Add Compiler to Aepp rpc methods. Update example app () ()
ACI: Fix address type transformation when decoding data () ()
TX_BUILDER: Channel tx serializations
TxValidator: Add minGasPrice validation to contract transactions
ACI: Update due to compiler API changes () ()
Aepp: Add Compiler to Aepp rpc methods. Update example app () (
ACI Remove 2.0.0 compiler compatibility
ACI: Add transform decoded data for 'address' type
AEPP: Add Compiler to Aepp rpc methods. Update example app
Channel: Add call contract static support
Channel: Add get contract state support
HTTP: Handle no response in http stamp error handler
Crypto: Fix crypto formatAddress
Crypto: Move ADDRESS_FORMAT to crypto
Channels:
channel.state() now returns offchain state instead of last co-signed offchain transaction
channel.update(...).state has been renamed to signedTx
Chore: Install and configure commitizen
Crypto: Add formatAddress function to Crypto
Contract: Add Contract Compiler API stamp to es/contract (now using instead contract node API)
Contract: decode node error coming from contract call and callStatic
Chain: Throw native error instead of object in chain chain.sendTransaction
Crypto: fix arguments parsing in Crypto.sing
Contract: Remove ContractNodeAPI stamp
Contract: Change Contract stamp API
Contract: Change default gasPrice from 1e6 to `1e9z
AEPP: Fix AEPP example app
Build: Force image pull before builds
Oracle: Oracle fee calculation
Tx: getAccountNonce function to tx stamp
TX_BUILDER: Change FEE_BYTE_SIZE from 1 to 8 bytes in fee
Node: Minerva comparability
Utils: Mnemonic wallet implementation es/utils/hd-wallet
Oracle: Change Channel legacy API to JSON RPC
Node: Change supported node version range to 1.4.0 <= version < 3.0.0
This release contain changes from: , , ,
Channel: channel withdraw and deposit methods
TX_BUILDER: Change default gasPrice in Contract stamp and Tx stamp to 1e9
TX_BUILDER: Add deserialization schema for Channel transactions(channelCreate, channelCloseMutual, channelDeposit, channelWithdraw, channelSettle)
Chain: Add rawTx
Chore: Fix linter errors
Node: Minerva comparability
Utils: Add Mnemonic wallet implementation es/utils/hd-wallet
Node: Change supported node version range to 1.4.0 <= version < 3.0.0
TX_BUILDER: Add unpackedTx, txType and signature to validate transaction function
Contract: Add top param to contract static call(dry-run)
Rpc: RpcServer: Avoid storing of window in instance properties
Chain: Disable balance formatting by default
Chain: Move verification of transaction
TX: Remove old transaction builder es/tx/js.js (Please use es/tx/builder instead)
Chore: Rename es/epoch.js to es/node.js
Chore: Rename Oracle
Ae: Add destroyInstance function to Ae stamp which remove all listeners for RPC event's
Docs: Add docs for TransactionValidator and TxBuilder stamp's
Build: Add TxBuilderHelper
Docs: Adjust doc's for Contract and Aens stamp's
Chore: Fix decoding of address from contract call
Build: Remove KeyStore from bundle due to build issue(for now you can export it only using tree-shaking import * as Keystore from '@aeternity/aepp-sdk/utils/keystore')
Channel: Add support for State Channels
TX_BUILDER: New transaction builder going through schema(build, unpack)
TX_VALIDATOR: Add new stamp TransactionValidator which can verify your transaction
Chore:
Old transaction builder es/tx/js.js will be removed in next major release.
Chain: amount formatter
Chain: amount format balance client.balance('AK_PUBLICKEY', { format: true })
Aepp: Oracle and Contracts API to Aepp stamp
Chore: Use
Chr: Fix Import RLP package (thanks @davidyuk)
Rpc: Fix for NetworkId propagation and override
Tx: TxJS is not a stamp anymore, and instead: it exports helper functions
Tx: TxJs stamp (not a stamp anymore)
Chain: balance now answer a formatted string composed of AMOUNT + ' ' + unit (eg. 10 exa for 10 AE)
Chore: 10 exa should be 10 ae
Chain: format shouldn't be a flag, but a request for unit eg. { format: ae }
Chore: isAddressValid check
Tx: Tx Fee formulas
Rpc: Fixed networkId propagation (and overriding on init of Flavors)
Crypto: Fixed encodeBase58Check by feeding Buffered input
Chore: Compatibility with Node >= 1.0.0 and <= 1.1.0
Rpc: Added a command to remove images after CI testing
Rpc: Fix Testing
Rpc: Fixed Oracle error for Wallet flavor
Oracle: Oracles functionality and flavor
Aepp: Simple example of aepp-in-aepp (see /examples folder)
Tx: Fixed issue with big numbers and TX
Node: ability to support Node range(s) using semver package (see https://www.npmjs.com/package/semver#ranges)
Node: Support for Node >= 1.0.0 and < 2.0.0
Contract: Contract native Transactions
BigNumber: Rolled back to bignumbers.js for easier fix with axios.get/post
Node: Support for Node < 1.0.0
Build: New NETWORK_ID (also used in docker/sdk.env for CI tests)
Protocol: Encoding of transaction (and other objects)
Channel: State Channels have been excluded for problems with CI, will be included in next release
Chore: See [0.25.0-0.1.0]
Utils Parsing of fee using bignum.js
Account Add networkId as param to Account flavor(default: ae_mainnet)
CLI and moved to separate repos and packages
Node Support for < 0.25.0
Contract Contract type checked call (Ability to call contract using contract address)
Contract Use ES methods instead of Ramda, where possible
Contract Fixed keystore by adding a salt param for derivedKey function
Contract Support for < 0.25.0
Contract Aens use domain .test instead of .aet (see )
Contract Use NETWORK_ID for signing (see )
Rpc RPC Client improvements
Rpc onContract Guard
CLI born
CLI Host
Chore The Cli flavor is now Universal
Chore the keypair keys changed from { pub, priv } to { publicKey, secretKey } for consistency with other systems using them (eg. AirGap and )
Chore CLI and AE PROJECT CLI will move to a separate package
Node Full support of
CLI Develop decode base58 address command in crypto module
CLI Add nonce param to all tx command's
Node Support for < 0.24.0
Keystore ethereum keystore usage will be removed in the next release
CLI CLI will move to a separate package
CLI Add CLI implementation
Crypto nameId function for commitment hash calculations
Node API endpoints to meet new Node specifications
Tx Add Nonce calculation on SDK side
Crypto Fixes commitment hash calculations in naming system, to be Hash(nameId(name) + name_salt) instead of Hash(Hash(name + name_salt)).
Node Support for < 0.22.0
Docs Lots of new documentation (prose and API)
Docs Fancy badges to README
Build Transitive dev dependencies for standard-loader not covered by pnpm
Build CI Dockerfile to include pnpm
Node Support for Node 0.18.0 (changed endpoints)
RPC Wallet/Aepp RPC support
Contract Contract call result decoding support
Docs Per-module API documentation (Markdown based on JSDoc)
Crypto Symmetric key encryption/decryption
Node Support for < 0.18.0 (changed endpoints)
Node Legacy Swagger file loading
Node Compatibility with < 0.15.0
Contract Contract unit state initialization
Node Missing required parameter for name transfers (workaround for)
API New, opinionated top-level API
API Rest of legacy API now uses new API as well
API Generated API now encapsulated in api object
API Automatic case conversion for remote parameter names
API [GH-49]: Handle existing path components correctly
API Remove Oracle API (for the time being)
API Remove Legacy API and tests
API Remove Compatibility with older versions of Node which provide the transaction hash the old way
Node Switch to curve ed25519 (from secp256k1) to align with Node protocol changes
Node Generate basic API directly from Swagger files, also validate input data
Build Compiled library now self-contained with all dependencies
Build Use Webpack 4 based cross-platform (Node/Web) compilation
Node Defunct scripts; will be brought back later
Chore More consistent code examples
aens: make getState's options override instance options (2e0d672)
aens: mark started_at as required in auction details (fba1012)
chain: set correct poll interval on hyperchain (0454c62)
contract: type checking of contract call return value (4c8926b)
middleware: generate api based on 1.97.1 (359c17a)
node,middleware: more strict enum handling (d3c5f0f)
tx-builder: replace OracleResponseTx with OracleRespondTx (19ec9b3)
wallet: don't require debug flag in BrowserRuntimeConnection (997db99)
middleware: require 1.81.0
sdk requires [email protected] or newer
sdk types requires [email protected] or newer
account: Save HD wallets methods removed
account: sign, signMessage removed
account: isValidKeypair removed
account: getAddressFromPriv removed
account: generateKeyPair removed
account: generateKeyPairFromSecret removed
recover, dump removed (AEX-3 keystore implementation)
node,compiler,middleware: $host is readonly in generated APIs
account: MemoryAccount accepts secret key as sk_-prefixed string
account: generateKeyPair returns secretKey encoded as sk_-prefixed string
aepp: RpcBroadcastError not exported anymore
NAME_BID_MAX_LENGTH not exported anymore
contract: encodeFateValue, decodeFateValue not exported anymore
Iris is not supported
middleware: sdk requires [email protected] and above
node: sdk requires aeternity node 7.1.0 and above
account: AccountBase inheritors required to implement signTypedData, signDelegation
signDelegationToContract removed
signNameDelegationToContract removed
signAllNamesDelegationToContract removed
signOracleQueryDelegationToContract removed
wallet,aepp: delegations used in Iris removed from aepp-wallet connection
createDelegationSignature removed
compiler: CompilerCli uses aesophia@8 by default
compiler: CompilerCli8 removed
compiler: CompilerCli and CompilerHttp requires aesophia@8
aens: aens* methods removed
tx-builder: NAME_*TTL, CLIENT_TTL not exported anymore
oracle: pollQueries don't return responded queries by default
oracle: pollForQueries method removed
oracle: extendOracleTtl method removed
oracle: respondToQuery method removed
oracle: getOracleObject method removed
oracle: registerOracle method removed
oracle: getQueryObject removed
oracle: postQueryToOracle, pollForQueryResponse methods removed
tx-builder: ORACLE_TTL, QUERY_TTL, RESPONSE_TTL not exported anymore
tx-builder: buildTx/unpackTx works only with transactions
tx-builder: Tag include only transactions
tx-builder: buildTx doesn't accept prefix anymore
contract: AeSdk:initializeContract removed
account: expose secretKey in MemoryAccount (d4320e6)
aepp: add api to ask wallet to select network (9871c91)
aepp: extract class to connect to wallet from AeSdkAepp (c3570ac)
middleware: add requestByPath method (ee5ac0c)
middleware: allow navigate to next/prev pages (b89cf5b)
middleware: mark as stable api (e25b06d)
middleware: prefixed types provided by OpenApi instead of strings (0b16a32)
middleware: return time as Date instance (e48ffd1)
middleware: switch to v3 api (b0015c0)
node: return time as Date instance (e0e33ea)
oracle: add includeResponded option to Oracle:pollQueries (78a07ab)
oracle: add Oracle:handleQueries method (03c77c0)
channel: accept host only if initiator (a7d4dde)
channel: reestablish flow (1f4a0c1)
channel: remove statePassword unsupported on node side (5cec07b)
channel: remove unsupported ways to reopen channel by a transaction (f3746a1)
middleware: accurate coin amounts (00a4f3e)
middleware: word casing in activity types (f1fbb29)
node,compiler,middleware: mark $host as readonly (9e47d5c)
node: avoid complex types by code replacements instead generics (4f531b1)
oracle: emit unhandled rejection instead printing error (3a57665)
tx-builder: count amount in execution cost when spend to yourself (5153649)
tx-builder: remove unused ChannelClientReconnectTx (e6e954a)
wallet: generate random string instead using external uuid dep (f8640d4)
wallet: origin if opened over file:// (cordova) (d529f30)
account: remove getAddressFromPriv (9446639)
account: remove isValidKeypair (512385a)
account: remove sign, signMessage (30077bc)
account: remove save HD wallet functions (10e7c89)
aens: replace aens methods with Name class (956daac)
aepp: remove RpcBroadcastError (1f0b3bb)
compiler: drop aesophia@7 support (df0e050)
contract: don't depend on Contract in AeSdk (00b4f86)
contract: remove encodeFateValue, decodeFateValue (c521597)
drop Iris support (61554b3)
drop [email protected] support (4008d12)
middleware: require 1.77.5 (08783fd)
middleware: require 1.81.0 (3243768)
node: require 7.1.0 (0dd3b49)
oracle: add Oracle class (54ee614)
oracle: add OracleClient class (0293fe4)
oracle: replace getQueryObject with OracleBase (bcab498)
remove createDelegationSignature (651b6ec)
remove NAME_BID_MAX_LENGTH (83797a4)
remove signAllNamesDelegationToContract (60a729d)
remove signDelegationToContract (cd495a6)
remove signNameDelegationToContract (9ab8f41)
remove signOracleQueryDelegationToContract (f948492)
remove keystore implementation (5e64ec9)
rename legacy bundles to cjs (46cd27b)
require [email protected] or newer (84d868c)
tx-builder: extract entries into separate builder (d5fde18)
tx-builder: remove deprecated constant exports (2ecf0f4)
tx-builder: remove deprecated constant exports (2342aa6)
update @types/node, drop TS below 4.8 (9d36e6c)
wallet,aepp: remove delegationToContract.sign method (c4d62b0)
channel: accept host only if initiator (cfdfd72)
channel: remove statePassword unsupported on node side (74db9bb)
don't allow upgrades @azure/core-rest-pipeline (03058d4)
don't allow upgrades @ledgerhq/hw-transport to 6.31.0 (1ef43e6)
wallet: origin if opened over file:// (cordova) (4ee44be)
chain: add cache option to getHeight (c7d0955)
compiler: add CompilerCli8 class (29f1cd3)
compiler: provide compilation warnings (d0ec012)
compiler: update cli and http compilers to 7.4.0 (2041d8b)
contract: resolve names on node side in Ceres (474f0fd)
contract: support all names delegation to contract (92dae86)
jwt utilities (c747ce6)
node: add param indicating retry (6f0dbd8)
node: show error code if available (2cce91d)
spend to payable contract (7621716)
support new delegation format in Ceres (786e954)
tx-builder: get actual gas price from node (09d19bf)
tx-builder: pick queryFee from the node if not provided (ca495c8)
tx-builder: reject used accounts in GaAttachTx in Ceres (88b1d5d)
tx-builder: validate nameTtl in NameUpdateTx (bca877e)
contract: don't duplicate NoSuchContractFunctionError message (2f3bba5)
improve error message when no wrapped value (054bc89)
node,middleware,compiler: version check if deployed at path (450296e)
node,middleware: remove duplicate retry policy (f6470a2)
node: add missed conversion of difficulty and hashrate to number (271ff5e)
node: don't remember failed version request (fba0e79)
node: show correct error message if body is missed (ed10482)
node: show correct error message if ECONNREFUSED (ef347a1)
tx-builder: don't accept ttl equal to block height (d9cde12)
tx-builder: don't estimate gas for non-transactions (f72167a)
tx-builder: limit ttl to 3 in case tx built internally (08d14c2)
tx-builder: remove invalid oracle tx type in validator (78e7c48)
contract: use current nonce in static calls (758bdfc)
node: don't retry 500 code responses (696e7db)
node: throw clear error message if unsupported protocol (21dfe34)
node: uncatchable exception if request failed in queue (dec62a4)
typos in error messages and docs (5c84671)
aepp,wallet: support signing typed data (78ce3b2)
compiler: add generateAci, generateAciBySourceCode (981bcf2)
middleware: generate autorest wrapper (bd08a08)
middleware: implement MiddlewareSubscriber (b51b0a3)
contract: use fallback account if onAccount not provided (9033cd7)
converting proxied options to JSON (efebbd1)
provide types in exports field of package.json (dbd19e7)
reject prefixes other than provided in isAddressValid (9462add)
tx-builder: buildTx produces the same type as unpackTx accepts (d3d6c88)
tx-builder: decode tag in entry error message (db0d96f)
wallet: emit internal error if something broke while broadcast (332d1b5)
wallet: throw reason of internal error to handle it in wallet (276699b)
AeSdk.getContractInstance renamed to AeSdk.initializeContract
getContractInstance function replaced with Contract class
Contract methods accessible on the instance itself
contract.methods.<name>.get,send removed
contract.bytecode,sourceCode moved to contract.$options
contract.calldata renamed to contract._calldata
contract.deployInfo removed
contract.options renamed to contract.$options
contract.decodeEvents renamed to contract.$decodeEvents
contract.call renamed to contract.$call
contract.compile renamed to contract.$compile
contract.deploy renamed to contract.$deploy
use sourceCode instead of source
getContractInstance accepts address instead of contractAddress
prepareTxParams, getVmVersion are not exported anymore
isGA method removed
TX_TTL not exported anymore
sync buildTx accepts denomination in the first argument
Enum FIELD_TYPES is not exported anymore
Not able to build/unpack CompilerSophia entry (tag 70)
Enums PROTOCOL_VM_ABI, interface CtVersion not exported anymore
Enums VM_VERSIONS, ABI_VERSIONS, PROTOCOL_VERSIONS renamed
stateHash of Channel entry decoded as st_-prefixed string instead of hex
key of MtreeValue entry decoded as a buffer instead of a hex
SpendTx payload doesn't accept arbitrary strings anymore
unpackTx return an object of transaction parameters
unpackTx doesn't return rlpEncoded anymore
verifyTransaction doesn't accept parent tx types anymore
TxBuilder accepts and returns poi field unpacked as TreesPoi
buildTx accepts transaction type and version in the first argument
buildTx return string instead of object
buildTx doesn't return txObject anymore
buildTx doesn't return binary anymore
buildTx doesn't return rlpEncoded anymore
buildTx doesn't accept excludeKeys option anymore
Use version instead of VSN, vsn in unpackTx, buildTx
txType property of unpackTx removed
get method of MPTree accepts and returns typed values
writeInt function removed
returnType of contract call result structure is a value of CallReturnType enum
writeId, readId functions removed
readPointers, buildPointers functions removed
formatSalt function removed
validateParams, unpackRawTx functions removed
AMOUNT constant removed
Dropped compatibility with aesophia_http below 7.1.1, aesophia_cli below 7.0.1
AccountMemory requires networkId in signTransaction
AccountBase simplified
address in AccountBase is a property
MemoryAccount accepts only secretKey
MemoryAccount is not compatible with GA
oracle.pollQueriesgetAddressFromPriv doesn't accept private key as base64-encoded or raw stringisValidKeypair doesn't accept public key as base64-encoded string
bytesToHex function removed
hexToBytes function removed
rename umd export to Aeternity
Subpaths imports of SDK are not allowed
Removed getNetworkId from AeSdkBase
address a getter in AeSdkBase
addAccount is a sync function
verifyMessage removed from accounts and AeSdkBase
verify and verifyMessage accepts address instead of hex string or Uint8Array
node@12 not supported
removeAccount throws an error if the account is not found
signMessage always returns Uint8Array
encryptKey, decryptKey are not exported anymore
sha256hash not exported anymore
height method removed
signUsingGA method removed
POINTER_KEY_BY_PREFIX removed
ID_TAG_PREFIX, PREFIX_ID_TAG, ID_TAG removed
TX_TYPE removed.
GAS_MAX removed
calculateMinFee removed
salt, createSalt removed
Pointer removed
getBalancechannel: emit newContract event (8d71bba)
contract: add ability to compile by path in node.js (74867b7)
contract: add CompilerCli (de56cbe)
contract: allow to create GA using sourceCodePath, bytecode (9410af2)
contract: decode emitted events of contract deploy (bf46eb6)
contract: don't require compiler (d2f9fa8)
contract: extract $getCallResultByTxHash method (0a8d138)
contract: support unit type (b5bf7a8)
node: exponential retry of requests on failure (aadec0d)
setup downleveled types for [email protected] and above (fd2b97f)
support CERES protocol version (8960a91)
tx-builder: deserialisation of channels.get.offchain_state (ed31aff)
tx-builder: implement buildAuthTxHashByGaMetaTx (bd656c2)
tx-builder: implement getExecutionCost and related functions (33085c2)
tx-builder: implement getTransactionSignerAddress function (2360cd2)
tx-builder: support incomplete MPTrees (115bcf5)
tx-builder: support recursive types (4f4dff6)
tx-builder: typed decoding of MPTrees (da1e35a)
tx-builder: unpack poi field of channel CloseSolo Slash tx (4a49b03)
tx-builder: validate address and enum fields in runtime (5898b3a)
account: add generate method to MemoryAccount (e0fa641)
add Ledger HW support (587e058)
ensure that used correct account type while signing transaction (46e8db3)
extract AeSdkMethods class with minimal interface (fd0fe76)
restore the ability to specify an array of accounts in AeSdk constructor (aba9b9f)
contract: avoid any in arguments (70453f1)
contract: don't mark event field as required in Aci (2c44cd1)
contract: dry-run accept top as number (ebe5986)
contract: static call at specific height (99441dd)
contract: type of FunctionAci (0929304)
node: don't throw unhandled exception if version check failed (d4e5250)
oracle: ask height right before querying oracle to avoid not found (42706ca)
oracle: import getHeight instead of using a missing context (565c827)
tx-builder: calculation of gasLimitMax (0fb8a37)
tx-builder: don't check consensus protocol if sdk knows a single (6b8888b)
tx-builder: drop nonce validator to avoid false positive (a669aae)
tx-builder: ensure that TX RLP have the same length as schema (c042d73)
tx-builder: field DelegateIds in ChannelCreateTx (405243c)
tx-builder: provide proper type depending on checks being done (3cff062)
wallet: don't use Event.hasListeners that is not available in FF (05c0424)
wallet: explicitly convert error to JSON to don't pass stack trace (3948153)
wallet: provide origin on webext side instead of empty string (662d8d0)
channel: log field type in result of getContractCall (600d9e7)
channel: add missed types for minimumDepth, fee, gasPrice (a14ddfc)
channel: emit incoming message handler error instead of printing (d71efad)
channel: messageQueue type (1197ec4)
contract: don't throw ambiguous error if event types the same (669c326)
contract: don't throw error if already compiled (dcedb61)
contract: more specific error on calling without address (5c5a241)
don't swallow errors without checking their type and message (7456b0f)
don't use any in AeSdkBase constructor options (51fd3ae)
sync options between Contract and AeSdkBase (6acebaf)
tx-builder: avoid extra requests in tx validator (03c77e5)
tx-builder: mark nameTtl as shortUInt in NameUpdateTx (3bfbb52)
tx-builder: type of binary fields (e979224)
use crypto random to generate salt (88dcf38)
channel: handle round as number (97d7984)
getNetworkId throw proper error without node (3d9e73c)
move type packages required by TS projects to dependencies (90c5eb8)
node: avoid ts-expect-error missed in generated d.ts file (60d9755)
node: don't transform autorest properties (7982327)
Node: tread nameTtl, clientTtl as number (b82c398)
pollForQueryResponse: poll until query is expired (436f4a9)
sendTransaction: don't fall if onAccount missed in AeSdkBase (eebbcb7)
switch to aepp-calldata with fixed decoding of lists (c1a3b24)
AccountBase and inheritors are classes now
ChainNode, Contract, Oracle, Aens, Ae, GeneralizedAccount stamps not exported in
the root, their methods exported instead
getNetworkId ignores force option
api and static properties are removed in Node
Node returns BigInts for coin amount fields instead of string or number
Node not accepts internalUrl
removed mempool method in Node
compilerVersion is removed in Compiler
setCompilerUrl changes compiler URL in sync
methods of Compiler requires options object according to their specification
methods of Compiler returns and accepts keys named in camelCase instead of snake_case
gas renamed to gasLimitunpackTx not accepting transaction as Buffer, only as tx-encoded string
unpackTx doesn't have binary field in result
encode: since the prefix is evaluated by the type itself the required prefix parameter is no more accepted
calculateMinFee returns BigNumber instead of string
Fee helpers not exported anymore (BASE_GAS, GAS_PER_BYTE, KEY_BLOCK_INTERVAL,TX_FEE_BASE_GAS, TX_FEE_OTHER_GAS, calculateFee, DEFAULT_FEE)
buildRawTx, calculateTtl not exported anymore
TX_TYPE mapped to tag (number) instead of string
OBJECT_ID_TX_TYPE not exported anymore
TX_SERIALIZATION_SCHEMA combined with TX_DESERIALIZATION_SCHEMA
Transaction schemas doesn't contain tag anymore
removed ensureNameValid
name.update, name.revoke doesn't accept address in onAccount, only instances of AccountBase
createGeneralizedAccount is requiredfilesystem option renamed to fileSystem
Contract instance doesn't accept address in onAccount, only instances of AccountBase
NodePool, AccountMultiple are removed (reimplemented in AeSdk)DENOMINATION_MAGNITUDE not exposed anymore
The result of unpackTx returned instead of TxObject (in txObject option of onSign handler
on wallet side; in tx field of contract call result)
validateKeyObj removed
deriveKeyUsingArgon2id removed
removed extra implementation of getAddressFromPriv in keystore
genSwaggerClient removed
RpcClient: sendMessage is a private method
RpcClient: handlers parameter is removed
RpcClient: doesn't contain aepp info anymore
RpcClient: doesn't contain networkId anymore
RPC helpers are not exposed anymore (isInIframe, sendMessage, getHandler, message,responseMessage, sendResponseMessage, isValidAccounts)
doesn't accept connection anymore
removed isConnected, isSubscribedAccount methods
signMessage returns Buffer by default
shareWalletInfo accepts rpcClientId instead of callback
shareNode argument in accept callback of onConnection removed
can't handle specific set of accounts for an app
txObject parameter of onSign callback is removed
callbacks accepts aeppId, params, and origin
rpcClients in wallet is not exposed anymore
onDisconnect callback on wallet side accepts client id instead of RpcClient
wallet can't selectively notify aepps about selecting/adding account
wallet can't provide metadata for accounts
removed action.{accept,deny} in permission callbacks
ae: drop stamps and use plain functions (8ed55d0)
aepp rpc: accept wallet info separately (baad98e)
aepp-rpc: depend on simplified version of RpcClient (f329549)
aepp-rpc: extract common error checks (eaa8683)
aepp-wallet: rewrite to ts all except rpc (19cb42f)
AeppRpc: make to init in sync (86c9d6c)
chain: drop stamps and use plain functions (4197b3d)
chain: remove deprecated methods (cefaa55)
compiler: extract genVersionCheckPolicy (ac14fd1)
don't provide default fee when transaction is not present (b004694)
drop ensureNameValid (d0d1258)
drop compiler stamp (ddf1363)
drop functions to generate txs with specific type (3cf767d)
drop TxObject wrapper (a083c7b)
encoder: remove required prefix param (dec13d7)
export in tree shaking friendly way (40aca86)
extract all fee-related stuff into a separate module (cebb90b)
extract base sdk classes (487cc14)
fix spend types (6b089e7)
getNetworkId: drop unnecessary force option (7d6549a)
getQueryObject: remove deprecated decode method (7e9835c)
inline NAME_BID_TIMEOUTS into computeAuctionEndBlock (5fdb80e)
NodeApi: return BigInt instead of string | number (7f37e74)
node: drop internalUrl (8336673)
node: rewrite to ts, drop stamp (370635e)
oracle: drop stamps and use plain functions (04ce814)
prepareTxParams: inline calculateTtl (2f03793)
remove ability to connect without sharing node if requested (7dd4af5)
remove extra getAddressFromPriv (0f88c39)
remove getAccountNonce (62a00e5)
remove outdated destroyInstance method (0213375)
rename gas to gasLimit where possible (dece758)
rewrite AE_AMOUNT_FORMATS to enum (448a2a3)
rewrite ae/contract to ts (8159d84)
rewrite TX_TYPE to enum (f97e479)
rpc account: don't pass extra options through rpc connection (141e932)
rpc-client: add notify method (9e97a1a)
rpc-client: provide method handlers instead of onMessage (5f1a007)
RpcClient: remove custom set of accounts (5c26f3a)
RpcClient: remove origin property (7155ed3)
rpc: inline extra helpers (9a0a2eb)
rpc: use webextension-polyfill (a54fdfd)
simplify transaction schema (5f720ec)
tests: migrate remaining tests ts (4e2ece7)
tx schema: add shortInt type for fields not needed big numbers (0095455)
unpackTx: accept only tx_string, don't return binary (658adee)
use calculateMinFee instead of calculateFee (4ea59d7)
utils: migrate keystore.js to ts (c013c01)
wallet rpc: don't pass networkId from aepp to wallet (153fd89)
wallet-rpc: drop info object in RpcClient (010ebbb)
wallet-rpc: remove meta, condition unused by known wallets (4630643)
wallet-rpc: return value/throw error instead of accept/deny (98b9955)
wallet-rpc: rewrite to TypeScript (930e7d7)
wallet-rpc: simplify callback arguments (5fc6f8a)
wallet-rpc: store rpc data in maps instead of objects (0d3f04f)
wallet-rpc: switch to TypeScript version of RpcClient (7d8f6d7)
crypto: make (encode/decode)Base(58/64)Check private
use bs58 instead of bs58check
update rlp to 3.0.0
tx builder: throw exception if deposit is not zero
tx schema: remove default NAME_FEE equal to 0
tx builder: accept unencoded name in nameClaimTx
spelling of GeneralizedAccount
aci: remove call/callStatic from deployInfo
aci: remove createdAt property generated at client
contract: remove deprecated contractCallStatic
contract: remove deprecated contractDeploy
contract: remove contractCompile
contract: remove deprecated contractCall
remove deprecated topBlock
remove unused functions
contract events: remote contract support
contract instance: store aci as it is
wallet-rpc: inline resolveOnAccount helper
aepp-wallet schema: convert to TS
aepp-wallet schema: rearrange METHODS enum
aepp-wallet schema: remove unused enums
contractCompile: remove encodeCall
compiler: remove contractEncodeCallDataAPI
compiler: remove getCompilerVersion
contract: remove compileContractAPI
contract: remove contractGetACI
contract: remove contractDecodeCallDataByCodeAPI
contract: remove contractDecodeCallDataBySourceAPI
contract: remove contractDecodeCallResultAPI
compiler: remove validateByteCodeAPI
compiler: remove getFateAssembler
compiler: remove getBytecodeCompilerVersion
poll: avoid extra transaction info request to node
drop https scheme workaround for hosted compiler
node: don't wrap internal endpoints if internalUrl missed
tx builder: inline VALIDATION_MESSAGE
decodeEvents: accept event schemas as it is in ACI
contract: remove already processed fields from decoded events
aci: drop redundant per-method event decoding
contract events: remote contract support (c7599c7)
createGeneralizeAccount: estimate gas limit instead of using const (da88852)
decode encode: validate base58 prefix and payload length (e836260)
package: build es version compatible with node (480c747)
poll: use getCheckTxInPool if available (690db5b)
swagger: converts operationId in snake case to pascal (e52b739)
swagger: split transactions by queues to post batch of txs from one account (0023fc7)
tx builder: accept unencoded name in nameClaimTx (eea92be)
tx builder: don't require produceNameId to create AENS txs (57ef9c7)
tx builder: provide default name fee (18e4bab)
validator: check contractId (5e667a5)
wallet: add switch for aepp wallet node sharing (b5640d6)
wallet: enable aepp to wallet node connection (d87e1fa)
wallet: provide switch for aepp wallet node connection (dfbab59)
chain: don't require address function to post transaction (07bc105)
channel force progress: add missed binary prefixes (78660d2)
channel: ignore messages that can't be handled, print to console (aaad8e3)
compatibility: update argon2-browser to version with default export (0e69d8b)
compatibility: use blakejs that doesn't refer to Buffer (94f1879)
contract events: don't throw error if events emitted by remote (fa1c569)
delegate signature: don't encode address depending on onAccount (563a972)
dry-run: don't combine requests by default (0f36efc)
error: remove duplicate error message (8b4df9a)
es: babel build on windows (30f5213)
keystore: encoding of hex privateKey, simplify tests (9f3ad6b)
spelling of GeneralizedAccount (21c1dd3)
tx builder: reject more than 32 pointers (9c06dab)
tx builder: throw exception if deposit is not zero (7b3d0e3)
aci: drop redundant per-method event decoding (a84d781)
aci: remove call/callStatic from deployInfo (84d082d)
aci: remove createdAt property generated at client (406684c)
aepp-wallet schema: convert to TS (1775e91)
aepp-wallet schema: rearrange METHODS enum (8a40105)
aepp-wallet schema: remove unused enums (95bf0e9)
compiler: remove contractEncodeCallDataAPI (7d02317)
compiler: remove getBytecodeCompilerVersion (13283be)
compiler: remove getCompilerVersion (fb929f8)
compiler: remove getFateAssembler (165d492)
compiler: remove validateByteCodeAPI (90ba164)
contract instance: store aci as it is (978225e)
contractCompile: remove encodeCall (6d0ade5)
contract: remove already processed fields from decoded events (45bae5f)
contract: remove compileContractAPI (5ae9c62)
contract: remove contractCompile (7390629)
contract: remove contractDecodeCallDataByCodeAPI (2fe798a)
contract: remove contractDecodeCallDataBySourceAPI (8b13f70)
contract: remove contractDecodeCallResultAPI (b9fbfa6)
contract: remove contractGetACI (23ada71)
contract: remove deprecated contractCall (c079e6e)
contract: remove deprecated contractCallStatic (1e3ac6d)
contract: remove deprecated contractDeploy (08e423e)
crypto: make (encode/decode)Base(58/64)Check private (c151183)
decodeEvents: accept event schemas as it is in ACI (17b9cc4)
drop https scheme workaround for hosted compiler (9fc0a02)
hd-wallet: expect that bip39 used externally (f6243ad)
hd-wallet: remove default export (951ebb2)
node: don't wrap internal endpoints if internalUrl missed (50d7bba)
poll: avoid extra transaction info request to node (22c4838)
remove deprecated topBlock (4535c07)
remove unused functions (8c00de5)
return empty array instead of throwing UnsignedTxError (c6bacdf)
rpc: remove forceValidation flag (9f958c3)
tx builder: inline VALIDATION_MESSAGE (defb7e1)
tx schema: remove default NAME_FEE equal to 0 (9d8339a)
update rlp to 3.0.0 (bb32b77)
use bs58 instead of bs58check (32e836b)
wallet-rpc: inline resolveOnAccount helper (1277b5b)
make contractDeploy a wrapper, remove unused code
inline getConsensusProtocolVersion function
invert and rename forceCodeCheck option to validateByteCode
require compiler 6 and above
make contractCall/Static a wrapper around getContractInstance
contract instance: thread all extra options as contract's
contract instance: remove unnecessary setOptions function
remove contractDecodeData as extra wrapper
remove contractEncodeCall as extra wrapper
don't accept ak_ addresses as hash, bytes and signature
transformation: drop extra wrapper around bindings
transformation: don't export extra functions
drop unnecessary skipTransformDecoded option
drop unnecessary skipArgsConvert option
encode using calldata package (eeebbd5)
poll-interval: reduce poll interval to be a more sensible default (9e55b2b)
events: fix event decoding order and address prefix (faad530)
events: fix test for incorrect address return type (31aaeec)
events: ignore unknown events in decoding (45795fa)
node errors: construct error message by server response (d556936)
semverSatisfies: ignore build number (c3cce0a)
swagger: detection of empty response (9bfab02)
contract instance: remove unnecessary setOptions function (b88e767)
contract instance: thread all extra options as contract's (10fb7ba)
crypto: remove unused asymmetric encode/decode functions (51def34)
drop unnecessary skipArgsConvert option (6d4a599)
drop unnecessary skipTransformDecoded option (bb49239)
inline getConsensusProtocolVersion function (75f0447)
invert and rename forceCodeCheck option to validateByteCode (72122fa)
make contractCall/Static a wrapper around getContractInstance (c4ec019)
make contractDeploy a wrapper, remove unused code (48d36f9)
remove contractDecodeData as extra wrapper (5df2285)
remove contractEncodeCall as extra wrapper (a4b303f)
require compiler 6 and above (f9cef12)
specify browserlist to better choice of features to transpile (c2ec71a)
transformation: don't export extra functions (fa38b40)
transformation: drop extra wrapper around bindings (9b70f8e)
invert and rename forceCodeCheck option to validateByteCode
require compiler 6 and above
make contractCall/Static a wrapper around getContractInstance
contract instance: thread all extra options as contract's
contract instance: remove unnecessary setOptions function
remove contractDecodeData as extra wrapper
remove contractEncodeCall as extra wrapper
don't accept ak_ addresses as hash, bytes and signature
transformation: drop extra wrapper around bindings
transformation: don't export extra functions
drop unnecessary skipTransformDecoded option
drop unnecessary skipArgsConvert option
aens: enable commitmentHash preclaim in tests (5de05e5)
semverSatisfies: ignore build number (c3cce0a)
commitlint issue (2c1cf54)
don't accept ak_ addresses as hash, bytes and signature (cbaac62)
drop unnecessary skipArgsConvert option (6d4a599)
drop unnecessary skipTransformDecoded option (bb49239)
inline getConsensusProtocolVersion function (75f0447)
invert and rename forceCodeCheck option to validateByteCode (72122fa)
make contractCall/Static a wrapper around getContractInstance (c4ec019)
make contractDeploy a wrapper, remove unused code (48d36f9)
remove contractDecodeData as extra wrapper (5df2285)
require compiler 6 and above (f9cef12)
specify browserlist to better choice of features to transpile (c2ec71a)
contract instance: remove unnecessary setOptions function (b88e767)
contract instance: thread all extra options as contract's (10fb7ba)
remove contractEncodeCall as extra wrapper (a4b303f)
transformation: don't export extra functions (fa38b40)
transformation: drop extra wrapper around bindings (9b70f8e)
delegateNameTransferSignature
delegateNameRevokeSignature
drop following oracle delegation signature methods over the new common createOracleDelegationSignature implementation accepts an object param (88b7bf3)
delegateOracleRegisterSignature
delegateOracleExtendSignature
delegateOracleRespondSignature
drop assertedType, use decode instead (00d563f)
drop waitMined static method (2f299de)
tx-validator now gives different, more meaningful, errors (95a2a23)
no longer exports buildHash function, use hash or buildTxHash (9e1fde7)
tx-verification is now done by default (989b36f)
deposittx serialisation: accept unpackTx output produced by deserialisator (ff0b3f5)
crypto: drop extra "personal" from message functions
crypto: remove unused formatAddress function
crypto: remove unused addressToHex function
node-pool: inline helpers, export by default
string: use isAddressValid instead of isAeAddress
string: remove unused snakeOrKebabToPascal function
drop outdated protocols and transactions schemas
drop compatibility with node@5
typo name of broadcast failed error generator (ae7e823)
examlple-aepp: open only when ready to accept connection (4872eb9)
crypto: drop extra "personal" from message functions (34288cb)
crypto: remove outdated generateSaveWallet function (37298be)
crypto: remove unused addressToHex function (93f9def)
crypto: remove unused formatAddress function (a5d4b62)
crypto: remove unused hexStringToByte function (ed39a76)
crypto: remove unused prepareTx, encodeTx, decodeTx functions (64d15eb)
crypto: rename messageToBinary to messageToHash adding hashing (df37004)
node-pool: inline helpers, export by default (ed1cfb5)
string: remove unused snakeOrKebabToPascal function (79bdc04)
string: use isAddressValid instead of isAeAddress (ac7d827)
drop compatibility with node@5 (f5e2fdb)
drop outdated protocols and transactions schemas (f18d305)
refactor: rename forceCompatibility to more clear ignoreVersion (72f1d326)
refactoring: require compiler above or equal to 4.1.0 (c9f48f91)
RpcClient: Drop unnecessary action stuff (84545fd7)
Combine RpcWallet and RpcClients (12892002)
Drop old names support, split ensureNameValid and isNameValid (315a78a9)
refactor(contract-aci): export single function instead of stamp (091b3282)
Combine Accounts and Selector into AccountMultiple (0cacd3b3)
Use swagger-client instead of a custom implementation (4b3260d5)
Remove OracleNodeAPI wrapper (c6f9a76d)
Flatten options of contractCallStatic, remove extra dryRunContractTx (f3ffb664)
txDryRun: Simplify arguments, support txEvents option (401c53da)
contracts: Mark handleCallError as private, simplify arguments (bdf76e24)
import/no-named-as-default linter error (d63e1511)
oracle: make pollForQueries a sync function (dc955e14)
chore: drop aevm support and backend (compiler) option (6eb702dd)
refactor(schema): export enum with consensus protocol versions (e92f187d)
Use es modules version in browser if supported (b49c38f0)
Add typescript support (abde033a)
remove outdated aecrypto example (7df05bfe)
refactor node examples (e8c443cf)
changelog: add missed single quote in example (45fd0002)
resolveName: Document verify option (ca865596)
Remove outdated docs (cf9c166f)
decodeTx: Fix arg naming and annotation (883819c0)
contract-events: Remove outdated contract, update links and markup (37d39d61)
Update docs/guides/import-nodejs.md (9dc274ed)
Update docs/guides/import-nodejs.md (93bfce11)
break down json obj keys necessary for account initialization in nodejs docs (af5ee41d)
Ignore pycache in the docs folder (9989e8e7)
Specify the python version more precisely (d6204523)
Add pycache to .gitignore (f0b7e1f1)
Add navigation and update some titles (8ad15ced)
docco template: Remove extra new lines around code, skip extra blocks (65ce3cf1)
aecontract: Make a list out of a long sentence (8ff7839c)
aens-usage: Use more semantic markup, compatible with mkdocs (de3d3cd5)
docs readme: Fix typos and formatting (5b0c790d)
Add initial mkdocs and readthedocs configuration (b688a96b)
Extract quick-start to guides (28f7e6f7)
Update testnet URL (7bb823f8)
assertedType: Make the last parameter more obvious (50094d3a)
travis: Build docs to gh-pages (7c935a2b)
Docs root: Add link to API reference (4a36102d)
Move outdated disclaimer to the root readme (80a6a663)
Remove generated docs (fd802b00)
Fix api docs generation (56e3aa9d)
remove extra char in regex (37eeefae)
refactor wallet detector (1bc8d027)
shareWalletInfo: Don't create unnecessary copy of info (3a4e50b9)
Inline receive helper that is used once (a4a13889)
rpc: Inline helpers used once (21903f4d)
rpc: Prefer default export (70fc3f0f)
rpc helpers: Remove unused getWindow function (c12b528f)
don't use AsyncInit where it is not necessary (84373697)
contract-aci: reuse defaults from Contract stamp (47013962)
cleanup MIN_GAS_PRICE (a5b28842)
remove unused option string (0e28af23)
remove unused dryRunAccount default option (8c42b706)
Consistent new on Error creation (39f93d3f)
height: Use a shorter syntax (b013bf9d)
height: Improve naming of internal promise (7915119a)
Move source code to "src" folder (ddbce389)
sign-using-ga: don't pass extra options (44bab6d0)
missed aepp id in wallet connect handler (1ed9284a)
get-node-info: bring url and internalUrl back (e984f3b3)
contract error decoding (d56931ac)
contract-aci: don't proxy prepareArgsForEncode from helpers (7e40eda0)
Improve handling of call error (584eb5e4)
require node above or equal to 5.2.0 (ebb36f06)
update dependencies (d876cff7)
deps: bump ssri from 6.0.1 to 6.0.2 (e0dfb8c9)
deps: bump y18n from 4.0.0 to 4.0.1 (9e4acd61)
deps: bump elliptic from 6.5.3 to 6.5.4 (feb3aa68)
deps: bump axios from 0.19.2 to 0.21.1 (0f619f27)
deps: bump ini from 1.3.5 to 1.3.7 (95580324)
deps: bump highlight.js from 10.4.0 to 10.4.1 (9fcfadfe)
deps: bump highlight.js from 10.1.1 to 10.4.0 (43aff25f)
deps: bump node-fetch from 2.6.0 to 2.6.1 (80ed6d70)
Update node to 5.8.0 (b6ff3422)
Update .gitignore (1f1563dc)
add vscode .history folder to gitignore (f4d61df4)
Update testnet URL in JS files (dc1b807a)
add Iris consensus protocol (41fd4a13)
add vsn 2 version of GA_META transaction (b5abe098)
add new versions of CHANNEL, CHANNEL_CREATE transactions (366981a3)
support compilers below 6.0.0 (876e5164)
update channel tests to fate (35a996d8)
Faster tests (5d629103)
Extract strings tests into separate file (f3c7d3fa)
ga: Remove extra await (72bfc746)
Make tests more precise (fe7a8567)
Add lint script (#1045)
Refactor tests (#1039)
Refactor bytes unit tests (#1050)
travis: Run linter and unit tests firstly (#1051)
Disable Travis on all branches except master, develop (#1054)
Refactor contract, oracle, chain (#1048)
Refactor state channels (#1047)
ACIHelpersACITransformationChain: Add option allowUnsynced for poll method which allow to depend on get tx/info API (9c80ce0)
Account: Implement Message Signing (singMessage, verifyMessage) (#903)
AEX-2: Add removeRpcClient method to RpcClient/RpcWallet stamp's(#912)
Guide Add guide for AENS usage
Aepp<->Wallet: Add tests for Aepp<->Wallet communication (#834)
ACI: Add additional method to RPC communication. Required sdk update on wallet side
Add getContractByteCode API
Flavor: Remove deprecated params:
remove url and internalUrl instead use nodes: [ { name: 'NODE_NAME', instance: await Node({ url, internalUrl }) } ]
remove keypair params instead use accounts: [MemmoryAccount({ keypair })]
remove setKeypair function from Account stamps
TxHelpers: Use BigNumber in auction end block calculation (777c012)
deploy/call/callStaticAENS: auction name fee calculation. Name fee validation and calculation in claim/bid (#706)
AENS: Add nameId computation function (#709) (#706)
AENS auction support
compiler 4.0.0 support
node 5.0.0 support
SDK use FATE for contract by default
AE: Add pointers verification for spend by name
AE Make all AE stamps composed with Accounts (#581)
options object like last arguments of generate fn under instance.methods(type:String, data: String) => Any to (source: String, fn: String, callValue: String, callResult:String) => Any.
(callResult is callType from call result, can be ok, revert, ...)
Dependencies: Use custom version of json-bigint
Dependencies: Avoid usage of semver package and cleanup deps
RPC: rpc client: Handle case if aepp opened without wallet
Channels: Fix state channel test's
WEBPACK: webpack configs: Mark all dependencies as external
WEBPACK: Setup webpack-bundle-analyzer plugin
Aepp: Refactor Aepp example app. Allow to spend with payload and add reverse iframe approach.
Channel: Get full channel state support
DOCS: Adjust ACI, Contract and Usage
channel.withdraw(...).state has been renamed to signedTx
channel.deposit(...).state has been renamed to signedTx
channel.leave().state has been renamed to signedTx
channel.createContract(...).state has been renamed to signedTx
channel.callContract(...).state has been renamed to signedTx
Utils: Add basic http client stamp (es/utils/http)
Contract: ACI stamp (New Contract interface base on contract ACI schema)
Account: Extend Account.address() with accountFormatter now you can do
Channel: Improve channel rpc usage
Channel: Improve channel tests and error handling
Channel: Improve state channel params handling
Chain: Add ability to get account/balance on specific block hash/height
Universal: Add { compilerUrl } to Universal, Contract, Wallet stamp initialization
Crypto: Fix name hash function arguments parsing in Crypto
TX_BUILDER: Improve error handling in tx builder
Oracle: Change default gasPrice to 1e6
Oracle: Change minFee calculation, multiply min fee by 1e9
TX: Fix contract tx fee calculation
Chain: Refactor error handling in sendTransaction function
Contract: Change default gasPrice to 1e9
TX_BUILDER: Change Fee byte_size to 1
verifyTxChore: Depend on bip39 from npm instead of git repo
Channel: Change Channel legacy API to JSON RPC
TX_BUILDER: Change minFee calculation, multiply min fee by 10^9
Contract: Add errors handling for dry-run
Docs: Add keystore docs
Ae: Add verify options to send function which verify tx before broadcasting and throw error if tx is invalid
Rpc: Add dryRun to RPC methods
Rpc: Add Oracle transaction creation to Aepp rpc
Docs: Add tx builder docs
Docs: Add doc's for utils/bytes and tx builder schema
TX_BUILDER: refactor calculateFee function in TxBuilder(use BigNumber)
TX_BUILDER: Extend response of Oracle, Aens, Contrat with rawTx
Ae: Change response of send function now it's and object with transaction data(hash, rawTxHash, ...)
Chain: Move Contract and Oracle API wrapper's to Chain stamp
Chore: Rename epoch in CHANGELOG, README, HACKING
chainNode: Retrieve node version from /api
Chore: Fix unpack tx example in bin/aecrypto.js
Chore: Remove unused function's from crypto.js
ContractChainepochnodeChore: Rename Contract api wrapper method's
Chore: Contract call static now using dry-run API
Test: Improve test's for Transaction verification
Tx: Use new tx builder in TX stamp
Contract: Set default values for amount and deposit to 0 for contract transaction
Rpc: Improve RPC server
preparepostinstall-buildDocs: Refreshed Docs: README.md + docs/usage.md
AENSKeystore Update keystore for new requirements
Url-u-UCLI New keystore following these specifications: https://www.pivotaltracker.com/n/projects/2124891/stories/155155204
CLI Add gas param to deploy and call commands
Tx Add ability to create spend transaction natively
Keystore Implement ethereum keystore using AES-126-CTR and SCRYPT as key derivation function
CLI Change --privateKey to flag on ACCOUNT ADDRESS command
Build Change node version in Dockerfile
Node API endpoints to meet new Node specifications
Chore Update docco config and change rename package to recursive-rename
Docs Improved documentation
Contract Add check for MAX_GAS in call and deploy contract
Chore change hash prefix separator from $ to _
Chore Add keywords ('SDK', 'CLI') to package.json
CLI Link aecli to ./bin/aecli.js in package.json (After "npm link" you can use CLI globally)
Aens Wait until pre-claim transaction block was mined before send claim transaction
Build Updated webpack, webpack-cli and added new dev deps accordingly
Node Add Node Compatibility Check
Docs Fancy-shmancy diagram in README
DocsGenerated documentation files since they are linked in static docs
Build Switch from Yarn to pnpm for building
Docs Structure of documentation
Docs Generate Markdown from Docco
Docs More API documentation (still incomplete)
Build SDK entrypoint factories (in /es/ae/universal.js)
Build Module load path (src -> es)
Chore Lower mining rate (5s) in docker-compose
API Remaining tests to use new API
API Adapted new method of obtaining transaction hash, breaks compatibility (see below)
Docs Package description now reads SDK for the æternity blockchain
Chore Authors are now taken from AUTHORS instead of package.json
Docs Moved code examples from README to separate file in docs
const contractIns = await client.getContractInstance(contractSourceCode)
console.log(contract)
{
interface: String, // Contract interface source code
aci: String, // Contract interface json schema
source: String, // Contract source code
compiled: String, // Compiled contract code
deployInfo: { address: contractAddress } // Object with deploy transaction,
// Function
compile: () => this, // Compile contract,
deploy: (init = [], options = { skipArgsConvert: false }) => this, // Deploy contract (compile before if needed)
call: (fn, params = [], options = { skipArgsConvert: false, skipTransformDecoded: false, callStatic: false } => CallRersult: Object // Call contract function
}export const ADDRESS_FORMAT = {
sophia: 1, // return address like `0xHEX_ADDRESS`
api: 2, // return address like `ak_9LJ8ne9tks78hTD2Tp571f7w2MJmzQMRsiZxKCkMA2d2Sbrc4`
}
//
export { ADDRESS_FORMAT } from 'es/account'
await account.address(format: ADDRESS_FORMAT) // default ADDRESS_FORMAT.api// from
await contract.methods.optionFn(Promise.resolve(1) || Promise.reject());
// to
await contract.methods.optionFn(1 || undefined); Exm: await client.spend(1, receiver, { onAccount: 'PUBLIC_KEY' })
Add `onAccount` to `AENS`, `Contract`, `Oracle`.
Add tests for using specific account to Contract, ACI, Account.1) Use Compiler instead of node API for encode/decode call-data and compile.
2) Change Contract interface:
- contractCallStatic (address, abi = 'sophia-address', name, { top, args = '()', call, options = {} } = {}) -> (source, address, name, args = [], { top, options = {} } = {}))
- contractCall (code, abi, address, name, { args = '()', options = {}, call } = {}) -> (source, address, name, args = [], options = {})
- contractDeploy (code, abi, { initState = '()', options = {} } = {}) -> (code, source, initState = [], options = {})
- contractEncodeCall (code, abi, name, args, call) -> (source, name, args) // 'source' is -> Contract source code or ACI interface sourceconst authContract = `YOUR_AUTH_CONTRACT`
// Make current account Generalized
await client.createGeneralizeAccount(authFnName, authContract, [...authFnArguments]
// Make spend transaction using GA
// One Way
// encoded call data for auth contract
const callData = 'cb_...'
await client.spend(10000, receiverPub, { authData: { callData } })
// or
// sdk will prepare callData itself
await client.spend(10000, receiverPub, { authData: { source: authContract, args: [...authContractArgs] } })const instance = await client.getContractInstance(source)
// Deploy contract
await.contract.init(100, 'test', options)
//or
await.contract.deploy([100, 'test'], options)
// Call function
const result = await instance.call('sum', [2, 5], options)
//
// Automatically decide to send tx on-chain or call-static(dry-run) base on if function stateful or not
const result = await instance.methods.sum(2, 5, options)
// Manually make on-chain
const result = await instance.methods.sum.send(2, 5, options)
// Manually make call-static
const result = await instance.methods.sum.get(2, 5, options)
//fix swapped name and symbol in aexn_contracts () ()
make invalid aexn tokens display with invalid flag instead of just error () ()
fix hc error when there is a fork and no total_stats records () ()
make tx stats async () ()
update ubuntu in actions due to deprecation () ()
add holders count to stats endpoint () ()
stream txs instead of fetching each in stats endpoint () ()
add ENV var to configure log file path () ()
add top miners for the last actual 24hs () ()
validate or handle scope parameter on all endpoints () ()
handle names that are both inactive and in auction on names endpoint () ()
implement standalone /aex141/transfers for when there is no contract () ()
make the claims endpoint return all claims instead of just from last auction () ()
activities crashing when there is a name created by a contract call () ()
move the hyperchains into their own scope and fix message () ()
add hyperchain/config endpoint to read aeternity.yaml settings () ()
make docker paths the same as in the node images () ()
make docker paths the same as in the node images ()
bump node to 7.3.0-rc5 () ()
remove deprecated poorly performant /by_names endpoint () ()
update docker OS versions to fix docker multiarch pipeline build () ()
increase the limit of the stats endpoints to 1000 () ()
introduce now transaction hash range scoping () ()
ignore query params that start with underscore () ()
update paginated test plug with new master test () ()
use Phoenix with Bandit HTTP server () ()
add top miners endpoint () ()
move tx fees to txs table to fix stats endpoint () ()
update dialyzer to catch further errors () ()
add endpoint to get the total count of transactions for a given period () ()
include DEX contract swaps contract_create_txi () ()
replace hc check to use the node functions () ()
swapped fields in transfer render function () ()
pin ae_plugin to the current master by ref () ()
remove block v1 endpoint due to significant performance impact () ()
fix regression by returning the v2 status endpoint () ()
return the correct number of transactions () ()
fix test-action database dir removal () ()
add hyperchain sync support ()
bump release-please version to 4 () ()
downgrade release please () ()
get rid of runtime startup warnings () ()
adjust state_pre_transform_micro_node function on Db mod () ()
allow more tries for the contract nonce when retrieving events () ()
ignore the case where the swap event does not belong to any pair () ()
update consensus.state_pre_transform_micro_node function () ()
validate oracles cursor () ()
adjust off by one stats () ()
handle empty aexn count () ()
handle empty blockchain last_gen retrieval () ()
handle no stats division by zero error () ()
change log lovel of log to warning from error () ()
fix default branch name in docker CI () ()
add debug endpoint temporarily to list swaps by txi_idx () ()
add gas to microblocks () ()
pass extra argument to function from the node () ()
recalculate account active names counter () ()
rename aex9 transfers operation openapi docs () ()
scope statistics via scope param () ()
always validate cursor deserialization, including miners () ()
remove Plug.Session usage from Endpoint () ()
add active accounts stats () ()
get the last key from a binary keys table () ()
dex regression () ()
reindex DEX swaps, now without DexCache () ()
remove DEX cache, sync instead () ()
add total accounts stats () ()
serialize/deserialize auction bids cursor to handle utf8 chars () ()
fix integration tests () ()
auction bid rendering issue () ()
add endpoint for account claims () ()
add mempool endpoint for listing pending transactions () ()
adjust aex9 balance history endpoint () ()
remove handle_input usage from different PR () ()
rerun aex9 tokens contrat mint events fix () ()
transactions for account listing () ()
fix all credo errors and avoid diffing () ()
remove NODE_VERSION dependancy in Dockerfile () ()
remove unused functions () ()
run all unrun migrations () ()
add mistaken aexn transfer routes back to controller () ()
transfers cursor deserialization () ()
txs count route priority () ()
aex9 transfer statistics () ()
adjust internal transfer activities structure when scoping () ()
call the right function on contract calls/logs endpoints () ()
fetch aex9 balance history using proper range structure () ()
make transfers endpoint work with new table fields order () ()
fix failing contract test () ()
add contract call index to origin () ()
add error description to invalid aexn contracts () ()
bump elixir version to 1.17 () ()
disable looger bloat in the tests () ()
add claims count on names/auctions () ()
add contracts count stats endpoint () ()
add empty chain key-blocks validation () ()
make dev container retain bash and iex history, updated logger () ()
add minutes per block in stats () ()
sort aexn transfers by txi_idx () ()
activities cursor for gen streams () ()
contemplate case sensitivity when looking for names () ()
adjust new aexn transfers format on activities test () ()
add default padding to base64 oracles response/queries () ()
remove deprecated 2023 migrations () ()
remove v1 unused routes () ()
include metadata and owner on aex141 token request () ()
make auctions endpoints use name and hash () ()
aexn transfer activities () ()
missing delta stat entry for last key block () ()
move console log config outside of json logs if () ()
repopulate dex swaps () ()
publish ARM images to dockerhub () ()
fix randomly failing transfers tests () ()
add support for handling WAE contracts as special AEx9 ones () ()
Add block dificulty stat () ()
add hashrate stats endpoint () ()
dex contract swaps () ()
add generation of key boundaries () ()
make lima files not required () ()
add beneficiary reward to key block response () ()
add block height to aex141 () ()
add node schemas to swagger definitions for mdw () ()
handle dex swaps scoping () ()
activities pagination () ()
inconsistent micro time naming () ()
new stats paths in openapi () ()
specify right aex9 contract to count aex9 logs () ()
structure oracle response as base64 () ()
add ability to roll back database on dev env () ()
add amount and name to activities info () ()
add dex action field () ()
add openapi missing stats route () ()
handle invalid unix dates in filter () ()
oracles v3 endpoint was returning v2 data () ()
fetch aexn tokens on render only () ()
redefine node module functions directly and avoid SmartGlobal () ()
rename statistics to stats to remain consistent () ()
sort DEX swaps by creation instead of contract creation () ()
filter aex9 balances by amount correctly () ()
take max expiration between extension and prev expiration () ()
remove overwrite of network_id and use values from aeternity.yaml () ()
calculate auction expiration correctly when extension present () ()
rename aex141 token path to conform to the others () ()
make aexn prefix search case insensitive () ()
correct url in openapi specs () ()
dex swaps retrieval () ()
use same format for pointers as the node () ()
simplify intermittent name count test () ()
add MIX_ENV=prod when building for SDK usage () ()
add endpoint to get names count () ()
add v3 for websockets () ()
additional fields to dex endpoints () ()
update node to 7.1.0 () ()
add missing mutations in profile sync () ()
handle parent contract DEX swaps () ()
add MIX_ENV=dev on docker-compose-dev () ()
add oracle extends endpoint on v3 () ()
ignore nil mutations in sync server () ()
add flag to disable ipv6 () ()
use the correct structure for mutations when syncing () ()
remove destructuring of gen_mutations for mem mutations () ()
add contract calls/logs nested routes () ()
add creation time and block hash to nft () ()
mark aex9 as invalid () ()
more explicit dex amount representation () ()
include opt_txi_idx when rendering transfers cursor too () ()
retrieve pair from external contract when external log () ()
randmly failing tests and warnings () ()
make the wealth rank task work with the database instead of AsyncStore and ets () ()
move aexn tokens rendering to contract modules () ()
restructure DEX endpoints () ()
task for generating migrations () ()
rename 20240528120000_sync_account_balances.ex to 20240528120001_sync_account_balances.ex () ()
aexn openapi schemas () ()
handle transfers txi_idx ref tuple () ()
reorder the PairCreated arguments for DEX events () ()
rename migration file so it runs again () ()
update aex141 and names swagger () ()
chunk dex_swaps migration and fix pattern match () ()
rename migrations () ()
create migration to sync account balances () ()
add new name pointees endpoint to v3 () ()
create RevTransfer on aex9 minting () ()
add aex141 contract transfers to v3 api () ()
add route for dex swaps by contract_id () ()
allow filtering names by prefix (case-insenstive) () ()
dex new swaps table () ()
arm docker incompatibility () ()
handle empty transactions count () ()
make all operationIds in swagger_v3 PascalCase () ()
update credo to get rid of warnings () ()
update openapi schema () ()
add average of transaction fees for last 24 hours with trend () ()
add openapi schema for dex controller () ()
extend auctions only if the extension is longer that the timeout () ()
handle not found auction bids () ()
bump otp version () ()
bump version to 7.0.0 () ()
add int-as-string on pagination next/prev urls () ()
extend auction properly () ()
update node to 7.0.0-rc1 () ()
update node to version 6.13 () ()
add support for paying_for txs on contract calls migration () ()
add reverted calls migration to update fun/args () ()
remove hardcoded node log level in favor of aeternity.yaml config () ()
store function name for reverted contract calls () ()
add raw data pointers support for ceres () ()
include 0 count statistics throughout the network lifespan () ()
resolve aens name to contract address when calling contract () ()
move transactions count to v3 properly () ()
update names and oracles to v3 () ()
use tx hash instead of index in v3 api version () ()
remove schemes from swagger v1 file () ()
avoid converting to atom on runtime metrics formatter () ()
change tests using nonexisting column () ()
add config to allow logging to console () ()
allow none logger level configuration () ()
render name_fee on names/auctions () ()
docker logs mount bad permissions () ()
include local-idx cursor when paginating tx call activities () ()
randomly failing tests () ()
telemetry error when application starts () ()
add credo checks on config files too () ()
allow getting block-specific AEx9 balances () ()
allow logger level configuration () ()
allow same creation block to be used on by-hash aex9 balances () ()
handle invalid hashes error () ()
use endpoint-specific ordering validation () ()
add logs message on deprecated routes () ()
restructure v3 routes and remove tx_index () ()
add remaining v3 routes without the ones deprecated () ()
allow encoding ints as strings via query parameter () ()
process HC seed contracts with the correct format () ()
return 404 when contract is not found () ()
logging revoked name on sped () ()
add v3 name and auction detail endpoint () ()
include 48hs transactions count trend on stats () ()
restructure aex141 activities meta_info match () ()
skip node call on empty db () ()
sync spend with revoked name () ()
migrate dex swap tokens () ()
update swagger.json schemes value () ()
handle heavy endpoint timeout () ()
ignore 0-gen db for name stats () ()
include all auction claims when closing up an auction () ()
index and fetch dex swap tokens () ()
pick starting transaction from 24hs ago for counting () ()
index name statistics using key blocks () ()
add names approximate time on expire/activation () ()
always return state on contract logs write () ()
check return_type instead of ret_value for errors () ()
handle micro-block cursor properly () ()
add cache manifest building on docker build () ()
update node version to most recent 6.12.0 () ()
use last gen status regardless of transaction index () ()
generalize json/view rendering () ()
fetch previous names before rendering them () ()
ignore errored contract calls fun_arg_res when syncing () ()
add last 24 hours transactions count () ()
add name activation statistics () ()
track dex pair creations () ()
add syncing queue for async syncing requirements () ()
filter all aex9 contract account transfers () ()
make names restructuring migration async () ()
unify pagination returns and cursor serialization () ()
add statistics date filtering () ()
check contract creation for child contracts () ()
update holders and contract balance on init () ()
add open auction bids to name history () ()
index aex9 mint and burn as transfer () ()
move previous names into separate table () ()
offloads app startup by async keys loading () ()
count microblock txs () ()
index and query aex9 transfers by contract and account () ()
sort aexn contracts by creation () ()
display only the current auction bids for a name () ()
enable 1000 limit on block statistics endpoint () ()
add aexn_type to contract txs () ()
add functional error responses and tests cases for it () ()
ensure suffix on name history () ()
reverse call logs () ()
add approximate_auction_end_time to auctions () ()
render sext encoded log () ()
add allowance and approval events () ()
enable V3 routes for all envs () ()
upgrade to node 6.11 () ()
handle aex141 templates without tokens count () ()
add contract_id to create internal calls () ()
match entity using nft collection and token id () ()
enable nft marketplaces tracking () ()
count holders based on events () ()
add block statistics endpoint () ()
enable async migrations () ()
use inner tx type to render contract creation () ()
prepare wealth to be updated on block basis () ()
query active entities (e.g auctions) () ()
include aexn meta info on aexn activties () ()
index entrypoints with proper cursor () ()
load aex141 contract for aex141 activities () ()
remove dup mgiration since it takes too long for testnet () ()
unify convert_params usage into util function () ()
use extracted tx mod and name () ()
return bad request for input exceptions () ()
add name history endpoint () ()
expire memory stores based on v1 heavy endpoints () ()
fix some readme typos () ()
ignore field/transaction counts when they are duplicated in the transaction () ()
return db state after broadcasting () ()
isolate async test cases () ()
count object keys only from memory () ()
remove old mocked websocket tests () ()
use functional single item pipe () ()
add drop tables config () ()
add statistics and /statistics/transactions endpoint () ()
add week/month interval filter on statistics () ()
dedup txs activities when present on several fields () ()
fix auction bids expiring index () ()
put revoked name key for counting () ()
use map for DeleteKeysMutation () ()
remove name cache () ()
add aexn type to contracts response () ()
add healthcheck on all swagger v2 endoints () ()
count names and oracles from keys () ()
fetch only oracles tree () ()
increase timeout of call affected by migration () ()
add v2 yaml file back to the static directory () ()
disable cache for DB block mutations () ()
get block height finding the header () ()
use aexn extensions from byte code () ()
include last tx hash on delta/total stats () ()
index Hyperchains seed contracts () ()
filter oracle by state param () ()
handle empty stats () ()
restructure pattern-match for decode_call_result () ()
log and reindex aexn () ()
remove all consistency credo warnings () ()
add auction-only claims v3 endpoint () ()
detect AEX-n meta info () ()
filter owned nfts by collection () ()
nft metadata endpoint () ()
allow using hyphen on name cursors () (), closes
rename AuctionBidBid to BidClaim () ()
create map or list directly () ()
allow nft owner call for hackaton contracts () ()
add missing fname contract creation call () ()
deps: bump node-fetch from 2.6.1 to 2.6.7 in /node_sdk () ()
deps: bump semver from 6.3.0 to 6.3.1 in /node_sdk () ()
move nested name records to individual tables () ()
add devmode test for Chain.clone calls () ()
add v3 initial endpoints for names/auctions () ()
rewrite some mem tests with store () ()
only bootstrap accounts for configured hardforks () ()
leave controller tests to coverage () ()
compact type increment counts mutations into a single one () ()
encode event logs within a single migration () ()
keep cache after switching from db to mem commit () ()
use builtin term to binary for values () ()
log mem and db sync profiling () ()
add further block times to different endpoints () ()
add channels last updated time () ()
use same get code logic from node () ()
add async: false to all test that mock modules () ()
stream generations mutations () ()
add block_time to all activities () ()
add micro block time to oracle nested resources () ()
add support for swagger using JSON format () ()
cache mem sync mutations () ()
create contract call event tx when Chain events () ()
add devmode Contract.create call test () ()
add decimals to account balances () ()
add migration for entrypoint () ()
add mix files to credo checks () ()
include credo and leave test for dev shell () ()
add approximate_expiration_time to names () ()
consider all oracles expirations () ()
include aexn contracts with special chars () ()
run aex9 count migration () ()
add async:false to more test modules () ()
fix intermittent test failures due to async mocking () ()
integrate devmode and SDK for custom test txs () ()
return txs count after cache () ()
add approximate_expiration_time to oracles () ()
add transactions count to websocket keyblock () ()
count only aexn contracts with valid meta info () ()
remove circular rendering on Oracles.render_query/2 () ()
add function parameter alias to contract logs () ()
remove mock from contracts sync () ()
add support for node 6.8.1 back () ()
add target to ws object msg () ()
allow filtering channels by active/inactive () ()
include inactive channels on channels listing () ()
adjust printed unit on store_account_balance log () ()
apply Node persist config () ()
track internal calls for wealth () ()
use count id by type also on /count () ()
rename OracleQueries migration to run after ContractLogs () ()
add counters to ws block broadcast () ()
encode custom event args () ()
filter internal calls by contract and function () ()
include oracle responses on oracle queries endpoints () ()
handle old oracle responses when migrating int transfers () ()
reindex reward_oracle int transfers () ()
rename OracleResponses migration table () ()
increase inactivity timeout () ()
let docket volumes be optional () ()
revert "chore: update node to 6.8.1 ()" () ()
update node to 6.8.1 () ()
filter logs by contract and event () ()
rename update_type_count file to match module () ()
check if record exists on delete keys mutation () ()
clear done in memory async tasks () ()
update account balance () ()
prune wealth migration () ()
delete async task if block is not found () ()
delete inactive name owner deactivation records when activated () ()
set correct node module for channel withdraw () ()
set proper migrations path on mix release () ()
show last applied migration () ()
add channels updates nested endpoint () ()
sort aex9 balance per amount () ()
consider existing oracles on inactive ones count () ()
commit migration instead of direct db write () ()
add contracts detail page () ()
wealth endpoint () ()
adapt activities to new int transfers format () ()
add /contracts endpoint to list contracts () ()
track aex9 contract supplies () ()
track aex9 logs count () ()
track aex9 token holders count per contract () ()
adjust the order for contract call event mutations () ()
update aex9 response with holders () ()
add /oracles/:id/responses nested endpoint () ()
aexn contracts count endpoints () ()
display int transfers source tx () ()
add lima contracts amount minted to supply () ()
fix credo refactor errors () ()
remove unused tx sync cache () ()
sum account mintings by network () ()
add /oracles/:id/queries to list an oracle queries () ()
count id txs by type or type group () ()
filter inner txs fields with ga_meta type () ()
ignore oracle responses that don't have associated query () ()
precompute tx ids () ()
count total pending async tasks from db () ()
handle return type for failed GAMeta txs as well () ()
remove name logs () ()
limit ws subscriptions () ()
remove LoggerJSON backend from test env () ()
add unit tests to Db.Channel module () ()
add unit tests to tx controller and context () ()
add base case for txs from gen () ()
ignore failed ga_meta_tx sync processing () ()
revert git change to allow dev build () ()
set config to serve endpoints on prod () ()
aggregate request metric per route () ()
allow mounting db dir with docker () ()
make web config runtime config () ()
set docker user to aeternity () ()
avoid deleting oracle queries for later use of them () ()
remove oracle query response check () ()
add fallback for contracts endpoints () ()
use top height hash for aex9 account balances () ()
add coverage for name auction endpoint () ()
add template token edition () ()
allow filtering activities by type () ()
encode args using types for AEX-N events () ()
add address to Burn event () ()
ignore all nft events with args mismatch () ()
set proper release node to reopen mnesia () ()
cleanup field parser module () ()
remove console info log for dev environment () ()
remove no longer needed oracle queries nonce fix () ()
skip dev and miners rewards for HC () ()
publish images with prod () ()
specialize ws subscription by source () ()
encode txs 404 address properly () ()
add activities integration tests for the new activity types () ()
add handling for previous update format () ()
let aeternity.yaml be used by default () ()
handle other call not found cases () ()
add optional json logger () ()
allow filtering by prefix and scoping contract calls () ()
allow retrieving the latest txs by hash () ()
encode blocks on the /v2/blocks endpoint using formatter () ()
handle call not found () ()
set hostname as default telemetry host () ()
update websocket integration tests () ()
fetch txs subscribers once () ()
removed unused block cache () ()
add NODE_URL docker build argument () ()
allow aex9 account balance at a block hash () ()
remove priv volume for prod () ()
use only Jason library () ()
add metrics observability () ()
monitor error 500 () ()
adapt claim actvities to use the new txi_idx stored format () ()
fix bugs found through integration tests () ()
look for pointee also on previous name record () ()
use proper names for transaction types for events and transactions () ()
remove duplicated v2 ws enqueuing () ()
add MIX_ENV=test for being able to run tests () ()
add support for channels local index reference () ()
cleanup dialyzer warning and util module () ()
fix some of dialyzer overspec errors () ()
allow cursors with names with dashes on them on pagination () ()
enqueue a block only once to ws broadcasting () ()
update node to version 6.7.0 () ()
skip importing hardfork accounts for custom networks () ()
add channel participants to channel txs () ()
formats call return composed by tuple value () ()
ignore gen-based internal transfers for txi indexed activities () ()
improve aex9 dex coverage () ()
ci: always enable semver tags () ()
add offchain rounds to channel transactions () ()
allow filtering activities by ownership only () ()
render inner tx details () ()
ci: use custom token instead of default () ()
cleanup library dependencies () ()
remove migrations since scratch sync needed for 1.34 () ()
remove unused code () ()
add block hash to activities () ()
include source tx_hash on nested names endpoints () ()
introduce {bi, {txi, local_idx}} for precise internal txs refs () ()
query channel reserve at a hash () ()
ci: conditional dockerhub build env () ()
ci: make sure workflow is triggered on push () ()
remove tx hashes handling on int contract calls () ()
use master instead of latest to pull docker image (
add node details to channel page () ()
add v2 websocket implementation () ()
format aexn activities same as aexn transfers endpoints () ()
return event name when it is aexn () ()
handle inner name_update pointers () ()
name of sender parameter of get_aex9_pair_transfers () ()
remove dockerization from ci tests run () ()
remove extra colon before in path parameter name () ()
enable docker image tests () ()
publish only tagged images (w/o tests) () ()
add migration and update docs for nft templates () ()
add proper typing to sync transaction nested function calls () ()
add typespecs to all Db.Model records () ()
add union of model-specific State typespecs () ()
add /v2/channels/:id detail page () ()
use aex9 event-based balance () ()
ensure proper model declaration () ()
automatically publish docker images () ()
allow network id for local environment () ()
index only event-based aex9 balances () ()
add aex9 presence after event () ()
add auth function name to ga_attach () ()
add name /transfers and /updates paginated endpoints () ()
handle nft template edition limit () ()
get immediately returned nft extensions () ()
use strict version on otp ci () ()
validate kbi range with blockchainsim () ()
add template limit details to edition () ()
add /names/:id/claims endpoint () ()
handle nft contract limits () ()
adjust git revision digits to allow variable length () ()
encode non-string contract log data () ()
update async tasks db count on save () ()
validate multiple and remote aexn transfers () ()
move ws subscription to specific module () ()
add node version argument to docker builds ()
handle dry run timeout () ()
remove unnecessary smart_record dependency () ()
remove unused migrations () ()
avoid double aex9 event balance update () ()
handle account_pubkey recipient pointee ()
divide swagger v2 docs into separate resource files () ()
add name claims to the activities retrieved by name hash () ()
add oracle query expiration internal refund transfers () ()
display name buyer from inner claim tx () ()
ignore oracle queries that do not have the right calculated nonce () ()
render binary pointer key on name related endpoints () ()
scope contract calls filtered by function properly () ()
use last call txi for hash account balance () ()
allow /txs/count to be filtered by tx_type () ()
use built-in phoenix websocket () ()
reintroduce nft_template model () ()
add response_id to channel settle rendering () ()
index nft templates () ()
handle non-existing mbs txs endpoint response () ()
recalculate internal oracle query tx nonces () ()
render all pointers on names endpoint () ()
update aex9 balance based on events () ()
consider name updates and transfers for NameOwnerDeactivations () ()
events from the node are obtained in reverse order () ()
render list of keyword lists args () ()
complement coverage for name syncing () ()
complement coverage for oracle syncing () ()
allow filtering names by owner/state ordered by deactivation () ()
handle burn nft () ()
render call details for ga_attach and ga_meta () ()
increment ga contract stat only on success () ()
add return_type for ga_attach_tx () ()
remove txi scoping support for new endpoints () ()
handle any meta info value () ()
add tx internal transfers to activities () ()
render bid for names in auction () ()
add return type for ga_meta_tx () ()
add generation-only internal transfers to activities () ()
always return txs from last microblock ()
index remote log also with called contract () ()
order gen-scoped txs and activities properly () ()
return original error messages on txs invalid requests () ()
use always valid contract for invalid range test () ()
update aex141 signatures () ()
allow rendering static swagger.json (temporary fix) () ()
allow sorting backward when gen first-last is the same ()
handle other node tx locations () ()
return {auction_bid, source} tuple on names owned_by_reply () ()
index oracle extend internal calls () ()
add missing origin to oracle created by internal call () ()
return proper error when aex141 token is a partial int () ()
set proper auction_timeout on names () ()
transform non encodable binary oracle fields into list () ()
move Db.Name syncing code to Sync.Name () ()
print migrations total/duration using returned values () ()
add aexn transfer activities () ()
consider last txs when calculating mb tx count () ()
add cases websocket broadcasting () ()
improve dialyzer warnings to catch unmatched results () ()
upgrade phoenix and other deps () ()
bump erlang to OTP 23 and elixir to 1.11 () ()
cleanup tests warnings () ()
add /accounts/:id/activities endpoint () ()
include internal transactions as activities () ()
allocate smaller tuples for query streams () ()
remove phoenix_swagger () ()
add /key-blocks endpoints with txs/mbs count () ()
add /key-blocks/:hash_or_kbi endpoint with mbs/txs count () ()
add /key-blocks/:hash_or_kbi/micro-blocks endpoint () ()
add /v2/micro-blocks/:hash endpoint () ()
accept contract param besides contract_id () ()
disable phoenix code_reloader by default () ()
map recipient record when filtering by nft collection () ()
generalize transfer history for aex141 () ()
index miners count and total rewards from fees () ()
index nft transfers by collection () ()
calculate prev on build_gen_pagination correctly () ()
convert transfer event token_id to integer () ()
handle out_of_gas_error on aex141 cleanup () ()
handle variant owner return () ()
add type definitions to Model records () ()
add micro_blocks to /v2/blocks/{height} () ()
update aex141 metadata signature () ()
add cases for rocksdb multiple dirty delete calls () ()
update oracle and aex9 integration tests () ()
log open/closed channels together with their locked AE () ()
check for nil before encoding contract pks () ()
filter contracts after account balance dry-run on blockhash () ()
query aexn by exact name or symbol on v1 and v2 () ()
use block_index on v1 aex9 height balances () ()
add progress indicator on name fees migration () ()
set dry run gas upper limit () ()
sorts aex9 account balances from last to first () ()
complement to missing unit tests for AEX-141 () ()
skip creating a store on integration tests () ()
update hardfork accounts integration case () ()
update integration test regardin aex9 missing presence () ()
add txs per second stat on /stats () ()
complement to migrated tokens () ()
expose names locked/burned fees on stats () ()
synchronize async tasks write () ()
decrease async task producer dequeue time () ()
dequeue async tasks non-preemptively () ()
handle dry-run error when contract is not present () ()
increase auctions started stat only once () ()
adapt to AEX-141 standard change () ()
decrease consumer async server wait and sleep () ()
include ga_attach_tx when counting contracts () ()
include tx-type-specific data inside "tx" attribute () ()
send duplicated tx websocekt message if sources differ () ()
update stats caching condition to only do it once per kb () ()
add typing and credo fixes to ets module () ()
imports hardforks preset accounts () ()
broadcast in-memory blocks () ()
remove unused supervisor () ()
remove unusued Sync.Server gens_per_min field () ()
add new store kind to serve async tasks () ()
add new type count index for /txs/count?type=x () ()
allow filtering transactions count by scope () ()
display tx hash instead of txi when tx_hash=true () ()
adjust inactive name owner table () ()
avoid dirty reads when using iterator () ()
avoid erasing mem state when State.commit/2 () ()
avoid returning results from other tables on AsyncStore.next/prev () ()
extract expand/top params into the PaginationPlug () ()
move formatting to main render functions () ()
save only the used txi on aex9 presence () ()
add helper with_state/2 function for declarative tests () ()
add name sync tests for more scenarios () ()
assert decimal is nil on out_of_gas_error () ()
fix random non-deterministic test failures () ()
add aex9 validation to v1 hash endpoints () ()
add aex9 validation to v1 range endpoints () ()
add mistakenly removed async in-mem tasks () ()
clear state hash for every key block () ()
add nft holder endpoints () ()
use block/hash param on account balances () ()
verify if task was concurrently deleted () ()
dedup aex9 presence () ()
truncate aexn name and symbol sorting fields () ()
add swagger files in docker image build ()
truncate aexn cursor ()
add truncate metainfo migration () ()
include tx_hash when listing AEx9 transfers () ()
handle names search endpoint when no prefix () (), closes
use valid name auction route as specified in docs () ()
enable credo and remove unused code () ()
reduce gas limit to Node base gas () ()
add endpoints to list aex141/nft contracts () ()
save and display aexn extensions () ()
set low gas limit according to Node base gas () ()
display unencoded block hash when not found () ()
fix name/stats integration tests () ()
add StatePlug to deal with endpoint responses () ()
generalize aexn create contract mutation () ()
handle update aex9 state on contract create logs () ()
retrieve block hash for name ptr_resolve from state () ()
add independent static swagger v1 and v2 files () ()
update aex9 state with logs () ()
include ga_attach_tx when trying to find call origins () (), closes
invalidate aexn contract () ()
replace aex9 sync cache with non deduped params () ()
update v1 auction bids structure in Format module () ()
use correct key format for listing name owner tables () ()
revert swagger name operation names () (), closes
fetch key hash using aec_chain on update_aex9_presence () ()
handle /tx/:hash endpoint when tx doesn't exist () ()
handle aex9_controller errors with FallbackController () ()
handle prev/next when key_boundary is nil () ()
dirty reads + add Store abstraction () ()
generalize aex9 meta info with aexn contract () ()
generalize fetch aexn tokens () ()
move aex9 contract pubkeys to aexn records () ()
add fallback for mismatched presence to balance () ()
replace aex9 migrations by one that creates all aex9 contracts () ()
add Ping operation to websocket () (), closes
display mdw gens processed per min on the status page () ()
allow contract call to GA contract () ()
docker include priv volume for migrations to be found () ()
handle requests for blocks that don't exist gracefully () ()
handle stating server when syncing from scratch () ()
add aex9 tests iterating throughout all contracts () ()
refactor integration tests to unit tests () ()
restructure AuctionBid table for better indexing () ()
use aex9 balance records on account endpoints () ()
use declarative state for executing mutations () ()
use State for building database streams () ()
include priv dir for db migrations ()
remove unused node and db stream code () ()
enable sync server to receive old :DOWN messages () ()
index aex9 contracts on Chain.clone and Chain.create () ()
don't display source_hash when invalid compilation info () (), closes
fix displaying single txis for v2 () ()
get next block hash on async task () ()
restart sync server after sync fails () ()
coverage analysis () ()
fix intermittent RocksDbCF concurrent error () ()
speed up dialyzer without docker () ()
add diffing script to compare two different environments () ()
get pubkey for child contracts () ()
clean node db hooks from mdw () ()
fix integration inactive names cases by expiration/deactivation () ()
fetch expired oracle/names inside mutation () ()
include code to fetch stats inside StatsMutation () ()
perform async invalidations on a sync server () ()
rename /v2/names/* by=expiration to by=deactivation () ()
get bi for a block hash () ()
initialize aex9 balance when not exists () ()
aex9 creation for child contracts () ()
deactivate name on update with ttl 0 () ()
delta stat resume when name is not revoked () ()
fix /names/owned_by path () ()
disable async tasks () ()
fix v1/v2 stats tests () ()
async tasks persisted with rocksdb () ()
chain and name tables persisted with rocksdb () ()
contract tables persisted with rocksdb () ()
oracles persisted with rocksdb () ()
/v2/deltastats () ()
add /v2 routes to support versioning () ()
add AEX9 v2 endpoint to retrieve balance history () ()
add aex9 v2 endpoints () ()
/aex9/transfers/from timeout () ()
/stats counters with negative values () ()
derive aex9 presence error handling () ()
fix missing streams errors () ()
fix intermittent prev_key async test () ()
add fallback controller to deal with errors consistently () ()
change name routes to be consistent with core () (), closes
commit only through mutations () ()
migrations with rocksdb () (
added check script for readme routes ()
drop old model sum_stat () ()
ignore data directory on docker/git () ()
mnesia and mdw.db under same data dir () ()
properly assign m_bid to actual bid value () ()
/aex9/by_contract search () ()
aex9 contract created by :contract_call_tx () ()
sum of auctions, names, oracles and contracts in total stats () ()
render auctions by name using just the AuctionBid key () ()
updates txi when internal call expiration is unchanged () ()
extract range independently of the direction requested () ()
/names/owned_by for inactive names () ()
add encoded query_id on query txs () (), closes
aex9 balances for an account with token info () ()
aex9 presence on calls other than transfer () (
aex9 migrations origin handling () ()
avoid loading block_hash for building oracle tree when syncing () ()
execute block_rewards mutation before stats mutation () (), closes
expirations shall run at the end of a height () (
disable accoutnt txs legacy endpoint (), closes
invert order to avoid setting git user ()
fix auction sorting check () ()
fix oracles and tx_controller integration tests () ()
fix the single stats test that is failing () ()
restructure oracles integration tests () ()
add name transfer/update/revoke mutations () ()
add tx context for dealing with tx mutations () ()
create ContractCreateMutation () ()
extract channel_create_tx syncing to Sync.Transaction () ()
add cursor-based pagination to contract logs/calls () ()
add cursor-based pagination to stats () ()
db transactions per microblock () ()
index contract init events and internal calls () ()
base32 encode account cursor on transfers ()
build expiring mutation using mnesia transaction ()
build oracles expiration transaction using mnesia transaction ()
get info for contract with :ref instead of :code ()
add additional logging information for auction updates (), closes
include date on info.log () (), closes
prev_stat is not used () ()
remove dep from chain subscriber ()
add contract controller endpoints integration tests () ()
refactor name controller integration tests () ()
add missing aliases on the Db.Oracle module ()
add oracle expiration mutation when syncing () ()
extract block rewards syncing into mutation () ()
add stats endpoints integration tests () ()
name and auction sync logs ()
remove cleanup name expiration ()
add cursor-based pagination to transfers endpoints ()
add mutations abstraction to deal with mnesia updates () (), closes
allow scoping transfers by txis () (), closes
async derive_aex9_presence ()
add name ttl to last_bid tx ()
allow filtering transfer by kind when backwards direction () ()
always display the correct contract_id on contract logs (), closes
binary encoding for websocket broadcasting ()
code review changes ()
move task sup to async tasks ()
task sets done and simplified long task consumer ()
tests comparision of names with auction ()
credo fixes ()
credo moduledoc finding ()
credo warnings ()
disable old credo warnings ()
remove comment ()
use Blocks.height type ()
add aditional test case for transfers ()
add test case with mixed prefixes ()
add testcase for account filtered transfers backwards ()
async store tests ()
gameta claimed name rendering ()
account presence based on aex9 balance () ()
add cursor-based pagination to scoped txs ()
add gas_used to create contract tx info () ()
add name hash to owned_by response () ()
add AETERNITY_CONFIG env variable to docker-compose ()
add ex_json_schema to deps for phoenix_swagger to use ()
adjust Mnesia module return types for consistency ()
aex9 presence async processing state () ()
base documentation on hosted infrastructure ()
expose service ports when starting docker-shell container () ()
simplified account presence filtering () ()
credo and unused code ()
dialyzer ()
new plt version ()
new plt version ()
add async task produce/consume tc ()
add sender = recipient integration case ()
add sync_transaction write fields test ()
add tests to Chain.clone events handling ()
add :scope, :query and :offset to Conn.assigns ()
add Collection module to deal with complex pagination () ()
add paginated auction name endpoints () ()
add paginated name endpoints without making use of streams () ()
/v2/blocks endpoint returns mbs sorted by time () ()
add oracles v2 endpoint without making use of streams () ()
adds recipient account and name to spendtx () ()
backup and restore db table () ()
adjust tuple structure sent on AEX9 balances endpoints ()
don't read from cache the last 6 blocks () ()
indexes remote call event logs also by called contract () ()
recipient account is the pointee if name have one () ()
add blockchain DSL for testing purposes () ()
move integration tests to a separate directory () ()
separate unit/integration tests and add to ci () ()
small integration tests updates () ()
add ci proposal with github actions ()
add commitlint ()
add credo to ci () ()
add dialyzer to project ()
add git_hooks lib for optional use () ()
format elixir files ()
prepend slash to pagination next () ()
remove warnings () ()
temporarily hardcode node version in docker build (a6da18c)
increase long tasks throughput (f93d72b)
update name routes to be consistent with core (40f598c)
fix dockerfile for multiple node releases (67b57a4)
sync height 0 without mbs and txs (9b9bbdf)
dedup existing records (03708c2)
long running async tasks (cd18e3d)
cancel task timer (a1d11f9)
contract might not be present (65b18df)
dedup args for any task type (af7b9c6)
filtering aex9 call (9c374bd)
getting aex9 recipients (6adf87c)
increase task timeout (8715600)
long task without timeout (f2256c7)
remove old oracle expiration (369aa50)
start long task (71b3404)
update contracts txi (e08334c)
validate name expiration (13703a4)
format and dialyzer (1d605f4)
ignore existing credo warnings (a953db1)
linter (63e4600)
new plt (bb7022b)
new plt (90b336e)
avoid mutual side effects on stats (1ca419a)
include kind filter on account transfers test (9b1e3d5)
long tasks test fixed (a77b5a6)
longs tasks stats (598c75e)
notify and wait for consumer (fb03a09)
proto_vsn for name unit tests (f8aaa10)
contract calls with dry-run (8407dc0)
delay slow aex9 migration balance (6e885fa)
aex9 presence check demands mnesia ctx (56d33fc)
application init warning (5461dc2)
duplicated indexation when receiver=sender (3a878e4)
fix default range gen fetching (095315c)
fix dockerfile for multiple node releases (d6c52cb)
missing AeMdw.Txs alias from rebase (778c059)
mix version comma (bbc74ac)
name auction bid details when expand=true (83d3831)
rescue :aeo_state_tree.get_query error (326a528)
revert field indexation (keeps both fields) (a03e1cf)
start all aecore services after starting app_ctrl_server (351c9cf)
plt version (cdc14d9)
revert force PLT creation (ce3aedf)
temp delete priv/plts (82cb5ba)
temporarily create plt without condition (f1f78d8)
temporarily remove old plt file (bd601f8)
additional sync case when recipient = sender (edb9d1e)
fix oracles/names tests (d5cb035)
replace last_txi with very high value (33e2d87)
uniq integration case check for recipient = sender (a81513f)
use mnesia sandbox (90e6688)
convert from gen to txi differently (2d3cdea)
migration logs with Log.info (f9b4e15)
move first_gen! and last_gen! to Db.Util module (385e00f)
only add contract creation txs when tx_type is contract (63417ee)
use aetx getters for retrieving tx fields (4197983)
add release please workflow (88cff95)
warnings as errors (cc162b8)