UNPKG

@aeternity/aepp-sdk

Version:
89 lines (81 loc) 4.06 kB
#!/usr/bin/env node // # Simple Sophia Contract Compiler // // This script demonstrates how to deal with the different phases of compiling // Sophia contracts to bytecode, deploying the bytecode to get a callable // contract address and ultimately, invoke the deployed contract on the // æternity blockchain. /* * ISC License (ISC) * Copyright (c) 2018 aeternity developers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ 'use strict' // We'll need the main client module `Ae` in the `Universal` flavor from the SDK. const { Universal: Ae } = require('@aeternity/aepp-sdk') const program = require('commander') const fs = require('fs') function exec (infile, fn, args) { if (!infile || !fn) { program.outputHelp() process.exit(1) } const code = fs.readFileSync(infile, 'utf-8') // Most methods in the SDK return _Promises_, so the recommended way of // dealing with subsequent actions is `then` chaining with a final `catch` // callback. // `Ae` itself is asynchronous as it determines the node's version and // rest interface automatically. Only once the Promise is fulfilled, we know // we have a working ae client. Please take note `Ae` is not a constructor but // a factory factory, which means it's *not* invoked with `new`. // `contractCompile` takes a raw Sophia contract in string form and sends it // off to the node for bytecode compilation. This might in the future be done // without talking to the node, but requires a bytecode compiler // implementation directly in the SDK. Ae({ url: program.host, debug: program.debug, process }).then(ae => { return ae.contractCompile(code) // Invoking `deploy` on the bytecode object will result in the contract // being written to the chain, once the block has been mined. // Sophia contracts always have an `init` method which needs to be invoked, // even when the contract's `state` is `unit` (`()`). The arguments to // `init` have to be provided at deployment time and will be written to the // block as well, together with the contract's bytecode. }).then(bytecode => { console.log(`Obtained bytecode ${bytecode.bytecode}`) return bytecode.deploy({ initState: program.init }) // Once the contract has been successfully mined, we can attempt to invoke // any public function defined within it. The miner who found the next block // will not only be rewarded a fixed amount, but also an amount depending on // the amount of gas spend. }).then(deployed => { console.log(`Contract deployed at ${deployed.address}`) return deployed.call(fn, { args: args.join(' ') }) // The execution result, if successful, will be an AEVM-encoded result // value. Once type decoding will be implemented in the SDK, this value will // not be a hexadecimal string, anymore. }).then(value => { console.log(`Execution result: ${value}`) }).catch(e => console.log(e.message)) } // ## Command Line Interface // // The `commander` library provides maximum command line parsing convenience. program .version('0.1.0') .arguments('<infile> <function> [args...]') .option('-i, --init [state]', 'Arguments to contructor function') .option('-H, --host [hostname]', 'Node to connect to', 'http://localhost:3013') .option('--debug', 'Switch on debugging') .action(exec) .parse(process.argv)