Macros specification
Last updated
Last updated
This page describes an overview of all macros that a Nana indexer should implement and make available to a program's method.
Some macros described here are of type view
. Any methods that are of type view
are restricted to only being able to call other "view
" macros. If a method is of type "view
" and attempts to call state-changing
macros, the NIP is invalid and will not be whitelisted.
View macros are prefixed with $
(just like NIP methods)
A macro (whether its view
or state_changing
) can error. A macro should only error because of the reasons specified in this document. If a macro errors while processing a banana, a rotten banana is produced. Producing a rotten banana requires the changes inside the transaction to be reverted and therefore program balances and states must be revertible - see for how this should be implemented.
Type | Can produce rotten banana? |
---|---|
The alloc()
macro takes in 3 parameters:
alloc(sender, recipient, nana, amount)
This function unallocates nanas from sender
and allocates them to recipient
nana
and amount
specify how much (amount
) of the nana (nana
)should be sent from the sender
to the recipient
(which is the opposite of whatever sender is)
If sender
does not have enough of nana
to satisfy the transfer of amount
, the function should error and therefore produce a rotten banana.
If nana
is set to all
, every nana balance from sender
is unallocated and allocated to recipient
with the amount
field being ignored. If a nana is set to all_recursive
and sender is a programId, all of the Nanas from the program and its boxes are unallocated and allocated to recipient. If sender is not of type programId, all_recursive
's logic is identical to all
.
If amount
is set to all
, all of nana
from sender
is unallocated and allocated to recipient
The following edge cases for parameters are considered invalid and produce a rotten banana:
nana
must be a valid Nana existing in sender
's balance or be a string of "all" or "all_recursive". If neither present it is considered invalid.
An amount
that overflows an LEB128 or is not "all" is considered invalid.
recipient
is a program that wasn't included in the NIPs use
return field.
The set()
macro takes 2 parameters:
set(key, value)
Under the hood every program on creation is assigned a JSON object - which they can alter by setting a key
, which sets a field in this object.
A key
can be separated with :
, which causes the key string to be split with :
with the items in the array referring to a field tree.
Example:
Is stored as:
If any parent specified by key
does not exist, the parent field and all child fields are recursively created.
Furthermore, the following edge cases should error and produce a rotten banana:
A set's key
parameter starts with :
A set's key
parameter ends with :
A set's key
parameter has any repeating :
A set's key
parameter attempts to assign a value (or a field tree) to an existing field already specifying a field tree (rather than just a value)
A set's key
parameter attempts to assign a field tree to an already existing value.
A set's value
parameter is not a string or integer.
A set's value
parameter is an integer that overflows an LEB128.
A field tree has a depth of more than 10 fields
The indexer also needs to keep track of the total byte size used by all value
parameters on all sets
in a transaction's call tree. If at any point this tracker goes over 1000 bytes, set()
should error a rotten banana should be produced.
set(program, method, params)
The call()
method allows any state_changing
method to call any other state_changing
method from another program or itself. 0:0
can be used to call a state_changing
method from itself (using the actual program id of self to call itself is considered invalid and such NIPs will not be whitelisted) while 0:nip_id
can be used to call a method from another NIP.
If params is excluded, the default of [0,0,0,0,0]
will be set instead
The call's return is inherited from whatever program or method it is calling (which can only be a String
or u128
)
Example:
Furthermore, the following edge cases should error and produce a rotten banana:
Every state_changing
function has the same type for the params field (vector of 5 uints) - anything other than this is considered invalid and error.
If the method being called was not imported in the programs use
export field, the method is invalid and will error.
In the future ProgramId
will be block:tx
, with the pointer being to an inscription specifying the Programs code. However, since this is currently disabled ( Programs ) - any "block" that is non-0 will be considered invalid and error.
The inherit() method takes in 1 parameter:
inherit(program)
This method deep clones another programs storage into its own storage, overriding and deleting anything that previously existed there.
Furthermore, the following edge cases should error and produce a rotten banana:
A valid program is not provided (parameter is malformed, or program does not exist)
Program wasnt imported with use
The assert view method takes in one parameter:
balance(expression)
This method evaluates an expression to a boolean, exiting and erroring the program (and therefore producing a rotten banana) if it evaluates to false
, or continuing with execution and having no effect if it evaluates to true
.
Furthermore, the following edge cases should error and produce a rotten banana:
expression is not of type boolean
The assert view method takes in one parameter:
exit(expression)
This method will forcefully exit the execution of a method. The method will be valid and change the Nana state if expression evaluates to true
or produce a rotten banana and revert changes from the call if expression evaluates to false
.
Furthermore, the following edge cases should error and produce a rotten banana:
expression is not of type boolean
The balance view method takes in two parameters:
balance(sender, nana)
This view method gets the total balance of nana
from to the programs balance (self
) or the unallocated nana payload (unallocated
) or vice versa. You can switch between the check by using the string self
or the string nana
Returns -> This method returns a u128
repreenting the nana
balance of sender
.
Furthermore, the following edge cases should error and produce a rotten banana:
The Nana being referred to with NanaID doesn't exist (note, if the nana does exist but simply isnt in the balance this will return "0", but will not error)
Sender is not a string that is equivalent to self
or unallocated
The hash view method takes in two parameter:
$sha256elided(value)
value
can be any input string into the sha256 hash function
-> Returns
The return value is a u128 representation of the hash, constructed from output bytes with the last 16 being elided.
Furthermore, the following edge cases should error and produce a rotten banana:
Value is not a string
Uses math.random() to produce a random integer.... just kidding hehe
The random view method takes in two parameters:
$random(min, max)
This view method gets a seed by running the following macros:
Then a range is determined with min and max:
Then using range seed is normalized to an integer between min and max
This normalized integer represents a random int within the scope of the block. Note - blockhashe's can be manipulated by miners, which the function depends on for the seed
. This should not be used in scenarios where a "correct value" encourages MEV. Such NIPs will be discarded.
Implementation in Javascript (returns BigInt):
-> Returns
u128
Furthermore, the following edge cases should error and produce a rotten banana:
Any of the parameters are malformed (min and max are not u128s)
The get view method takes in one parameter:
get(key)
Returns a value
from a programs local storage.
A key
can be separated with :
, which causes the key string to be split with :
with the items in the array referring to a field tree.
-> Returns
The exists
field is a boolean that checks for the existence of a non-fieldtree value at key
.
The value
field represents a string
or a u128
that represents the value stored at that specific field on the programs storage. If exists is false, this field will be set to NULL.
Furthermore, the following edge cases should error and produce a rotten banana:
A get's key
parameter starts with :
A get's key
parameter ends with :
A get's key
parameter has any repeating :
A field tree has a depth of more than 10 fields
The block view method takes in one parameter:
$block(key)
Is able to fetch headers from the current block with key
. A map of available values can be found below:
-> Returns
Furthermore, the following edge cases should error and produce a rotten banana:
The key
field isn't a valid property listed in the table above (or is not of type string)
The sender view method takes in no parameters:
$sender()
Returns the owning address of the first vin
UTXO in a transaction's inputs that had Nanas allocated . In the case no input utxo had nanas present, output will be "GENESIS"
Furthermore, the following edge cases should error:
The view function is called outside the scope of a Banana process. This macro cannot produce a rotten banana, however, since if called within the processing of a Banana it will always have a sender assigned.
sender
can only "unallocated
" as a string, an existing programId, or a "Box" inside a program ( ) . Anything else is considered invalid.
Note -> Any methods in the call tree (called with call()
) inherit the ability to use the balance of its parents. See
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
The call() method takes in 3 parameters (with params being in the same format specified in )
Type | Can produce rotten banana? |
---|---|
The only real usecase for this method is incase of a disable_tx
scenario taking place, with a new NIP being deployed to fix issues in a previous NIP. You can learn more about this here:
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
Type | Can produce rotten banana? |
---|---|
key | value |
---|---|
Type | Can produce rotten banana? |
---|---|
state_changing
yes
state_changing
yes
state_changing
yes
view
yes
view
yes
view
yes
view
yes
view
yes
view
yes
view
yes
hash
String
: the block's hash
merkleroot
String
: the merkle root of the block
time
u64
: The block time in seconds since epoch (Jan 1 1970 GMT)
height
u32
: The blocks height or index
ntx
u16
: Number of transactions in the block
view
no
state_changing
yes