Definition: [
"autonomous agent",
{
"bounce_fees": {
"base": 10000
},
"init": "{
$HOUSE_CUT = 0.03; //We charge a 3% fee on all sales
$BYTES_IN_GBYTE = 1000000000;
if (NOT trigger.data["method"])
bounce("method field is mandatory");
$method = trigger.data["method"];
$spendableFunds = balance["base"] - storage_size; //The max amount I can withdraw without bouncing
$owner = var["owner"];
$oracle = var["oracle"]; //Used for GBYTE_USD price
}",
"messages": {
"cases": [
{
"if": "{
NOT $owner //The owner has not been set
}",
"messages": [
{
"app": "state",
"state": "{
var["owner"] = "IUU43O7TS2TBYKAPGKUARDZHOTAE275A";
var["oracle"] = "F4KHJUCLJKY4JV7M5F754LAJX4EB7M4N";
}"
}
]
},
{
"if": "{
trigger.address == $owner
AND ($method == "payout" //We also check the method so the Owner can also act as an user
OR $method == "mint"
OR $method == "stopSale"
OR $method == "transferOwnership"
OR $method == "setOracle")
}",
"messages": {
"cases": [
{
"if": "{
$method == "payout"
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{trigger.address}",
"amount": "{$spendableFunds}"
}
]
}
}
]
},
{
"if": "{
$method == "transferOwnership"
}",
"init": "{
if (NOT trigger.data["newOwner"])
bounce("newOwner field is mandatory");
if (NOT is_valid_address(trigger.data["newOwner"]))
bounce("newOwner field is not a valid address");
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{trigger.address}",
"amount": "{$spendableFunds}"
}
]
}
},
{
"app": "state",
"state": "{
var["owner"] = trigger.data["newOwner"];
}"
}
]
},
{
"if": "{
$method == "mint"
}",
"init": "{
if (NOT exists(trigger.data["amount"]))
bounce("amount field is mandatory. Set it to 0 for unlimited");
if ((NOT is_valid_amount(trigger.data["amount"])) AND trigger.data["amount"] != 0) //amount=0 => uncapped
bounce("The amount of NFT copies to mint is not valid");
$price = trigger.data["priceUSD"] OTHERWISE trigger.data["price"];
if (NOT $price)
bounce("price or priceUSD field must be filled");
if (NOT trigger.data["title"])
bounce("title field is mandatory");
if (NOT trigger.data["priceUSD"]){ //It is priced in bytes
if ($price < 20000)
bounce("The minium price is 20000 bytes");
if (NOT is_valid_amount($price))
bounce("price is not valid");
}
if (NOT trigger.data["ipfs"]) //meta.json
bounce("ipfs field is mandatory");
if (exists(trigger.data["validity"])){
if (NOT is_integer(trigger.data["validity"]))
bounce("validity must be an integer");
if (trigger.data["validity"] <= 0)
bounce("You cannot make a license valid for 0s");
}
if (NOT is_valid_address(trigger.data["seller"]))
bounce("The seller address is not valid");
$pendingNaming = var["NFT_" || var["pendingNaming"]]; //Previosly issued NFT
}",
"messages": {
"cases": [
{
"if": "{
trigger.data["amount"]
}",
"messages": [
{
"app": "asset",
"payload": {
"cap": "{trigger.data["amount"]}",
"is_private": false,
"is_transferrable": "{trigger.data["tranferrable"]}",
"auto_destroy": false,
"fixed_denominations": false,
"issued_by_definer_only": true,
"cosigned_by_definer": false,
"spender_attested": false
}
},
{
"app": "data",
"if": "{
$pendingNaming
}",
"payload": {
"asset": "{var["recordToData"]}",
"name": "{$pendingNaming.title || "license"}",
"author": "{$pendingNaming.seller}",
"ipfs": "{$pendingNaming.ipfs}",
"type": "LIC",
"decimals": 0
}
},
{
"app": "state",
"state": "{
var["NFT_" || response_unit] = {
price: trigger.data["price"] OTHERWISE false,
priceUSD: trigger.data["priceUSD"] OTHERWISE false,
title: trigger.data["title"],
ipfs: trigger.data["ipfs"],
author: trigger.data["seller"],
validity: trigger.data["validity"],
onSale: true
};
var["pendingNaming"] = response_unit;
}"
}
]
},
{
"messages": [
{
"app": "asset",
"payload": {
"is_private": false,
"is_transferrable": "{trigger.data["tranferrable"] OTHERWISE false}",
"auto_destroy": false,
"fixed_denominations": false,
"issued_by_definer_only": true,
"cosigned_by_definer": false,
"spender_attested": false
}
},
{
"app": "data",
"if": "{
$pendingNaming
}",
"payload": {
"asset": "{var["recordToData"]}",
"name": "{$pendingNaming.title OTHERWISE "Untitled"}",
"author": "{$pendingNaming.seller}",
"ipfs": "{$pendingNaming.ipfs}",
"type": "LIC",
"decimals": 0
}
},
{
"app": "state",
"state": "{
var["NFT_" || response_unit] = {
price: trigger.data["price"] OTHERWISE false,
priceUSD: trigger.data["priceUSD"] OTHERWISE false,
title: trigger.data["title"],
ipfs: trigger.data["ipfs"], //Hash of the content
author: trigger.data["seller"], //The original seller
onSale: true
};
var["recordToData"] = response_unit;
}"
}
]
}
]
}
},
{
"if": "{
$method == "setOracle"
}",
"init": "{
if (NOT is_valid_address(trigger.data["oracle"]))
bounce("Invalid oracle address");
if (NOT data_feed[[oracles=trigger.data["oracle"], feed_name="GBYTE_USD", ifseveral="last"]])
bounce("That oracle is not posting a GBYTE_USD datafeed");
}",
"messages": [
{
"app": "state",
"state": "{
var["oracle"] = trigger.data["oracle"];
}"
}
]
}
]
}
},
{
"if": "{
$method == "END_SALE"
}",
"init": "{
if (NOT trigger.data["NFT"])
bounce("NFT field is mandatory");
$NFT = var["NFT_" || trigger.data["NFT"]];
if (NOT $NFT)
bounce("That NFT is not known by this AA");
if (trigger.address != $NFT.author AND trigger.address != $owner) //The owner can also stops sales (as we expect authors losing their private keys)
bounce("You cannot stop a sale not created by yourself");
}",
"messages": [
{
"app": "state",
"state": "{
var["NFT_" || trigger.data["NFT"]] ||= {onSale: false};
}"
}
]
},
{
"if": "{
trigger.data["method"] == "BUY"
}",
"init": "{
$NFT = var["NFT_" || trigger.data["NFT"]];
if (NOT $NFT.onSale)
bounce("That NFT is not on sale");
$expectedAmount = $NFT.price
? $NFT.price
: round($NFT.priceUSD * 1 / data_feed[[oracles=$oracle, feed_name="GBYTE_USD", ifseveral="last"]] * $BYTES_IN_GBYTE, 0);
if (trigger.output[[asset="base"]].amount < $expectedAmount)
bounce("Your payment is lower than the NFT price. You have to send " || $expectedAmount || " bytes");
$pendingNaming = var["NFT_" || var["recordToData"]];
}",
"messages": [
{
"app": "payment",
"if": "{
floor($expectedAmount * (1 - $HOUSE_CUT), 0) > 0
}",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{$NFT.author}",
"amount": "{floor($expectedAmount * (1 - $HOUSE_CUT), 0)}"
}
]
}
},
{
"app": "payment",
"payload": {
"asset": "{trigger.data['NFT']}",
"outputs": [
{
"address": "{trigger.address}",
"amount": 1
}
]
}
},
{
"app": "data",
"if": "{
$pendingNaming
}",
"payload": {
"asset": "{var["recordToData"]}",
"name": "{$pendingNaming.title OTHERWISE "Untitled"}",
"author": "{$pendingNaming.seller}",
"ipfs": "{$pendingNaming.ipfs}",
"type": "LIC",
"decimals": 0
}
},
{
"app": "state",
"state": "{
if ($pendingNaming){
var["recordToData"] = false;
}
if ($NFT.validity){
var[trigger.data["NFT"] || trigger.data["address"]] = timestamp + $NFT.validity;
}
}"
}
]
},
{
"if": "{
$method == "CHANGE_PRICE"
}",
"init": "{
if (NOT trigger.data["NFT"])
bounce("NFT field is mandatory");
$NFT = var["NFT_" || trigger.data["NFT"]];
if (NOT $NFT)
bounce("NFT not found");
if ($NFT.author != trigger.address)
bounce("You can only change the price of your own licenses!");
if (NOT exists(trigger.data["price"]))
bounce("price field is mandatory");
if (NOT is_integer(trigger.data["price"]))
bounce("price must be an integer");
if (NOT is_valid_amount(trigger.data["price"]))
bounce("price is invalid");
}",
"messages": [
{
"app": "state",
"state": "{
var["NFT_" || trigger.data["NFT"]] ||= {
price: $NFT.price ? trigger.data["price"] : false,
priceUSD: $NFT.priceUSD ? trigger.data["price"] : false
};
}"
}
]
},
{
"if": "{
$method == "REDEEM"
}",
"init": "{
if (NOT exists(trigger.data["spack"]))
bounce("You need to provide a signed package");
$spack = json_parse(trigger.data["spack"]);
if (NOT is_valid_signed_package($spack, $spack.authors[0].address))
bounce("The signed message signature is invalid");
if (NOT $spack.signed_message.NFT)
bounce("The signer of this message did not include a NFT field");
$NFT = var["NFT_" || $spack.signed_message.NFT];
//Check if sale is over and expire was set in the signed message. Otherwise the NFT can be redeemed even if the sale was over.
if ($spack.signed_message.expireDate){
if ($spack.signed_message.expireDate < timestamp)
bounce("That license is no longer claimable");
}
$signedAmount = $spack.signed_message.amount OTHERWISE 1;
if (NOT $NFT.cap)
$amount = $signedAmount;
//If it is going over the cap we need to reduce the claimed amount to match the asset cap
else{
if ($NFT.unitsSold + $signedAmount > $NFT.cap)
$amount = $NFT.cap - $NFT.unitsSold;
else
$amount = $signedAmount;
}
//All units were issued
if ($amount == 0)
bounce("All units of that NFT have been already minted");
if ($NFT.author != $spack.authors[0].address)
bounce("The signer of that message is not the author of that NFT");
if (NOT $NFT)
bounce("That NFT does not exist");
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$spack.signed_message.NFT}",
"outputs": [
{
"address": "{trigger.address}",
"amount": "{$amount}"
}
]
}
},
{
"app": "state",
"state": "{
if (var["FREE_" || $spack.signed_message.NFT])
var["FREE_" || $spack.signed_message.NFT] ||= {unitsSold: $NFT.unitsSold + $amount};
else
var["NFT_" || $spack.signed_message.NFT] ||= {unitsSold: $NFT.unitsSold + $amount};
}"
}
]
}
]
}
}
]