forgAE, SDK and the unpleasant experience of an unexperienced developer


#1

Hey guys,

Please, please, I beg you ( I really do) to update your documentation, examples, tutorials and everything that the developers need in order to develop on the Aeternity Blockchain Network.

Also, please when there is a major release that breaks everything, give a simple example for stupid people like me, so we can easily migrate our code, so we don’t have to actually go and see all your 6436347 commits so we can get an idea what is changed and what not.

The first place every developer goes - or the second (the first being documentation, which is either missing or outdated or incomplete) is the tutorials.

So after I had to write some Sophia tests for my smart contract using our favourite and “I-can-do-everything-for-you” tool forgAE and I had to deploy a contract with init params where do you think I went first?

Well of course https://github.com/aeternity/tutorials/blob/master/deploy-with-init-params.md

Did it work? Well of course not. At least you can either delete it or write down with huge font size that it is out-dated.

After going through 34757868 examples I had to actually go and see the god damn source of the JS-SDK so I can find out that the init params are now passed as an array…

So, after successfully deploying the contract on the test network, I was hit by several errors that speaks nothing to me. Can you please be so kind (hopefully as kind as I was) to help me resolve my issue?

The issue is:
I’m trying to deploy a smart contract inside the unit tests with 3 params - (address, int, int).
Going through all possible scenarios of different format I always end up with an error (and it’s always different).
Using the same method I used to deploy the contract using forgae deploy I get the following error:

     Error: Http request for https://compiler.aepps.com/encode-calldata failed with status code 403. Status: Forbidden. 
Error data: {"reason":"Type errors\nUnbound variable ak_2mwRmUeYmfuW93ti9HMSUJzCk1EYcQEfikVSzgo6k2VghsWhgU at line 420, column 28\n"}

If you need more details (I assume you would need the whole source code of course) just let me know.

P.S. peace


#2

Your words in gods ears. Thank you for this important feedback, there is extensive work being done to clean up this mess. One of the main reasons for this is the fact that the development of everything SDK related did not follow a strategic, but evolutionary approach. This means, things are just being stacked on top and adjusted as needed, totally impossible to build something upon such a thing and even more: Impossible to keep up with an up-to-date documentation. And that is about to change with an AEX proposal I am struggling to publish just this very minute (markdown files are of very limited use when it comes to tables >_< ), which would put taking care of all this mess from your upon our shoulders. You are more than welcome to express your opinion on that, I will post the link here.

I am sorry. We can and we will do better. Please stick to aeternity.

For your issue: I have a vague clue, but could you please describe in more detail what you are about to do in which way? Also, seeing the address in line 420 lets me assume you hardcoded it somewhere in the contract? Escaping " like " in the contract before doing the API call is necessary.


#3

curious about the upcoming AEX :slight_smile:


#4

I didn’t want to open a new thread regarding this, since its related. Not sure if it’s just me (maybe not since this thread exists), but forgae is somewhat broken. Initializing a new project with forgae, and trying to run the built-in test, which only deploys the example 2 line contract results to this:

Log:

➜  test2 forgae init
===== Initializing ForgAE =====
===== Installing aepp-sdk =====
===== Installing ForgAE locally =====
===== Creating project file & dir structure =====
===== Creating contracts directory =====
===== Creating tests directory =====
===== Creating deploy directory =====
===== Creating docker directory =====
===== ForgAE was successfully initialized! =====
➜  test2 forgae node

===== Node already started and healthy! =====
➜  test2 forgae test
===== Starting Tests =====


  Example Contract
    1) Deploying Example Contract


  0 passing (4s)
  1 failing

  1) Example Contract
       Deploying Example Contract:
     AssertionError: Could not deploy the ExampleContract Smart Contract: expected promise to be fulfilled but it was rejected with 'Error: While calling postTransaction (body), POST to http://localhost:3001/v2/transactions failed with 400: Invalid tx'

Screen:


#5

@nikita-fuchs I also thought the same thing when I was looking at the error message, but I haven’t hard-coded that address in the smart contract. I’m passing it as an argument to the deploy function.


#6

Managed to fix this.

For some reason

➜  test2 forgae -V
1.4.0

was initializing a project with

image

Tried forgae init --update without any luck.

Ended up deleting everything forgae related in the global npm packages, cleaned the npm cache (with --force).

Install forgae globally again and then initialized new project.

This is what worked for me, i assume there was a cached older version of forgae which was used and causing the problem, but then again as @kraykov said backwards compatibility breaking changes should be at least mentioned in the changelog.


#7

Hello @kraykov,

as already mentioned we are aware that some of the tutorials are outdated and don’t represent working state if the corresponding dependencies are in a newer version that at time the tutorial was written.

I do agree that we need to work on this and also put more effort in writing change logs and upgrade paths which should be documented in places like this: https://github.com/aeternity/aepp-sdk-js/releases

Please ensure you use [email protected]. I did setup forgae using forgae init and then forgae node to run my tests.

I setup a sample contract to reproduce your issues, it takes to arguments, address, amount to initialize and then has a function to spend this to address if funded.

contract ExampleContract =
  record state =
    { receiver : address
    , amount : int }

  public function init(receiver : address, amount : int) : state =
    { receiver = receiver, amount = amount }

  public function spend() =
    Chain.spend(state.receiver, state.amount)

In my tests I did choose to use the getContractInstance highlevel contract instance, which differs from the usual way forgae sets up the project. A contract instance keeps track of the state of the contract, e.g. its address and source when deployed to make calling very easy. This interface was introduced in sdk 2.4.0 and its usage id documented well in the changelog https://github.com/aeternity/aepp-sdk-js/blob/master/CHANGELOG.md#240-2019-04-17. I use it as follows in my test:

let contractSource = utils.readFileRelative('./contracts/ExampleContract.aes', "utf-8"); 

receiverPublicKey = wallets[1].publicKey; // globally defined as it will be reused in later tests

contract = await owner.getContractInstance(contractSource); // globally defined as it will be reused in later tests
let deploy = await contract.deploy([receiverPublicKey, 1000]); // address is as string in ak_ format

assert.equal(deploy.deployInfo.result.returnType, 'ok', 'Could not deploy Example Contract');

You can find the full code here: https://github.com/thepiwo/aeternity-kraykov-support
Also there is another project of mine which does this very similar at: https://github.com/aeternity/aepp-hybrid-voting/tree/master/multisig-contract

If you have any further questions let me know.


#8

@piwo, it is working that way. Thanks. I suggest to either change that in forgAE or make an example with “your way” (because it seems to be the working one), so other people don’t get in the same troubles I did.


#9

It should also be possible to keep using the non-high-level as documented here: https://github.com/aeternity/aepp-sdk-js/blob/develop/docs/api/ae/contract.md

(aepp-sdk-js repo readme -> usage documentation headline -> contract development)


#10

@piwo, nope.

Using compiled.deploy(init = [], options = {}) does not work.


#11

@kraykov I did adjust my example to use the low-level contracts api: https://github.com/thepiwo/aeternity-kraykov-support/commit/d066319df2f90571b96a03a058b00d93f143c782

according to the docs your deploy init will have to be initState
https://github.com/aeternity/aepp-sdk-js/blob/develop/docs/api/ae/contract.md contractDeploy


#12

and @kraykov, if you would like building on aeternity to be simple as the following example,

const ae = require("aepp-sdk");

// connect to a node
const myMainnetNode = ae.nodeProvider(“http://publicNode.aeternity.com/”, “ae_mainnet”, “cors-params”) 

// create contract reference
TokenContract = ae.fromArtifact(require(./MyToken.json)); // automatically taking latest deployment address for current net

// define which node to use
TokenContract.options.setNodeProvider(myMainnetNode);

//do a transaction
var oneTransaction = await TokenContract.methods.transfer("ak_xyz", 1337, {...tx params...})

//read data from latest contract state
var myTokenBalance = await TokenContract.methods.checkBalance("ak_xyz")

then you should express support for AEX 6 right here: AEX 6 - Strategic Semantic Syntax: Contract Interaction Wrapper !

currently a draft in: https://github.com/aeternity/AEXs/blob/956e06ef25c3088f0ff8c1012fcd510c56c0e5da/assets/aex-2/aex_SSS.md

No more headaches, that’s the goal.