mirror of https://github.com/waku-org/js-rln.git
feat: update contract (#72)
* feat: update contract * update ABI * update contract and fix name of ABI * update exports * ignore constants * fix tests * update mock * up mock * add logs * add mock
This commit is contained in:
parent
891ee3474a
commit
5b9414aede
|
@ -33,7 +33,8 @@
|
|||
"gen",
|
||||
"proto",
|
||||
"*.spec.ts",
|
||||
"src/resources.ts"
|
||||
"src/resources.ts",
|
||||
"src/constants.ts"
|
||||
],
|
||||
"patterns": [
|
||||
{
|
||||
|
|
|
@ -1,14 +1,68 @@
|
|||
export const RLN_ABI = [
|
||||
"function MEMBERSHIP_DEPOSIT() public view returns(uint256)",
|
||||
"function register(uint256 pubkey) external payable",
|
||||
"function withdraw(uint256 secret, uint256 _pubkeyIndex, address payable receiver) external",
|
||||
"event MemberRegistered(uint256 pubkey, uint256 index)",
|
||||
"event MemberWithdrawn(uint256 pubkey, uint256 index)",
|
||||
// ref https://github.com/waku-org/waku-rln-contract/blob/19fded82bca07e7b535b429dc507cfb83f10dfcf/deployments/sepolia/WakuRlnRegistry_Implementation.json#L3
|
||||
export const RLN_REGISTRY_ABI = [
|
||||
"error IncompatibleStorage()",
|
||||
"error IncompatibleStorageIndex()",
|
||||
"error NoStorageContractAvailable()",
|
||||
"error StorageAlreadyExists(address storageAddress)",
|
||||
"event AdminChanged(address previousAdmin, address newAdmin)",
|
||||
"event BeaconUpgraded(address indexed beacon)",
|
||||
"event Initialized(uint8 version)",
|
||||
"event NewStorageContract(uint16 index, address storageAddress)",
|
||||
"event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)",
|
||||
"event Upgraded(address indexed implementation)",
|
||||
"function forceProgress()",
|
||||
"function initialize(address _poseidonHasher)",
|
||||
"function newStorage()",
|
||||
"function nextStorageIndex() view returns (uint16)",
|
||||
"function owner() view returns (address)",
|
||||
"function poseidonHasher() view returns (address)",
|
||||
"function proxiableUUID() view returns (bytes32)",
|
||||
"function register(uint16 storageIndex, uint256 commitment)",
|
||||
"function register(uint256[] commitments)",
|
||||
"function register(uint16 storageIndex, uint256[] commitments)",
|
||||
"function registerStorage(address storageAddress)",
|
||||
"function renounceOwnership()",
|
||||
"function storages(uint16) view returns (address)",
|
||||
"function transferOwnership(address newOwner)",
|
||||
"function upgradeTo(address newImplementation)",
|
||||
"function upgradeToAndCall(address newImplementation, bytes data) payable",
|
||||
"function usingStorageIndex() view returns (uint16)",
|
||||
];
|
||||
|
||||
// ref https://github.com/waku-org/waku-rln-contract/blob/19fded82bca07e7b535b429dc507cfb83f10dfcf/deployments/sepolia/WakuRlnStorage_0.json#L3
|
||||
export const RLN_STORAGE_ABI = [
|
||||
"constructor(address _poseidonHasher, uint16 _contractIndex)",
|
||||
"error DuplicateIdCommitment()",
|
||||
"error FullTree()",
|
||||
"error InvalidIdCommitment(uint256 idCommitment)",
|
||||
"error NotImplemented()",
|
||||
"event MemberRegistered(uint256 idCommitment, uint256 index)",
|
||||
"event MemberWithdrawn(uint256 idCommitment, uint256 index)",
|
||||
"event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)",
|
||||
"function DEPTH() view returns (uint256)",
|
||||
"function MEMBERSHIP_DEPOSIT() view returns (uint256)",
|
||||
"function SET_SIZE() view returns (uint256)",
|
||||
"function contractIndex() view returns (uint16)",
|
||||
"function deployedBlockNumber() view returns (uint32)",
|
||||
"function idCommitmentIndex() view returns (uint256)",
|
||||
"function isValidCommitment(uint256 idCommitment) view returns (bool)",
|
||||
"function memberExists(uint256) view returns (bool)",
|
||||
"function members(uint256) view returns (uint256)",
|
||||
"function owner() view returns (address)",
|
||||
"function poseidonHasher() view returns (address)",
|
||||
"function register(uint256[] idCommitments)",
|
||||
"function register(uint256 idCommitment) payable",
|
||||
"function renounceOwnership()",
|
||||
"function slash(uint256 idCommitment, address receiver, uint256[8] proof) pure",
|
||||
"function stakedAmounts(uint256) view returns (uint256)",
|
||||
"function transferOwnership(address newOwner)",
|
||||
"function verifier() view returns (address)",
|
||||
"function withdraw() pure",
|
||||
"function withdrawalBalance(address) view returns (uint256)",
|
||||
];
|
||||
|
||||
export const SEPOLIA_CONTRACT = {
|
||||
chainId: 11155111,
|
||||
startBlock: 3193048,
|
||||
address: "0x9C09146844C1326c2dBC41c451766C7138F88155",
|
||||
abi: RLN_ABI,
|
||||
address: "0xF1935b338321013f11068abCafC548A7B0db732C",
|
||||
abi: RLN_REGISTRY_ABI,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { RLNDecoder, RLNEncoder } from "./codec.js";
|
||||
import { RLN_ABI, SEPOLIA_CONTRACT } from "./constants.js";
|
||||
import {
|
||||
RLN_REGISTRY_ABI,
|
||||
RLN_STORAGE_ABI,
|
||||
SEPOLIA_CONTRACT,
|
||||
} from "./constants.js";
|
||||
import { Keystore } from "./keystore/index.js";
|
||||
import {
|
||||
IdentityCredential,
|
||||
|
@ -29,6 +33,7 @@ export {
|
|||
RLNDecoder,
|
||||
MerkleRootTracker,
|
||||
RLNContract,
|
||||
RLN_ABI,
|
||||
RLN_STORAGE_ABI,
|
||||
RLN_REGISTRY_ABI,
|
||||
SEPOLIA_CONTRACT,
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as rln from "./index.js";
|
|||
chai.use(spies);
|
||||
|
||||
describe("RLN Contract abstraction", () => {
|
||||
it("should be able to fetch members from events and store to rln instance", async () => {
|
||||
it.only("should be able to fetch members from events and store to rln instance", async () => {
|
||||
const rlnInstance = await rln.create();
|
||||
|
||||
rlnInstance.insertMember = () => undefined;
|
||||
|
@ -19,9 +19,13 @@ describe("RLN Contract abstraction", () => {
|
|||
provider: voidSigner,
|
||||
});
|
||||
|
||||
rlnContract["_contract"] = {
|
||||
rlnContract["storageContract"] = {
|
||||
queryFilter: () => Promise.resolve([mockEvent()]),
|
||||
} as unknown as ethers.Contract;
|
||||
rlnContract["_membersFilter"] = {
|
||||
address: "",
|
||||
topics: [],
|
||||
} as unknown as ethers.EventFilter;
|
||||
|
||||
await rlnContract.fetchMembers(rlnInstance);
|
||||
|
||||
|
@ -39,12 +43,19 @@ describe("RLN Contract abstraction", () => {
|
|||
provider: voidSigner,
|
||||
});
|
||||
|
||||
rlnContract["_contract"] = {
|
||||
rlnContract["storageIndex"] = 1;
|
||||
rlnContract["_membersFilter"] = {
|
||||
address: "",
|
||||
topics: [],
|
||||
} as unknown as ethers.EventFilter;
|
||||
rlnContract["registryContract"] = {
|
||||
register: () =>
|
||||
Promise.resolve({ wait: () => Promise.resolve(undefined) }),
|
||||
MEMBERSHIP_DEPOSIT: () => Promise.resolve(1),
|
||||
} as unknown as ethers.Contract;
|
||||
const contractSpy = chai.spy.on(rlnContract["_contract"], "register");
|
||||
const contractSpy = chai.spy.on(
|
||||
rlnContract["registryContract"],
|
||||
"register"
|
||||
);
|
||||
|
||||
await rlnContract.registerWithSignature(rlnInstance, mockSignature);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ethers } from "ethers";
|
||||
|
||||
import { RLN_ABI } from "./constants.js";
|
||||
import { RLN_REGISTRY_ABI, RLN_STORAGE_ABI } from "./constants.js";
|
||||
import { IdentityCredential, RLNInstance } from "./rln.js";
|
||||
import { MerkleRootTracker } from "./root_tracker.js";
|
||||
|
||||
|
@ -9,9 +9,11 @@ type Member = {
|
|||
index: number;
|
||||
};
|
||||
|
||||
type Provider = ethers.Signer | ethers.providers.Provider;
|
||||
|
||||
type ContractOptions = {
|
||||
address: string;
|
||||
provider: ethers.Signer | ethers.providers.Provider;
|
||||
provider: Provider;
|
||||
};
|
||||
|
||||
type FetchMembersOptions = {
|
||||
|
@ -21,10 +23,14 @@ type FetchMembersOptions = {
|
|||
};
|
||||
|
||||
export class RLNContract {
|
||||
private _contract: ethers.Contract;
|
||||
private membersFilter: ethers.EventFilter;
|
||||
private registryContract: ethers.Contract;
|
||||
private merkleRootTracker: MerkleRootTracker;
|
||||
|
||||
private deployBlock: undefined | number;
|
||||
private storageIndex: undefined | number;
|
||||
private storageContract: undefined | ethers.Contract;
|
||||
private _membersFilter: undefined | ethers.EventFilter;
|
||||
|
||||
private _members: Member[] = [];
|
||||
|
||||
public static async init(
|
||||
|
@ -33,6 +39,7 @@ export class RLNContract {
|
|||
): Promise<RLNContract> {
|
||||
const rlnContract = new RLNContract(rlnInstance, options);
|
||||
|
||||
await rlnContract.initStorageContract(options.provider);
|
||||
await rlnContract.fetchMembers(rlnInstance);
|
||||
rlnContract.subscribeToMembers(rlnInstance);
|
||||
|
||||
|
@ -45,24 +52,53 @@ export class RLNContract {
|
|||
) {
|
||||
const initialRoot = rlnInstance.getMerkleRoot();
|
||||
|
||||
this._contract = new ethers.Contract(address, RLN_ABI, provider);
|
||||
this.registryContract = new ethers.Contract(
|
||||
address,
|
||||
RLN_REGISTRY_ABI,
|
||||
provider
|
||||
);
|
||||
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
||||
this.membersFilter = this.contract.filters.MemberRegistered();
|
||||
}
|
||||
|
||||
private async initStorageContract(provider: Provider): Promise<void> {
|
||||
const index = await this.registryContract.usingStorageIndex();
|
||||
const address = await this.registryContract.storages(index);
|
||||
|
||||
this.storageIndex = index;
|
||||
this.storageContract = new ethers.Contract(
|
||||
address,
|
||||
RLN_STORAGE_ABI,
|
||||
provider
|
||||
);
|
||||
this._membersFilter = this.storageContract.filters.MemberRegistered();
|
||||
|
||||
this.deployBlock = await this.storageContract.deployedBlockNumber();
|
||||
}
|
||||
|
||||
public get contract(): ethers.Contract {
|
||||
return this._contract;
|
||||
if (!this.storageContract) {
|
||||
throw Error("Storage contract was not initialized.");
|
||||
}
|
||||
return this.storageContract as ethers.Contract;
|
||||
}
|
||||
|
||||
public get members(): Member[] {
|
||||
return this._members;
|
||||
}
|
||||
|
||||
private get membersFilter(): ethers.EventFilter {
|
||||
if (!this._membersFilter) {
|
||||
throw Error("Members filter was not initialized.");
|
||||
}
|
||||
return this._membersFilter as ethers.EventFilter;
|
||||
}
|
||||
|
||||
public async fetchMembers(
|
||||
rlnInstance: RLNInstance,
|
||||
options: FetchMembersOptions = {}
|
||||
): Promise<void> {
|
||||
const registeredMemberEvents = await queryFilter(this.contract, {
|
||||
fromBlock: this.deployBlock,
|
||||
...options,
|
||||
membersFilter: this.membersFilter,
|
||||
});
|
||||
|
@ -164,12 +200,19 @@ export class RLNContract {
|
|||
public async registerWithKey(
|
||||
credential: IdentityCredential
|
||||
): Promise<ethers.Event | undefined> {
|
||||
const depositValue = await this.contract.MEMBERSHIP_DEPOSIT();
|
||||
|
||||
if (!this.storageIndex) {
|
||||
throw Error(
|
||||
"Cannot register credential, no storage contract index found."
|
||||
);
|
||||
}
|
||||
const txRegisterResponse: ethers.ContractTransaction =
|
||||
await this.contract.register(credential.IDCommitmentBigInt, {
|
||||
value: depositValue,
|
||||
});
|
||||
await this.registryContract.register(
|
||||
this.storageIndex,
|
||||
credential.IDCommitmentBigInt,
|
||||
{
|
||||
gasLimit: 100000,
|
||||
}
|
||||
);
|
||||
const txRegisterReceipt = await txRegisterResponse.wait();
|
||||
|
||||
return txRegisterReceipt?.events?.[0];
|
||||
|
|
Loading…
Reference in New Issue