Improve ease and consistancy of monorepo setup

Move contract addresses from env vars to a common JSON network config.
Add io-ts to client to verify network config JSON.
Add setup.ts to bootstrap repo.
Add deploy script for use with deploying all contracts.
Add docker-compose.yml as alternative for postgres setup.
Add main README, update component READMEs.

Co-authored-by: Andrew Morris <voltrevo@gmail.com>
This commit is contained in:
Jacob Caban-Tomski
2021-10-20 22:47:30 -06:00
parent 12cb252bab
commit e222b53102
49 changed files with 671 additions and 225 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.data

4
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"editor.tabSize": 2,
"editor.insertSpaces": true
}

162
README.md Normal file
View File

@@ -0,0 +1,162 @@
# bls-wallet
An Ethereum Layer 2 smart contract wallet that uses [BLS signatures](https://en.wikipedia.org/wiki/BLS_digital_signature) and aggregated transactions to reduce gas costs.
## Components
See each component's directory `README` for more details.
### Aggregator
Service which aggregates BLS wallet transactions.
### Clients
TS/JS Client libraries for web apps and services.
### Contracts
`bls-wallet` Solidity contracts.
### Extension
Quill browser extension used to manage BLS Wallets and sign transactions.
### Signer
TS/JS BLS Signing lib.
## Dependencies
### Required
- [NodeJS](https://nodejs.org)
- [Yarn](https://yarnpkg.com/getting-started/install) (`npm install -g yarn`)
- [Deno](https://deno.land/#installation)
### Optional (Recomended)
- [nvm](https://github.com/nvm-sh/nvm#installing-and-updating)
- [docker-compose](https://docs.docker.com/compose/install/)
- [MetaMask](https://metamask.io/)
## Setup
Run the repo setup script
```sh
./setup.ts
```
Then choose to target either a local Hardhat node or the Arbitrum Testnet.
### Local
Start a local Hardhat node for RPC use.
```sh
cd ./contracts
npx hardhat node
```
You can use any two of the private keys displayed for the aggregator (PK0 & PK1)
Update `./contracts/.env`.
```
...
DEPLOYER_MNEMONIC="test test test test test test test test test test test junk"
...
```
Deploy PrecompileCostEstimator.
```sh
npx hardhat run scripts/0_deploy_precompile_cost_estimator.ts --network gethDev
```
Copy the address that is output.
Update `./contracts/contracts/lib/hubble-contracts/contracts/libs/BLS.sol`'s `COST_ESTIMATOR_ADDRESS` to the value of that address;
```solidity
...
address private constant COST_ESTIMATOR_ADDRESS = 0x57047C275bbCb44D85DFA50AD562bA968EEba95A;
...
```
Deploy all remaining `bls-wallet` contracts.
```sh
npx hardhat run scripts/deploy_all.ts --network gethDev
```
Update `./aggregator/.env`.
```
...
PRIVATE_KEY_AGG=PK0
PRIVATE_KEY_ADMIN=PK1
...
```
### Arbitrum Testnet (Rinkeby Arbitrum Testnet)
You will need two ETH addresses with Rinkeby ETH and their private keys (PK0 & PK1) for running the aggregator. It is NOT recommended that you use any primary wallets with ETH Mainnet assets.
You can get Rinkeby ETH at https://app.mycrypto.com/faucet, and transfer it into the Arbitrum testnet via https://bridge.arbitrum.io/. Make sure when doing so that your network is set to Rinkeby in MetaMask.
Update `./aggregator/.env`
```
RPC_URL=https://rinkeby.arbitrum.io/rpc
...
NETWORK_CONFIG_PATH=../contracts/networks/rinkarby.json
PRIVATE_KEY_AGG=PK0
PRIVATE_KEY_ADMIN=PK1
...
```
Update `./extension/.env`
```
...
CHAIN_RPC_URL=https://rinkeby.arbitrum.io/rpc
...
```
## Run
```sh
docker-compose up -d postgres # Or see local postgres instructions in ./aggregator/README.md#PostgreSQL
cd ./aggregator
./programs/aggregator.ts
```
In a seperate terminal/shell instance
```sh
cd ./extension
yarn run dev:chrome # or dev:firefox, dev:opera
```
### Chrome
1. Go to Chrome's [extension page](chrome://extensions).
2. Enable `Developer mode`.
3. Either click `Load unpacked extension...` and select `./extension/extension/chrome` or drag that folder into the page.
### Firefox
1. Go to Firefox's [debugging page](about:debugging#/runtime/this-firefox).
2. Click `Load Temporary Add-on...`.
3. Select `./extension/extension/firefox/manifest.json`.
## Testing/using updates to ./clients
For `extension`:
```sh
cd ./contracts/clients
yarn build
yarn link
cd ../extension
yarn link bls-wallet-clients
```
For aggregator, you will need to push up a release canidate (-rc) version to 'bls-wallet-clients' on npm and update the version in `./aggregtor/src/deps.ts` until a local linking solution for deno is found. See https://github.com/alephjs/esm.sh/discussions/216 for details.
`./aggregtor/deps.ts`
```typescript
...
} from "https://cdn.skypack.dev/bls-wallet-clients@x.y.z-rc.w?dts";
...
```

View File

@@ -1,21 +1,15 @@
RPC_URL=http://localhost:8545
USE_TEST_NET=true
USE_TEST_NET=false
ORIGIN=http://localhost:3000
PORT=3000
NETWORK_CONFIG_PATH=../contracts/networks/local.json
PRIVATE_KEY_AGG=0x0000000000000000000000000000000000000000000000000000000000000a99
PRIVATE_KEY_ADMIN=
TEST_BLS_WALLETS_SECRET=test-bls-wallets-secret
DEPLOYER_ADDRESS=0xF28eA4691841aD169DaCeA9E1aE13BE34F55F149
VERIFICATION_GATEWAY_ADDRESS=0x2d5fE6D528557F543c3CD47f002f536F733B4F62
REWARD_TOKEN_ADDRESS=0x841b79116C437D8694091bfe6b8F33057d3e7ca7
BLS_EXPANDER_ADDRESS=0x49d3Fa402d99db9D0CD9737EefeA5E0a41523385
TEST_TOKEN_ADDRESS=0x6F714e7b5a7F0913038664d932e8acd6fDf1Ad55
PG_HOST=localhost
PG_PORT=5432
PG_USER=bls

View File

@@ -31,6 +31,15 @@ commands.
### PostgreSQL
#### With docker-compose
```sh
cd .. # root of repo
docker-compose up -d postgres
```
#### Local Install
Install, e.g.:
```sh
@@ -124,7 +133,7 @@ Tests are defined in `test`. Running them directly is a bit verbose because of
the deno flags you need:
```sh
deno test -j --allow-net --allow-env --allow-read --unstable -- --env local
deno test -j --allow-net --allow-env --allow-read --unstable
```
Instead, `./programs/premerge.ts` may be more useful for you. It'll make sure

View File

@@ -41,8 +41,15 @@ export type {
export {
Aggregator as AggregatorClient,
BlsWallet,
getConfig,
NetworkConfig,
VerificationGateway,
} from "https://esm.sh/bls-wallet-clients@0.2.2";
/**
* TODO (merge-ok) Switch back to esm.sh when HKT import resolves correctly.
* error: Import 'https://cdn.esm.sh/v58/fp-ts@2.11.5/lib/HKT/HKT.d.ts' failed: 404 Not Found
* at https://cdn.esm.sh/v58/bls-wallet-clients@0.2.5-rc.1/deno/bls-wallet-clients.js:2:34
*/
} from "https://cdn.skypack.dev/bls-wallet-clients@0.2.5-rc.1?dts";
// Database dependencies
export {

View File

@@ -3,6 +3,7 @@
import { AggregatorClient, BlsWallet, ethers, parseArgs } from "../deps.ts";
import assert from "../src/helpers/assert.ts";
import getNetworkConfig from "../src/helpers/networkConfig.ts";
import nil from "../src/helpers/nil.ts";
import Rng from "../src/helpers/Rng.ts";
import * as env from "../test/env.ts";
@@ -25,9 +26,11 @@ if (!seed) {
const privateKey = rng.seed(`${seed}`).address();
const { addresses } = await getNetworkConfig();
const wallet = await BlsWallet.connect(
privateKey,
env.VERIFICATION_GATEWAY_ADDRESS,
addresses.verificationGateway,
provider,
);
@@ -38,7 +41,7 @@ if (wallet !== nil) {
const tx = await BlsWallet.signCreation(
privateKey,
env.VERIFICATION_GATEWAY_ADDRESS,
addresses.verificationGateway,
provider,
);

View File

@@ -4,11 +4,14 @@ import * as env from "../../test/env.ts";
import AdminWallet from "../../src/chain/AdminWallet.ts";
import Range from "../../src/helpers/Range.ts";
import Rng from "../../src/helpers/Rng.ts";
import getNetworkConfig from "../../src/helpers/networkConfig.ts";
export default async function TestBlsWallets(
provider: ethers.providers.Provider,
count: number,
) {
const { addresses } = await getNetworkConfig();
const parent = AdminWallet(provider);
const rng = Rng.root.seed(env.PRIVATE_KEY_ADMIN, env.TEST_BLS_WALLETS_SECRET);
@@ -17,7 +20,7 @@ export default async function TestBlsWallets(
const secret = rng.seed(`${i}`).address();
return await BlsWallet.connect(
secret,
env.VERIFICATION_GATEWAY_ADDRESS,
addresses.verificationGateway,
parent.provider,
);
}),
@@ -36,7 +39,7 @@ export default async function TestBlsWallets(
wallets.push(
await BlsWallet.connectOrCreate(
secret,
env.VERIFICATION_GATEWAY_ADDRESS,
addresses.verificationGateway,
parent,
),
);

View File

@@ -3,13 +3,16 @@
import { AggregatorClient, delay, ethers } from "../deps.ts";
import assert from "../src/helpers/assert.ts";
import getNetworkConfig from "../src/helpers/networkConfig.ts";
import * as env from "../test/env.ts";
import MockErc20 from "../test/helpers/MockErc20.ts";
import TestBlsWallets from "./helpers/TestBlsWallets.ts";
const { addresses } = await getNetworkConfig();
const provider = new ethers.providers.JsonRpcProvider(env.RPC_URL);
const testErc20 = new MockErc20(env.TEST_TOKEN_ADDRESS, provider);
const testErc20 = new MockErc20(addresses.testToken, provider);
const client = new AggregatorClient(env.ORIGIN);

View File

@@ -6,6 +6,9 @@ import WalletService from "../src/app/WalletService.ts";
import * as env from "../test/env.ts";
import MockErc20 from "../test/helpers/MockErc20.ts";
import TestBlsWallets from "./helpers/TestBlsWallets.ts";
import getNetworkConfig from "../src/helpers/networkConfig.ts";
const { addresses } = await getNetworkConfig();
const provider = new ethers.providers.JsonRpcProvider(env.RPC_URL);
@@ -13,10 +16,11 @@ const walletService = await WalletService.create(
(evt) => {
console.log(evt);
},
addresses.verificationGateway,
env.PRIVATE_KEY_AGG,
);
const testErc20 = new MockErc20(env.TEST_TOKEN_ADDRESS, provider);
const testErc20 = new MockErc20(addresses.testToken, provider);
const [wallet] = await TestBlsWallets(provider, 1);

View File

@@ -12,6 +12,7 @@ import * as env from "../test/env.ts";
import AdminWallet from "../src/chain/AdminWallet.ts";
import MockErc20 from "../test/helpers/MockErc20.ts";
import TestBlsWallets from "./helpers/TestBlsWallets.ts";
import getNetworkConfig from "../src/helpers/networkConfig.ts";
const logStartTime = Date.now();
@@ -29,10 +30,12 @@ const leadTarget = env.MAX_AGGREGATION_SIZE * env.MAX_UNCONFIRMED_AGGREGATIONS;
const pollingInterval = 400;
const sendWalletCount = 50;
const { addresses } = await getNetworkConfig();
const provider = new ethers.providers.JsonRpcProvider(env.RPC_URL);
const adminWallet = AdminWallet(provider);
const testErc20 = new MockErc20(env.TEST_TOKEN_ADDRESS, provider);
const testErc20 = new MockErc20(addresses.testToken, provider);
const client = new AggregatorClient(env.ORIGIN);
@@ -47,7 +50,7 @@ log("Checking/minting test tokens...");
for (const wallet of sendWallets) {
const testErc20 = new MockErc20(
env.TEST_TOKEN_ADDRESS,
addresses.testToken,
adminWallet,
);

View File

@@ -35,10 +35,11 @@ export default class WalletService {
public emit: (evt: AppEvent) => void,
public aggregatorSigner: Wallet,
public blsWalletSigner: BlsWalletSigner,
verificationGatewayAddress: string,
public nextNonce: number,
) {
this.verificationGateway = new VerificationGateway(
env.VERIFICATION_GATEWAY_ADDRESS,
verificationGatewayAddress,
this.aggregatorSigner,
);
}
@@ -50,6 +51,7 @@ export default class WalletService {
static async create(
emit: (evt: AppEvent) => void,
verificationGatewayAddress: string,
aggPrivateKey: string,
): Promise<WalletService> {
const aggregatorSigner = WalletService.getAggregatorSigner(aggPrivateKey);
@@ -61,6 +63,7 @@ export default class WalletService {
emit,
aggregatorSigner,
blsWalletSigner,
verificationGatewayAddress,
nextNonce,
);
}
@@ -79,7 +82,7 @@ export default class WalletService {
const nextNonce = await BlsWallet.Nonce(
tx.publicKey,
env.VERIFICATION_GATEWAY_ADDRESS,
this.verificationGateway.address,
this.aggregatorSigner,
);

View File

@@ -12,10 +12,13 @@ import TxTable from "./TxTable.ts";
import createQueryClient from "./createQueryClient.ts";
import Mutex from "../helpers/Mutex.ts";
import Clock from "../helpers/Clock.ts";
import getNetworkConfig from "../helpers/getNetworkConfig.ts";
import AppEvent from "./AppEvent.ts";
import WalletRouter from "./WalletRouter.ts";
export default async function app(emit: (evt: AppEvent) => void) {
const { addresses } = await getNetworkConfig();
const clock = Clock.create();
const queryClient = createQueryClient(emit);
@@ -29,7 +32,11 @@ export default async function app(emit: (evt: AppEvent) => void) {
env.FUTURE_TX_TABLE_NAME,
);
const walletService = await WalletService.create(emit, env.PRIVATE_KEY_AGG);
const walletService = await WalletService.create(
emit,
addresses.verificationGateway,
env.PRIVATE_KEY_AGG
);
const txService = new TxService(
emit,

View File

@@ -11,19 +11,10 @@ export const PORT = requireIntEnv("PORT");
export const USE_TEST_NET = requireBoolEnv("USE_TEST_NET");
export const NETWORK_CONFIG_PATH = requireEnv("NETWORK_CONFIG_PATH");
export const PRIVATE_KEY_AGG = requireEnv("PRIVATE_KEY_AGG");
export const PRIVATE_KEY_ADMIN = requireEnv("PRIVATE_KEY_ADMIN");
export const DEPLOYER_ADDRESS = requireEnv("DEPLOYER_ADDRESS");
export const VERIFICATION_GATEWAY_ADDRESS = requireEnv(
"VERIFICATION_GATEWAY_ADDRESS",
);
export const BLS_EXPANDER_ADDRESS = requireEnv("BLS_EXPANDER_ADDRESS");
export const REWARD_TOKEN_ADDRESS = requireEnv("REWARD_TOKEN_ADDRESS");
export const PG = {
HOST: requireEnv("PG_HOST"),
PORT: requireEnv("PG_PORT"),

View File

@@ -0,0 +1,6 @@
import { NetworkConfig, getConfig } from "../../deps.ts";
import * as env from "../env.ts";
export default function getNetworkConfig(): Promise<NetworkConfig> {
return getConfig(env.NETWORK_CONFIG_PATH, Deno.readTextFile);
}

View File

@@ -1,12 +1,11 @@
import { assertEquals, BlsWallet, keccak256 } from "./deps.ts";
import Fixture from "./helpers/Fixture.ts";
import * as env from "./env.ts";
Fixture.test("should register new wallet", async (fx) => {
const wallet = await BlsWallet.connectOrCreate(
fx.rng.seed("blsPrivateKey").address(),
env.VERIFICATION_GATEWAY_ADDRESS,
fx.networkConfig.addresses.verificationGateway,
fx.adminWallet,
);
@@ -21,13 +20,13 @@ Fixture.test(
async (fx) => {
const firstWallet = await BlsWallet.connectOrCreate(
fx.rng.seed("blsPrivateKey").address(),
env.VERIFICATION_GATEWAY_ADDRESS,
fx.networkConfig.addresses.verificationGateway,
fx.adminWallet,
);
const secondWallet = await BlsWallet.connectOrCreate(
fx.rng.seed("blsPrivateKey").address(),
env.VERIFICATION_GATEWAY_ADDRESS,
fx.networkConfig.addresses.verificationGateway,
fx.adminWallet,
);

View File

@@ -2,7 +2,6 @@ import { assertEquals, BigNumber, BlsWallet } from "./deps.ts";
import Fixture from "./helpers/Fixture.ts";
import Range from "../src/helpers/Range.ts";
import * as env from "./env.ts";
Fixture.test("WalletService sends single tx", async (fx) => {
const [wallet] = await fx.setupWallets(1);
@@ -173,7 +172,7 @@ Fixture.test(
Fixture.test("WalletService can create a wallet", async (fx) => {
const tx = await BlsWallet.signCreation(
fx.rng.seed("aggregator-free-wallet").address(),
env.VERIFICATION_GATEWAY_ADDRESS,
fx.networkConfig.addresses.verificationGateway,
fx.adminWallet.provider,
);

View File

@@ -7,7 +7,6 @@ import {
export * from "../src/env.ts";
export const TEST_SEED = optionalEnv("TEST_SEED");
export const TEST_TOKEN_ADDRESS = requireEnv("TEST_TOKEN_ADDRESS");
export const TEST_LOGGING = requireBoolEnv("TEST_LOGGING");

View File

@@ -13,6 +13,7 @@ import AdminWallet from "../../src/chain/AdminWallet.ts";
import AppEvent from "../../src/app/AppEvent.ts";
import MockErc20 from "./MockErc20.ts";
import nil, { isNotNil } from "../../src/helpers/nil.ts";
import getNetworkConfig, { NetworkConfig } from "../../src/helpers/getNetworkConfig.ts";
// deno-lint-ignore no-explicit-any
type ExplicitAny = any;
@@ -41,10 +42,12 @@ export default class Fixture {
}
static async create(testName: string): Promise<Fixture> {
const netCfg = await getNetworkConfig();
const rng = testRng.seed(testName);
const walletService = await WalletService.create(
(evt) => fx.emit(evt),
netCfg.addresses.verificationGateway,
env.PRIVATE_KEY_AGG,
);
@@ -56,6 +59,7 @@ export default class Fixture {
rng,
chainId,
walletService,
netCfg,
);
return fx;
@@ -87,14 +91,15 @@ export default class Fixture {
public rng: typeof testRng,
public chainId: number,
public walletService: WalletService,
public networkConfig: NetworkConfig,
) {
this.testErc20 = new MockErc20(
env.TEST_TOKEN_ADDRESS,
this.networkConfig.addresses.testToken,
this.walletService.aggregatorSigner,
);
this.rewardErc20 = new MockErc20(
env.REWARD_TOKEN_ADDRESS,
this.networkConfig.addresses.rewardToken,
this.walletService.aggregatorSigner,
);
@@ -170,7 +175,7 @@ export default class Fixture {
for (const i of Range(count)) {
const wallet = await BlsWallet.connectOrCreate(
this.createBlsPrivateKey(`${i}`, ...extraSeeds),
env.VERIFICATION_GATEWAY_ADDRESS,
this.networkConfig.addresses.verificationGateway,
this.adminWallet,
);

View File

@@ -1,12 +1,12 @@
ETHERSCAN_API_KEY=
ROPSTEN_URL=
RINKEBY_URL=
ROPSTEN_URL=fill_me_in
RINKEBY_URL=fill_me_in
ARBITRUM_TESTNET_URL=https://rinkeby.arbitrum.io/rpc
ARBITRUM_URL=https://arb1.arbitrum.io/rpc
OPTIMISM_LOCAL_URL=http://localhost:8545
OPTIMISM_TESETNET_URL=https://kovan.optimism.io
OPTIMISM_URL=
OPTIMISM_URL=https://mainnet.optimism.io
# Only used for deploying the deployer contract at the same address on each evm network
DEPLOYER_MNEMONIC="sock poet alone around radar forum quiz session observe rebel another choice"
@@ -18,9 +18,9 @@ DEPLOYER_CONTRACT_ADDRESS=0x036d996D6855B83cd80142f2933d8C2617dA5617
MAIN_MNEMONIC="test test test test test test test test test test test junk"
PRIVATE_KEY_AGG=0000000000000000000000000000000000000000000000000000000000000a99
PRIVATE_KEY_AGG_OKOV=
PRIVATE_KEY_AGG_RINKARBY=
PRIVATE_KEY_AGG_ARB1=
PRIVATE_KEY_AGG_OKOV=0000000000000000000000000000000000000000000000000000000000000001
PRIVATE_KEY_AGG_RINKARBY=0000000000000000000000000000000000000000000000000000000000000001
PRIVATE_KEY_AGG_ARB1=0000000000000000000000000000000000000000000000000000000000000001
PRIVATE_KEY_002=0000000000000000000000000000000000000000000000000000000000000002
PRIVATE_KEY_003=0000000000000000000000000000000000000000000000000000000000000003
PRIVATE_KEY_004=0000000000000000000000000000000000000000000000000000000000000004
@@ -29,26 +29,3 @@ PRIVATE_KEY_005=0000000000000000000000000000000000000000000000000000000000000005
# Addresses as deployed with create2 from deployer contract (same address per network)
PRECOMPILE_COST_ESTIMATOR_ADDRESS=0x22E4a5251C1F02de8369Dd6f192033F6CB7531A4
ARB1_PRECOMPILE_COST_ESTIMATOR_ADDRESS=
ARB1_BLS_LIBRARY=
ARB1_VERIFICATION_GATEWAY_ADDRESS=
ARB1_BLS_EXPANDER_ADDRESS=
ARB1_ERC20_CONTRACT_ADDRESS=
RINKARBY_PRECOMPILE_COST_ESTIMATOR_ADDRESS=0x85C17E7180879a71EDAE76B43E4a85159a7eA601
RINKARBY_BLS_LIBRARY=0xA86c40ad4b04E0228BB89B672bb32214Cb9bf02f
RINKARBY_VERIFICATION_GATEWAY_ADDRESS=0xb679755176c3cCad9120d99d4715FCE176998b15
RINKARBY_BLS_EXPANDER_ADDRESS=0x2eC878702014849Ca7739c2a6DaFe795A8a8F778
RINKARBY_ERC20_CONTRACT_ADDRESS=0x8CD755F93E56C90E3d5803c036771CFCc12B7c53
OKOVAN_PRECOMPILE_COST_ESTIMATOR_ADDRESS=
OKOVAN_BLS_LIBRARY
OKOVAN_VERIFICATION_GATEWAY_ADDRESS=
OKOVAN_BLS_EXPANDER_ADDRESS=
OKOVAN_ERC20_CONTRACT_ADDRESS=
OETH_PRECOMPILE_COST_ESTIMATOR_ADDRESS=
OETH_BLS_LIBRARY
OETH_VERIFICATION_GATEWAY_ADDRESS=
OETH_BLS_EXPANDER_ADDRESS=
OETH_ERC20_CONTRACT_ADDRESS=

View File

@@ -5,6 +5,7 @@ node_modules
coverage
coverage.json
/typechain
networks/local.json
#Hardhat files
artifacts

View File

@@ -78,10 +78,10 @@ Proposed solution to make use of [BLS](https://github.com/thehubbleproject/hubbl
# Dev/test
- Run the aggregation server (see `./server`).
- Run the aggregation server (see `../aggregator`).
- build and test contracts - `npx hardhat test`
Note: Depending on the network being used, the address of the deployed PrecompileCostEstimator will need to be set [here](https://github.com/jzaki/bls-wallet/blob/main/contracts/contracts/lib/hubble-contracts/contracts/libs/BLS.sol#L42). #15 will resolve this.
-Note: Depending on the network being used, the address of the deployed PrecompileCostEstimator will need to be set [here](https://github.com/jzaki/bls-wallet/blob/main/contracts/contracts/lib/hubble-contracts/contracts/libs/BLS.sol#L42).
For each network, the deployer contract can be deployed with the following script (only needed once)
`DEPLOY_DEPLOYER=true yarn hardhat run scripts/deploy-deployer.ts --network <network-name>`

View File

@@ -2,6 +2,20 @@
*Client libraries for interacting with BLS Wallet components*
## Network Config
Deployed contract addresses and metadata.
```ts
import { NetworkConfig, getConfig } from 'bls-wallet-clients';
const netCfg: NetworkConfig = await getConfig(
'/path/to/network/config',
async (path) => ... /* fetch, fs.readFile, etc. */
);
// Read from netCfg.addresses.verificationGateway, etc.
```
## Aggregator
Exposes typed functions for interacting with the Aggregator's HTTP api.

View File

@@ -17,13 +17,15 @@
"publish-experimental-dry-run": "node scripts/showVersion.js >.version && npm version $(node scripts/showBaseVersion.js)-$(git rev-parse HEAD | head -c7) --allow-same-version && npm publish --tag experimental --dry-run && npm version $(cat .version) && rm .version"
},
"dependencies": {
"ethers": "^5.5.0",
"@ethersproject/abi": "^5.4.0",
"@ethersproject/bignumber": "^5.4.1",
"@ethersproject/bytes": "^5.4.0",
"@ethersproject/keccak256": "^5.4.0",
"@ethersproject/sha2": "^5.4.0",
"@ethersproject/solidity": "^5.4.0",
"ethers": "^5.5.0",
"fp-ts": "^2.11.5",
"io-ts": "^2.2.16",
"mcl-wasm": "0.7.6",
"typescript": "^4.3.5"
},

View File

@@ -0,0 +1,82 @@
import * as t from "io-ts";
import { PathReporter } from "io-ts/PathReporter";
const NetworkConfigType = t.readonly(
t.type({
/**
* Parameters used in contract deployment. Currently unused.
*/
parameters: t.UnknownRecord,
/**
* Contract addresses
*/
addresses: t.type({
create2Deployer: t.string,
precompileCostEstimator: t.string,
verificationGateway: t.string,
blsLibrary: t.string,
blsExpander: t.string,
testToken: t.string,
rewardToken: t.string,
}),
/**
* Additional information about deployment/deployed state
*/
auxiliary: t.type({
chainid: t.number,
/**
* Domain used for BLS signing
*/
domain: t.string,
/**
* Starting block contracts began dpeloyment at
*/
genesisBlock: t.number,
/**
* Address of the EOA which deployed the contracts
*/
deployedBy: t.string,
/**
* Git commit SHA of the contracts
*/
version: t.string,
}),
}),
);
/**
* Config representing the deployed state of bls-wallet contracts
*/
export type NetworkConfig = t.TypeOf<typeof NetworkConfigType>;
type ReadFileFunc = (filePath: string) => Promise<string>;
/**
* Validates and returns a network config.
*
* @param cfg The config object to validate.
*/
export function validateConfig(cfg: unknown): NetworkConfig {
const result = NetworkConfigType.decode(cfg);
const report = PathReporter.report(result);
const hasErrors = report.length > 0 && report[0] !== "No errors!";
if (hasErrors) {
throw new Error(report.join(", "));
}
return cfg as NetworkConfig;
}
/**
* Retrieves, validates, and returns a network config.
*
* @param networkConfigPath Path to config JSON file.
* @param readFileFunc Callback to retrieve the config. This could be via fetch, fs.readFile, etc.
*/
export async function getConfig(
networkConfigPath: string,
readFileFunc: ReadFileFunc,
): Promise<NetworkConfig> {
const cfg = JSON.parse(await readFileFunc(networkConfigPath));
validateConfig(cfg);
return cfg;
}

View File

@@ -4,6 +4,7 @@ import BlsWalletWrapper from "./BlsWalletWrapper";
import type { VerificationGateway } from "../typechain/VerificationGateway";
// eslint-disable-next-line camelcase
import { VerificationGateway__factory } from "../typechain/factories/VerificationGateway__factory";
import { NetworkConfig, getConfig, validateConfig } from "./NetworkConfig";
export * from "./signer";
@@ -13,4 +14,7 @@ export {
VerificationGateway,
// eslint-disable-next-line camelcase
VerificationGateway__factory,
NetworkConfig,
getConfig,
validateConfig,
};

View File

@@ -626,6 +626,11 @@ flat@^5.0.2:
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
fp-ts@^2.11.5:
version "2.11.5"
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.11.5.tgz#97cceb26655b1452d7088d6fb0864f84cceffbe4"
integrity sha512-OqlwJq1BdpB83BZXTqI+dNcA6uYk6qk4u9Cgnt64Y+XS7dwdbp/mobx8S2KXf2AXH+scNmA/UVK3SEFHR3vHZA==
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -710,6 +715,11 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4:
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
io-ts@^2.2.16:
version "2.2.16"
resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.16.tgz#597dffa03db1913fc318c9c6df6931cb4ed808b2"
integrity sha512-y5TTSa6VP6le0hhmIyN0dqEXkrZeJLeC5KApJq6VLci3UEKF80lZ+KuoUs02RhBxNWlrqSNxzfI7otLX1Euv8Q==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"

View File

@@ -0,0 +1,18 @@
{
"parameters": {},
"addresses": {
"precompileCostEstimator": "0x85C17E7180879a71EDAE76B43E4a85159a7eA601",
"verificationGateway": "0xb679755176c3cCad9120d99d4715FCE176998b15",
"blsLibrary": "0xA86c40ad4b04E0228BB89B672bb32214Cb9bf02f",
"blsExpander": "0x2eC878702014849Ca7739c2a6DaFe795A8a8F778",
"testToken": "0x8CD755F93E56C90E3d5803c036771CFCc12B7c53",
"rewardToken": "0x8CD755F93E56C90E3d5803c036771CFCc12B7c53"
},
"auxiliary": {
"chainid": 421611,
"domain": "0x0054159611832e24cdd64c6a133e71d373c5f8553dde6c762e6bffe707ad83cc",
"genesisBlock": 123456,
"deployedBy": "TODO fill in",
"version": "c1d1f197ba9b68284cbc4ec145e286a4e84c0eaf"
}
}

View File

@@ -1,21 +1,11 @@
/* eslint-disable no-process-exit */
import { network } from "hardhat";
// import getDeployedAddresses from "../shared/helpers/getDeployedAddresses";
import Fixture from "../shared/helpers/Fixture";
require("dotenv").config();
async function main() {
let fx: Fixture;
if (network.name === "rinkarby") {
// const addresses = getDeployedAddresses(network.name);
fx = await Fixture.create();
} else {
fx = await Fixture.create();
}
const fx = await Fixture.create();
console.log(`Deployer account address: ${fx.addresses[0]}`);
console.log(`verificationGateway: ${fx.verificationGateway.address}`);

View File

@@ -0,0 +1,88 @@
/* eslint-disable no-process-exit */
import * as dotenv from "dotenv";
import util from "util";
import { exec as execCb } from "child_process";
import { writeFile } from "fs/promises";
import { ethers } from "hardhat";
import { NetworkConfig } from "../clients/src";
import deployDeployer from "../shared/helpers/deployDeployer";
import precompileCostEstimator from "../shared/helpers/deployAndRunPrecompileCostEstimator";
import Fixture from "../shared/helpers/Fixture";
dotenv.config();
const exec = util.promisify(execCb);
const netCfgFilePath = "./networks/local.json";
async function deployToken(): Promise<string> {
const MockERC20 = await ethers.getContractFactory("MockERC20");
const initialSupply = ethers.utils.parseUnits("1000000");
const testToken = await MockERC20.deploy("AnyToken", "TOK", initialSupply);
await testToken.deployed();
return testToken.address;
}
async function getVersion(): Promise<string> {
const { stdout } = await exec("git rev-parse HEAD");
return stdout.trim();
}
async function main() {
console.log("starting bls-wallet contracts deployment");
const genesisBlock = await ethers.provider.getBlockNumber();
console.log("deploying create2Deployer...");
const create2Deployer = await deployDeployer();
console.log("deploying precompile cost estimator...");
const precompileCostEstimatorAddress = await precompileCostEstimator();
console.log("deploying bls-wallet contracts...");
const fx = await Fixture.create();
const [deployedBy] = fx.addresses;
console.log("deploying test token...");
// These can be run in parallel
const [testToken, version] = await Promise.all([deployToken(), getVersion()]);
const netCfg: NetworkConfig = {
parameters: {},
addresses: {
create2Deployer: create2Deployer.address,
precompileCostEstimator: precompileCostEstimatorAddress,
blsLibrary: fx.blsLibrary.address,
verificationGateway: fx.verificationGateway.address,
blsExpander: fx.blsExpander.address,
testToken,
rewardToken: testToken,
},
auxiliary: {
chainid: fx.chainId,
// From VerificationGateway.sol:BLS_DOMAIN
domain:
"0x0054159611832e24cdd64c6a133e71d373c5f8553dde6c762e6bffe707ad83cc",
genesisBlock,
deployedBy,
version,
},
};
const jsonStr = JSON.stringify(netCfg, null, 4);
console.log(`writing network config to ${netCfgFilePath}`);
console.log(jsonStr);
await writeFile(netCfgFilePath, jsonStr);
console.log("bls-wallet contracts deployment complete");
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => {
process.exit(0);
})
.catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -1,14 +1,11 @@
/* eslint-disable no-process-exit */
import { BigNumber } from "ethers";
import { solidityPack } from "ethers/lib/utils";
import { Bundle } from "../../clients/src";
import getDeployedAddresses from "../../shared/helpers/getDeployedAddresses";
import Fixture from "../../shared/helpers/Fixture";
import TokenHelper from "../../shared/helpers/TokenHelper";
import { network } from "hardhat";
import { solidityPack } from "ethers/lib/utils";
let fx: Fixture;
let th: TokenHelper;
@@ -31,16 +28,8 @@ async function logGasForTransfers() {
txHash: -1,
};
const config = getDeployedAddresses(network.name);
fx = await Fixture.create(1);
fx = await Fixture.create(
1,
false,
config.blsLibAddress,
config.vgAddress,
config.expanderAddress,
[+process.env.BLS_SECRET_NUM_1],
);
th = new TokenHelper(fx);
const blsWallets = await th.walletTokenSetup();

View File

@@ -2,36 +2,25 @@
import { network, ethers } from "hardhat";
import Fixture from "../../shared/helpers/Fixture";
import getDeployedAddresses, {
DeployedAddresses,
} from "../../shared/helpers/getDeployedAddresses";
import getNetworkConfig from "../../shared/helpers/getNetworkConfig";
let config: DeployedAddresses;
let config;
// let ethToken: Contract;
// let blsWallets: Contract[];
let blsAddresses: string[];
async function setup(blsSecretNumbers: number[]): Promise<Fixture> {
config = getDeployedAddresses(network.name);
config = await getNetworkConfig(network.name);
console.log("config:", config);
console.log("Creating fixture from use wallet...");
const fx = await Fixture.create(
blsSecretNumbers.length,
true,
config.blsLibAddress,
config.vgAddress,
config.expanderAddress,
blsSecretNumbers,
);
const fx = await Fixture.create(blsSecretNumbers.length, blsSecretNumbers);
console.log("Attaching to token:", config.tokenAddress);
console.log("Attaching to token:", config.addresses.testToken);
const ERC20 = await ethers.getContractFactory("MockERC20");
ERC20.attach(config.tokenAddress);
// if (config.ethAddress) {
// ethToken = ERC20.attach(config.ethAddress);
// }
ERC20.attach(config.addresses.testToken);
return fx;
}
@@ -43,12 +32,10 @@ async function main() {
+process.env.BLS_SECRET_NUM_3,
]);
config.blsAddresses = (await fx.createBLSWallets()).map(
(wallet) => wallet.address,
);
console.log(`BlsWallet contract addresses: ${config.blsAddresses}`);
blsAddresses = (await fx.createBLSWallets()).map((wallet) => wallet.address);
console.log(`BlsWallet contract addresses: ${blsAddresses}`);
// blsWallets = config.blsAddresses.map((a) => fx.BLSWallet.attach(a));
// blsWallets = blsAddresses.map((a) => fx.BLSWallet.attach(a));
// blsSignFunction({
// blsSigner: fx.blsSigners[0],

View File

@@ -16,6 +16,7 @@ import {
VerificationGateway,
// eslint-disable-next-line camelcase
VerificationGateway__factory,
BLSOpen,
} from "../../typechain";
export default class Fixture {
@@ -33,6 +34,7 @@ export default class Fixture {
public verificationGateway: VerificationGateway,
public blsLibrary: BLSOpen,
public blsExpander: Contract,
public BLSWallet: ContractFactory,
@@ -42,10 +44,6 @@ export default class Fixture {
/// @dev Contracts deployed by first ethers signer
static async create(
blsWalletCount: number = Fixture.DEFAULT_BLS_ACCOUNTS_LENGTH,
initialized: boolean = true,
blsAddress?: string,
vgAddress?: string,
expanderAddress?: string,
secretNumbers?: number[],
) {
const chainId = (await ethers.provider.getNetwork()).chainId;
@@ -70,7 +68,7 @@ export default class Fixture {
const vgContract = await create2Fixture.create2Contract(
"VerificationGateway",
);
const bls = await create2Fixture.create2Contract("BLSOpen");
const bls = (await create2Fixture.create2Contract("BLSOpen")) as BLSOpen;
try {
await (
@@ -96,7 +94,7 @@ export default class Fixture {
if (secretNumbers !== undefined) {
secretNumber = secretNumbers[i];
assert(secretNumber !== undefined);
assert(!isNaN(secretNumber), "secret ");
} else {
secretNumber = Math.abs((Math.random() * 0xffffffff) << 0);
}
@@ -126,6 +124,7 @@ export default class Fixture {
addresses,
lazyBlsWallets,
verificationGateway,
bls,
blsExpander,
BLSWallet,
await initBlsWalletSigner({ chainId }),

View File

@@ -0,0 +1,26 @@
const blsAddresses = {
arb1: [],
rinkarby: [
"0x3f509901664E21e2dc3a189C9E67DDC2864848cC",
"0x4AA467DA53E722E0C9aa516083aC5A0b40e5a0c8",
"0xAA0E6088e0B8801c9D679A1C715EF836129458Cc",
],
optimistic: [
"0x69A9c53e7000c8B7aF3f70212ba7a8E30fB30Cb4",
"0xAeaDee30db4e75c64BC8ABE54f818b8fc9097f1b",
"0x4FCa9CA9938Ee6b4E3200a295b1152c72d6df0b7",
],
optimisticKovan: [
"0xEc76AE8adEFc6462986A673Feff40b2Cdd56B3BC",
"0x808AeC84A987368B915a7Fd048cd1B20859FcbC9",
"0x00478B7Ea27581f901D84a7ea2989f68416d3568",
],
};
export default function getBLSAddresses(networkName: string): string[] {
const addresses = blsAddresses[networkName];
if (!addresses) {
throw new Error(`No configuration for: "${networkName}"`);
}
return addresses;
}

View File

@@ -1,64 +0,0 @@
export interface DeployedAddresses {
ethAddress: string | undefined;
blsLibAddress: string | undefined;
vgAddress: string | undefined;
expanderAddress: string | undefined;
tokenAddress: string | undefined;
blsAddresses: string[] | undefined;
}
export default function getDeployedAddresses(
networkName: string,
): DeployedAddresses {
if (networkName === `arb1`) {
return {
ethAddress: undefined,
blsLibAddress: undefined,
vgAddress: process.env.ARB1_VERIFICATION_GATEWAY_ADDRESS,
expanderAddress: process.env.ARB1_BLS_EXPANDER_ADDRESS,
tokenAddress: undefined,
blsAddresses: [],
};
} else if (networkName === `rinkarby`) {
return {
ethAddress: undefined,
blsLibAddress: process.env.RINKARBY_BLS_LIBRARY,
vgAddress: process.env.RINKARBY_VERIFICATION_GATEWAY_ADDRESS,
expanderAddress: process.env.RINKARBY_BLS_EXPANDER_ADDRESS,
tokenAddress: process.env.RINKARBY_ERC20_CONTRACT_ADDRESS,
blsAddresses: [
"0x3f509901664E21e2dc3a189C9E67DDC2864848cC",
"0x4AA467DA53E722E0C9aa516083aC5A0b40e5a0c8",
"0xAA0E6088e0B8801c9D679A1C715EF836129458Cc",
],
};
} else if (networkName === `optimistic`) {
return {
ethAddress: undefined,
blsLibAddress: undefined,
vgAddress: process.env.LOCAL_VERIFICATION_GATEWAY_ADDRESS,
expanderAddress: process.env.LOCAL_BLS_EXPANDER_ADDRESS,
tokenAddress: undefined,
blsAddresses: [
"0x69A9c53e7000c8B7aF3f70212ba7a8E30fB30Cb4",
"0xAeaDee30db4e75c64BC8ABE54f818b8fc9097f1b",
"0x4FCa9CA9938Ee6b4E3200a295b1152c72d6df0b7",
],
};
} else if (networkName === `optimisticKovan`) {
return {
ethAddress: process.env.OKOVAN_ETH_CONTRACT_ADDRESS,
blsLibAddress: undefined,
vgAddress: process.env.OKOVAN_VERIFICATION_GATEWAY_ADDRESS,
expanderAddress: process.env.OKOVAN_BLS_EXPANDER_ADDRESS,
tokenAddress: process.env.OKOVAN_ERC20_CONTRACT_ADDRESS,
blsAddresses: [
"0xEc76AE8adEFc6462986A673Feff40b2Cdd56B3BC",
"0x808AeC84A987368B915a7Fd048cd1B20859FcbC9",
"0x00478B7Ea27581f901D84a7ea2989f68416d3568",
],
};
} else {
throw new Error(`No configuration for: "${networkName}"`);
}
}

View File

@@ -0,0 +1,21 @@
import { readFile } from "fs/promises";
import path from "path";
import { NetworkConfig, getConfig } from "../../clients/src";
function getFileName(networkName: string) {
if (networkName === "gethDev") {
return "local";
}
return networkName;
}
export default function getNetworkConfig(
networkName: string,
): Promise<NetworkConfig> {
const netCfgPath = path.resolve(
__dirname,
"../../networks",
`${getFileName(networkName)}.json`,
);
return getConfig(netCfgPath, async (path) => readFile(path, "utf8"));
}

View File

@@ -9,7 +9,7 @@ import TokenHelper from "../shared/helpers/TokenHelper";
import { BigNumber } from "ethers";
import { parseEther } from "@ethersproject/units";
import deployAndRunPrecompileCostEstimator from "../shared/helpers/deployAndRunPrecompileCostEstimator";
import getDeployedAddresses from "../shared/helpers/getDeployedAddresses";
// import splitHex256 from "../shared/helpers/splitHex256";
import { defaultDeployerAddress } from "../shared/helpers/deployDeployer";
import { solidityPack } from "ethers/lib/utils";
const utils = ethers.utils;
@@ -41,15 +41,7 @@ describe("WalletActions", async function () {
let th: TokenHelper;
beforeEach(async function () {
if (network.name === "rinkarby") {
const config = getDeployedAddresses(network.name);
fx = await Fixture.create(
Fixture.DEFAULT_BLS_ACCOUNTS_LENGTH,
false,
config.blsLibAddress,
config.vgAddress,
config.expanderAddress,
);
fx = await Fixture.create(Fixture.DEFAULT_BLS_ACCOUNTS_LENGTH);
} else {
fx = await Fixture.create();
}

34
docker-compose.yml Normal file
View File

@@ -0,0 +1,34 @@
version: '3'
services:
postgres:
container_name: postgres
image: 'postgres:latest'
ports:
- 5432:5432
environment:
POSTGRES_USER: bls
POSTGRES_PASSWORD: generate-a-strong-password
POSTGRES_DB: bls_aggregator
volumes:
- ./.data/postgres/:/var/lib/postgresql/data/
# Not currently used, but could be helpful in the future
geth:
container_name: geth
image: ethereum/client-go:stable
ports:
- "8545:8545"
volumes:
- "./.data/geth/dev-chain:/dev-chain"
command: >
--datadir dev-chain/
--http
--http.addr=0.0.0.0
--http.vhosts='*'
--dev
--dev.period=14

View File

@@ -1,9 +1,6 @@
CHAIN_ID=420
PRIVATE_KEY_STORAGE_KEY=default-private-key
AGGREGATOR_URL=http://localhost:3000
CHAIN_RPC_URL=http://localhost:8545
CREATE_TX_URL=
PROVIDER_URL=
ETHERSCAN_KEY=
VERIFICATION_GATEWAY_ADDRESS=0xCbd1D63d0Ca2228484a7772733717e934CD52aC3

View File

@@ -77,13 +77,10 @@ Interaction with web3 applications can be slow, costly, and risky.
## Development
Copy `.env.example` to `.env.local`, updating values as needed.
The 'local' in `.env.local` is your environment name. You need to supply this
to webpack by prefixing webpack-related commands with `ENV=local`.
Copy `.env.example` to `.env`, updating values as needed.
To run the dev server:
```sh
ENV=local yarn run dev:chrome # or dev:firefox etc, see scripts in package.json
yarn run dev:chrome # or dev:firefox etc, see scripts in package.json
```

View File

@@ -53,6 +53,7 @@
"@babel/preset-env": "^7.14.2",
"@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.13.0",
"@types/axios": "^0.14.0",
"@types/react": "^17.0.6",
"@types/react-dom": "^17.0.5",
"@types/webpack": "^4.41.29",

View File

@@ -208,7 +208,7 @@ export default class App {
try {
const creationTx = await BlsWallet.signCreation(
this.state.privateKey,
env.VERIFICATION_GATEWAY_ADDRESS,
env.NETWORK_CONFIG.addresses.verificationGateway,
this.provider,
);
@@ -244,7 +244,7 @@ export default class App {
try {
this.wallet = await BlsWallet.connect(
this.state.privateKey,
env.VERIFICATION_GATEWAY_ADDRESS,
env.NETWORK_CONFIG.addresses.verificationGateway,
this.provider,
);

View File

@@ -8,11 +8,11 @@ import App from '../App';
import getPropOrUndefined from '../helpers/getPropOrUndefined';
import RequestHandler from './RequestHandler';
import { AGGREGATOR_URL, CHAIN_ID, CHAIN_RPC_URL } from '../env';
import { AGGREGATOR_URL, NETWORK_CONFIG, CHAIN_RPC_URL } from '../env';
(async () => {
const app = new App(
await initBlsWalletSigner({ chainId: CHAIN_ID }),
await initBlsWalletSigner({ chainId: NETWORK_CONFIG.auxiliary.chainid }),
new Aggregator(AGGREGATOR_URL),
new ethers.providers.JsonRpcProvider(CHAIN_RPC_URL),
browser.storage.local,

View File

@@ -6,14 +6,14 @@ import ReactDOM from 'react-dom';
import { browser } from 'webextension-polyfill-ts';
import App from '../App';
import { AGGREGATOR_URL, CHAIN_ID, CHAIN_RPC_URL } from '../env';
import { AGGREGATOR_URL, NETWORK_CONFIG, CHAIN_RPC_URL } from '../env';
import Popup from './Popup';
import './styles.scss';
const appPromise = (async () =>
new App(
await initBlsWalletSigner({ chainId: CHAIN_ID }),
await initBlsWalletSigner({ chainId: NETWORK_CONFIG.auxiliary.chainid }),
new Aggregator(AGGREGATOR_URL),
new ethers.providers.JsonRpcProvider(CHAIN_RPC_URL),
browser.storage.local,

View File

@@ -1,9 +1,7 @@
import { requireEnv, requireIntEnv } from './helpers/envTools';
import { validateConfig } from 'bls-wallet-clients';
import { requireEnv } from './helpers/envTools';
export const CHAIN_ID = requireIntEnv(process.env.CHAIN_ID);
export const PROVIDER_URL = requireEnv(process.env.PROVIDER_URL);
// export const ETHERSCAN_KEY = requireEnv(process.env.ETHERSCAN_KEY);
export const PRIVATE_KEY_STORAGE_KEY = requireEnv(
process.env.PRIVATE_KEY_STORAGE_KEY,
);
@@ -12,6 +10,6 @@ export const AGGREGATOR_URL = requireEnv(process.env.AGGREGATOR_URL);
export const CHAIN_RPC_URL = requireEnv(process.env.CHAIN_RPC_URL);
export const CREATE_TX_URL = requireEnv(process.env.CREATE_TX_URL);
export const VERIFICATION_GATEWAY_ADDRESS = requireEnv(
process.env.VERIFICATION_GATEWAY_ADDRESS,
export const NETWORK_CONFIG = validateConfig(
JSON.parse(requireEnv(process.env.NETWORK_CONFIG)),
);

View File

@@ -1,10 +1,10 @@
import { ethers } from 'ethers';
import { useEffect, useState } from 'react';
import { PROVIDER_URL } from '../env';
import { CHAIN_RPC_URL } from '../env';
import axios from 'axios';
const getParitySigRegistry = () => {
const provider = new ethers.providers.JsonRpcProvider(PROVIDER_URL);
const provider = new ethers.providers.JsonRpcProvider(CHAIN_RPC_URL);
const address = '0x44691B39d1a75dC4E0A0346CBB15E310e6ED1E86';
const abi = [
{

View File

@@ -1,6 +1,7 @@
/* eslint-disable */
const path = require('path');
const fs = require("fs");
const webpack = require('webpack');
const FilemanagerPlugin = require('filemanager-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
@@ -49,6 +50,8 @@ const getExtensionFileType = (browser) => {
return 'zip';
};
const networkConfigPath = process.env.NETWORK_CONFIG_PATH ?? path.join(__dirname, "..", "contracts", "networks", "local.json");
module.exports = {
devtool: false, // https://github.com/webpack/webpack/issues/1194#issuecomment-560382342
@@ -144,7 +147,11 @@ module.exports = {
new webpack.SourceMapDevToolPlugin({filename: false}),
new ForkTsCheckerWebpackPlugin(),
// environmental variables
new webpack.EnvironmentPlugin(['NODE_ENV', 'TARGET_BROWSER']),
new webpack.EnvironmentPlugin({
NODE_ENV: undefined,
TARGET_BROWSER: undefined,
NETWORK_CONFIG: fs.readFileSync(networkConfigPath, 'utf8'),
}),
// delete previous build files
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [
@@ -187,7 +194,11 @@ module.exports = {
// plugin to enable browser reloading in development mode
extensionReloaderPlugin,
new DotenvWebpackPlugin({
path: `./.env.${requireEnv(process.env.ENV)}`,
path: `./.env${
process.env.ENV === undefined ?
'' :
`.${process.env.ENV}`
}`,
}),
],

View File

@@ -1543,6 +1543,13 @@
resolved "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz"
integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
"@types/axios@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46"
integrity sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=
dependencies:
axios "*"
"@types/color-name@^1.1.1":
version "1.1.1"
resolved "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz"
@@ -2367,6 +2374,13 @@ axe-core@^4.0.2:
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.0.2.tgz"
integrity sha512-arU1h31OGFu+LPrOLGZ7nB45v940NMDMEJeNmbutu57P+UFDVnkZg3e+J1I2HJRZ9hT7gO8J91dn/PMrAiKakA==
axios@*:
version "0.24.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
dependencies:
follow-redirects "^1.14.4"
axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz"
@@ -4523,6 +4537,11 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@^1.14.4:
version "1.14.5"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz"

51
setup.ts Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env -S deno run --unstable --allow-run --allow-read --allow-write
import { exists } from "https://deno.land/std@0.103.0/fs/mod.ts";
import * as shell from "./aggregator/programs/helpers/shell.ts";
const components = [
{ name: "aggregator", skipYarn: true },
{ name: "contracts" },
{ name: "contracts/clients" },
{ name: "extension" },
];
async function runYarn(name: string): Promise<void> {
const { success } = await Deno.run({ cmd: ["yarn"], cwd: `./${name}` }).status();
if (!success) {
throw new Error(`yarn install failed for ${name}`);
}
}
console.log("initializing bls-wallet repo");
console.log("initializing git submodules...");
await shell.run(..."git submodule update --init --recursive".split(" "));
console.log(`setting up components (${components.map(c => c.name).join(", ")})...`);
await Promise.all(components.map(async ({ name, skipYarn }) => {
if (!skipYarn) {
console.log(`yarn installing in ${name}...`);
await runYarn(name);
}
const envFilePath = `./${name}/.env`;
const envExampleFilePath = `${envFilePath}.example`;
const [envExists, envExampleExists] = await Promise.all([
exists(envFilePath),
exists(envExampleFilePath)
]);
if (envExists) {
console.warn(`${envExampleFilePath} already exists`);
return;
}
if (envExampleExists) {
console.log(`copying ${envExampleFilePath} to ${envFilePath}...`);
await Deno.copyFile(envExampleFilePath, envFilePath);
}
}));
console.log("bls-wallet repo initializing complete");