Creation successful. Fixes + test deployment Betanet
This commit is contained in:
parent
0559f2c6b0
commit
43e68eb9b8
|
@ -1,16 +1,14 @@
|
||||||
const algosdk = require('algosdk')
|
const algosdk = require('algosdk')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const { exit } = require('process')
|
const tools = require('../tools/app-tools')
|
||||||
const tools = require('./tools/app-tools')
|
|
||||||
|
|
||||||
const approvalProgramFilename = 'contracts/price-keeper.teal'
|
const approvalProgramFilename = 'teal/pricekeeper.teal'
|
||||||
const clearProgramFilename = 'contracts/clearstate.teal'
|
const clearProgramFilename = 'teal/clearstate.teal'
|
||||||
|
|
||||||
class PricecasterLib {
|
class PricecasterLib {
|
||||||
constructor (algodClient, ownerAddr = undefined, assetId = 0) {
|
constructor (algodClient, ownerAddr = undefined) {
|
||||||
this.algodClient = algodClient
|
this.algodClient = algodClient
|
||||||
this.ownerAddr = ownerAddr
|
this.ownerAddr = ownerAddr
|
||||||
this.assetId = assetId
|
|
||||||
this.minFee = 1000
|
this.minFee = 1000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,15 +20,6 @@ class PricecasterLib {
|
||||||
this.appId = applicationId
|
this.appId = applicationId
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the wALGO asset id used in all the functions of this class.
|
|
||||||
* @param {number} assId asset id
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
this.setAssetId = function (assId) {
|
|
||||||
this.assetId = assId
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get minimum fee to pay for transactions.
|
* Get minimum fee to pay for transactions.
|
||||||
* @return {Number} minimum transaction fee
|
* @return {Number} minimum transaction fee
|
||||||
|
@ -126,8 +115,7 @@ class PricecasterLib {
|
||||||
* @return {String} base64 string containing the compiled program
|
* @return {String} base64 string containing the compiled program
|
||||||
*/
|
*/
|
||||||
this.compileApprovalProgram = async function (validatorAddress) {
|
this.compileApprovalProgram = async function (validatorAddress) {
|
||||||
let program = fs.readFileSync(approvalProgramFilename, 'utf8')
|
const program = fs.readFileSync(approvalProgramFilename, 'utf8')
|
||||||
program = program.replace(/TMPL_VALIDATOR/g, validatorAddress)
|
|
||||||
return this.compileProgram(program)
|
return this.compileProgram(program)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,11 +134,11 @@ class PricecasterLib {
|
||||||
* @param {Function} signCallback callback with prototype signCallback(sender, tx) used to sign transactions
|
* @param {Function} signCallback callback with prototype signCallback(sender, tx) used to sign transactions
|
||||||
* @return {String} transaction id of the created application
|
* @return {String} transaction id of the created application
|
||||||
*/
|
*/
|
||||||
this.createApp = async function (sender, validatorAddr, signCallback) {
|
this.createApp = async function (sender, validatorAddr, symbol, signCallback) {
|
||||||
const localInts = 2
|
const localInts = 0
|
||||||
const localBytes = 3
|
const localBytes = 0
|
||||||
const globalInts = 0
|
const globalInts = 2
|
||||||
const globalBytes = 0
|
const globalBytes = 4
|
||||||
|
|
||||||
// declare onComplete as NoOp
|
// declare onComplete as NoOp
|
||||||
const onComplete = algosdk.OnApplicationComplete.NoOpOC
|
const onComplete = algosdk.OnApplicationComplete.NoOpOC
|
||||||
|
@ -161,14 +149,17 @@ class PricecasterLib {
|
||||||
params.fee = this.minFee
|
params.fee = this.minFee
|
||||||
params.flatFee = true
|
params.flatFee = true
|
||||||
|
|
||||||
const approvalProgramCompiled = await this.compileApprovalProgram(validatorAddr)
|
const approvalProgramCompiled = await this.compileApprovalProgram()
|
||||||
const clearProgramCompiled = await this.compileClearProgram()
|
const clearProgramCompiled = await this.compileClearProgram()
|
||||||
|
|
||||||
|
const enc = new TextEncoder()
|
||||||
|
const appArgs = [new Uint8Array(algosdk.decodeAddress(validatorAddr).publicKey), enc.encode(symbol)]
|
||||||
|
|
||||||
// create unsigned transaction
|
// create unsigned transaction
|
||||||
const txApp = algosdk.makeApplicationCreateTxn(
|
const txApp = algosdk.makeApplicationCreateTxn(
|
||||||
sender, params, onComplete,
|
sender, params, onComplete,
|
||||||
approvalProgramCompiled, clearProgramCompiled,
|
approvalProgramCompiled, clearProgramCompiled,
|
||||||
localInts, localBytes, globalInts, globalBytes
|
localInts, localBytes, globalInts, globalBytes, appArgs
|
||||||
)
|
)
|
||||||
const txId = txApp.txID().toString()
|
const txId = txApp.txID().toString()
|
||||||
|
|
||||||
|
@ -240,6 +231,37 @@ class PricecasterLib {
|
||||||
return txId
|
return txId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permanent delete the application.
|
||||||
|
* @param {String} sender owner account
|
||||||
|
* @param {Function} signCallback callback with prototype signCallback(sender, tx) used to sign transactions
|
||||||
|
* @param {Function} applicationId use this application id instead of the one set
|
||||||
|
* @return {String} transaction id of one of the transactions of the group
|
||||||
|
*/
|
||||||
|
this.deleteApp = async function (sender, signCallback, applicationId) {
|
||||||
|
// get node suggested parameters
|
||||||
|
const params = await this.algodClient.getTransactionParams().do()
|
||||||
|
|
||||||
|
params.fee = this.minFee
|
||||||
|
params.flatFee = true
|
||||||
|
|
||||||
|
if (!applicationId) {
|
||||||
|
applicationId = this.appId
|
||||||
|
}
|
||||||
|
|
||||||
|
// create unsigned transaction
|
||||||
|
const txApp = algosdk.makeApplicationDeleteTxn(sender, params, applicationId)
|
||||||
|
const txId = txApp.txID().toString()
|
||||||
|
|
||||||
|
// Sign the transaction
|
||||||
|
const txAppSigned = signCallback(sender, txApp)
|
||||||
|
|
||||||
|
// Submit the transaction
|
||||||
|
await this.algodClient.sendRawTransaction(txAppSigned).do()
|
||||||
|
|
||||||
|
return txId
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to wait until transaction txId is included in a block/round.
|
* Helper function to wait until transaction txId is included in a block/round.
|
||||||
* @param {String} txId transaction id to wait for
|
* @param {String} txId transaction id to wait for
|
|
@ -4,7 +4,7 @@
|
||||||
"description": "Experimentation with pyth",
|
"description": "Experimentation with pyth",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha"
|
"test": "mocha --timeout 60000"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
#pragma version 5
|
#pragma version 5
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
// Pricecaster Program
|
// PriceKeeper Approval Program
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
//
|
//
|
||||||
// This contract has the following invariants at
|
|
||||||
// deployment stage:
|
|
||||||
//
|
|
||||||
// TMPL_VALIDATOR Unique data validator address that signs and sends the incoming message
|
|
||||||
//
|
|
||||||
// App-globals:
|
// App-globals:
|
||||||
// symbol : byte[] pair supported by this app.
|
// sym : byte[] Symbol to keep price for
|
||||||
|
// vaddr : byte[] Validator account
|
||||||
// nonce : uint64 last sequence ID
|
// nonce : uint64 last sequence ID
|
||||||
// price : byte[] current price
|
// price : byte[] current price
|
||||||
// stdev : byte[] current confidence (standard deviation)
|
// stdev : byte[] current confidence (standard deviation)
|
||||||
|
@ -43,7 +39,7 @@
|
||||||
int 0
|
int 0
|
||||||
txn ApplicationID
|
txn ApplicationID
|
||||||
==
|
==
|
||||||
bnz success
|
bnz handle_create
|
||||||
|
|
||||||
// Handle app call: send price message
|
// Handle app call: send price message
|
||||||
txn OnCompletion
|
txn OnCompletion
|
||||||
|
@ -51,9 +47,37 @@ int NoOp
|
||||||
==
|
==
|
||||||
bnz handle_call
|
bnz handle_call
|
||||||
|
|
||||||
|
// Handle deletion.
|
||||||
|
txn OnCompletion
|
||||||
|
int DeleteApplication
|
||||||
|
==
|
||||||
|
bnz success
|
||||||
|
|
||||||
// Fail otherwise
|
// Fail otherwise
|
||||||
err
|
err
|
||||||
|
|
||||||
|
handle_create:
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// Handle creation
|
||||||
|
// Arg 0: Validator address
|
||||||
|
// Arg 1: Symbol to keep price data
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
byte "vaddr"
|
||||||
|
txn ApplicationArgs 0
|
||||||
|
app_global_put
|
||||||
|
|
||||||
|
byte "sym"
|
||||||
|
txn ApplicationArgs 1
|
||||||
|
dup
|
||||||
|
len
|
||||||
|
int 16
|
||||||
|
==
|
||||||
|
assert
|
||||||
|
app_global_put
|
||||||
|
|
||||||
|
b success
|
||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// Receive price message
|
// Receive price message
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
|
@ -62,7 +86,8 @@ handle_call:
|
||||||
|
|
||||||
// Verify if sender is the data validator
|
// Verify if sender is the data validator
|
||||||
txn Sender
|
txn Sender
|
||||||
addr PIQHXRVFDP4KSEZUPW6TB4UCDVJ5GJ3YYJIQWKWMEW2AUHJJCHPB4GPNCU
|
byte "vaddr"
|
||||||
|
app_global_get
|
||||||
==
|
==
|
||||||
assert
|
assert
|
||||||
|
|
||||||
|
@ -141,6 +166,8 @@ load 0
|
||||||
extract 98 32
|
extract 98 32
|
||||||
|
|
||||||
// Unpack pubkey X,Y components
|
// Unpack pubkey X,Y components
|
||||||
|
byte "vaddr"
|
||||||
|
app_global_get
|
||||||
ecdsa_pk_decompress Secp256k1
|
ecdsa_pk_decompress Secp256k1
|
||||||
|
|
||||||
// Verify signature
|
// Verify signature
|
|
@ -0,0 +1,50 @@
|
||||||
|
const PricecasterLib = require('../lib/pricecaster')
|
||||||
|
const tools = require('../tools/app-tools')
|
||||||
|
const algosdk = require('algosdk')
|
||||||
|
// Test general configuration for Betanet
|
||||||
|
|
||||||
|
const validatorAddr = 'OPDM7ACAW64Q4VBWAL77Z5SHSJVZZ44V3BAN7W44U43SUXEOUENZMZYOQU'
|
||||||
|
const validatorMnemo = 'assault approve result rare float sugar power float soul kind galaxy edit unusual pretty tone tilt net range pelican avoid unhappy amused recycle abstract master'
|
||||||
|
const otherAddr = 'DMTBK62XZ6KNI7L5E6TRBTPB4B3YNVB4WYGSWR42SEV4XKV4LYHGBW4O34'
|
||||||
|
const otherMnemo = 'old agree harbor cost pink fog chunk hope vital used rural soccer model acquire clown host friend bring marriage surge dirt surge slab absent punch'
|
||||||
|
const symbol = 'BTC/USD '
|
||||||
|
const signatures = {}
|
||||||
|
signatures[validatorAddr] = algosdk.mnemonicToSecretKey(validatorMnemo)
|
||||||
|
signatures[otherAddr] = algosdk.mnemonicToSecretKey(otherMnemo)
|
||||||
|
|
||||||
|
function signCallback (sender, tx) {
|
||||||
|
const txSigned = tx.signTxn(signatures[sender].sk)
|
||||||
|
return txSigned
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Price-Keeper contract tests', function () {
|
||||||
|
let pclib
|
||||||
|
let algodClient
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
algodClient = new algosdk.Algodv2('', 'https://api.betanet.algoexplorer.io', '')
|
||||||
|
pclib = new PricecasterLib.PricecasterLib(algodClient)
|
||||||
|
|
||||||
|
console.log('Clearing accounts of all previous apps...')
|
||||||
|
const appsTo = await tools.readCreatedApps(algodClient, validatorAddr)
|
||||||
|
for (let i = 0; i < appsTo.length; i++) {
|
||||||
|
console.log('Clearing ' + appsTo[i].id)
|
||||||
|
try {
|
||||||
|
const txId = await pclib.deleteApp(validatorAddr, signCallback, appsTo[i].id)
|
||||||
|
await pclib.waitForConfirmation(txId)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Could not delete application! Reason: ' + e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Creating new app...')
|
||||||
|
const txId = await pclib.createApp(validatorAddr, validatorAddr, symbol, signCallback)
|
||||||
|
const txResponse = await pclib.waitForTransactionResponse(txId)
|
||||||
|
const appId = pclib.appIdFromCreateAppResponse(txResponse)
|
||||||
|
pclib.setAppId(appId);
|
||||||
|
console.log('App Id: %d', appId)
|
||||||
|
})
|
||||||
|
it('x', function () {
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,270 @@
|
||||||
|
/*************************************************************************
|
||||||
|
* [2018] - [2020] Rand Labs Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* NOTICE: All information contained herein is, and remains
|
||||||
|
* the property of Rand Labs Inc.
|
||||||
|
* The intellectual and technical concepts contained
|
||||||
|
* herein are proprietary to Rand Labs Inc.
|
||||||
|
*/
|
||||||
|
const sha512 = require('js-sha512')
|
||||||
|
const hibase32 = require('hi-base32')
|
||||||
|
|
||||||
|
const ALGORAND_ADDRESS_SIZE = 58
|
||||||
|
|
||||||
|
function timeoutPromise (ms, promise) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
reject(new Error('promise timeout'))
|
||||||
|
}, ms)
|
||||||
|
promise.then(
|
||||||
|
(res) => {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInt64Bytes (x, len) {
|
||||||
|
if (!len) {
|
||||||
|
len = 8
|
||||||
|
}
|
||||||
|
const bytes = new Uint8Array(len)
|
||||||
|
do {
|
||||||
|
len -= 1
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
bytes[len] = x & (255)
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
x >>= 8
|
||||||
|
} while (len)
|
||||||
|
return bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
function addressFromByteBuffer (addr) {
|
||||||
|
const bytes = Buffer.from(addr, 'base64')
|
||||||
|
|
||||||
|
// compute checksum
|
||||||
|
const checksum = sha512.sha512_256.array(bytes).slice(28, 32)
|
||||||
|
|
||||||
|
const c = new Uint8Array(bytes.length + checksum.length)
|
||||||
|
c.set(bytes)
|
||||||
|
c.set(checksum, bytes.length)
|
||||||
|
|
||||||
|
const v = hibase32.encode(c)
|
||||||
|
|
||||||
|
return v.toString().slice(0, ALGORAND_ADDRESS_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
function printAppCallDeltaArray (deltaArray) {
|
||||||
|
for (let i = 0; i < deltaArray.length; i++) {
|
||||||
|
if (deltaArray[i].address) {
|
||||||
|
console.log('Local state change address: ' + deltaArray[i].address)
|
||||||
|
for (let j = 0; j < deltaArray[i].delta.length; j++) {
|
||||||
|
printAppCallDelta(deltaArray[i].delta[j])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Global state change')
|
||||||
|
printAppCallDelta(deltaArray[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function printAppStateArray (stateArray) {
|
||||||
|
for (let n = 0; n < stateArray.length; n++) {
|
||||||
|
printAppState(stateArray[n])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function appValueState (stateValue) {
|
||||||
|
let text = ''
|
||||||
|
|
||||||
|
if (stateValue.type == 1) {
|
||||||
|
const addr = addressFromByteBuffer(stateValue.bytes)
|
||||||
|
if (addr.length == ALGORAND_ADDRESS_SIZE) {
|
||||||
|
text += addr
|
||||||
|
} else {
|
||||||
|
text += stateValue.bytes
|
||||||
|
}
|
||||||
|
} else if (stateValue.type == 2) {
|
||||||
|
text = stateValue.uint
|
||||||
|
} else {
|
||||||
|
text += stateValue.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
function appValueStateString (stateValue) {
|
||||||
|
let text = ''
|
||||||
|
|
||||||
|
if (stateValue.type == 1) {
|
||||||
|
const addr = addressFromByteBuffer(stateValue.bytes)
|
||||||
|
if (addr.length == ALGORAND_ADDRESS_SIZE) {
|
||||||
|
text += addr
|
||||||
|
} else {
|
||||||
|
text += stateValue.bytes
|
||||||
|
}
|
||||||
|
} else if (stateValue.type == 2) {
|
||||||
|
text += stateValue.uint
|
||||||
|
} else {
|
||||||
|
text += stateValue.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
function printAppState (state) {
|
||||||
|
let text = Buffer.from(state.key, 'base64').toString() + ': '
|
||||||
|
|
||||||
|
text += appValueStateString(state.value)
|
||||||
|
|
||||||
|
console.log(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function printAppLocalState (algodClient, appId, accountAddr) {
|
||||||
|
const ret = await readAppLocalState(algodClient, appId, accountAddr)
|
||||||
|
if (ret) {
|
||||||
|
console.log('Application %d local state for account %s:', appId, accountAddr)
|
||||||
|
printAppStateArray(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function printAppGlobalState (algodClient, appId, accountAddr) {
|
||||||
|
const ret = await readAppGlobalState(algodClient, appId, accountAddr)
|
||||||
|
if (ret) {
|
||||||
|
console.log('Application %d global state:', appId)
|
||||||
|
printAppStateArray(ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readCreatedApps (algodClient, accountAddr) {
|
||||||
|
const accountInfoResponse = await algodClient.accountInformation(accountAddr).do()
|
||||||
|
return accountInfoResponse['created-apps']
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readOptedInApps (algodClient, accountAddr) {
|
||||||
|
const accountInfoResponse = await algodClient.accountInformation(accountAddr).do()
|
||||||
|
return accountInfoResponse['apps-local-state']
|
||||||
|
}
|
||||||
|
|
||||||
|
// read global state of application
|
||||||
|
async function readAppGlobalState (algodClient, appId, accountAddr) {
|
||||||
|
const accountInfoResponse = await algodClient.accountInformation(accountAddr).do()
|
||||||
|
for (let i = 0; i < accountInfoResponse['created-apps'].length; i++) {
|
||||||
|
if (accountInfoResponse['created-apps'][i].id === appId) {
|
||||||
|
const globalState = accountInfoResponse['created-apps'][i].params['global-state']
|
||||||
|
|
||||||
|
return globalState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readAppGlobalStateByKey (algodClient, appId, accountAddr, key) {
|
||||||
|
const accountInfoResponse = await algodClient.accountInformation(accountAddr).do()
|
||||||
|
for (let i = 0; i < accountInfoResponse['created-apps'].length; i++) {
|
||||||
|
if (accountInfoResponse['created-apps'][i].id === appId) {
|
||||||
|
// console.log("Application's global state:")
|
||||||
|
const stateArray = accountInfoResponse['created-apps'][i].params['global-state']
|
||||||
|
for (let j = 0; j < stateArray.length; j++) {
|
||||||
|
const text = Buffer.from(stateArray[j].key, 'base64').toString()
|
||||||
|
|
||||||
|
if (key === text) {
|
||||||
|
return appValueState(stateArray[j].value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read local state of application from user account
|
||||||
|
async function readAppLocalState (algodClient, appId, accountAddr) {
|
||||||
|
const accountInfoResponse = await algodClient.accountInformation(accountAddr).do()
|
||||||
|
for (let i = 0; i < accountInfoResponse['apps-local-state'].length; i++) {
|
||||||
|
if (accountInfoResponse['apps-local-state'][i].id === appId) {
|
||||||
|
// console.log(accountAddr + " opted in, local state:")
|
||||||
|
|
||||||
|
if (accountInfoResponse['apps-local-state'][i]['key-value']) {
|
||||||
|
return accountInfoResponse['apps-local-state'][i]['key-value']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readAppLocalStateByKey (algodClient, appId, accountAddr, key) {
|
||||||
|
const accountInfoResponse = await algodClient.accountInformation(accountAddr).do()
|
||||||
|
for (let i = 0; i < accountInfoResponse['apps-local-state'].length; i++) {
|
||||||
|
if (accountInfoResponse['apps-local-state'][i].id === appId) {
|
||||||
|
const stateArray = accountInfoResponse['apps-local-state'][i]['key-value']
|
||||||
|
|
||||||
|
if (!stateArray) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
for (let j = 0; j < stateArray.length; j++) {
|
||||||
|
const text = Buffer.from(stateArray[j].key, 'base64').toString()
|
||||||
|
|
||||||
|
if (key === text) {
|
||||||
|
return appValueState(stateArray[j].value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// not found assume 0
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function uintArray8ToString (byteArray) {
|
||||||
|
return Array.from(byteArray, function (byte) {
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
return ('0' + (byte & 0xFF).toString(16)).slice(-2)
|
||||||
|
}).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if transactionResponse has any information about a transaction local or global state change.
|
||||||
|
* @param {Object} transactionResponse object containing the transaction response of an application call
|
||||||
|
* @return {Boolean} returns true if there is a local or global delta meanining that
|
||||||
|
* the transaction made a change in the local or global state
|
||||||
|
*/
|
||||||
|
function anyAppCallDelta (transactionResponse) {
|
||||||
|
return (transactionResponse['global-state-delta'] || transactionResponse['local-state-delta'])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print to stdout the changes introduced by the transaction that generated the transactionResponse if any.
|
||||||
|
* @param {Object} transactionResponse object containing the transaction response of an application call
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
function printAppCallDelta (transactionResponse) {
|
||||||
|
if (transactionResponse['global-state-delta'] !== undefined) {
|
||||||
|
console.log('Global State updated:')
|
||||||
|
printAppCallDeltaArray(transactionResponse['global-state-delta'])
|
||||||
|
}
|
||||||
|
if (transactionResponse['local-state-delta'] !== undefined) {
|
||||||
|
console.log('Local State updated:')
|
||||||
|
printAppCallDeltaArray(transactionResponse['local-state-delta'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
timeoutPromise,
|
||||||
|
getInt64Bytes,
|
||||||
|
addressFromByteBuffer,
|
||||||
|
printAppStateArray,
|
||||||
|
printAppState,
|
||||||
|
printAppLocalState,
|
||||||
|
printAppGlobalState,
|
||||||
|
readCreatedApps,
|
||||||
|
readOptedInApps,
|
||||||
|
readAppGlobalState,
|
||||||
|
readAppGlobalStateByKey,
|
||||||
|
readAppLocalState,
|
||||||
|
readAppLocalStateByKey,
|
||||||
|
uintArray8ToString,
|
||||||
|
anyAppCallDelta,
|
||||||
|
printAppCallDelta
|
||||||
|
}
|
Loading…
Reference in New Issue