mirror of
https://github.com/getwax/bls-wallet.git
synced 2026-01-08 23:28:21 -05:00
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:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.data
|
||||
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true
|
||||
}
|
||||
162
README.md
Normal file
162
README.md
Normal 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";
|
||||
...
|
||||
```
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"),
|
||||
|
||||
6
aggregator/src/helpers/getNetworkConfig.ts
Normal file
6
aggregator/src/helpers/getNetworkConfig.ts
Normal 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);
|
||||
}
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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=
|
||||
|
||||
1
contracts/.gitignore
vendored
1
contracts/.gitignore
vendored
@@ -5,6 +5,7 @@ node_modules
|
||||
coverage
|
||||
coverage.json
|
||||
/typechain
|
||||
networks/local.json
|
||||
|
||||
#Hardhat files
|
||||
artifacts
|
||||
|
||||
@@ -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>`
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
82
contracts/clients/src/NetworkConfig.ts
Normal file
82
contracts/clients/src/NetworkConfig.ts
Normal 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;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
|
||||
18
contracts/networks/rinkarby.json
Normal file
18
contracts/networks/rinkarby.json
Normal 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"
|
||||
}
|
||||
}
|
||||
@@ -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}`);
|
||||
|
||||
88
contracts/scripts/deploy_all.ts
Normal file
88
contracts/scripts/deploy_all.ts
Normal 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);
|
||||
});
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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 }),
|
||||
|
||||
26
contracts/shared/helpers/getBLSAddresses.ts
Normal file
26
contracts/shared/helpers/getBLSAddresses.ts
Normal 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;
|
||||
}
|
||||
@@ -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}"`);
|
||||
}
|
||||
}
|
||||
21
contracts/shared/helpers/getNetworkConfig.ts
Normal file
21
contracts/shared/helpers/getNetworkConfig.ts
Normal 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"));
|
||||
}
|
||||
@@ -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
34
docker-compose.yml
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)),
|
||||
);
|
||||
|
||||
@@ -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 = [
|
||||
{
|
||||
|
||||
@@ -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}`
|
||||
}`,
|
||||
}),
|
||||
],
|
||||
|
||||
|
||||
@@ -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
51
setup.ts
Executable 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");
|
||||
Reference in New Issue
Block a user