function big(str) {
if (str.slice(0, 2) == '0x') {
return new BigNumber(str.slice(2), 16);
}
return new BigNumber(str);
}
// Time window: 1 week
var window = 1000 * 3600 * 24 * 7;
// Limit : 1 lax
var limit = new BigNumber('1e18');
function isLimitOk(transaction) {
var value = big(transaction.value);
// Start of our window function
var windowstart = new Date().getTime() - window;
var txs = [];
var stored = storage.get('txs');
if (stored != '') {
txs = JSON.parse(stored);
}
// First, remove all that have passed out of the time-window
var newtxs = txs.filter(function (tx) {
return tx.tstamp > windowstart;
});
console.log(txs, newtxs.length);
// Secondly, aggregate the current sum
sum = new BigNumber(0);
sum = newtxs.reduce(function (agg, tx) {
return big(tx.value).plus(agg);
}, sum);
console.log('ApproveTx > Sum so far', sum);
console.log('ApproveTx > Requested', value.toNumber());
// Would we exceed weekly limit ?
return sum.plus(value).lt(limit);
}
function ApproveTx(r) {
if (isLimitOk(r.transaction)) {
return 'Approve';
}
return 'Nope';
}
/**
* OnApprovedTx(str) is called when a transaction has been approved and signed. The parameter
* 'response_str' contains the return value that will be sent to the external caller.
* The return value from this method is ignore - the reason for having this callback is to allow the
* ruleset to keep track of approved transactions.
*
* When implementing rate-limited rules, this callback should be used.
* If a rule responds with neither 'Approve' nor 'Reject' - the tx goes to manual processing. If the user
* then accepts the transaction, this method will be called.
*
* TLDR; Use this method to keep track of signed transactions, instead of using the data in ApproveTx.
*/
function OnApprovedTx(resp) {
var value = big(resp.tx.value);
var txs = [];
// Load stored transactions
var stored = storage.get('txs');
if (stored != '') {
txs = JSON.parse(stored);
}
// Add this to the storage
txs.push({ tstamp: new Date().getTime(), value: value });
storage.put('txs', JSON.stringify(txs));
}