zkcloudworker 0.18.29 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/node/index.cjs +160 -1568
  2. package/dist/node/mina/api/api.js +15 -3
  3. package/dist/node/mina/api/api.js.map +1 -1
  4. package/dist/node/mina/token/api.js +1 -4
  5. package/dist/node/mina/token/api.js.map +1 -1
  6. package/dist/node/mina/token/index.d.ts +0 -7
  7. package/dist/node/mina/token/index.js +0 -7
  8. package/dist/node/mina/token/index.js.map +1 -1
  9. package/dist/node/mina/transactions/transaction.d.ts +15 -3
  10. package/dist/node/mina/transactions/transaction.js +49 -6
  11. package/dist/node/mina/transactions/transaction.js.map +1 -1
  12. package/dist/tsconfig.web.tsbuildinfo +1 -1
  13. package/dist/web/mina/api/api.js +15 -3
  14. package/dist/web/mina/api/api.js.map +1 -1
  15. package/dist/web/mina/token/api.js +1 -4
  16. package/dist/web/mina/token/api.js.map +1 -1
  17. package/dist/web/mina/token/index.d.ts +0 -7
  18. package/dist/web/mina/token/index.js +0 -7
  19. package/dist/web/mina/token/index.js.map +1 -1
  20. package/dist/web/mina/transactions/transaction.d.ts +15 -3
  21. package/dist/web/mina/transactions/transaction.js +49 -6
  22. package/dist/web/mina/transactions/transaction.js.map +1 -1
  23. package/package.json +5 -5
  24. package/src/mina/api/api.ts +15 -3
  25. package/src/mina/token/api.ts +2 -4
  26. package/src/mina/token/index.ts +0 -7
  27. package/src/mina/transactions/transaction.ts +73 -13
  28. package/src/mina/token/FungibleTokenAdmin.ts +0 -89
  29. package/src/mina/token/FungibleTokenContract.ts +0 -327
  30. package/src/mina/token/FungibleTokenWhitelistedAdmin.ts +0 -112
  31. package/src/mina/token/bid.ts +0 -173
  32. package/src/mina/token/build.ts +0 -620
  33. package/src/mina/token/fee.ts +0 -2
  34. package/src/mina/token/offer.ts +0 -174
  35. package/src/mina/token/token.ts +0 -127
  36. package/src/mina/token/vk.ts +0 -42
  37. package/src/mina/token/whitelist.ts +0 -204
@@ -1,4 +1,3 @@
1
- import axios, { all } from "axios";
2
1
  import chalk from "chalk";
3
2
  import { sleep } from "../../cloud/utils/index.js";
4
3
  import { LocalCloud, LocalStorage } from "../local/local.js";
@@ -576,8 +575,21 @@ export class zkCloudWorkerClient {
576
575
  };
577
576
 
578
577
  try {
579
- const response = await axios.post(this.endpoint, apiData);
580
- return { success: true, data: response.data };
578
+ const response = await fetch(this.endpoint, {
579
+ method: "POST",
580
+ headers: {
581
+ "Content-Type": "application/json",
582
+ },
583
+ body: JSON.stringify(apiData),
584
+ });
585
+ if (!response.ok) {
586
+ return {
587
+ success: false,
588
+ error: `fetch error: ${response.statusText} status: ${response.status}`,
589
+ };
590
+ }
591
+ const data = await response.json();
592
+ return { success: true, data: data };
581
593
  } catch (error: any) {
582
594
  console.error("apiHub error:", error.message ?? error);
583
595
  return { success: false, error: error };
@@ -211,10 +211,8 @@ export class TokenAPI {
211
211
  async getResult(jobId: string): Promise<FungibleTokenJobResult> {
212
212
  try {
213
213
  const callResult = await this.client.jobResult({ jobId });
214
- // const jobStatus: JobStatus | undefined =
215
- // callResult?.success === true
216
- // ? callResult?.result?.jobStatus
217
- // : undefined;
214
+
215
+ // TODO: filter the repo and developer
218
216
  const jobStatus: JobStatus | undefined =
219
217
  typeof callResult?.result === "string"
220
218
  ? undefined
@@ -1,8 +1 @@
1
1
  export * from "./api.js";
2
- export * from "./bid.js";
3
- export * from "./build.js";
4
- export * from "./fee.js";
5
- export * from "./offer.js";
6
- export * from "./token.js";
7
- export * from "./vk.js";
8
- export * from "./whitelist.js";
@@ -1,6 +1,50 @@
1
1
  import { Field, PublicKey, Transaction, Mina, UInt64 } from "o1js";
2
+ import { TransactionPayloads } from "@minatokens/api";
2
3
  import { fieldToBase64, fieldFromBase64 } from "../utils/base64.js";
3
4
 
5
+ export function createTransactionPayloads(
6
+ tx: Mina.Transaction<false, false> | Mina.Transaction<false, true>
7
+ ): TransactionPayloads {
8
+ const transaction = tx.toJSON();
9
+ const txJSON = JSON.parse(transaction);
10
+ const signedData = JSON.stringify({ zkappCommand: txJSON });
11
+ const proverPayload = serializeTransaction(tx);
12
+ const fee = tx.transaction.feePayer.body.fee.toJSON();
13
+ const sender = tx.transaction.feePayer.body.publicKey.toBase58();
14
+ const nonce = Number(tx.transaction.feePayer.body.nonce.toBigint());
15
+ const memo = tx.transaction.memo;
16
+ const minaSignerPayload = {
17
+ zkappCommand: txJSON,
18
+ feePayer: {
19
+ feePayer: sender,
20
+ fee,
21
+ nonce,
22
+ memo,
23
+ },
24
+ };
25
+ const walletPayload = {
26
+ transaction,
27
+ nonce,
28
+ onlySign: true,
29
+ feePayer: {
30
+ fee,
31
+ memo,
32
+ },
33
+ };
34
+
35
+ return {
36
+ sender,
37
+ nonce,
38
+ memo,
39
+ fee,
40
+ walletPayload,
41
+ minaSignerPayload,
42
+ proverPayload,
43
+ signedData,
44
+ transaction,
45
+ };
46
+ }
47
+
4
48
  interface ForestSerialized {
5
49
  length: number;
6
50
  restoredItems?: number;
@@ -13,15 +57,21 @@ interface ForestSerialized {
13
57
  }
14
58
 
15
59
  export function transactionParams(
16
- serializedTransaction: string,
17
- signedJson: any
60
+ params:
61
+ | {
62
+ proverPayload: string;
63
+ signedData: string;
64
+ }
65
+ | TransactionPayloads
18
66
  ): {
19
67
  fee: UInt64;
20
68
  sender: PublicKey;
21
69
  nonce: number;
22
70
  memo: string;
23
71
  } {
24
- const { sender, nonce, tx } = JSON.parse(serializedTransaction);
72
+ const { proverPayload, signedData } = params;
73
+ const signedJson = JSON.parse(signedData);
74
+ const { sender, tx } = JSON.parse(proverPayload);
25
75
  const transaction = Mina.Transaction.fromJSON(JSON.parse(tx));
26
76
  const memo = transaction.transaction.memo;
27
77
  return {
@@ -32,20 +82,30 @@ export function transactionParams(
32
82
  };
33
83
  }
34
84
 
35
- export function deserializeTransaction(
36
- serializedTransaction: string,
37
- txNew: Mina.Transaction<false, false>,
38
- signedJson: any
85
+ export function parseTransactionPayloads(
86
+ params:
87
+ | {
88
+ proverPayload: string;
89
+ signedData: string;
90
+ txNew: Mina.Transaction<false, false> | Mina.Transaction<false, true>;
91
+ }
92
+ | {
93
+ payloads: TransactionPayloads;
94
+ txNew: Mina.Transaction<false, false> | Mina.Transaction<false, true>;
95
+ }
39
96
  ): Transaction<false, true> {
40
- //console.log("new transaction", txNew);
41
- const { tx, blindingValues, length, forestJSONs } = JSON.parse(
42
- serializedTransaction
43
- );
97
+ const { txNew } = params;
98
+ const proverPayload =
99
+ "payloads" in params ? params.payloads.proverPayload : params.proverPayload;
100
+ const signedData =
101
+ "payloads" in params ? params.payloads.signedData : params.signedData;
102
+ const signedJson = JSON.parse(signedData);
103
+ const { tx, blindingValues, length, forestJSONs } = JSON.parse(proverPayload);
44
104
  const transaction = Mina.Transaction.fromJSON(JSON.parse(tx));
45
105
  const forests: ForestSerialized[] = forestJSONs.map(
46
106
  (f: string) => JSON.parse(f) as ForestSerialized
47
107
  );
48
- //console.log("transaction", transaction);
108
+
49
109
  if (length !== txNew.transaction.accountUpdates.length) {
50
110
  throw new Error("New Transaction length mismatch");
51
111
  }
@@ -106,7 +166,7 @@ export function deserializeTransaction(
106
166
  }
107
167
 
108
168
  export function serializeTransaction(
109
- tx: Mina.Transaction<false, false>
169
+ tx: Mina.Transaction<false, false> | Mina.Transaction<false, true>
110
170
  ): string {
111
171
  const length = tx.transaction.accountUpdates.length;
112
172
  let i;
@@ -1,89 +0,0 @@
1
- import {
2
- AccountUpdate,
3
- assert,
4
- Bool,
5
- DeployArgs,
6
- method,
7
- Permissions,
8
- Provable,
9
- PublicKey,
10
- SmartContract,
11
- State,
12
- state,
13
- VerificationKey,
14
- } from "o1js";
15
- import { FungibleTokenAdminBase } from "./FungibleTokenContract.js";
16
-
17
- export interface FungibleTokenAdminDeployProps
18
- extends Exclude<DeployArgs, undefined> {
19
- adminPublicKey: PublicKey;
20
- }
21
-
22
- /** A contract that grants permissions for administrative actions on a token.
23
- *
24
- * We separate this out into a dedicated contract. That way, when issuing a token, a user can
25
- * specify their own rules for administrative actions, without changing the token contract itself.
26
- *
27
- * The advantage is that third party applications that only use the token in a non-privileged way
28
- * can integrate against the unchanged token contract.
29
- */
30
- export class FungibleTokenAdmin
31
- extends SmartContract
32
- implements FungibleTokenAdminBase
33
- {
34
- @state(PublicKey)
35
- private adminPublicKey = State<PublicKey>();
36
-
37
- async deploy(props: FungibleTokenAdminDeployProps) {
38
- await super.deploy(props);
39
- this.adminPublicKey.set(props.adminPublicKey);
40
- this.account.permissions.set({
41
- ...Permissions.default(),
42
- setVerificationKey:
43
- Permissions.VerificationKey.impossibleDuringCurrentVersion(),
44
- setPermissions: Permissions.impossible(),
45
- });
46
- }
47
-
48
- /** Update the verification key.
49
- * Note that because we have set the permissions for setting the verification key to `impossibleDuringCurrentVersion()`, this will only be possible in case of a protocol update that requires an update.
50
- */
51
- @method
52
- async updateVerificationKey(vk: VerificationKey) {
53
- this.account.verificationKey.set(vk);
54
- }
55
-
56
- private async ensureAdminSignature() {
57
- const admin = await Provable.witnessAsync(PublicKey, async () => {
58
- let pk = await this.adminPublicKey.fetch();
59
- assert(pk !== undefined, "could not fetch admin public key");
60
- return pk;
61
- });
62
- this.adminPublicKey.requireEquals(admin);
63
- return AccountUpdate.createSigned(admin);
64
- }
65
-
66
- @method.returns(Bool)
67
- public async canMint(_accountUpdate: AccountUpdate) {
68
- await this.ensureAdminSignature();
69
- return Bool(true);
70
- }
71
-
72
- @method.returns(Bool)
73
- public async canChangeAdmin(_admin: PublicKey) {
74
- await this.ensureAdminSignature();
75
- return Bool(true);
76
- }
77
-
78
- @method.returns(Bool)
79
- public async canPause(): Promise<Bool> {
80
- await this.ensureAdminSignature();
81
- return Bool(true);
82
- }
83
-
84
- @method.returns(Bool)
85
- public async canResume(): Promise<Bool> {
86
- await this.ensureAdminSignature();
87
- return Bool(true);
88
- }
89
- }
@@ -1,327 +0,0 @@
1
- import {
2
- AccountUpdate,
3
- AccountUpdateForest,
4
- assert,
5
- Bool,
6
- DeployArgs,
7
- Field,
8
- Int64,
9
- method,
10
- Permissions,
11
- Provable,
12
- PublicKey,
13
- SmartContract,
14
- State,
15
- state,
16
- Struct,
17
- TokenContract,
18
- Types,
19
- UInt64,
20
- UInt8,
21
- VerificationKey,
22
- } from "o1js";
23
-
24
- export type FungibleTokenAdminBase = SmartContract & {
25
- canMint(accountUpdate: AccountUpdate): Promise<Bool>;
26
- canChangeAdmin(admin: PublicKey): Promise<Bool>;
27
- canPause(): Promise<Bool>;
28
- canResume(): Promise<Bool>;
29
- };
30
-
31
- export type FungibleTokenAdminConstructor = new (
32
- adminPublicKey: PublicKey
33
- ) => FungibleTokenAdminBase;
34
-
35
- export interface FungibleTokenDeployProps
36
- extends Exclude<DeployArgs, undefined> {
37
- /** The token symbol. */
38
- symbol: string;
39
- /** A source code reference, which is placed within the `zkappUri` of the contract account.
40
- * Typically a link to a file on github. */
41
- src: string;
42
- }
43
-
44
- export const FungibleTokenErrors = {
45
- noAdminKey: "could not fetch admin contract key",
46
- noPermissionToChangeAdmin: "Not allowed to change admin contract",
47
- tokenPaused: "Token is currently paused",
48
- noPermissionToMint: "Not allowed to mint tokens",
49
- noPermissionToPause: "Not allowed to pause token",
50
- noPermissionToResume: "Not allowed to resume token",
51
- noTransferFromCirculation: "Can't transfer to/from the circulation account",
52
- noPermissionChangeAllowed:
53
- "Can't change permissions for access or receive on token accounts",
54
- flashMinting:
55
- "Flash-minting or unbalanced transaction detected. Please make sure that your transaction is balanced, and that your `AccountUpdate`s are ordered properly, so that tokens are not received before they are sent.",
56
- unbalancedTransaction: "Transaction is unbalanced",
57
- };
58
-
59
- export function FungibleTokenContract(
60
- adminContract: FungibleTokenAdminConstructor
61
- ) {
62
- class FungibleToken extends TokenContract {
63
- @state(UInt8)
64
- decimals = State<UInt8>();
65
- @state(PublicKey)
66
- admin = State<PublicKey>();
67
- @state(Bool)
68
- paused = State<Bool>();
69
-
70
- readonly events = {
71
- SetAdmin: SetAdminEvent,
72
- Pause: PauseEvent,
73
- Mint: MintEvent,
74
- Burn: BurnEvent,
75
- BalanceChange: BalanceChangeEvent,
76
- };
77
-
78
- async deploy(props: FungibleTokenDeployProps) {
79
- await super.deploy(props);
80
- this.paused.set(Bool(true));
81
- this.account.zkappUri.set(props.src);
82
- this.account.tokenSymbol.set(props.symbol);
83
-
84
- this.account.permissions.set({
85
- ...Permissions.default(),
86
- setVerificationKey:
87
- Permissions.VerificationKey.impossibleDuringCurrentVersion(),
88
- setPermissions: Permissions.impossible(),
89
- access: Permissions.proof(),
90
- });
91
- }
92
-
93
- /** Update the verification key.
94
- * Note that because we have set the permissions for setting the verification key to `impossibleDuringCurrentVersion()`, this will only be possible in case of a protocol update that requires an update.
95
- */
96
- @method
97
- async updateVerificationKey(vk: VerificationKey) {
98
- this.account.verificationKey.set(vk);
99
- }
100
-
101
- /** Initializes the account for tracking total circulation.
102
- * @argument {PublicKey} admin - public key where the admin contract is deployed
103
- * @argument {UInt8} decimals - number of decimals for the token
104
- * @argument {Bool} startPaused - if set to `Bool(true), the contract will start in a mode where token minting and transfers are paused. This should be used for non-atomic deployments
105
- */
106
- @method
107
- async initialize(admin: PublicKey, decimals: UInt8, startPaused: Bool) {
108
- this.account.provedState.requireEquals(Bool(false));
109
-
110
- this.admin.set(admin);
111
- this.decimals.set(decimals);
112
- this.paused.set(Bool(false));
113
-
114
- this.paused.set(startPaused);
115
-
116
- const accountUpdate = AccountUpdate.createSigned(
117
- this.address,
118
- this.deriveTokenId()
119
- );
120
- let permissions = Permissions.default();
121
- // This is necessary in order to allow token holders to burn.
122
- permissions.send = Permissions.none();
123
- permissions.setPermissions = Permissions.impossible();
124
- accountUpdate.account.permissions.set(permissions);
125
- }
126
-
127
- public async getAdminContract(): Promise<FungibleTokenAdminBase> {
128
- const admin = await Provable.witnessAsync(PublicKey, async () => {
129
- let pk = await this.admin.fetch();
130
- assert(pk !== undefined, FungibleTokenErrors.noAdminKey);
131
- return pk;
132
- });
133
- this.admin.requireEquals(admin);
134
- return new adminContract(admin);
135
- }
136
-
137
- @method
138
- async setAdmin(admin: PublicKey) {
139
- const adminContract = await this.getAdminContract();
140
- const canChangeAdmin = await adminContract.canChangeAdmin(admin);
141
- canChangeAdmin.assertTrue(FungibleTokenErrors.noPermissionToChangeAdmin);
142
- this.admin.set(admin);
143
- this.emitEvent("SetAdmin", new SetAdminEvent({ adminKey: admin }));
144
- }
145
-
146
- @method.returns(AccountUpdate)
147
- async mint(recipient: PublicKey, amount: UInt64): Promise<AccountUpdate> {
148
- this.paused
149
- .getAndRequireEquals()
150
- .assertFalse(FungibleTokenErrors.tokenPaused);
151
- const accountUpdate = this.internal.mint({ address: recipient, amount });
152
- const adminContract = await this.getAdminContract();
153
- const canMint = await adminContract.canMint(accountUpdate);
154
- canMint.assertTrue(FungibleTokenErrors.noPermissionToMint);
155
- recipient
156
- .equals(this.address)
157
- .assertFalse(FungibleTokenErrors.noTransferFromCirculation);
158
- this.approve(accountUpdate);
159
- this.emitEvent("Mint", new MintEvent({ recipient, amount }));
160
- const circulationUpdate = AccountUpdate.create(
161
- this.address,
162
- this.deriveTokenId()
163
- );
164
- circulationUpdate.balanceChange = Int64.fromUnsigned(amount);
165
- return accountUpdate;
166
- }
167
-
168
- @method.returns(AccountUpdate)
169
- async burn(from: PublicKey, amount: UInt64): Promise<AccountUpdate> {
170
- this.paused
171
- .getAndRequireEquals()
172
- .assertFalse(FungibleTokenErrors.tokenPaused);
173
- const accountUpdate = this.internal.burn({ address: from, amount });
174
- const circulationUpdate = AccountUpdate.create(
175
- this.address,
176
- this.deriveTokenId()
177
- );
178
- from
179
- .equals(this.address)
180
- .assertFalse(FungibleTokenErrors.noTransferFromCirculation);
181
- circulationUpdate.balanceChange = Int64.fromUnsigned(amount).neg();
182
- this.emitEvent("Burn", new BurnEvent({ from, amount }));
183
- return accountUpdate;
184
- }
185
-
186
- @method
187
- async pause() {
188
- const adminContract = await this.getAdminContract();
189
- const canPause = await adminContract.canPause();
190
- canPause.assertTrue(FungibleTokenErrors.noPermissionToPause);
191
- this.paused.set(Bool(true));
192
- this.emitEvent("Pause", new PauseEvent({ isPaused: Bool(true) }));
193
- }
194
-
195
- @method
196
- async resume() {
197
- const adminContract = await this.getAdminContract();
198
- const canResume = await adminContract.canResume();
199
- canResume.assertTrue(FungibleTokenErrors.noPermissionToResume);
200
- this.paused.set(Bool(false));
201
- this.emitEvent("Pause", new PauseEvent({ isPaused: Bool(false) }));
202
- }
203
-
204
- @method
205
- async transfer(from: PublicKey, to: PublicKey, amount: UInt64) {
206
- this.paused
207
- .getAndRequireEquals()
208
- .assertFalse(FungibleTokenErrors.tokenPaused);
209
- from
210
- .equals(this.address)
211
- .assertFalse(FungibleTokenErrors.noTransferFromCirculation);
212
- to.equals(this.address).assertFalse(
213
- FungibleTokenErrors.noTransferFromCirculation
214
- );
215
- this.internal.send({ from, to, amount });
216
- }
217
-
218
- checkPermissionsUpdate(update: AccountUpdate) {
219
- let permissions = update.update.permissions;
220
-
221
- let { access, receive } = permissions.value;
222
- let accessIsNone = Provable.equal(
223
- Types.AuthRequired,
224
- access,
225
- Permissions.none()
226
- );
227
- let receiveIsNone = Provable.equal(
228
- Types.AuthRequired,
229
- receive,
230
- Permissions.none()
231
- );
232
- let updateAllowed = accessIsNone.and(receiveIsNone);
233
-
234
- assert(
235
- updateAllowed.or(permissions.isSome.not()),
236
- FungibleTokenErrors.noPermissionChangeAllowed
237
- );
238
- }
239
-
240
- /** Approve `AccountUpdate`s that have been created outside of the token contract.
241
- *
242
- * @argument {AccountUpdateForest} updates - The `AccountUpdate`s to approve. Note that the forest size is limited by the base token contract, @see TokenContract.MAX_ACCOUNT_UPDATES The current limit is 9.
243
- */
244
- @method
245
- async approveBase(updates: AccountUpdateForest): Promise<void> {
246
- this.paused
247
- .getAndRequireEquals()
248
- .assertFalse(FungibleTokenErrors.tokenPaused);
249
- let totalBalance = Int64.from(0);
250
- this.forEachUpdate(updates, (update, usesToken) => {
251
- // Make sure that the account permissions are not changed
252
- this.checkPermissionsUpdate(update);
253
- this.emitEventIf(
254
- usesToken,
255
- "BalanceChange",
256
- new BalanceChangeEvent({
257
- address: update.publicKey,
258
- amount: update.balanceChange,
259
- })
260
- );
261
- // Don't allow transfers to/from the account that's tracking circulation
262
- update.publicKey
263
- .equals(this.address)
264
- .and(usesToken)
265
- .assertFalse(FungibleTokenErrors.noTransferFromCirculation);
266
- totalBalance = Provable.if(
267
- usesToken,
268
- totalBalance.add(update.balanceChange),
269
- totalBalance
270
- );
271
- totalBalance.isPositive().assertFalse(FungibleTokenErrors.flashMinting);
272
- });
273
- totalBalance.assertEquals(
274
- Int64.zero,
275
- FungibleTokenErrors.unbalancedTransaction
276
- );
277
- }
278
-
279
- @method.returns(UInt64)
280
- async getBalanceOf(address: PublicKey): Promise<UInt64> {
281
- const account = AccountUpdate.create(
282
- address,
283
- this.deriveTokenId()
284
- ).account;
285
- const balance = account.balance.get();
286
- account.balance.requireEquals(balance);
287
- return balance;
288
- }
289
-
290
- /** Reports the current circulating supply
291
- * This does take into account currently unreduced actions.
292
- */
293
- async getCirculating(): Promise<UInt64> {
294
- let circulating = await this.getBalanceOf(this.address);
295
- return circulating;
296
- }
297
-
298
- @method.returns(UInt8)
299
- async getDecimals(): Promise<UInt8> {
300
- return this.decimals.getAndRequireEquals();
301
- }
302
- }
303
- return FungibleToken;
304
- }
305
-
306
- export class SetAdminEvent extends Struct({
307
- adminKey: PublicKey,
308
- }) {}
309
-
310
- export class PauseEvent extends Struct({
311
- isPaused: Bool,
312
- }) {}
313
-
314
- export class MintEvent extends Struct({
315
- recipient: PublicKey,
316
- amount: UInt64,
317
- }) {}
318
-
319
- export class BurnEvent extends Struct({
320
- from: PublicKey,
321
- amount: UInt64,
322
- }) {}
323
-
324
- export class BalanceChangeEvent extends Struct({
325
- address: PublicKey,
326
- amount: Int64,
327
- }) {}
@@ -1,112 +0,0 @@
1
- import {
2
- AccountUpdate,
3
- assert,
4
- Bool,
5
- DeployArgs,
6
- method,
7
- Permissions,
8
- Provable,
9
- PublicKey,
10
- SmartContract,
11
- State,
12
- state,
13
- UInt64,
14
- VerificationKey,
15
- } from "o1js";
16
- import { Whitelist } from "./whitelist.js";
17
- import { FungibleTokenAdminBase } from "./FungibleTokenContract.js";
18
-
19
- export interface FungibleTokenWhitelistedAdminDeployProps
20
- extends Exclude<DeployArgs, undefined> {
21
- adminPublicKey: PublicKey;
22
- whitelist: Whitelist;
23
- }
24
-
25
- /** A contract that grants permissions for administrative actions on a token.
26
- *
27
- * We separate this out into a dedicated contract. That way, when issuing a token, a user can
28
- * specify their own rules for administrative actions, without changing the token contract itself.
29
- *
30
- * The advantage is that third party applications that only use the token in a non-privileged way
31
- * can integrate against the unchanged token contract.
32
- */
33
- export class FungibleTokenWhitelistedAdmin
34
- extends SmartContract
35
- implements FungibleTokenAdminBase
36
- {
37
- @state(PublicKey) adminPublicKey = State<PublicKey>();
38
- @state(Whitelist) whitelist = State<Whitelist>();
39
-
40
- async deploy(props: FungibleTokenWhitelistedAdminDeployProps) {
41
- await super.deploy(props);
42
- this.adminPublicKey.set(props.adminPublicKey);
43
- this.whitelist.set(props.whitelist);
44
- this.account.permissions.set({
45
- ...Permissions.default(),
46
- setVerificationKey:
47
- Permissions.VerificationKey.impossibleDuringCurrentVersion(),
48
- setPermissions: Permissions.impossible(),
49
- });
50
- }
51
-
52
- events = { updateWhitelist: Whitelist };
53
-
54
- /** Update the verification key.
55
- * Note that because we have set the permissions for setting the verification key to `impossibleDuringCurrentVersion()`, this will only be possible in case of a protocol update that requires an update.
56
- */
57
- @method
58
- async updateVerificationKey(vk: VerificationKey) {
59
- this.account.verificationKey.set(vk);
60
- }
61
-
62
- private async ensureAdminSignature() {
63
- const admin = await Provable.witnessAsync(PublicKey, async () => {
64
- let pk = await this.adminPublicKey.fetch();
65
- assert(pk !== undefined, "could not fetch admin public key");
66
- return pk;
67
- });
68
- this.adminPublicKey.requireEquals(admin);
69
- return AccountUpdate.createSigned(admin);
70
- }
71
-
72
- @method.returns(Bool)
73
- public async canMint(_accountUpdate: AccountUpdate) {
74
- const address = _accountUpdate.body.publicKey;
75
- const balanceChange = _accountUpdate.body.balanceChange;
76
- balanceChange.isPositive().assertTrue();
77
- const whitelist = this.whitelist.getAndRequireEquals();
78
- const whitelistedAmount = await whitelist.getWhitelistedAmount(address);
79
- return balanceChange.magnitude.lessThanOrEqual(
80
- whitelistedAmount.orElse(UInt64.from(0)) // here can be a minimum amount allowed by travel rule instead of 0
81
- );
82
- }
83
-
84
- @method.returns(Bool)
85
- public async canChangeAdmin(_admin: PublicKey) {
86
- await this.ensureAdminSignature();
87
- return Bool(true);
88
- }
89
-
90
- @method.returns(Bool)
91
- public async canPause(): Promise<Bool> {
92
- await this.ensureAdminSignature();
93
- return Bool(true);
94
- }
95
-
96
- @method.returns(Bool)
97
- public async canResume(): Promise<Bool> {
98
- await this.ensureAdminSignature();
99
- return Bool(true);
100
- }
101
-
102
- @method async updateWhitelist(whitelist: Whitelist) {
103
- const admin = this.adminPublicKey.getAndRequireEquals();
104
- const sender = this.sender.getUnconstrained();
105
- const senderUpdate = AccountUpdate.createSigned(sender);
106
- senderUpdate.body.useFullCommitment = Bool(true);
107
- admin.assertEquals(sender);
108
-
109
- this.whitelist.set(whitelist);
110
- this.emitEvent("updateWhitelist", whitelist);
111
- }
112
- }