mirror of
https://github.com/logos-messaging/js-rln.git
synced 2026-01-03 22:23:09 +00:00
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",
|
"gen",
|
||||||
"proto",
|
"proto",
|
||||||
"*.spec.ts",
|
"*.spec.ts",
|
||||||
"src/resources.ts"
|
"src/resources.ts",
|
||||||
|
"src/constants.ts"
|
||||||
],
|
],
|
||||||
"patterns": [
|
"patterns": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,14 +1,68 @@
|
|||||||
export const RLN_ABI = [
|
// ref https://github.com/waku-org/waku-rln-contract/blob/19fded82bca07e7b535b429dc507cfb83f10dfcf/deployments/sepolia/WakuRlnRegistry_Implementation.json#L3
|
||||||
"function MEMBERSHIP_DEPOSIT() public view returns(uint256)",
|
export const RLN_REGISTRY_ABI = [
|
||||||
"function register(uint256 pubkey) external payable",
|
"error IncompatibleStorage()",
|
||||||
"function withdraw(uint256 secret, uint256 _pubkeyIndex, address payable receiver) external",
|
"error IncompatibleStorageIndex()",
|
||||||
"event MemberRegistered(uint256 pubkey, uint256 index)",
|
"error NoStorageContractAvailable()",
|
||||||
"event MemberWithdrawn(uint256 pubkey, uint256 index)",
|
"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 = {
|
export const SEPOLIA_CONTRACT = {
|
||||||
chainId: 11155111,
|
chainId: 11155111,
|
||||||
startBlock: 3193048,
|
address: "0xF1935b338321013f11068abCafC548A7B0db732C",
|
||||||
address: "0x9C09146844C1326c2dBC41c451766C7138F88155",
|
abi: RLN_REGISTRY_ABI,
|
||||||
abi: RLN_ABI,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
import { RLNDecoder, RLNEncoder } from "./codec.js";
|
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 { Keystore } from "./keystore/index.js";
|
||||||
import {
|
import {
|
||||||
IdentityCredential,
|
IdentityCredential,
|
||||||
@ -29,6 +33,7 @@ export {
|
|||||||
RLNDecoder,
|
RLNDecoder,
|
||||||
MerkleRootTracker,
|
MerkleRootTracker,
|
||||||
RLNContract,
|
RLNContract,
|
||||||
RLN_ABI,
|
RLN_STORAGE_ABI,
|
||||||
|
RLN_REGISTRY_ABI,
|
||||||
SEPOLIA_CONTRACT,
|
SEPOLIA_CONTRACT,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import * as rln from "./index.js";
|
|||||||
chai.use(spies);
|
chai.use(spies);
|
||||||
|
|
||||||
describe("RLN Contract abstraction", () => {
|
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();
|
const rlnInstance = await rln.create();
|
||||||
|
|
||||||
rlnInstance.insertMember = () => undefined;
|
rlnInstance.insertMember = () => undefined;
|
||||||
@ -19,9 +19,13 @@ describe("RLN Contract abstraction", () => {
|
|||||||
provider: voidSigner,
|
provider: voidSigner,
|
||||||
});
|
});
|
||||||
|
|
||||||
rlnContract["_contract"] = {
|
rlnContract["storageContract"] = {
|
||||||
queryFilter: () => Promise.resolve([mockEvent()]),
|
queryFilter: () => Promise.resolve([mockEvent()]),
|
||||||
} as unknown as ethers.Contract;
|
} as unknown as ethers.Contract;
|
||||||
|
rlnContract["_membersFilter"] = {
|
||||||
|
address: "",
|
||||||
|
topics: [],
|
||||||
|
} as unknown as ethers.EventFilter;
|
||||||
|
|
||||||
await rlnContract.fetchMembers(rlnInstance);
|
await rlnContract.fetchMembers(rlnInstance);
|
||||||
|
|
||||||
@ -39,12 +43,19 @@ describe("RLN Contract abstraction", () => {
|
|||||||
provider: voidSigner,
|
provider: voidSigner,
|
||||||
});
|
});
|
||||||
|
|
||||||
rlnContract["_contract"] = {
|
rlnContract["storageIndex"] = 1;
|
||||||
|
rlnContract["_membersFilter"] = {
|
||||||
|
address: "",
|
||||||
|
topics: [],
|
||||||
|
} as unknown as ethers.EventFilter;
|
||||||
|
rlnContract["registryContract"] = {
|
||||||
register: () =>
|
register: () =>
|
||||||
Promise.resolve({ wait: () => Promise.resolve(undefined) }),
|
Promise.resolve({ wait: () => Promise.resolve(undefined) }),
|
||||||
MEMBERSHIP_DEPOSIT: () => Promise.resolve(1),
|
|
||||||
} as unknown as ethers.Contract;
|
} 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);
|
await rlnContract.registerWithSignature(rlnInstance, mockSignature);
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ethers } from "ethers";
|
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 { IdentityCredential, RLNInstance } from "./rln.js";
|
||||||
import { MerkleRootTracker } from "./root_tracker.js";
|
import { MerkleRootTracker } from "./root_tracker.js";
|
||||||
|
|
||||||
@ -9,9 +9,11 @@ type Member = {
|
|||||||
index: number;
|
index: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Provider = ethers.Signer | ethers.providers.Provider;
|
||||||
|
|
||||||
type ContractOptions = {
|
type ContractOptions = {
|
||||||
address: string;
|
address: string;
|
||||||
provider: ethers.Signer | ethers.providers.Provider;
|
provider: Provider;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FetchMembersOptions = {
|
type FetchMembersOptions = {
|
||||||
@ -21,10 +23,14 @@ type FetchMembersOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class RLNContract {
|
export class RLNContract {
|
||||||
private _contract: ethers.Contract;
|
private registryContract: ethers.Contract;
|
||||||
private membersFilter: ethers.EventFilter;
|
|
||||||
private merkleRootTracker: MerkleRootTracker;
|
private merkleRootTracker: MerkleRootTracker;
|
||||||
|
|
||||||
|
private deployBlock: undefined | number;
|
||||||
|
private storageIndex: undefined | number;
|
||||||
|
private storageContract: undefined | ethers.Contract;
|
||||||
|
private _membersFilter: undefined | ethers.EventFilter;
|
||||||
|
|
||||||
private _members: Member[] = [];
|
private _members: Member[] = [];
|
||||||
|
|
||||||
public static async init(
|
public static async init(
|
||||||
@ -33,6 +39,7 @@ export class RLNContract {
|
|||||||
): Promise<RLNContract> {
|
): Promise<RLNContract> {
|
||||||
const rlnContract = new RLNContract(rlnInstance, options);
|
const rlnContract = new RLNContract(rlnInstance, options);
|
||||||
|
|
||||||
|
await rlnContract.initStorageContract(options.provider);
|
||||||
await rlnContract.fetchMembers(rlnInstance);
|
await rlnContract.fetchMembers(rlnInstance);
|
||||||
rlnContract.subscribeToMembers(rlnInstance);
|
rlnContract.subscribeToMembers(rlnInstance);
|
||||||
|
|
||||||
@ -45,24 +52,53 @@ export class RLNContract {
|
|||||||
) {
|
) {
|
||||||
const initialRoot = rlnInstance.getMerkleRoot();
|
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.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 {
|
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[] {
|
public get members(): Member[] {
|
||||||
return this._members;
|
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(
|
public async fetchMembers(
|
||||||
rlnInstance: RLNInstance,
|
rlnInstance: RLNInstance,
|
||||||
options: FetchMembersOptions = {}
|
options: FetchMembersOptions = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const registeredMemberEvents = await queryFilter(this.contract, {
|
const registeredMemberEvents = await queryFilter(this.contract, {
|
||||||
|
fromBlock: this.deployBlock,
|
||||||
...options,
|
...options,
|
||||||
membersFilter: this.membersFilter,
|
membersFilter: this.membersFilter,
|
||||||
});
|
});
|
||||||
@ -164,12 +200,19 @@ export class RLNContract {
|
|||||||
public async registerWithKey(
|
public async registerWithKey(
|
||||||
credential: IdentityCredential
|
credential: IdentityCredential
|
||||||
): Promise<ethers.Event | undefined> {
|
): 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 =
|
const txRegisterResponse: ethers.ContractTransaction =
|
||||||
await this.contract.register(credential.IDCommitmentBigInt, {
|
await this.registryContract.register(
|
||||||
value: depositValue,
|
this.storageIndex,
|
||||||
});
|
credential.IDCommitmentBigInt,
|
||||||
|
{
|
||||||
|
gasLimit: 100000,
|
||||||
|
}
|
||||||
|
);
|
||||||
const txRegisterReceipt = await txRegisterResponse.wait();
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
||||||
|
|
||||||
return txRegisterReceipt?.events?.[0];
|
return txRegisterReceipt?.events?.[0];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user