Skip to content

Commit

Permalink
feat(cli): improve cli integration ux
Browse files Browse the repository at this point in the history
- [x] Return transaction hash from signup command
- [x] Add indexed params for signup event
- [x] Add command to check if user is registered and get state index
  • Loading branch information
0xmad committed Feb 19, 2024
1 parent 96db616 commit 4c5c1ba
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 18 deletions.
4 changes: 3 additions & 1 deletion cli/tests/e2e/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,9 @@ describe("e2e tests", function test() {

it("should signup one user", async () => {
stateIndex = BigInt(
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: user.pubKey.serialize(), signer }),
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: user.pubKey.serialize(), signer }).then(
(result) => result.stateIndex,
),
);
});

Expand Down
12 changes: 9 additions & 3 deletions cli/tests/e2e/keyChange.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ describe("keyChange tests", function test() {
// deploy a poll contract
await deployPoll({ ...deployPollArgs, signer });
stateIndex = BigInt(
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: keypair1.pubKey.serialize(), signer }),
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: keypair1.pubKey.serialize(), signer }).then(
(result) => result.stateIndex,
),
);
await publish({
pubkey: keypair1.pubKey.serialize(),
Expand Down Expand Up @@ -172,7 +174,9 @@ describe("keyChange tests", function test() {
// deploy a poll contract
await deployPoll({ ...deployPollArgs, signer });
stateIndex = BigInt(
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: keypair1.pubKey.serialize(), signer }),
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: keypair1.pubKey.serialize(), signer }).then(
(result) => result.stateIndex,
),
);
await publish({
pubkey: keypair1.pubKey.serialize(),
Expand Down Expand Up @@ -240,7 +244,9 @@ describe("keyChange tests", function test() {
// deploy a poll contract
await deployPoll({ ...deployPollArgs, signer });
stateIndex = BigInt(
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: keypair1.pubKey.serialize(), signer }),
await signup({ maciAddress: maciAddresses.maciAddress, maciPubKey: keypair1.pubKey.serialize(), signer }).then(
(result) => result.stateIndex,
),
);
await publish({
pubkey: keypair1.pubKey.serialize(),
Expand Down
49 changes: 43 additions & 6 deletions cli/ts/commands/signup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { MACI__factory as MACIFactory } from "maci-contracts/typechain-types";
import {
MACI__factory as MACIFactory,
EASGatekeeper__factory as EASGatekeeperFactory,
} from "maci-contracts/typechain-types";
import { PubKey } from "maci-domainobjs";

import type { SignupArgs } from "../utils/interfaces";
import type { IRegisteredAttestationArgs, SignupArgs } from "../utils/interfaces";
import type { ContractTransactionReceipt } from "ethers";

import { banner } from "../utils/banner";
import { contractExists } from "../utils/contracts";
Expand All @@ -11,7 +15,7 @@ import { info, logError, logGreen, logYellow, success } from "../utils/theme";
/**
* Signup a user to the MACI contract
* @param SignupArgs - The arguments for the signup command
* @returns The state index of the user
* @returns The state index of the user and transaction hash
*/
export const signup = async ({
maciPubKey,
Expand All @@ -20,7 +24,7 @@ export const signup = async ({
ivcpDataArg,
signer,
quiet = true,
}: SignupArgs): Promise<string> => {
}: SignupArgs): Promise<{ stateIndex: string; hash: string }> => {
banner(quiet);

// validate user key
Expand Down Expand Up @@ -51,10 +55,12 @@ export const signup = async ({
const maciContract = MACIFactory.connect(maciAddress, signer);

let stateIndex = "";
let receipt: ContractTransactionReceipt | null = null;

try {
// sign up to the MACI contract
const tx = await maciContract.signUp(userMaciPubKey.asContractParam(), sgData, ivcpData);
const receipt = await tx.wait();
receipt = await tx.wait();

logYellow(quiet, info(`Transaction hash: ${tx.hash}`));

Expand All @@ -77,5 +83,36 @@ export const signup = async ({
logError((error as Error).message);
}

return stateIndex ? stateIndex.toString() : "";
return {
stateIndex: stateIndex ? stateIndex.toString() : "",
hash: receipt!.hash,
};
};

/**
* Checks if user is registered with attestation id
* @param IRegisteredAttestationArgs - The arguments for the registered attestation check command
* @returns user registered or not and state index
*/
export const isRegisteredAttestation = async ({
maciAddress,
maciPubKey,
signer,
attestationId,
}: IRegisteredAttestationArgs): Promise<{ isRegistered: boolean; stateIndex?: string }> => {
const maciContract = MACIFactory.connect(maciAddress, signer);
const gatekeeperAddress = await maciContract.signUpGatekeeper();

const gatekeeperContract = EASGatekeeperFactory.connect(gatekeeperAddress, signer);
const publicKey = PubKey.deserialize(maciPubKey).asContractParam();

const [isRegistered, events] = await Promise.all([
gatekeeperContract.registeredAttestations(attestationId),
maciContract.queryFilter(maciContract.filters.SignUp(undefined, publicKey.x, publicKey.y)),
]);

return {
isRegistered,
stateIndex: events[0]?.args[0].toString(),
};
};
6 changes: 4 additions & 2 deletions cli/ts/sdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { genKeyPair } from "../commands/genKeyPair";
import { genMaciPubKey } from "../commands/genPubKey";
import { publish } from "../commands/publish";
import { signup } from "../commands/signup";
import { signup, isRegisteredAttestation } from "../commands/signup";
import { verify } from "../commands/verify";

export { genKeyPair, genMaciPubKey, publish, signup, verify };
export { genKeyPair, genMaciPubKey, publish, signup, isRegisteredAttestation, verify };

export type { Signer } from "ethers";

export type {
DeployedContracts,
Expand Down
25 changes: 25 additions & 0 deletions cli/ts/utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,31 @@ export interface SignupArgs {
quiet?: boolean;
}

/**
* Interface for the arguments to the registered attestation check command
*/
export interface IRegisteredAttestationArgs {
/**
* A signer object
*/
signer: Signer;

/**
* The public key of the user
*/
maciPubKey: string;

/**
* The address of the MACI contract
*/
maciAddress: string;

/**
* Attestation ID
*/
attestationId: string;
}

/**
* Interface for the arguments to the topup command
*/
Expand Down
10 changes: 8 additions & 2 deletions contracts/contracts/MACI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,13 @@ contract MACI is IMACI, Params, Utilities, Ownable {
}

// Events
event SignUp(uint256 _stateIndex, PubKey _userPubKey, uint256 _voiceCreditBalance, uint256 _timestamp);
event SignUp(
uint256 _stateIndex,
uint256 indexed _userPubKeyX,
uint256 indexed _userPubKeyY,
uint256 _voiceCreditBalance,
uint256 _timestamp
);
event DeployPoll(uint256 _pollId, PubKey _pubKey, PollContracts pollAddr);

/// @notice Only allow a Poll contract to call the modified function.
Expand Down Expand Up @@ -179,7 +185,7 @@ contract MACI is IMACI, Params, Utilities, Ownable {
uint256 stateLeaf = hashStateLeaf(StateLeaf(_pubKey, voiceCreditBalance, timestamp));
uint256 stateIndex = stateAq.enqueue(stateLeaf);

emit SignUp(stateIndex, _pubKey, voiceCreditBalance, timestamp);
emit SignUp(stateIndex, _pubKey.x, _pubKey.y, voiceCreditBalance, timestamp);
}

/// @notice Deploy a new Poll contract.
Expand Down
2 changes: 1 addition & 1 deletion contracts/deploy-config-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"EASGatekeeper": {
"deploy": true,
"easAddress": "0xC2679fBD37d54388Ce493F1DB75320D236e1815e",
"schema": "0xfdcfdad2dbe7489e0ce56b260348b7f14e8365a8a325aef9834818c00d46b31b",
"schema": "0xe2636f31239f7948afdd9a9c477048b7fc2a089c347af60e3aa1251e5bf63e5c",
"attester": "attester-address"
},
"MACI": {
Expand Down
10 changes: 8 additions & 2 deletions contracts/ts/genMaciState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,13 @@ export const genMaciStateFromContract = async (
assert(!!log);
const mutableLog = { ...log, topics: [...log.topics] };
const event = maciIface.parseLog(mutableLog) as unknown as {
args: { _stateIndex: number; _userPubKey: string[]; _voiceCreditBalance: number; _timestamp: number };
args: {
_stateIndex: number;
_userPubKeyX: string;
_userPubKeyY: string;
_voiceCreditBalance: number;
_timestamp: number;
};
};

actions.push({
Expand All @@ -95,7 +101,7 @@ export const genMaciStateFromContract = async (
transactionIndex: log.transactionIndex,
data: {
stateIndex: Number(event.args._stateIndex),
pubKey: new PubKey(event.args._userPubKey.map((x) => BigInt(x)) as [bigint, bigint]),
pubKey: new PubKey([BigInt(event.args._userPubKeyX), BigInt(event.args._userPubKeyY)]),
voiceCreditBalance: Number(event.args._voiceCreditBalance),
timestamp: Number(event.args._timestamp),
},
Expand Down
2 changes: 1 addition & 1 deletion integrationTests/ts/__tests__/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ describe("Integration tests", function test() {
sgDataArg: SG_DATA,
ivcpDataArg: ivcpData,
signer,
}),
}).then((result) => result.stateIndex),
);

// signup on local maci state
Expand Down

0 comments on commit 4c5c1ba

Please sign in to comment.