1.0.0 • Published 6 years ago

lemojs-lib v1.0.0

Weekly downloads
3
License
GPL-3.0
Repository
github
Last release
6 years ago

NPM

lemojs-lib

General purpose library for the LEMO blockchain.

Fork from eosjs

Usage (read-only)

Lemo = require('lemojs-lib') // Lemo = require('./src')

// lemo = Lemo.Localnet() // 127.0.0.1:8888
lemo = Lemo.Testnet() // testnet at lemo.io

// All API methods print help when called with no-arguments.
lemo.getBlock()

// Next, your going to need lemod running on localhost:8888

// If a callback is not provided, a Promise is returned
lemo.getBlock(1).then(result => {console.log(result)})

// Parameters can be sequential or an object
lemo.getBlock({block_num_or_id: 1}).then(result => console.log(result))

// Callbacks are similar
callback = (err, res) => {err ? console.error(err) : console.log(res)}
lemo.getBlock(1, callback)
lemo.getBlock({block_num_or_id: 1}, callback)

// Provide an empty object or a callback if an API call has no arguments
lemo.getInfo({}).then(result => {console.log(result)})

Configuration

Lemo = require('lemojs-lib') // Lemo = require('./src')

// Optional configuration..
config = {
  keyProvider: ['PrivateKeys...'], // WIF string or array of keys..
  httpEndpoint: 'http://127.0.0.1:8888',
  mockTransactions: () => 'pass', // or 'fail'
  transactionHeaders: (expireInSeconds, callback) => {
    callback(null/*error*/, headers)
  },
  expireInSeconds: 60,
  broadcast: true,
  debug: false,
  sign: true
}

lemo = Lemo.Localnet(config)
  • mockTransactions (optional)

    • pass - do not broadcast, always pretend that the transaction worked
    • fail - do not broadcast, pretend the transaction failed
    • null|undefined - broadcast as usual
  • transactionHeaders (optional) - manually calculate transaction header. This may be provided so lemojs-lib does not need to make header related API calls to eosd. This callback is called for every transaction.

Options

Options may be provided immediately after parameters.

Example: lemo.transfer(params, options)

options = {
  broadcast: true,
  sign: true,
  scope: null,
  authorization: null
}
  • scope {array<string>|string} - account name or names that may undergo a change in state.

    • If missing default scopes will be calculated.
    • If provided additional scopes will not be added.
    • Sorting is always performed.
  • authorization {array<auth>|auth} - identifies the signing account and permission typically in a multi-sig configuration. Authorization may be a string formatted as account@permission or an object<{account, permission}>.

    • If missing default authorizations will be calculated.
    • If provided additional authorizations will not be added.
    • Sorting is always performed (by account name).

Usage (read/write)

If you use the Testnet, you'll need to replace the private key in keyProvider.

Lemo = require('lemojs-lib') // Lemo = require('./src')

lemo = Lemo.Localnet({keyProvider: '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3'})

// Run with no arguments to print usage.
lemo.transfer()

// Usage with options (options are always optional)
options = {broadcast: false}
lemo.transfer({from: 'inita', to: 'initb', amount: 1, memo: ''}, options)

// Object or ordered args may be used.
lemo.transfer('inita', 'initb', 1, 'memo', options)

// A broadcast boolean may be provided as a shortcut for {broadcast: false}
lemo.transfer('inita', 'initb', 1, '', false)

Shorthand

Shorthand is available for some types such as Asset and Authority.

For example:

  • deposit: '1 EOS' is shorthand for 1.0000 EOS
  • owner: 'EOS6MRy..' is shorthand for {threshold: 1, keys: [key: 'EOS6MRy..', weight: 1]}
  • recovery: inita or inita@active is shorthand
    • {{threshold: 1, accounts: [..account: inita, permission: active, weight: 1]}}
    • inita@other would replace the permission active with other
Lemo = require('lemojs-lib') // Lemo = require('./src')

initaPrivate = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3'
initaPublic = 'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'
keyProvider = initaPrivate

lemo = Lemo.Localnet({keyProvider})

lemo.newaccount({
  creator: 'inita',
  name: 'mynewacct',
  owner: initaPublic,
  active: initaPublic,
  recovery: 'inita',
  deposit: '1 EOS'
})

Contract

Deploy a smart contract.

The setcode command accepts WASM text and converts this to binary before signing and broadcasting. For this, the Binaryen library is used. Because this is a large library it is not included in lemojs-lib by default.

Add binaryen to your project:

npm i binaryen

Import and include the library when you configure Lemo:

const binaryen = require('binaryen')
lemo = Lemo.Testnet({..., binaryen})

Complete example:

Lemo = require('lemojs-lib') // Lemo = require('./src')
let {ecc} = Lemo.modules

initaPrivate = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3'

// New deterministic key for the currency account.  Only use a simple
// seedPrivate in production if you want to give away money.
currencyPrivate = ecc.seedPrivate('currency')
currencyPublic = ecc.privateToPublic(currencyPrivate)

keyProvider = [initaPrivate, currencyPrivate]

//  Requires a large library, separate from the lemojs-lib bundle
// $ npm install binaryen
binaryen = require('binaryen')

lemo = Lemo.Localnet({keyProvider, binaryen})

lemo.newaccount({
  creator: 'inita',
  name: 'currency',
  owner: currencyPublic,
  active: currencyPublic,
  recovery: 'inita',
  deposit: '1 EOS'
})

contractDir = `${process.env.HOME}/lemoio/lemo/build/contracts/currency`
wast = fs.readFileSync(`${contractDir}/currency.wast`)
abi = fs.readFileSync(`${contractDir}/currency.abi`)

// Publish contract to the blockchain
lemo.setcode('currency', 0, 0, wast, abi)

// lemo.contract(code<string>, [options], [callback])
lemo.contract('currency').then(currency => {
  // Transfer is one of the actions in currency.abi 
  currency.transfer('currency', 'inita', 100)
})

Atomic Operations

Blockchain level atomic operations. All will pass or fail.

Lemo = require('lemojs-lib') // Lemo = require('./src')

keyProvider = [
  '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3',
  Lemo.modules.ecc.seedPrivate('currency')
]

testnet = Lemo.Localnet({keyProvider})

// if either transfer fails, both will fail (1 transaction, 2 messages)
testnet.transaction(lemo =>
  {
    lemo.transfer('inita', 'initb', 1, '')
    lemo.transfer('inita', 'initc', 1, '')
    // Returning a promise is optional (but handled as expected)
  }
  // [options],
  // [callback]
)

// transaction on a single contract
testnet.transaction('currency', currency => {
  currency.transfer('inita', 'initd', 1)
})

// mix contracts in the same transaction
testnet.transaction(['currency', 'lemo'], ({currency, lemo}) => {
  currency.transfer('inita', 'initd', 1)
  lemo.transfer('inita', 'initd', 1, '')
})

// contract lookups then transactions
testnet.contract('currency').then(currency => {
  currency.transaction(tr => {
    tr.transfer('inita', 'initd', 1)
    tr.transfer('initd', 'inita', 1)
  })
  currency.transfer('inita', 'inite', 1)
})

// Note, the contract method does not take an array.  Just use Await or yield
// if multiple contracts are needed outside of a transaction.

Usage (manual)

A manual transaction provides for more flexibility.

Lemo = require('lemojs-lib') // Lemo = require('./src')

lemo = Lemo.Localnet({keyProvider: '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3'})

lemo.transaction({
  scope: ['inita', 'initb'],
  messages: [
    {
      code: 'lemo',
      type: 'transfer',
      authorization: [{
        account: 'inita',
        permission: 'active'
      }],
      data: {
        from: 'inita',
        to: 'initb',
        amount: 7,
        memo: ''
      }
    }
  ]
})

Development

From time-to-time the lemojs-lib and lemod binary format will change between releases so you may need to start lemod with the --skip-transaction-signatures parameter to get your transactions to pass.

Note, package.json has a "main" pointing to ./lib. The ./lib folder is for es2015 code built in a separate step. If your changing and testing code, import from ./src instead.

Lemo = require('./src')

Use Node v8+ to package-lock.json.

Related Libraries

These libraries are exported from lemojs-lib or may be used separately.

var {api, ecc, json, Fcbuffer, format} = Lemo.modules
  • format ./format.md

    • Blockchain name validation
    • Asset string formatting
  • eosjs-api [Github, NPM]

    • Remote API to an EOS blockchain node (eosd)
    • Use this library directly if you need read-only access to the blockchain (don't need to sign transactions).
  • lemojs-lib-ecc [Github, NPM]

    • Private Key, Public Key, Signature, AES, Encryption / Decryption
    • Validate public or private keys
    • Encrypt or decrypt with EOS compatible checksums
    • Calculate a shared secret
  • eosjs-json [Github, NPM]

    • Blockchain definitions (api method names, blockchain operations, etc)
    • Maybe used by any language that can parse json
    • Kept up-to-date
  • lemojs-lib-keygen [Github, NPM]

    • private key storage and key management
  • Fcbuffer [Github, NPM]

    • Binary serialization used by the blockchain
    • Clients sign the binary form of the transaction
    • Essential so the client knows what it is signing

Browser

git clone https://github.com/LemoFoundationLtd/lemojs-lib.git
cd lemojs-lib
npm install
npm run build
# builds: ./dist/lemo.js
<script src="lemo.js"></script>
<script>
var lemo = Lemo.Testnet()
//...
</script>

Environment

Node 6+ and browser (browserify, webpack, etc)

React Native should work, create an issue if you find a bug.