| title |
Transferring Tokens - Part 1 |
| actions |
|
| material |
| editor |
| language |
startingCode |
answer |
c# |
public class AlienFinder : SmartContract {
...
// Complete (1) and (2) HERE
public static string name () => "Alien";
public static string symbol () => "ALI";
public static BigInteger totalSupply () => getCounter ();
public static byte decimals () => 0;
public static BigInteger balanceOf (byte[] addr) {
if (addr.Length != 20)
throw new InvalidOperationException ("The parameter owner should be a 20-byte address");
BigInteger balance = 0;
byte[] value = Storage.Get(addr);
if (value != null)
balance = value.ToBigInteger();
return balance;
}
public static byte[] ownerOf (byte[] id) {
Alien a = Query (id);
if (a != null) return a.Owner;
return null;
}
public static Alien[] tokensOf (byte[] owner) {
if (owner.Length != 20)
throw new InvalidOperationException ("The parameter owner should be a 20-byte address");
int balance = (int) balanceOf (owner);
Alien[] tokens = new Alien[balance + 1];
int idx = 0;
for (BigInteger id = 1; id <= totalSupply (); id = id + 1) {
Alien token = Query (id.ToByteArray ());
if (token != null && token.Owner == owner) {
tokens[idx] = token;
idx = idx + 1;
}
}
return tokens;
}
public static bool transfer (byte[] to, byte[] tokenid) {
// Complete (3) HERE
// Complete (4) HERE
Alien token =
// Complete (5) HERE
}
}
|
public class AlienFinder : SmartContract {
...
public static event Action<byte[], byte[], byte[]> Transfer;
public static void OnTransfer (byte[] from, byte[] to, byte[] tokenId) {
if (Transfer != null)
Transfer (from, to, tokenId);
}
public static string name () => "Alien";
public static string symbol () => "ALI";
public static BigInteger totalSupply () => getCounter ();
public static byte decimals () => 0;
public static BigInteger balanceOf (byte[] addr) {
if (addr.Length != 20)
throw new InvalidOperationException ("The parameter owner should be a 20-byte address");
BigInteger balance = 0;
byte[] value = Storage.Get(addr);
if (value != null)
balance = value.ToBigInteger();
return balance;
}
public static byte[] ownerOf (byte[] id) {
Alien a = Query (id);
if (a != null) return a.Owner;
return null;
}
public static Alien[] tokensOf (byte[] owner) {
if (owner.Length != 20)
throw new InvalidOperationException ("The parameter owner should be a 20-byte address");
int balance = (int) balanceOf (owner);
Alien[] tokens = new Alien[balance + 1];
int idx = 0;
for (BigInteger id = 1; id <= totalSupply (); id = id + 1) {
Alien token = Query (id.ToByteArray ());
if (token != null && token.Owner == owner) {
tokens[idx] = token;
idx = idx + 1;
}
}
return tokens;
}
public static bool transfer (byte[] to, byte[] tokenid) {
if (to.Length != 20)
throw new InvalidOperationException ("The parameter owner should be a 20-byte address");
Alien token = Query (tokenid);
if (token == null)
throw new InvalidOperationException ("Invalid Alien token id");
if (!Runtime.CheckWitness (token.Owner)) return false;
}
}
|
|
|
Now that the other components of our token is implemented according to the NEP-11 standard, we can define the function that performs a token transaction.
According to the specification, an event must trigger when tokens are transferred. For non-divisible tokens such as Aliens, such events have three parameters: byte[] from, byte[] to, byte[] tokenid.
- Define a
Transfer event, its signature should be Action<T, T, T> with three appropriate types.
- Define an
OnTransfer () event handler. It has three appropriate parameters and calls the Transfer event when it is not null.
Before performing the transfer, we need to check the validity of the parameters. A transfer cannot be carried out if either to address or tokenid is invalid, or if the caller of the contract is not the token's owner.
- Raise
InvalidOperationException if to is not a byte[] of Length 20. Error message: "The parameter owner should be a 20-byte address"
- Raise
InvalidOperationException if tokenid does not point to a valid Alien. Error message: "Invalid Alien token id"
- Check if the caller of the contract is the token's owner. If not, return
false. (Do this in a single line)
This completes the first part of transfer ().