140 lines
8.6 KiB
JavaScript
140 lines
8.6 KiB
JavaScript
const PricecasterLib = require('../lib/pricecaster')
|
|
const tools = require('../tools/app-tools')
|
|
const algosdk = require('algosdk')
|
|
const { expect } = require('chai')
|
|
const chai = require('chai')
|
|
chai.use(require('chai-as-promised'))
|
|
// Test general configuration for Betanet
|
|
|
|
const VALIDATOR_ADDR = 'OPDM7ACAW64Q4VBWAL77Z5SHSJVZZ44V3BAN7W44U43SUXEOUENZMZYOQU'
|
|
const VALIDATOR_MNEMO = '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 OTHER_ADDR = 'DMTBK62XZ6KNI7L5E6TRBTPB4B3YNVB4WYGSWR42SEV4XKV4LYHGBW4O34'
|
|
const OTHER_MNEMO = '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 SIGNATURES = {}
|
|
SIGNATURES[VALIDATOR_ADDR] = algosdk.mnemonicToSecretKey(VALIDATOR_MNEMO)
|
|
SIGNATURES[OTHER_ADDR] = algosdk.mnemonicToSecretKey(OTHER_MNEMO)
|
|
|
|
const VALID_SYMBOL = 'BTC/USD '
|
|
const VALID_PRICE = BigInt(485265555)
|
|
const VALID_EXPONENT = BigInt(4)
|
|
const VALID_CONF = BigInt(1400000)
|
|
const VALID_SLOT = BigInt(104566700)
|
|
|
|
function signCallback (sender, tx) {
|
|
const txSigned = tx.signTxn(SIGNATURES[sender].sk)
|
|
return txSigned
|
|
}
|
|
|
|
describe('Price-Keeper contract tests', function () {
|
|
let pclib
|
|
let algodClient
|
|
let appId
|
|
let lastTs
|
|
|
|
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, VALIDATOR_ADDR)
|
|
for (let i = 0; i < appsTo.length; i++) {
|
|
console.log('Clearing ' + appsTo[i].id)
|
|
try {
|
|
const txId = await pclib.deleteApp(VALIDATOR_ADDR, 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(VALIDATOR_ADDR, VALIDATOR_ADDR, VALID_SYMBOL, signCallback)
|
|
const txResponse = await pclib.waitForTransactionResponse(txId)
|
|
appId = pclib.appIdFromCreateAppResponse(txResponse)
|
|
pclib.setAppId(appId)
|
|
console.log('App Id: %d', appId)
|
|
})
|
|
it('Must create app with proper initial global state', async function () {
|
|
const stVAddr = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'vaddr')
|
|
const stSym = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'sym')
|
|
expect(Buffer.from(stSym, 'base64').toString()).to.equal(VALID_SYMBOL)
|
|
expect(stVAddr.toString()).to.equal(VALIDATOR_ADDR)
|
|
})
|
|
it('Must accept valid message and store data', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, VALID_SLOT, SIGNATURES[VALIDATOR_ADDR].sk)
|
|
const txid = await pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)
|
|
expect(txid).to.have.length(52)
|
|
await pclib.waitForTransactionResponse(txid)
|
|
// console.log(await tools.printAppGlobalState(algodClient, appId, VALIDATOR_ADDR))
|
|
const stPrice = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'price')
|
|
const stExp = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'exp')
|
|
const stConf = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'conf')
|
|
const stSlot = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'slot')
|
|
expect(stPrice.toString()).to.equal(VALID_PRICE.toString())
|
|
expect((Buffer.from(stExp, 'base64')).readBigInt64BE()).to.equal(VALID_EXPONENT)
|
|
expect(stSlot.toString()).to.equal(VALID_SLOT.toString())
|
|
expect(stConf.toString()).to.equal(VALID_CONF.toString())
|
|
})
|
|
it('Must accept second message with different price', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE + BigInt(400), VALID_EXPONENT + BigInt(3), VALID_CONF + BigInt(2), VALID_SLOT + BigInt(100), SIGNATURES[VALIDATOR_ADDR].sk)
|
|
const txid = await pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)
|
|
expect(txid).to.have.length(52)
|
|
await pclib.waitForTransactionResponse(txid)
|
|
const stPrice = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'price')
|
|
const stExp = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'exp')
|
|
const stConf = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'conf')
|
|
const stSlot = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'slot')
|
|
expect(stPrice.toString()).to.equal((VALID_PRICE + BigInt(400)).toString())
|
|
expect((Buffer.from(stExp, 'base64')).readBigInt64BE()).to.equal(VALID_EXPONENT + BigInt(3))
|
|
expect(stSlot.toString()).to.equal((VALID_SLOT + BigInt(100)).toString())
|
|
expect(stConf.toString()).to.equal((VALID_CONF + BigInt(2)).toString())
|
|
lastTs = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'ts')
|
|
})
|
|
it('Must accept negative exponent, stored as 2-complement 64bit', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, BigInt(-9), VALID_CONF, VALID_SLOT, SIGNATURES[VALIDATOR_ADDR].sk)
|
|
const txid = await pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)
|
|
expect(txid).to.have.length(52)
|
|
await pclib.waitForTransactionResponse(txid)
|
|
const stExp = await tools.readAppGlobalStateByKey(algodClient, appId, VALIDATOR_ADDR, 'exp')
|
|
const bufExp = Buffer.from(stExp, 'base64')
|
|
const val = bufExp.readBigInt64BE()
|
|
expect(val.toString()).to.equal('-9')
|
|
})
|
|
it('Must reject non-validator as signer', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, VALID_SLOT, SIGNATURES[OTHER_ADDR].sk)
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject non-validator as sender', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, VALID_SLOT, SIGNATURES[VALIDATOR_ADDR].sk)
|
|
await expect(pclib.submitMessage(OTHER_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject future timestamp', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, VALID_SLOT, SIGNATURES[VALIDATOR_ADDR].sk, undefined, undefined, undefined, BigInt(lastTs + 200))
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject old timestamp', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, VALID_SLOT, SIGNATURES[VALIDATOR_ADDR].sk, undefined, undefined, undefined, BigInt(lastTs - 999999))
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject zero-priced message', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, BigInt(0), VALID_EXPONENT, VALID_CONF, VALID_SLOT, SIGNATURES[VALIDATOR_ADDR].sk)
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject zero slot', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, BigInt(0), SIGNATURES[VALIDATOR_ADDR].sk)
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject bad header', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, BigInt(0), SIGNATURES[VALIDATOR_ADDR].sk, 'BADHEADER')
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject bad destination appId', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, BigInt(0), SIGNATURES[VALIDATOR_ADDR].sk, undefined, BigInt(100))
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
it('Must reject bad message version', async function () {
|
|
const msgBuffer = pclib.createMessage(VALID_SYMBOL, VALID_PRICE, VALID_EXPONENT, VALID_CONF, BigInt(0), SIGNATURES[VALIDATOR_ADDR].sk, undefined, undefined, 0)
|
|
await expect(pclib.submitMessage(VALIDATOR_ADDR, msgBuffer, signCallback)).to.be.rejectedWith('Bad Request')
|
|
})
|
|
})
|