Skip to content

Commit

Permalink
feat(Oracle): Oracle commands (#134)
Browse files Browse the repository at this point in the history
* feat(Oracle): Prepare structure for Oracle commands

* feat(Oracle): Add oracle register command

* feat(Oracle): Add oracle post query and get oracle command's

* feat(Oracle): Add Oracle respond query command

* feat(Oracle): Add Oracle extend command

* feat(Oracle): Adjust docs

* chore(node): bump node version to 5.5.4

* chore(build): regenerate lock

* fix(Test): Fix transaction builder test
  • Loading branch information
nduchak committed Jun 9, 2020
1 parent 8848a7b commit 05b079a
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 23 deletions.
128 changes: 128 additions & 0 deletions bin/aecli-oracle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env node
// # æternity CLI `name` file
//
// This script initialize all `name` commands
/*
* 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.
*/
// We'll use `commander` for parsing options
//
// Also we need `esm` package to handle `ES imports`
const program = require('commander')

require = require('esm')(module/*, options*/) //use to handle es6 import/export
const utils = require('./utils/index')
const { Oracle } = require('./commands')

// ## Initialize `options`
program
.option('-u, --url [hostname]', 'Node to connect to', utils.constant.NODE_URL)
.option('-U, --internalUrl [internal]', 'Node to connect to(internal)', utils.constant.NODE_INTERNAL_URL)
.option('--ttl [ttl]', 'Override the ttl that the transaction is going to be sent with', utils.constant.TX_TTL)
.option('--fee [fee]', 'Override the fee that the transaction is going to be sent with')
.option('--nonce [nonce]', 'Override the nonce that the transaction is going to be sent with')
.option('-P, --password [password]', 'Wallet Password')
.option('--networkId [networkId]', 'Network id (default: ae_mainnet)')
.option('-f --force', 'Ignore node version compatibility check')
.option('--json', 'Print result in json format', utils.constant.OUTPUT_JSON)

// ## Initialize `create` command
//
// You can use this command to `create` Oracle
//
// Example: `aecli oracle create ./myWalletKeyFile --password testpass string string`
//
// And wait until it will be mined. You can force waiting by using `--waitMined false` option. Default: true
//
// You can use `--ttl` to pre-set transaction `time to leave`
program
.command('create <wallet_path> <queryFormat> <responseFormat>')
.option('-M, --no-waitMined', 'Do not wait until transaction will be mined')
.option('--oracleTtl [oracleTtl]', 'Relative Oracle time to leave', utils.constant.ORACLE_TTL)
.option('--queryFee [queryFee]', 'Oracle query fee', utils.constant.QUERY_FEE)
.description('Register Oracle')
.action(async (walletPath, queryFormat, responseFormat, ...arguments) => await Oracle.createOracle(walletPath, queryFormat, responseFormat, utils.cli.getCmdFromArguments(arguments)))

// ## Initialize `extend oracle` command
//
// You can use this command to `extend` Oracle time to leave
//
// Example: `aecli oracle extend ./myWalletKeyFile --password testpass ok_12dasdgfa32fasf 200`
//
// And wait until it will be mined. You can force waiting by using `--waitMined false` option. Default: true
//
// You can use `--ttl` to pre-set transaction `time to leave`
program
.command('extend <wallet_path> <oracleId> <oracleTtl>')
.option('-M, --no-waitMined', 'Do not wait until transaction will be mined')
.description('Extend Oracle')
.action(async (walletPath, oracleId, oracleTtl, ...arguments) => await Oracle.extendOracle(walletPath, oracleId, oracleTtl, utils.cli.getCmdFromArguments(arguments)))

// ## Initialize `create oracle query` command
//
// You can use this command to `create` an Oracle Query
//
// Example: `aecli oracle create-query ./myWalletKeyFile --password testpass ok_123asdasd... WhatTheWeatherIs?`
//
// And wait until it will be mined. You can force waiting by using `--waitMined false` option. Default: true
//
// You can use `--ttl` to pre-set transaction `time to leave`
program
.command('create-query <wallet_path> <oracleId> <query>')
.option('-M, --no-waitMined', 'Do not wait until transaction will be mined')
.option('--responseTtl [responseTtl]', 'Query response time to leave', utils.constant.RESPONSE_TTL)
.option('--queryTtl [queryTtl]', 'Query time to leave', utils.constant.QUERY_TTL)
.option('--queryFee [queryFee]', 'Oracle query fee', utils.constant.QUERY_FEE)
.description('Create Oracle query')
.action(async (walletPath, oracleId, query, ...arguments) => await Oracle.createOracleQuery(walletPath, oracleId, query, utils.cli.getCmdFromArguments(arguments)))

// ## Initialize `respond query` command
//
// You can use this command to `respond` to Oracle Query
//
// Example: `aecli oracle respondQuery ./myWalletKeyFile --password testpass ok_12313... oq_12efdsafa... +16Degree`
//
// And wait until it will be mined. You can force waiting by using `--waitMined false` option. Default: true
//
// You can use `--ttl` to pre-set transaction `time to leave`
program
.command('respond-query <wallet_path> <oracleId> <queryId> <response>')
.option('-M, --no-waitMined', 'Do not wait until transaction will be mined')
.option('--responseTtl [responseTtl]', 'Query response time to leave', utils.constant.RESPONSE_TTL)
.description('Respond to Oracle Query')
.action(async (walletPath, oracleId, queryId, response, ...arguments) => await Oracle.respondToQuery(walletPath, oracleId, queryId, response, utils.cli.getCmdFromArguments(arguments)))

// ## Initialize `get oracle` command
//
// You can use this command to `get` an Oracle
//
// Example: `aecli oracle respondQuery ./myWalletKeyFile --password testpass ok_12313... oq_12efdsafa... +16Degree`
//
// And wait until it will be mined. You can force waiting by using `--waitMined false` option. Default: true
//
// You can use `--ttl` to pre-set transaction `time to leave`
program
.command('get <oracleId>')
.description('Get Oracle')
.action(async (oracleId, ...arguments) => await Oracle.queryOracle(oracleId, utils.cli.getCmdFromArguments(arguments)))


// Handle unknown command's
program.on('command:*', () => utils.errors.unknownCommandHandler(program)())

// Parse arguments or show `help` if argument's is empty
program.parse(process.argv)
if (program.args.length === 0) program.help()
4 changes: 2 additions & 2 deletions bin/aecli-tx.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ program
.option('-T, --ttl [ttl]', 'Validity of the transaction in number of blocks (default forever)', utils.constant.TX_TTL)
.option('-F, --fee [fee]', 'Transaction fee.')
.option('--queryFee [queryFee]', 'Oracle Query fee.', utils.constant.QUERY_FEE)
.option('--oracleTtl [oracleTtl]', 'Oracle Ttl.', utils.constant.ORACLE_TTL)
.option('--oracleTtl [oracleTtl]', 'Oracle Ttl.', utils.constant.ORACLE_TTL.value)
.description('Build oracle register transaction.')
.action(async (accountId, queryFormat, responseFormat, nonce, ...arguments) => await Transaction.oracleRegister(accountId, queryFormat, responseFormat, nonce, utils.cli.getCmdFromArguments(arguments)))

Expand All @@ -169,7 +169,7 @@ program
.option('-T, --ttl [ttl]', 'Validity of the transaction in number of blocks (default forever)', utils.constant.TX_TTL)
.option('-F, --fee [fee]', 'Transaction fee.')
.option('--queryFee [queryFee]', 'Oracle Query fee.', utils.constant.QUERY_FEE)
.option('--queryTtl [oracleTtl]', 'Oracle Ttl.', utils.constant.QUERY_TTL)
.option('--queryTtl [oracleTtl]', 'Oracle Ttl.', utils.constant.QUERY_TTL.value)
.option('--responseTtl [oracleTtl]', 'Oracle Ttl.', utils.constant.RESPONSE_TTL)
.description('Build oracle post query transaction.')
.action(async (accountId, oracleId, query, nonce, ...arguments) => await Transaction.oraclePostQuery(accountId, oracleId, query, nonce, utils.cli.getCmdFromArguments(arguments)))
Expand Down
4 changes: 1 addition & 3 deletions bin/aecli.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ const EXECUTABLE_CMD = [
{ name: 'contract', desc: 'Compile contracts' },
{ name: 'name', desc: 'AENS system' },
{ name: 'tx', desc: 'Transaction builder' },
/* TODO implement oracle module
* {name: 'oracle', desc: 'Interact with oracles'},
*/
{name: 'oracle', desc: 'Interact with oracles'},
{ name: 'crypto', desc: 'Crypto helpers' }
]
// ##Get version from `package.json`
Expand Down
1 change: 1 addition & 0 deletions bin/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { Inspect } from './inspect'
export { Account } from './account'
export { AENS } from './aens'
export { Transaction } from './transaction'
export { Oracle } from './oracle'
191 changes: 191 additions & 0 deletions bin/commands/oracle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#!/usr/bin/env node
// # æternity CLI `contract` file
//
// This script initialize all `contract` function
/*
* 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.
*/

import { exit, initChain, initClientByWalletFile } from '../utils/cli'
import { handleApiError } from '../utils/errors'
import { printError, print, printTransaction, printOracle, printQueries } from '../utils/print'
import { BUILD_ORACLE_TTL } from '../utils/constant';
import { assertedType } from '@aeternity/aepp-sdk/es/utils/crypto';


// ## Create Oracle
async function createOracle (walletPath, queryFormat, responseFormat, options) {
const { ttl, fee, nonce, waitMined, json, oracleTtl, queryFee } = options

try {
const client = await initClientByWalletFile(walletPath, options)
await handleApiError(async () => {
// Register Oracle
const oracle = await client.registerOracle(
queryFormat,
responseFormat,
{ ttl,
waitMined,
nonce,
fee,
oracleTtl: isNaN(parseInt(oracleTtl)) ? oracleTtl : BUILD_ORACLE_TTL(oracleTtl),
queryFee
}
)
if (waitMined) {
printTransaction(
oracle,
json
)
} else {
print('Transaction send to the chain. Tx hash: ', oracle)
}
exit()
})
} catch (e) {
printError(e.message)
exit(1)
}
}

// ## Extend Oracle
async function extendOracle (walletPath, oracleId, oracleTtl, options) {
const { ttl, fee, nonce, waitMined, json } = options

try {
if (isNaN(+oracleTtl)) throw new Error('Oracle Ttl should be a number')
if (!assertedType(oracleId, 'ok', true)) throw new Error('Invalid oracleId')
const client = await initClientByWalletFile(walletPath, options)
await handleApiError(async () => {
const oracle = await client.getOracleObject(oracleId)
const extended = await oracle.extendOracle(
BUILD_ORACLE_TTL(oracleTtl),
{ ttl,
waitMined,
nonce,
fee,
}
)
if (waitMined) {
printTransaction(
extended,
json
)
} else {
print('Transaction send to the chain. Tx hash: ', extended)
}
exit()
})
} catch (e) {
printError(e.message)
exit(1)
}
}

// ## Create Oracle Query
async function createOracleQuery (walletPath, oracleId, query, options) {
const { ttl, fee, nonce, waitMined, json, queryTll, queryFee, responseTtl } = options

try {
if (!assertedType(oracleId, 'ok', true)) throw new Error('Invalid oracleId')
const client = await initClientByWalletFile(walletPath, options)

await handleApiError(async () => {
const oracle = await client.getOracleObject(oracleId)
const oracleQuery = await oracle.postQuery(query, {
ttl,
waitMined,
nonce,
fee,
queryTll: isNaN(parseInt(queryTll)) ? queryTll : BUILD_ORACLE_TTL(queryTll),
responseTtl: isNaN(parseInt(responseTtl)) ? responseTtl : BUILD_ORACLE_TTL(responseTtl),
queryFee
})
if (waitMined) {
printTransaction(
oracleQuery,
json
)
} else {
print('Transaction send to the chain. Tx hash: ', oracleQuery)
}
exit()
})
} catch (e) {
printError(e.message)
exit(1)
}
}

// ## Respond to Oracle Query
async function respondToQuery (walletPath, oracleId, queryId, response, options) {
const { ttl, fee, nonce, waitMined, json, responseTtl } = options

try {
if (!assertedType(oracleId, 'ok', true)) throw new Error('Invalid oracleId')
if (!assertedType(queryId, 'oq', true)) throw new Error('Invalid queryId')
const client = await initClientByWalletFile(walletPath, options)

await handleApiError(async () => {
const oracle = await client.getOracleObject(oracleId)
const queryResponse = await oracle.respondToQuery(queryId, response, {
ttl,
waitMined,
nonce,
fee,
responseTtl: isNaN(parseInt(responseTtl)) ? responseTtl : BUILD_ORACLE_TTL(responseTtl)
})
if (waitMined) {
printTransaction(
queryResponse,
json
)
} else {
print('Transaction send to the chain. Tx hash: ', queryResponse)
}
exit()
})
} catch (e) {
printError(e.message)
exit(1)
}
}

// ## Get oracle
async function queryOracle (oracleId, options) {
try {
if (!assertedType(oracleId, 'ok', true)) throw new Error('Invalid oracleId')
const client = await initChain(options)
await handleApiError(async () => {
const oracle = await client.getOracle(oracleId)
const { oracleQueries: queries } = await client.getOracleQueries(oracleId)
printOracle(oracle, options.json)
printQueries(queries, options.json)
exit()
})
} catch (e) {
printError(e.message)
exit(1)
}
}

export const Oracle = {
createOracle,
extendOracle,
queryOracle,
createOracleQuery,
respondToQuery
}
12 changes: 6 additions & 6 deletions bin/utils/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export {
// # CONTRACT
ABI_VERSIONS,
VM_VERSIONS,
VM_TYPE
VM_TYPE,
ORACLE_TTL,
QUERY_TTL,
QUERY_FEE,
} from '@aeternity/aepp-sdk/es/tx/builder/schema'

// ## HAST TYPES
Expand All @@ -49,8 +52,8 @@ export const HASH_TYPES = {
}

// ## CONNECTION
export const NODE_URL = 'http://localhost:3013'
export const NODE_INTERNAL_URL = 'http://localhost:3113'
export const NODE_URL = 'https://sdk-testnet.aepps.com'
export const NODE_INTERNAL_URL = 'https://sdk-testnet.aepps.com'
export const NODE_WEBSOCKET_URL = 'https://sdk-testnet.aepps.com'
export const COMPILER_URL = 'http://localhost:3080'

Expand All @@ -69,10 +72,7 @@ export const ORACLE_VM_VERSION = 0
export const AMOUNT = 0

// ## ORACLE
export const QUERY_FEE = 30000
export const BUILD_ORACLE_TTL = (ttl) => { return { type: 'delta', value: ttl } }
export const ORACLE_TTL = 500
export const QUERY_TTL = 10
export const RESPONSE_TTL = 10

// ## Default transaction build param's
Expand Down

0 comments on commit 05b079a

Please sign in to comment.