-
Notifications
You must be signed in to change notification settings - Fork 0
/
project.mo
152 lines (126 loc) · 5.41 KB
/
project.mo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import Int "mo:base/Int";
import Option "mo:base/Option";
import Buffer "mo:base/Buffer";
import Result "mo:base/Result";
import Nat "mo:base/Nat";
import Text "mo:base/Text";
import Bool "mo:base/Bool";
import HashMap "mo:base/HashMap";
import TrieMap "mo:base/TrieMap";
import Hash "mo:base/Hash";
import Iter "mo:base/Iter";
import Principal "mo:base/Principal";
import Order "mo:base/Order";
import Array "mo:base/Array";
import Coin "Coin";
// NOTE: only use for local dev,
// when deploying to IC, import from "rww3b-zqaaa-aaaam-abioa-cai"
import BootcampLocalActor "BootcampLocalActor";
import Debug "mo:base/Debug";
actor bc2305 {
//=============== DAY 4 - THE MOTOKO COIN ===============\\
// https://github.com/motoko-bootcamp/motoko-starter/tree/main/days/day-4/project
type Account = Coin.Account;
var ledger = TrieMap.TrieMap<Account, Nat>(Coin.accountsEqual, Coin.accountsHash);
let airdropAmount : Nat = 100;
let bcICNetworkCanister = actor ("rww3b-zqaaa-aaaam-abioa-cai") : actor {
getAllStudentsPrincipal : shared () -> async [Principal];
};
// Returns the name of the token
public query func name() : async Text {
return "MotoCoin";
};
// Returns the symbol of the token
public query func symbol() : async Text {
return "MOC";
};
// Returns the the total number of tokens on all accounts
public query func totalSupply() : async Nat {
var total : Nat = 0;
for ((account, balance) in ledger.entries()) {
total += balance;
};
return total;
};
public query func getAccounts() : async [Principal] {
let newMap = TrieMap.map<Account, Nat, Principal>(ledger, Coin.accountsEqual, Coin.accountsHash, func(key, value) = key.owner);
return Iter.toArray<Principal>(newMap.vals());
};
public query func getAccountFromPrincipal(principal : Principal) : async Account {
return Coin.getAccountFromPrincipal(principal);
};
public func addPrincipalToLedger(principal : Principal) : async () {
let account : Account = Coin.getAccountFromPrincipal(principal);
ledger.put(account, 0);
};
public query func balanceOf(account : Account) : async (Nat) {
let balance : ?Nat = ledger.get(account);
switch (balance) {
case (null) { return 0 };
case (?amount) { return amount };
};
};
// Transfer tokens to another account
public shared ({ caller }) func transfer(from : Account, to : Account, amount : Nat) : async Result.Result<(), Text> {
var senderBalance : ?Nat = ledger.get(from);
var receiverBalance : ?Nat = ledger.get(to);
switch (senderBalance) {
case (null) {
return #err("The sender doesn't have any balance.");
};
case (?balance) {
if (balance < amount) {
return #err("The sender doesn't have enough balance.");
};
ledger.put(from, balance - amount);
switch (receiverBalance) {
case (null) { ledger.put(to, amount) };
case (?rBalance) { ledger.put(to, rBalance + amount) };
};
return #ok();
};
};
};
// Airdrop 1000 MotoCoin to any student that is part of the Bootcamp.
// dfx canister --network ic call rww3b-zqaaa-aaaam-abioa-cai getAllStudentsPrincipal '()'
public func airdrop() : async Result.Result<(), Text> {
let principals : [Principal] = await getAllAccounts();
for (principal in principals.vals()) {
try {
// Debug.print("Starting airdrop for " # debug_show(principal));
let account : Account = Coin.getAccountFromPrincipal(principal);
// Debug.print("Fetched account " # debug_show(account));
ledger.put(account, airdropAmount);
// Debug.print("Aidrop successful for " # debug_show(principal));
} catch (e) {
Debug.print("An error occured when perforing the airdrop for principal: " # Principal.toText(principal));
return #err("An error occured when perforing the airdrop.");
};
};
return #ok();
};
// dfx canister call bc2305 getAllAccounts '()'
private func getAllAccounts() : async [Principal] {
// TODO: Change this to "true" for local testing.
let isLocal : Bool = true;
if (isLocal) {
let bootcampTestActor = await BootcampLocalActor.BootcampLocalActor();
let principals : [Principal] = await bootcampTestActor.getAllStudentsPrincipal();
for (principal in principals.vals()) {
// Debug.print("Creating ledger entry for principal: " # debug_show(principal));
let account : Account = Coin.getAccountFromPrincipal(principal);
// Debug.print("Account: " # debug_show(account));
ledger.put(account, 0);
};
// Debug.print("getAllAccounts() - ledger entries done");
return principals;
} else {
// For the IC network.
let principals : [Principal] = await bcICNetworkCanister.getAllStudentsPrincipal();
for (principal in principals.vals()) {
ledger.put(Coin.getAccountFromPrincipal(principal), 0);
};
return principals;
};
};
};