Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add persona-js package, add simple ri launcher #29

Merged
merged 10 commits into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/persona-js/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
4 changes: 4 additions & 0 deletions packages/persona-js/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
3 changes: 3 additions & 0 deletions packages/persona-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# persona-js

TypeScript wrapper for Persona (https://github.com/latticexyz/persona)
7 changes: 7 additions & 0 deletions packages/persona-js/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* eslint-disable no-undef */
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
export default {
preset: "ts-jest",
testEnvironment: "node",
roots: ["tests"],
};
39 changes: 39 additions & 0 deletions packages/persona-js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@latticexyz/persona-js",
"license": "MIT",
"version": "0.1.8",
"main": "src/index.ts",
"type": "module",
"repository": {
"type": "git",
"url": "https://github.com/latticexyz/mud.git",
"directory": "packages/persona-js"
},
"scripts": {
"lint": "eslint . --ext .ts",
"test": "jest",
"build": "rimraf dist && rollup -c rollup.config.js",
"types": "rimraf src/ethers-types && typechain --target=ethers-v5 ../../node_modules/@latticexyz/persona/abi/*.json --out-dir src/ethers-types"
},
"devDependencies": {
"@latticexyz/persona": "https://github.com/latticexyz/persona.git#a53e26a670ed6f041dc5dec365be293457a90b5d",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-typescript": "^8.3.1",
"@typechain/ethers-v5": "^10.1.0",
"@types/jest": "^27.4.1",
"ethers": "^5.6.9",
"jest": "^27.5.1",
"rimraf": "^3.0.2",
"rollup": "^2.69.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-peer-deps-external": "^2.2.4",
"ts-jest": "^27.1.3",
"tslib": "^2.3.1",
"typechain": "^8.1.0",
"typescript": "^4.5.5"
},
"peerDependencies": {
"@latticexyz/persona": "https://github.com/latticexyz/persona.git#a53e26a670ed6f041dc5dec365be293457a90b5d",
"ethers": "^5.6.9"
}
}
16 changes: 16 additions & 0 deletions packages/persona-js/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import typescript from "@rollup/plugin-typescript";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import peerDepsExternal from "rollup-plugin-peer-deps-external";

import { defineConfig } from "rollup";

export default defineConfig({
input: "./src/index.ts",
treeshake: true,
output: {
dir: "dist",
sourcemap: true,
},
plugins: [nodeResolve(), typescript(), commonjs(), peerDepsExternal()],
});
68 changes: 68 additions & 0 deletions packages/persona-js/src/Persona.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Contract, Signer, Wallet } from "ethers";
import { ChainSpec } from "./types";
import { abi as PersonaAbi } from "@latticexyz/persona/abi/Persona.json";
import { abi as PersonaMirrorAbi } from "@latticexyz/persona/abi/PersonaMirror.json";
import { abi as PersonaAllMinterAbi } from "@latticexyz/persona/abi/PersonaAllMinter.json";
import { JsonRpcProvider } from "@ethersproject/providers";
import { Persona as PersonaContract, PersonaAllMinter, PersonaMirror } from "./ethers-types";
import { hexZeroPad } from "ethers/lib/utils";

export function Persona({ personaAddress, personaAllMinterAddress, personaMirrorAddress, chainId, rpc }: ChainSpec) {
const provider = new JsonRpcProvider(rpc, chainId);
let persona = new Contract(personaAddress, PersonaAbi, provider) as PersonaContract;
let personaMirror = new Contract(personaMirrorAddress, PersonaMirrorAbi, provider) as PersonaMirror;
let personaAllMinter = new Contract(personaAllMinterAddress, PersonaAllMinterAbi, provider) as PersonaAllMinter;

function getPersonasOfAddress(address: string) {
// Iterate over all personas and filter by address
// TODO: make persona contract enumerable
return [];
}

function connectSigner(signer: Signer) {
persona = persona.connect(signer);
personaMirror = personaMirror.connect(signer);
personaAllMinter = personaAllMinter.connect(signer);
}

async function mintPersona(): Promise<number> {
if (!persona.signer) throw new Error("Signer is not connected");
const tx = await personaAllMinter.mintPersona(persona.signer.getAddress(), { gasLimit: 1000000, gasPrice: 0 });
const receipt = await tx.wait();
let id: number | undefined;
for (const log of receipt.logs) {
try {
const { args } = persona.interface.parseLog(log);
if (args.id) {
id = args.id.toNumber();
break;
}
} catch {
// Unknown event
}
}
if (id == null) throw new Error("Could not mint persona");
return id;
}

async function authorize(personaId: number, user: string, consumer: string) {
const isAuthorized = await personaMirror.isAuthorized(personaId, user, consumer, hexZeroPad("0x0", 4));
if (!isAuthorized) await personaMirror.authorize(personaId, user, consumer, [], { gasLimit: 1000000, gasPrice: 0 });
return true;
}

async function impersonate(user: Wallet, personaId: number, consumer: string) {
const tx = await personaMirror.connect(user).impersonate(personaId, consumer, { gasLimit: 1000000, gasPrice: 0 });
return tx.wait();
}

async function mintAndBurner(consumer: string): Promise<{ personaId: number; burnerWallet: Wallet }> {
const personaId = await mintPersona();
const burnerWallet = Wallet.createRandom().connect(provider);
await authorize(personaId, burnerWallet.address, consumer);
await impersonate(burnerWallet, personaId, consumer);
return { personaId, burnerWallet };
}

return { connectSigner, getPersonasOfAddress, mintPersona, authorize, impersonate, mintAndBurner };
}
116 changes: 116 additions & 0 deletions packages/persona-js/src/ethers-types/MockL2Bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type {
BaseContract,
BigNumber,
BigNumberish,
BytesLike,
CallOverrides,
ContractTransaction,
Overrides,
PopulatedTransaction,
Signer,
utils,
} from "ethers";
import type { FunctionFragment, Result } from "@ethersproject/abi";
import type { Listener, Provider } from "@ethersproject/providers";
import type { TypedEventFilter, TypedEvent, TypedListener, OnEvent, PromiseOrValue } from "./common";

export interface MockL2BridgeInterface extends utils.Interface {
functions: {
"sendMessage(address,bytes,uint32)": FunctionFragment;
"xDomainMessageSender()": FunctionFragment;
};

getFunction(nameOrSignatureOrTopic: "sendMessage" | "xDomainMessageSender"): FunctionFragment;

encodeFunctionData(
functionFragment: "sendMessage",
values: [PromiseOrValue<string>, PromiseOrValue<BytesLike>, PromiseOrValue<BigNumberish>]
): string;
encodeFunctionData(functionFragment: "xDomainMessageSender", values?: undefined): string;

decodeFunctionResult(functionFragment: "sendMessage", data: BytesLike): Result;
decodeFunctionResult(functionFragment: "xDomainMessageSender", data: BytesLike): Result;

events: {};
}

export interface MockL2Bridge extends BaseContract {
connect(signerOrProvider: Signer | Provider | string): this;
attach(addressOrName: string): this;
deployed(): Promise<this>;

interface: MockL2BridgeInterface;

queryFilter<TEvent extends TypedEvent>(
event: TypedEventFilter<TEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TEvent>>;

listeners<TEvent extends TypedEvent>(eventFilter?: TypedEventFilter<TEvent>): Array<TypedListener<TEvent>>;
listeners(eventName?: string): Array<Listener>;
removeAllListeners<TEvent extends TypedEvent>(eventFilter: TypedEventFilter<TEvent>): this;
removeAllListeners(eventName?: string): this;
off: OnEvent<this>;
on: OnEvent<this>;
once: OnEvent<this>;
removeListener: OnEvent<this>;

functions: {
sendMessage(
target: PromiseOrValue<string>,
message: PromiseOrValue<BytesLike>,
gasLimit: PromiseOrValue<BigNumberish>,
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;

xDomainMessageSender(overrides?: CallOverrides): Promise<[string]>;
};

sendMessage(
target: PromiseOrValue<string>,
message: PromiseOrValue<BytesLike>,
gasLimit: PromiseOrValue<BigNumberish>,
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<ContractTransaction>;

xDomainMessageSender(overrides?: CallOverrides): Promise<string>;

callStatic: {
sendMessage(
target: PromiseOrValue<string>,
message: PromiseOrValue<BytesLike>,
gasLimit: PromiseOrValue<BigNumberish>,
overrides?: CallOverrides
): Promise<void>;

xDomainMessageSender(overrides?: CallOverrides): Promise<string>;
};

filters: {};

estimateGas: {
sendMessage(
target: PromiseOrValue<string>,
message: PromiseOrValue<BytesLike>,
gasLimit: PromiseOrValue<BigNumberish>,
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<BigNumber>;

xDomainMessageSender(overrides?: CallOverrides): Promise<BigNumber>;
};

populateTransaction: {
sendMessage(
target: PromiseOrValue<string>,
message: PromiseOrValue<BytesLike>,
gasLimit: PromiseOrValue<BigNumberish>,
overrides?: Overrides & { from?: PromiseOrValue<string> }
): Promise<PopulatedTransaction>;

xDomainMessageSender(overrides?: CallOverrides): Promise<PopulatedTransaction>;
};
}
Loading