Definition: [
"autonomous agent",
{
"bounce_fees": {
"base": 10000
},
"getters": "{
$isLicenseRevoked = $user=>{
return NOT NOT var["revoked_" || $user];
};
$isLicenseActive = $user =>{
return var["user_" || $user] >= timestamp AND NOT $isLicenseRevoked($user);
};
$timeRemainingOf = $user=>{
$stored = var["user_" || $user];
if (NOT $stored)
return 0;
return max($stored - timestamp, 0);
};
$licensePeriod = ()=>var["period"];
$periodPrice = ()=>var["price"];
$isTradeable = ()=>var["tradeable"];
$maxPeriods = ()=>var["maxPeriods"] OTHERWISE 31556952 * 100; // 100 years by default
$maxTopUpOf = ($user)=>{
$expiry = var["user_" || $user];
$currentPeriods = ($expiry - timestamp) / $licensePeriod();
$maxPeriodsInAdvance = $maxPeriods();
return $maxPeriodsInAdvance - $currentPeriods;
};
$topUpPrice = ($periods)=>{
$price = $periodPrice();
return $price * $periods;
};
$issuer = ()=>params.issuer;
$owner = ()=>var["owner"] OTHERWISE params.issuer;
$name = ()=>params.name;
$isHelper = ($user)=>var["helper_" || $user];
}",
"init": "{
$currentOwner = $owner();
$trig = trigger.initial_unit;
$data = $trig.messages[[.app="data"]];
$method = $data.method;
bounce(json_stringify($data));
if (NOT $method)
bounce("method field is mandatory");
$KRANGA_ADDRESS = "ZIT3YPDTLGAO7MVO2ONNDMSEYS2VELX6";
$SERVICE_FEE = 0.03;
$REFERRAL_FEE = 0.015;
$currency = var["currency"];
$PERIOD_PRICE = var["price"];
$IS_TRADEABLE = var["tradeable"];
$ASSET = var["asset"];
$PERIOD_DURATION = var["period"];
$CALLER_TIME_REMAINING = $timeRemainingOf(trigger.initial_address);
$REFERRAL_ADDRESS = $data["r"] AND is_valid_address($data["r"]) ? $data["r"] : false;
}",
"messages": {
"cases": [
{
"if": "{
trigger.address == $currentOwner AND
($method == "init" OR
$method == "payout" OR
$method == "changePrice" OR
$method == "setTradeable" OR
$method == "setMaxPeriods" OR
$method == "setPeriod" OR
$method == "toggleHelper" OR
$method == "transferOwnership")
}",
"messages": {
"cases": [
{
"if": "{$method == "toggleHelper"}",
"init": "{
if (NOT trigger.data["helper"])
bounce("helper field is mandatory");
if (NOT is_valid_address(trigger.data["helper"]))
bounce("Helper address is invalid");
}",
"messages": [
{
"app": "state",
"state": "{
var["helper_" || trigger.data["helper"]] = NOT var["helper_" || trigger.data["helper"]];
}"
}
]
},
{
"if": "{$method == "init"}",
"init": "{
if (var["price"])
bounce("The AA has already been initialized");
}",
"messages": [
{
"app": "asset",
"payload": {
"is_private": false,
"is_transferrable": true,
"auto_destroy": false,
"fixed_denominations": false,
"issued_by_definer_only": true,
"cosigned_by_definer": false,
"spender_attested": false
}
},
{
"app": "state",
"init": "{
if (NOT trigger.data["initialPrice"])
bounce("initialPrice field is mandatory");
if (NOT trigger.data["currency"] AND NOT is_valid_amount(trigger.data["initialPrice"]))
bounce("The price is not a valid amount");
if (trigger.data["initialPrice"] < 0)
bounce("The initial price must be >= 0");
if (trigger.data["maxPeriods"]){
if (NOT is_integer(trigger.data["maxPeriods"]))
bounce("maxPeriods must be an integer");
if (trigger.data["maxPeriods"] < 0)
bounce("maxPeriods must be a positive integer");
}
if (NOT is_integer(trigger.data["period"]))
bounce ("period must be an integer");
if (trigger.data["period"] < 0)
bounce("period must be positive");
if (trigger.data["currency"] AND NOT asset[trigger.data["currency"]].exists)
bounce("That currency does not exist");
}",
"state": "{
var["price"] = trigger.data["initialPrice"];
var["tradeable"] = NOT NOT trigger.data["tradeable"];
var["period"] = trigger.data["period"];
var["currency"] = trigger.data["currency"] OTHERWISE "base";
var["asset"] = response_unit;
}"
}
]
},
{
"if": "{$method == "payout"}",
"messages": [
{
"app": "payment",
"payload": {
"outputs": [
{
"address": "{$currentOwner}"
}
]
}
},
{
"if": "{balance[$currency] AND $currency != "base"}",
"app": "payment",
"payload": {
"asset": "{$currency}",
"outputs": [
{
"address": "{$currentOwner}"
}
]
}
},
{
"if": "{trigger.data["asset"] AND balance[trigger.data["asset"]]}",
"app": "payment",
"payload": {
"asset": "{trigger.data["asset"]}",
"outputs": [
{
"address": "{$currentOwner}"
}
]
}
}
]
},
{
"if": "{$method == "changePrice"}",
"init": "{
if (NOT trigger.data["price"])
bounce("price field is mandatory");
if (trigger.data["price"] < 0)
bounce("price must be positive");
else if (NOT is_valid_amount(trigger.data["price"]))
bounce("Price is not a valid amount");
}",
"messages": [
{
"app": "state",
"state": "{
var["price"] = trigger.data["price"];
if (trigger.data["currency"]){
var["currency"] = trigger.data["currency"];
}
}"
}
]
},
{
"if": "{$method == "setMaxPeriods"}",
"init": "{
if (NOT trigger.data["maxPeriods"])
bounce("maxPeriods field is mandatory");
if (trigger.data["maxPeriods"] < 0)
bounce("maxPeriods must be positive");
if (NOT is_integer(trigger.data["maxPeriods"]))
bounce("maxPeriods must be an integer");
}",
"messages": [
{
"app": "state",
"state": "{
var["maxPeriods"] = trigger.data["maxPeriods"];
}"
}
]
},
{
"if": "{$method == "setTradeable"}",
"messages": [
{
"app": "state",
"state": "{
var["tradeable"] = NOT $IS_TRADEABLE;
}"
}
]
},
{
"if": "{$method == "transferOwnership"}",
"init": "{
if (NOT trigger.data["address"])
bounce("address field is mandatory");
if (NOT is_valid_address(trigger.data["address"]))
bounce("The provided address is not a valid address");
}",
"messages": [
{
"app": "state",
"state": "{
var["owner"] = trigger.data["address"];
}"
}
]
}
]
}
},
{
"if": "{
($isHelper(trigger.address) OR trigger.address == $currentOwner) AND
(trigger.data["method"] == "toggleRevoked")
}",
"messages": {
"cases": [
{
"if": "{trigger.data["method"] == "toggleRevoked"}",
"init": "{
if (NOT trigger.data["user"])
bounce("user field is mandatory");
if (NOT is_valid_address(trigger.data["user"]))
bounce("user field is not a valid address");
}",
"messages": [
{
"app": "state",
"state": "{
var["revoked_" || trigger.data["user"]] = NOT var["revoked_" || trigger.data["user"]];
}"
}
]
}
]
}
},
{
"if": "{$method == "topup"}",
"init": "{
$_periodsToBuy = trigger.output[[asset=$currency]].amount / $PERIOD_PRICE;
$periodsToBuy = floor($_periodsToBuy, 0);
$maxTopup = $maxTopUpOf(trigger.initial_address);
$cut = round(trigger.output[[asset=$currency]].amount * ($REFERRAL_ADDRESS ? $REFERRAL_FEE : $SERVICE_FEE), 0);
if ($periodsToBuy == 0)
bounce("That's not enough to buy even a single license period");
if ($periodsToBuy > $maxTopup)
bounce("You can buy at most " || $maxTopup || " periods");
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$currency}",
"outputs": [
{
"address": "{$KRANGA_ADDRESS}",
"amount": "{$cut}"
},
{
"if": "{$REFERRAL_ADDRESS}",
"address": "{$data["r"]}",
"amount": "{$cut}"
}
]
}
},
{
"app": "state",
"state": "{
var["user_" || trigger.initial_address] = timestamp + ($CALLER_TIME_REMAINING OTHERWISE 0) + $periodsToBuy * $PERIOD_DURATION;
}"
}
]
},
{
"if": "{$method == "buy"}",
"init": "{
if (NOT $IS_TRADEABLE)
bounce("That license cannot be traded");
$amount = floor(trigger.output[[asset=$currency]].amount / $PERIOD_PRICE);
if ($amount < 1)
bounce("You cannot buy less than 1 license period. You are buying " || trigger.output[[asset=$currency]].amount / $PERIOD_PRICE || " " || trigger.output[[asset=$currency]].amount || $PERIOD_PRICE);
$cut = round(trigger.output[[asset=$currency]].amount * ($REFERRAL_ADDRESS ? $REFERRAL_FEE : $SERVICE_FEE), 0);
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$ASSET}",
"outputs": [
{
"address": "{trigger.initial_address}",
"amount": "{$amount}"
}
]
}
},
{
"app": "payment",
"payload": {
"asset": "{$currency}",
"outputs": [
{
"address": "{$KRANGA_ADDRESS}",
"amount": "{$cut}"
},
{
"if": "{$REFERRAL_ADDRESS}",
"address": "{$REFERRAL_ADDRESS}",
"amount": "{$cut}"
}
]
}
}
]
},
{
"if": "{$method == "deposit"}",
"init": "{
$periods = trigger.output[[asset=$ASSET]].amount;
}",
"messages": [
{
"app": "state",
"state": "{
var["user_" || trigger.initial_address] = timestamp + ($CALLER_TIME_REMAINING OTHERWISE 0) + $periods * $PERIOD_DURATION;
}"
}
]
},
{
"if": "{$method == "tip"}",
"init": "{
if (trigger.output[[asset!="base"]].asset == "ambigous")
bounce("You cannot tip several assets at the same time");
if (trigger.output[[asset!="base"]].asset != 'none'){
$assetCut = round(trigger.output[[asset!="base"]].amount * $SERVICE_FEE);
$asset = trigger.output[[asset!="base"]].asset;
$cut = round(trigger.output[[asset!="base"]].amount * $SERVICE_FEE);
}
else
$cut = round(trigger.output[[asset="base"]].amount * $SERVICE_FEE);
}",
"messages": [
{
"app": "payment",
"payload": {
"outputs": [
{
"amount": "{$cut}",
"address": "{$KRANGA_ADDRESS}"
}
]
}
},
{
"if": "{$asset}",
"app": "payment",
"payload": {
"asset": "{$asset}",
"outputs": [
{
"amount": "{$assetCut}",
"address": "{$KRANGA_ADDRESS}"
}
]
}
},
{
"app": "state",
"state": "{
if ($assetCut)
var["tip_" || $asset || "_" || trigger.initial_address] += trigger.output[[asset!="base"]].amount;
var["tip_base_" || trigger.initial_address] += trigger.output[[asset="base"]].amount;
}"
}
]
}
]
}
}
]