forked from funded-labs/escrow_manager
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.mo
134 lines (116 loc) · 4.98 KB
/
main.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
import Blob "mo:base/Blob";
import Cycles "mo:base/ExperimentalCycles";
import Error "mo:base/Error";
import Nat "mo:base/Nat";
import Principal "mo:base/Principal";
import Text "mo:base/Text";
import Time "mo:base/Time";
import Trie "mo:base/Trie";
import Account "./account";
import Escrow "./escrow";
import Hex "./hex";
import Types "./types";
import Utils "./utils";
actor EscrowManager {
let admin : Principal = Principal.fromText("sqvf2-x3s5d-3a5m3-czni6-2zuda-rg4bk-7le4o-md733-uc75o-yihay-4ae");
type canister_id = Principal;
type user_id = Principal;
type wasm_module = Blob;
type canister_settings = {
controllers : ?[Principal];
compute_allocation : ?Nat;
memory_allocation : ?Nat;
freezing_threshold : ?Nat;
};
type definite_canister_settings = {
controllers : ?[Principal];
compute_allocation : Nat;
memory_allocation : Nat;
freezing_threshold : Nat;
};
// We want to eventually make all escrow canister "black hole" canisters,
// which means they have no controllers, and hence their code cannot be
// altered. Until then, since we have at times had to update an escrow
// canister's code due to a glitch, we use this function to temporarily take
// control of the escrow canister.
// TODO: Remove this function.
public func test () : async definite_canister_settings {
let ManagementCanister = actor "aaaaa-aa" : actor {
canister_status : shared { canister_id : canister_id } -> async {
status : { #running; #stopping; #stopped };
settings: definite_canister_settings;
module_hash: ?Blob;
memory_size: Nat;
cycles: Nat;
};
update_settings : shared {
canister_id : Principal;
settings : canister_settings
} -> async ();
};
let canister_id = Principal.fromText("4abzf-3iaaa-aaaak-aaraq-cai");
let newControllers = [
Principal.fromText("3fhg4-qiaaa-aaaak-aajiq-cai"),
Principal.fromText("xohn2-daaaa-aaaak-aadvq-cai")
];
await ManagementCanister.update_settings({ canister_id = canister_id; settings = {
controllers = ?newControllers;
compute_allocation = ?(0 : Nat);
memory_allocation = ?(0 : Nat);
freezing_threshold = ?(2_592_000 : Nat);
}});
return (await ManagementCanister.canister_status({ canister_id = canister_id })).settings;
};
type AccountIdText = Types.AccountIdText;
type CanisterId = Principal;
type CanisterIdText = Text;
type NFTInfo = Types.NFTInfo;
type ProjectId = Types.ProjectId;
type ProjectIdText = Text;
type SubaccountBlob = Types.SubaccountBlob;
stable var escrowCanisters : Trie.Trie<ProjectIdText, CanisterId> = Trie.empty();
// Canister management
public query func getProjectEscrowCanisterPrincipal(p: ProjectId) : async ?CanisterIdText {
switch (getProjectEscrowCanister(p)) {
case (?canister) ?Principal.toText(canister);
case (null) null;
};
};
// TODO: Remove self as controller of created escrow canister to turn the canister into true "black hole" canister.
public shared(msg) func createEscrowCanister (p: ProjectId, recipient: Principal, nfts: [NFTInfo], endTime : Time.Time, maxNFTsPerWallet : Nat) : async () {
assert(msg.caller == admin);
switch (getProjectEscrowCanister(p)) {
case (?canister) { throw Error.reject("Project already has an escrow canister: " # Principal.toText(canister)); };
case (null) {
Cycles.add(1000000000000);
let canister = await Escrow.EscrowCanister(p, recipient, nfts, endTime, maxNFTsPerWallet);
escrowCanisters := Trie.putFresh<ProjectIdText, CanisterId>(escrowCanisters, projectIdKey(p), Text.equal, Principal.fromActor(canister));
};
};
};
func getProjectEscrowCanister (p: ProjectId) : ?CanisterId {
Trie.get<ProjectIdText, CanisterId>(escrowCanisters, projectIdKey(p), Text.equal);
};
// helpers
func projectIdKey (p: ProjectId) : Trie.Key<ProjectIdText> {
{ key = Nat.toText(p); hash = Text.hash(Nat.toText(p)) };
};
// cycles management
//Internal cycle management - good general case
type RecieveOptions = {
memo: ?Text;
};
public func wallet_receive() : async () {
let available = Cycles.available();
let accepted = Cycles.accept(available);
assert (accepted == available);
};
public func acceptCycles() : async () {
let available = Cycles.available();
let accepted = Cycles.accept(available);
assert (accepted == available);
};
public query func availableCycles() : async Nat {
return Cycles.balance();
};
}