diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..bb73d05c --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,19 @@ +name: Pre-commit checks + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + components: rustfmt, clippy + - uses: pre-commit/action@v2.0.3 diff --git a/.github/workflows/pyth-cosmwasm-contract.yml b/.github/workflows/pyth-cosmwasm-contract.yml index fc112a64..14cfa436 100644 --- a/.github/workflows/pyth-cosmwasm-contract.yml +++ b/.github/workflows/pyth-cosmwasm-contract.yml @@ -16,8 +16,8 @@ jobs: run: working-directory: ./cosmwasm/contracts/pyth steps: - - uses: actions/checkout@v2 - - name: Build - run: cargo build --verbose - - name: Run tests - run: cargo test --verbose + - uses: actions/checkout@v2 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/.github/workflows/remote-executor.yml b/.github/workflows/remote-executor.yml index abf189aa..829532fa 100644 --- a/.github/workflows/remote-executor.yml +++ b/.github/workflows/remote-executor.yml @@ -2,10 +2,10 @@ name: Check Remote Executor on: pull_request: - paths: [ pythnet/remote-executor/** ] + paths: [pythnet/remote-executor/**] push: branches: [main] - paths: [ pythnet/remote-executor/** ] + paths: [pythnet/remote-executor/**] jobs: pre-commit: runs-on: ubuntu-latest @@ -24,4 +24,3 @@ jobs: echo "/home/runner/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH - name: Run executor tests run: cargo test-bpf --manifest-path ./pythnet/remote-executor/Cargo.toml - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 413b5737..bba59d50 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,19 +3,36 @@ repos: rev: v3.2.0 hooks: - id: trailing-whitespace - files: pythnet/ - id: end-of-file-fixer - files: pythnet/ - id: check-added-large-files + # Hook to format many type of files in the repo + # including solidity contracts. + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v2.7.1" + hooks: + - id: prettier + additional_dependencies: + - "prettier@2.7.1" + - "prettier-plugin-solidity@1.0.0-rc.1" - repo: local hooks: + # Hooks for the remote executor - id: cargo-fmt-executor name: Cargo format executor language: "rust" entry: cargo +nightly fmt --manifest-path ./pythnet/remote-executor/Cargo.toml --all pass_filenames: false + files: pythnet/remote-executor/ - id: cargo-clippy-executor name: Cargo clippy executor language: "rust" entry: cargo +nightly clippy --manifest-path ./pythnet/remote-executor/Cargo.toml -- -D warnings pass_filenames: false + files: pythnet/remote-executor/ + # Hooks for the attester + - id: cargo-fmt-executor + name: Cargo format executor + language: "rust" + entry: cargo +nightly fmt --manifest-path ./solana/pyth2wormhole/Cargo.toml --all + pass_filenames: false + files: solana/pyth2wormhole/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68180804..54e1cc2f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,18 +10,18 @@ and code reviews are our most important tools to accomplish that. complex features, it can be useful to submit a [formal design document](design/template.md). - Development happens on a long-lived development branch (`dev.v2` and `dev.v1`). - Every change going into a development branch is reviewed individually (see below). Release branches may be used + Every change going into a development branch is reviewed individually (see below). Release branches may be used to support in-the-wild releases of Wormhole. We aim to support at most two release branches at the same time. Changes can be cherry-picked from the development branch to release branches, but never from release branches to a development branch. - + - Releases are first tested on a testnet. - Commits should be small and have a meaningful commit message. One commit should, roughly, be "one idea" and be as atomic as possible. A feature can consist of many such commits. - + - Feature flags and interface evolution are better than breaking changes and long-lived feature branches. - + - We optimize for reading, not for writing - over its lifetime, code is read much more often than written. Small commits, meaningful commit messages and useful comments make it easier to review code and improve the quality of code review as well as review turnaround times. It's much easier to spot mistakes in small, @@ -42,12 +42,12 @@ The answer is... maybe? The following things are needed in order to fully suppor a node or light client for every chain supported by Wormhole. This adds up, and the barrier to support new chains is pretty high. Your proposal should clearly outline the value proposition of supporting the new chain. **Convincing the DAO to run nodes for your chain is the first step in supporting a new chain.** - + - The chain needs to support smart contracts capable of verifying 19 individual secp256k1 signatures. - The smart contract needs to be built and audited. In some cases, existing contracts can be used, like with EVM-compatible chains. - + - Support for observing the chain needs to be added to guardiand. - Web wallet integration needs to be built to actually interact with Wormhole. diff --git a/DEVELOP.md b/DEVELOP.md index a11af6d5..aeec7b40 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -7,7 +7,7 @@ The following dependencies are required for local development: - [Go](https://golang.org/dl/) >= 1.17.5 - [Tilt](http://tilt.dev/) >= 0.20.8 - Any of the local Kubernetes clusters supported by Tilt. - We strongly recommend [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/) >= + We strongly recommend [minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/) >= v1.21.0 with the kvm2 driver. - Tilt will use Minikube's embedded Docker server. If Minikube is not used, a local instance of [Docker](https://docs.docker.com/engine/install/) / moby-engine >= 19.03 is required. diff --git a/Dockerfile.client b/Dockerfile.client index bd9395c9..ae9f0e2a 100644 --- a/Dockerfile.client +++ b/Dockerfile.client @@ -8,7 +8,7 @@ ARG WORMHOLE_TAG=v2.8.9 RUN apt-get update && apt-get install -yq libudev-dev ncat RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs -COPY solana /usr/src/solana +COPY solana /usr/src/solana WORKDIR /usr/src/solana/pyth2wormhole RUN --mount=type=cache,target=/root/.cache \ diff --git a/Dockerfile.cosmwasm b/Dockerfile.cosmwasm index 000a1d10..5531bb85 100644 --- a/Dockerfile.cosmwasm +++ b/Dockerfile.cosmwasm @@ -20,7 +20,7 @@ FROM cosmwasm/workspace-optimizer:0.12.6@sha256:e6565a5e87c830ef3e8775a9035006b3 COPY cosmwasm/Cargo.lock /code/ COPY cosmwasm/Cargo.toml /code/ COPY cosmwasm/contracts /code/contracts -COPY third_party/pyth/p2w-sdk/rust /third_party/pyth/p2w-sdk/rust +COPY third_party/pyth/p2w-sdk/rust /third_party/pyth/p2w-sdk/rust RUN --mount=type=cache,target=/code/target,id=cosmwasm_pyth_target --mount=type=cache,target=/usr/local/cargo/registry optimize_workspace.sh # Contract deployment stage diff --git a/Dockerfile.solana b/Dockerfile.solana index a4237096..3032af73 100644 --- a/Dockerfile.solana +++ b/Dockerfile.solana @@ -20,7 +20,7 @@ RUN sh -c "$(curl -sSfL https://release.solana.com/v1.10.31/install)" ENV PATH="/root/.local/share/solana/install/active_release/bin:$PATH" -ADD solana/rust-toolchain /rust-toolchain +ADD solana/pyth2wormhole/rust-toolchain /rust-toolchain # Solana does a questionable download at the beginning of a *first* build-bpf call. Trigger and layer-cache it explicitly. RUN cargo init --lib /tmp/decoy-crate && \ cd /tmp/decoy-crate && cargo build-bpf && \ diff --git a/README.md b/README.md index 678a934c..c96f0638 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ Pyth2Wormhole. The base repository is a fork from Certus One's reference for building projects based on Wormhole's various SDKs. Much of the existing documentation from there will also apply to this repository. -[Wormhole]: https://github.com/wormhole-foundation/wormhole +[wormhole]: https://github.com/wormhole-foundation/wormhole Within this monorepo you will find the following subprojects: ## Pyth2Wormhole Solana -> solana/pyth2wormhole +> solana/pyth2wormhole The main Pyth implementation currently exists as an [on-chain contract][] on Solana. In order to expose these prices cross-chain, the Pyth2Wormhole Solana @@ -24,7 +24,8 @@ various P2W receiver contracts. [on-chain contract]: https://github.com/pyth-network/pyth-client ## Pyth2Wormhole Ethereum -> ethereum/contracts/pyth + +> ethereum/contracts/pyth The Ethereum P2W contract acts as a receiver for Pyth prices relayed from the P2W Solana contract. It also provides a public API for other Ethereum contracts @@ -35,7 +36,8 @@ examples. [pyth-evm-sdk]: https://github.com/pyth-network/pyth-sdk-solidity ## Pyth2Wormhole Price Service -> third_party/pyth + +> third_party/pyth The P2W Price Service is an off-chain service which constantly observes the Wormhole network watching for price attestations emitted from the Pyth Solana @@ -48,7 +50,7 @@ the [pyth-js][] repository. [pyth-js]: https://github.com/pyth-network/pyth-js --------------------------------------------------------------------------------- +--- See [DEVELOP.md](DEVELOP.md) for instructions on how to set up a local devnet, and [CONTRIBUTING.md](CONTRIBUTING.md) for instructions on how to contribute to this project. @@ -60,3 +62,15 @@ implied. See the License for the specific language governing permissions and lim spoken - this is a very complex piece of software which targets a bleeding-edge, experimental smart contract runtime. Mistakes happen, and no matter how hard you try and whether you pay someone to audit it, it may eat your tokens, set your printer on fire or startle your cat. Cryptocurrencies are a high-risk investment, no matter how fancy. + +## Development + +### Releases + +We use [Semantic Versioning](https://semver.org/) for our releases. + +### pre-commit hooks + +pre-commit is a tool that checks and fixes simple issues (formatting, ...) before each commit. You can install it by following [their website](https://pre-commit.com/). In order to enable checks for this repo run `pre-commit install` from command-line in the root of this repo. + +The checks are also performed in the CI to ensure the code follows consistent formatting. diff --git a/SECURITY.md b/SECURITY.md index c4116112..e9b16c7e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -5,13 +5,13 @@ Pyth operates a self hosted [bug bounty program](https://pyth.network/bounty) to financially incentivize independent researchers (with up to $1,000,000 USDC) for finding and responsibly disclosing security issues. - **Scopes** - - [Pyth Oracle](https://github.com/pyth-network/pyth-client/tree/main/program) - - [Pyth Crosschain Ethereum](https://github.com/pyth-network/pyth-crosschain/tree/main/ethereum/contracts/pyth) - - [Pyth Crosschain Aptos](https://github.com/pyth-network/pyth-crosschain/tree/main/aptos/contracts) - - [Pyth Governance](https://github.com/pyth-network/governance/tree/master/staking/programs/staking) + - [Pyth Oracle](https://github.com/pyth-network/pyth-client/tree/main/program) + - [Pyth Crosschain Ethereum](https://github.com/pyth-network/pyth-crosschain/tree/main/ethereum/contracts/pyth) + - [Pyth Crosschain Aptos](https://github.com/pyth-network/pyth-crosschain/tree/main/aptos/contracts) + - [Pyth Governance](https://github.com/pyth-network/governance/tree/master/staking/programs/staking) - **Rewards** - - Critical: Up to $1,000,000 - - High: Up to $100,000 + - Critical: Up to $1,000,000 + - High: Up to $100,000 If you find a security issue in Pyth, please [report the issue](https://yyyf63zqhtu.typeform.com/to/dBV4qcP0) immediately to our security team. @@ -19,16 +19,16 @@ If there is a duplicate report, either the same reporter or different reporters, ## 3rd Party Security Audits -We engage 3rd party firms to conduct independent security audits of Pyth. At any given time, we likely have multiple audit streams in progress. +We engage 3rd party firms to conduct independent security audits of Pyth. At any given time, we likely have multiple audit streams in progress. As these 3rd party audits are completed and issues are sufficiently addressed, we make those audit reports public. - **[April 27, 2022 - Zellic](https://github.com/pyth-network/audit-reports/blob/main/2022_04_27/pyth2wormhole_zellic.pdf)** - - **Scope**: *pyth-crosschain (formerly known as pyth2wormhole))* + - **Scope**: _pyth-crosschain (formerly known as pyth2wormhole))_ - **[October 10, 2022 - OtterSec](https://github.com/pyth-network/audit-reports/blob/main/2022_10_10/pyth_aptos.pdf)** - - **Scope**: *pyth-aptos contracts* + - **Scope**: _pyth-aptos contracts_ - **[November 01, 2022 - Zellic](https://github.com/pyth-network/audit-reports/blob/main/2022_11_01/pyth.pdf)** - - **Scope**: *pyth-evm contracts* + - **Scope**: _pyth-evm contracts_ ## Social Media Monitoring @@ -42,7 +42,7 @@ In the case of a large ecosystem development that requires response, the Pyth pr The Pyth project maintains an incident response program to respond to vulnerabilities or active threats to Pyth, its users, or the ecosystems it's connected to. Pyth can be made aware about a security event from a variety of different sources (eg. bug bounty program, audit finding, security monitoring, social media, etc.) -When a Pyth project contributor becomes aware of a security event, that contributor immediately holds the role of [incident commander](https://en.wikipedia.org/wiki/Incident_commander) for the issue until they hand off to a more appropriate incident commander. A contributor does not need to be a "security person" or have any special priviledges to hold the role of incident commander, they simply need to be responsible, communicate effectively, and maintain the following obligations to manage the incident to completion. +When a Pyth project contributor becomes aware of a security event, that contributor immediately holds the role of [incident commander](https://en.wikipedia.org/wiki/Incident_commander) for the issue until they hand off to a more appropriate incident commander. A contributor does not need to be a "security person" or have any special priviledges to hold the role of incident commander, they simply need to be responsible, communicate effectively, and maintain the following obligations to manage the incident to completion. The role of the incident commander for Pyth includes the following minimum obligations: diff --git a/Tiltfile b/Tiltfile index 2309154e..f316a873 100644 --- a/Tiltfile +++ b/Tiltfile @@ -179,8 +179,8 @@ docker_build( k8s_yaml_with_ns("./devnet/pyth.yaml") k8s_resource( - "pyth", - resource_deps = ["solana-devnet"], + "pyth", + resource_deps = ["solana-devnet"], labels = ["pyth"], trigger_mode = trigger_mode, ) diff --git a/aptos/contracts/Move.toml b/aptos/contracts/Move.toml index 1dd24208..76c7767c 100644 --- a/aptos/contracts/Move.toml +++ b/aptos/contracts/Move.toml @@ -18,7 +18,7 @@ deployer = "_" wormhole = "_" [dev-addresses] -# Note that these are localnet addresses, for use in testing. The contracts are deployed to the real networks at the +# Note that these are localnet addresses, for use in testing. The contracts are deployed to the real networks at the # addresses documented at https://docs.pyth.network/consume-data/aptos#addresses pyth = "0x377f0d7c4aaeea8dd73a7a2c6bc817e59aea569e1f9ae0d2f4a80ea1be93bf01" deployer = "0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b" diff --git a/aptos/contracts/sources/batch_price_attestation.move b/aptos/contracts/sources/batch_price_attestation.move index abd26787..0901c164 100644 --- a/aptos/contracts/sources/batch_price_attestation.move +++ b/aptos/contracts/sources/batch_price_attestation.move @@ -118,13 +118,13 @@ module pyth::batch_price_attestation { let ema_price = deserialize::deserialize_i64(cur); let ema_conf = deserialize::deserialize_u64(cur); let status = price_status::from_u64((deserialize::deserialize_u8(cur) as u64)); - + // Skip obselete fields let _num_publishers = deserialize::deserialize_u32(cur); let _max_num_publishers = deserialize::deserialize_u32(cur); let attestation_time = deserialize::deserialize_u64(cur); - let publish_time = deserialize::deserialize_u64(cur); // + let publish_time = deserialize::deserialize_u64(cur); // let prev_publish_time = deserialize::deserialize_u64(cur); let prev_price = deserialize::deserialize_i64(cur); let prev_conf = deserialize::deserialize_u64(cur); @@ -139,7 +139,7 @@ module pyth::batch_price_attestation { current_price = pyth::price::new(prev_price, prev_conf, expo, prev_publish_time); }; - // If status is trading, use the timestamp of the aggregate as the timestamp for the + // If status is trading, use the timestamp of the aggregate as the timestamp for the // EMA price. If not, the EMA will have last been updated when the aggregate last had // trading status, so use prev_publish_time (the time when the aggregate last had trading status). let ema_timestamp = publish_time; @@ -175,10 +175,10 @@ module pyth::batch_price_attestation { let arrival_time = 1663074349; timestamp::update_global_time_for_test(1663074349 * 1000000); - // A raw batch price attestation + // A raw batch price attestation // The first attestation has a status of UNKNOWN let bytes = x"5032574800030000000102000400951436e0be37536be96f0896366089506a59763d036728332d3e3038047851aea7c6c75c89f14810ec1c54c03ab8f1864a4c4032791f05747f560faec380a695d1000000000000049a0000000000000008fffffffb00000000000005dc0000000000000003000000000100000001000000006329c0eb000000006329c0e9000000006329c0e400000000000006150000000000000007215258d81468614f6b7e194c5d145609394f67b041e93e6695dcc616faadd0603b9551a68d01d954d6387aff4df1529027ffb2fee413082e509feb29cc4904fe000000000000041a0000000000000003fffffffb00000000000005cb0000000000000003010000000100000001000000006329c0eb000000006329c0e9000000006329c0e4000000000000048600000000000000078ac9cf3ab299af710d735163726fdae0db8465280502eb9f801f74b3c1bd190333832fad6e36eb05a8972fe5f219b27b5b2bb2230a79ce79beb4c5c5e7ecc76d00000000000003f20000000000000002fffffffb00000000000005e70000000000000003010000000100000001000000006329c0eb000000006329c0e9000000006329c0e40000000000000685000000000000000861db714e9ff987b6fedf00d01f9fea6db7c30632d6fc83b7bc9459d7192bc44a21a28b4c6619968bd8c20e95b0aaed7df2187fd310275347e0376a2cd7427db800000000000006cb0000000000000001fffffffb00000000000005e40000000000000003010000000100000001000000006329c0eb000000006329c0e9000000006329c0e400000000000007970000000000000001"; - + let expected = BatchPriceAttestation { header: Header { magic: 0x50325748, diff --git a/aptos/contracts/sources/deserialize.move b/aptos/contracts/sources/deserialize.move index 0ea94c35..3339c511 100644 --- a/aptos/contracts/sources/deserialize.move +++ b/aptos/contracts/sources/deserialize.move @@ -26,7 +26,7 @@ module pyth::deserialize { public fun deserialize_i32(cur: &mut Cursor): I64 { let deserialized = deserialize_u32(cur); - + // If negative, pad the value let negative = (deserialized >> 31) == 1; if (negative) { @@ -49,7 +49,7 @@ module pyth::deserialize { fun test_deserialize_u8() { let input = x"48258963"; let cursor = cursor::init(input); - + let result = deserialize_u8(&mut cursor); assert!(result == 0x48, 1); @@ -61,7 +61,7 @@ module pyth::deserialize { fun test_deserialize_u16() { let input = x"48258963"; let cursor = cursor::init(input); - + let result = deserialize_u16(&mut cursor); assert!(result == 0x4825, 1); @@ -73,7 +73,7 @@ module pyth::deserialize { fun test_deserialize_u32() { let input = x"4825896349741695"; let cursor = cursor::init(input); - + let result = deserialize_u32(&mut cursor); assert!(result == 0x48258963, 1); @@ -85,7 +85,7 @@ module pyth::deserialize { fun test_deserialize_i32_positive() { let input = x"4825896349741695"; let cursor = cursor::init(input); - + let result = deserialize_i32(&mut cursor); assert!(result == i64::from_u64(0x48258963), 1); @@ -97,7 +97,7 @@ module pyth::deserialize { fun test_deserialize_i32_negative() { let input = x"FFFFFDC349741695"; let cursor = cursor::init(input); - + let result = deserialize_i32(&mut cursor); assert!(result == i64::from_u64(0xFFFFFFFFFFFFFDC3), 1); @@ -109,7 +109,7 @@ module pyth::deserialize { fun test_deserialize_u64() { let input = x"48258963497416957497253486"; let cursor = cursor::init(input); - + let result = deserialize_u64(&mut cursor); assert!(result == 0x4825896349741695, 1); @@ -121,7 +121,7 @@ module pyth::deserialize { fun test_deserialize_i64_positive() { let input = x"48258963497416957497253486"; let cursor = cursor::init(input); - + let result = deserialize_i64(&mut cursor); assert!(result == i64::from_u64(0x4825896349741695), 1); @@ -133,7 +133,7 @@ module pyth::deserialize { fun test_deserialize_i64_negative() { let input = x"FFFFFFFFFFFFFDC37497253486"; let cursor = cursor::init(input); - + let result = deserialize_i64(&mut cursor); assert!(result == i64::from_u64(0xFFFFFFFFFFFFFDC3), 1); diff --git a/aptos/contracts/sources/error.move b/aptos/contracts/sources/error.move index bc3fbe2c..e6d8ff4a 100644 --- a/aptos/contracts/sources/error.move +++ b/aptos/contracts/sources/error.move @@ -78,7 +78,7 @@ module pyth::error { public fun positive_value(): u64 { error::invalid_state(19) } - + public fun invalid_governance_magic_value(): u64 { error::invalid_argument(20) } diff --git a/aptos/contracts/sources/event.move b/aptos/contracts/sources/event.move index 6c770b50..eb3bb73f 100644 --- a/aptos/contracts/sources/event.move +++ b/aptos/contracts/sources/event.move @@ -35,5 +35,5 @@ module pyth::event { timestamp, } ); - } + } } diff --git a/aptos/contracts/sources/governance/contract_upgrade.move b/aptos/contracts/sources/governance/contract_upgrade.move index 958ce170..01554ed4 100644 --- a/aptos/contracts/sources/governance/contract_upgrade.move +++ b/aptos/contracts/sources/governance/contract_upgrade.move @@ -25,7 +25,7 @@ module pyth::contract_upgrade { let cursor = cursor::init(bytes); let hash = contract_upgrade_hash::from_byte_vec(deserialize::deserialize_vector(&mut cursor, HASH_LENGTH)); cursor::destroy_empty(cursor); - + AuthorizeContractUpgrade { hash, } @@ -51,7 +51,7 @@ module pyth::contract_upgrade { vector::reverse(&mut reversed); let flattened = aptos_hash::keccak256(metadata_serialized); while (!vector::is_empty(&reversed)) vector::append(&mut flattened, aptos_hash::keccak256(vector::pop_back(&mut reversed))); - + aptos_hash::keccak256(flattened) == contract_upgrade_hash::destroy(hash) } } diff --git a/aptos/contracts/sources/governance/governance.move b/aptos/contracts/sources/governance/governance.move index bdbc1b70..55399c67 100644 --- a/aptos/contracts/sources/governance/governance.move +++ b/aptos/contracts/sources/governance/governance.move @@ -141,7 +141,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 1 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 2 let vaa_bytes = x"010000000001001d9fd73b3fb0fc522eae5eb5bd40ddf68941894495d7cec8c8efdbf462e48715171b5c6d4bbca0c1e3843b3c28d0ca6f3f76874624b5595a3a2cbfdb3907b62501527e4f9b000000010032f06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf0000000000000001005054474d0202001003001793a28e2e5b4cb88f69e96fb29a8287a88b23f0e99f5502f81744e904da8e3b4d000c9a4066ce1fa26da1c102a3e268abd3ca58e3b3c25f250e6ad9a3525066fbf8b00012f7778ca023d5cbe37449bab2faa2a133fe02b056c2c25605950320df08750f35"; governance::execute_governance_instruction(vaa_bytes); @@ -156,7 +156,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 1 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 17 != wormhole test chain ID 22 let vaa_bytes = x"010000000001001ed81e10f8e52e6a7daeca12bf0859c14e8dabed737eaed9a1f8227190a9d11c48d58856713243c5d7de08ed49de4aa1efe7c5e6020c11056802e2d702aa4b2e00527e4f9b000000010032f06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf0000000000000001005054474d0102001103001793a28e2e5b4cb88f69e96fb29a8287a88b23f0e99f5502f81744e904da8e3b4d000c9a4066ce1fa26da1c102a3e268abd3ca58e3b3c25f250e6ad9a3525066fbf8b00012f7778ca023d5cbe37449bab2faa2a133fe02b056c2c25605950320df08750f35"; @@ -172,7 +172,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 1 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - Action 19 (invalid) @@ -188,14 +188,14 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 5 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - AuthorizeContractUpgrade { // hash: 0xa381a47fd0e97f34c71ef491c82208f58cd0080e784c697e65966d2a25d20d56, // } let vaa_bytes = x"010000000001002242229aec7d320a437cb241672dacfbc34c9155c02f60cd806bbfcd69bb7ba667fc069e372ae0443a7f3e08eaad61930b00784faeb2b72ecf5d1b0f0fa486a101527e4f9b000000010032f06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf0000000000000005005054474d01000016a381a47fd0e97f34c71ef491c82208f58cd0080e784c697e65966d2a25d20d56"; - + governance::execute_governance_instruction(vaa_bytes); assert!(state::get_last_executed_governance_sequence() == 5, 1); @@ -212,14 +212,14 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 5 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 0 // - AuthorizeContractUpgrade { // hash: 0xa381a47fd0e97f34c71ef491c82208f58cd0080e784c697e65966d2a25d20d56, // } let vaa_bytes = x"01000000000100303c10020c537205ed0322b7ec9d9b296f4e3e12e39ebde985ed4ef4c8f5565256cfc6f90800c4683dba62b577cc994e2ca9135d32b955040b94718cdcb5527600527e4f9b000000010032f06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf0000000000000005005054474d01000000a381a47fd0e97f34c71ef491c82208f58cd0080e784c697e65966d2a25d20d56"; - + governance::execute_governance_instruction(vaa_bytes); assert!(state::get_last_executed_governance_sequence() == 5, 1); @@ -234,7 +234,7 @@ module pyth::governance_test { setup_test(100, initial_governance_emitter_chain_id, initial_governance_emitter_address, 100); state::set_last_executed_governance_sequence(25); - + let initial_governance_data_source = data_source::new(initial_governance_emitter_chain_id, external_address::from_bytes(initial_governance_emitter_address)); assert!(state::is_valid_governance_data_source(initial_governance_data_source), 1); @@ -242,7 +242,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 27 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - SetGovernanceDataSource { @@ -266,7 +266,7 @@ module pyth::governance_test { // - Emitter chain ID 9 // - Emitter address 0x625bae57728a368652a0ab0a89808de5fffa61d3312f1a27c3e200e99b1f3058 // - Sequence number 15 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - SetStalePriceThreshold { @@ -287,7 +287,7 @@ module pyth::governance_test { setup_test(100, initial_governance_emitter_chain_id, initial_governance_emitter_address, 100); state::set_last_executed_governance_sequence(25); - + let initial_governance_data_source = data_source::new(initial_governance_emitter_chain_id, external_address::from_bytes(initial_governance_emitter_address)); assert!(state::is_valid_governance_data_source(initial_governance_data_source), 1); @@ -295,7 +295,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address x"f06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf" // - Sequence number 27 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - SetGovernanceDataSource { @@ -333,7 +333,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 1 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - SetUpdateFee { @@ -359,7 +359,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 1 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - SetStalePriceThreshold { @@ -381,7 +381,7 @@ module pyth::governance_test { // - Emitter chain ID 50 // - Emitter address 0xf06413c0148c78916554f134dcd17a7c8029a3a2bda475a4a1182305c53078bf // - Sequence number 1 - // - A payload representing a governance instruction with: + // - A payload representing a governance instruction with: // - Module number 1 // - Target chain 22 // - SetDataSources { diff --git a/aptos/contracts/sources/governance/governance_instruction.move b/aptos/contracts/sources/governance/governance_instruction.move index ae9f9311..b103ee87 100644 --- a/aptos/contracts/sources/governance/governance_instruction.move +++ b/aptos/contracts/sources/governance/governance_instruction.move @@ -20,7 +20,7 @@ module pyth::governance_instruction { let target_chain_id = instruction.target_chain_id; assert!(target_chain_id == u16::to_u64(wormhole::state::get_chain_id()) || target_chain_id == 0, error::invalid_governance_target_chain_id()); } - + public fun from_byte_vec(bytes: vector): GovernanceInstruction { let cursor = cursor::init(bytes); let magic = deserialize::deserialize_vector(&mut cursor, 4); diff --git a/aptos/contracts/sources/governance/set_update_fee.move b/aptos/contracts/sources/governance/set_update_fee.move index d308b73d..91ac63e6 100644 --- a/aptos/contracts/sources/governance/set_update_fee.move +++ b/aptos/contracts/sources/governance/set_update_fee.move @@ -10,7 +10,7 @@ module pyth::set_update_fee { struct SetUpdateFee { mantissa: u64, - exponent: u64, + exponent: u64, } public(friend) fun execute(payload: vector) { diff --git a/aptos/contracts/sources/i64.move b/aptos/contracts/sources/i64.move index da696942..5e3ad055 100644 --- a/aptos/contracts/sources/i64.move +++ b/aptos/contracts/sources/i64.move @@ -1,12 +1,12 @@ module pyth::i64 { use pyth::error; - + const MAX_POSITIVE_MAGNITUDE: u64 = (1 << 63) - 1; const MAX_NEGATIVE_MAGNITUDE: u64 = (1 << 63); /// As Move does not support negative numbers natively, we use our own internal - /// representation. - /// + /// representation. + /// /// To consume these values, first call `get_is_negative()` to determine if the I64 /// represents a negative or positive value. Then call `get_magnitude_if_positive()` or /// `get_magnitude_if_negative()` to get the magnitude of the number in unsigned u64 format. @@ -22,7 +22,7 @@ module pyth::i64 { max_magnitude = MAX_NEGATIVE_MAGNITUDE; }; assert!(magnitude <= max_magnitude, error::magnitude_too_large()); - + // Ensure we have a single zero representation: (0, false). // (0, true) is invalid. diff --git a/aptos/contracts/sources/price_info.move b/aptos/contracts/sources/price_info.move index 9f0d1de2..e533fc9b 100644 --- a/aptos/contracts/sources/price_info.move +++ b/aptos/contracts/sources/price_info.move @@ -18,7 +18,7 @@ module pyth::price_info { public fun get_price_feed(price_info: &PriceInfo): &PriceFeed { &price_info.price_feed } - + public fun get_attestation_time(price_info: &PriceInfo): u64 { price_info.attestation_time } diff --git a/aptos/contracts/sources/price_status.move b/aptos/contracts/sources/price_status.move index fb0f4898..61d4193d 100644 --- a/aptos/contracts/sources/price_status.move +++ b/aptos/contracts/sources/price_status.move @@ -1,6 +1,6 @@ module pyth::price_status { use pyth::error; - + /// The price feed is not currently updating for an unknown reason. const UNKNOWN: u64 = 0; /// The price feed is updating as expected. diff --git a/aptos/contracts/sources/pyth.move b/aptos/contracts/sources/pyth.move index b53ef22d..29e72e8d 100644 --- a/aptos/contracts/sources/pyth.move +++ b/aptos/contracts/sources/pyth.move @@ -119,22 +119,22 @@ module pyth::pyth { // ----------------------------------------------------------------------------- // Update the cached prices // -// Pyth uses an uses an on-demand update model, where consumers need to update the +// Pyth uses an uses an on-demand update model, where consumers need to update the /// cached prices before using them. Please read more about this at https://docs.pyth.network/consume-data/on-demand. - /// Update the cached price feeds with the data in the given VAAs. This is a + /// Update the cached price feeds with the data in the given VAAs. This is a /// convenience wrapper around update_price_feeds(), which allows you to update the price feeds /// using an entry function. - /// + /// /// If possible, it is recommended to use update_price_feeds() instead, which avoids the need /// to pass a signer account. update_price_feeds_with_funder() should only be used when /// you need to call an entry function. - /// + /// /// This function will charge an update fee, transferring some AptosCoin's /// from the given funder account to the Pyth contract. The amount of coins that will be transferred - /// to perform this update can be queried with get_update_fee(&vaas). The signer must have sufficient + /// to perform this update can be queried with get_update_fee(&vaas). The signer must have sufficient /// account balance to pay this fee, otherwise the transaction will abort. - /// + /// /// Please read more information about the update fee here: https://docs.pyth.network/consume-data/on-demand#fees public entry fun update_price_feeds_with_funder(account: &signer, vaas: vector>) { let coins = coin::withdraw(account, get_update_fee(&vaas)); @@ -143,14 +143,14 @@ module pyth::pyth { /// Update the cached price feeds with the data in the given VAAs. /// The vaas argument is a vector of VAAs encoded as bytes. - /// + /// /// The javascript https://github.com/pyth-network/pyth-js/tree/main/pyth-aptos-js package /// should be used to fetch these VAAs from the Price Service. More information about this /// process can be found at https://docs.pyth.network/consume-data. - /// + /// /// The given fee must contain a sufficient number of coins to pay the update fee for the given vaas. /// The update fee amount can be queried by calling get_update_fee(&vaas). - /// + /// /// Please read more information about the update fee here: https://docs.pyth.network/consume-data/on-demand#fees public fun update_price_feeds(vaas: vector>, fee: Coin) { // Charge the message update fee @@ -198,7 +198,7 @@ module pyth::pyth { /// A convenience wrapper around update_price_feeds_if_fresh(), allowing you to conditionally /// update the price feeds using an entry function. - /// + /// /// If possible, it is recommended to use update_price_feeds_if_fresh() instead, which avoids the need /// to pass a signer account. update_price_feeds_if_fresh_with_funder() should only be used when /// you need to call an entry function. @@ -216,9 +216,9 @@ module pyth::pyth { /// prices in the update are fresh. The price_identifiers and publish_times parameters /// are used to determine if the update is fresh without doing any serialisation or verification /// of the VAAs, potentially saving time and gas. If the update contains no fresh data, this function - /// will revert with error::no_fresh_data(). - /// - /// For a given price update i in the batch, that price is considered fresh if the current cached + /// will revert with error::no_fresh_data(). + /// + /// For a given price update i in the batch, that price is considered fresh if the current cached /// price for price_identifiers[i] is older than publish_times[i]. public entry fun update_price_feeds_if_fresh( vaas: vector>, @@ -265,7 +265,7 @@ module pyth::pyth { return true }; let cached_timestamp = price::get_timestamp(&get_price_unsafe(*price_identifier)); - + update_timestamp > cached_timestamp } @@ -280,17 +280,17 @@ module pyth::pyth { state::price_info_cached(price_identifier) } - /// Get the latest available price cached for the given price identifier, if that price is + /// Get the latest available price cached for the given price identifier, if that price is /// no older than the stale price threshold. - /// + /// /// Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for /// how to how this price safely. - /// - /// Important: Pyth uses an on-demand update model, where consumers need to update the + /// + /// Important: Pyth uses an on-demand update model, where consumers need to update the /// cached prices before using them. Please read more about this at https://docs.pyth.network/consume-data/on-demand. /// get_price() is likely to abort unless you call update_price_feeds() to update the cached price /// beforehand, as the cached prices may be older than the stale price threshold. - /// + /// /// Note that the price_identifier does not correspond to a seperate Aptos account: /// all price feeds are stored in the single pyth account. The price identifier is an /// opaque identifier for a price feed. @@ -298,7 +298,7 @@ module pyth::pyth { get_price_no_older_than(price_identifier, state::get_stale_price_threshold_secs()) } - /// Get the latest available price cached for the given price identifier, if that price is + /// Get the latest available price cached for the given price identifier, if that price is /// no older than the given age. public fun get_price_no_older_than(price_identifier: PriceIdentifier, max_age_secs: u64): Price { let price = get_price_unsafe(price_identifier); @@ -308,11 +308,11 @@ module pyth::pyth { } /// Get the latest available price cached for the given price identifier. - /// + /// /// WARNING: the returned price can be from arbitrarily far in the past. /// This function makes no guarantees that the returned price is recent or /// useful for any particular application. Users of this function should check - /// the returned timestamp to ensure that the returned price is sufficiently + /// the returned timestamp to ensure that the returned price is sufficiently /// recent for their application. The checked get_price_no_older_than() /// function should be used in preference to this. public fun get_price_unsafe(price_identifier: PriceIdentifier): Price { @@ -339,10 +339,10 @@ module pyth::pyth { assert!(age < max_age_secs, error::stale_price_update()); } - /// Get the latest available exponentially moving average price cached for the given + /// Get the latest available exponentially moving average price cached for the given /// price identifier, if that price is no older than the stale price threshold. - /// - /// Important: Pyth uses an on-demand update model, where consumers need to update the + /// + /// Important: Pyth uses an on-demand update model, where consumers need to update the /// cached prices before using them. Please read more about this at https://docs.pyth.network/consume-data/on-demand. /// get_ema_price() is likely to abort unless you call update_price_feeds() to update the cached price /// beforehand, as the cached prices may be older than the stale price threshold. @@ -357,14 +357,14 @@ module pyth::pyth { check_price_is_fresh(&price, max_age_secs); price - } + } /// Get the latest available exponentially moving average price cached for the given price identifier. - /// + /// /// WARNING: the returned price can be from arbitrarily far in the past. /// This function makes no guarantees that the returned price is recent or /// useful for any particular application. Users of this function should check - /// the returned timestamp to ensure that the returned price is sufficiently + /// the returned timestamp to ensure that the returned price is sufficiently /// recent for their application. The checked get_ema_price_no_older_than() /// function should be used in preference to this. public fun get_ema_price_unsafe(price_identifier: PriceIdentifier): Price { @@ -373,7 +373,7 @@ module pyth::pyth { } /// Get the number of AptosCoin's required to perform the given price updates. - /// + /// /// Please read more information about the update fee here: https://docs.pyth.network/consume-data/on-demand#fees public fun get_update_fee(update_data: &vector>): u64 { state::get_base_update_fee() * vector::length(update_data) @@ -419,7 +419,7 @@ module pyth::pyth_test { account::create_test_signer_cap(@0x277fa055b6a73c42c0662d5236c65c864ccbf2d4abd21f174a30c8b786eab84b)); let (_pyth, signer_capability) = account::create_resource_account(&deployer, b"pyth"); pyth::init_test(signer_capability, stale_price_threshold, governance_emitter_chain_id, governance_emitter_address, data_sources, update_fee); - + let (burn_capability, mint_capability) = aptos_coin::initialize_for_test(aptos_framework); let coins = coin::mint(to_mint, &mint_capability); (burn_capability, mint_capability, coins) @@ -485,7 +485,7 @@ module pyth::pyth_test { public fun update_cache_for_test(updates: vector) { pyth::update_cache(updates); } - + #[test(aptos_framework = @aptos_framework)] fun test_get_update_fee(aptos_framework: &signer) { let single_update_fee = 50; @@ -570,7 +570,7 @@ module pyth::pyth_test { #[test(aptos_framework = @aptos_framework)] fun test_update_price_feeds_success(aptos_framework: &signer) { let (burn_capability, mint_capability, coins) = setup_test(aptos_framework, 500, 1, x"5d1f252d5de865279b00c84bce362774c2804294ed53299bc4a0389a5defef92", data_sources_for_test_vaa(), 50, 100); - + // Update the price feeds from the VAA pyth::update_price_feeds(TEST_VAAS, coins); @@ -597,7 +597,7 @@ module pyth::pyth_test { assert!(coin::balance(signer::address_of(&funder)) == initial_balance, 1); assert!(coin::balance(@pyth) == 0, 1); - // Update the price feeds using the funder + // Update the price feeds using the funder pyth::update_price_feeds_with_funder(&funder, TEST_VAAS); // Check that the price feeds are now cached @@ -629,7 +629,7 @@ module pyth::pyth_test { assert!(coin::balance(signer::address_of(&funder)) == initial_balance, 1); assert!(coin::balance(@pyth) == 0, 1); - // Update the price feeds using the funder + // Update the price feeds using the funder pyth::update_price_feeds_with_funder(&funder, TEST_VAAS); cleanup_test(burn_capability, mint_capability); @@ -673,7 +673,7 @@ module pyth::pyth_test { assert!(!pyth::price_feed_exists(*price_feed::get_price_identifier(price_feed)), 1); i = i + 1; }; - + // Submit the updates pyth::update_cache(updates); @@ -687,7 +687,7 @@ module pyth::pyth_test { #[test(aptos_framework = @aptos_framework)] fun test_update_cache_old_update(aptos_framework: &signer) { let (burn_capability, mint_capability, coins) = setup_test(aptos_framework, 1000, 1, x"5d1f252d5de865279b00c84bce362774c2804294ed53299bc4a0389a5defef92", data_sources_for_test_vaa(), 50, 0); - + // Submit a price update let timestamp = 1663680700; let price_identifier = price_identifier::from_byte_vec(x"baa284eaf23edf975b371ba2818772f93dbae72836bbdea28b07d40f3cf8b485"); @@ -725,7 +725,7 @@ module pyth::pyth_test { assert!(pyth::get_price(price_identifier) == price, 1); assert!(pyth::get_ema_price(price_identifier) == ema_price, 1); - // Update the cache with a fresh update + // Update the cache with a fresh update let fresh_price = price::new(i64::new(4857, true), 9979, i64::new(243, false), timestamp + 200); let fresh_ema_price = price::new(i64::new(74637, false), 9979, i64::new(1433, false), timestamp + 1); let fresh_update = price_info::new( @@ -827,8 +827,8 @@ module pyth::pyth_test { #[expected_failure(abort_code = 65541)] fun test_update_price_feeds_if_fresh_invalid_length(aptos_framework: &signer) { let (burn_capability, mint_capability, coins) = setup_test(aptos_framework, 500, 1, x"5d1f252d5de865279b00c84bce362774c2804294ed53299bc4a0389a5defef92", data_sources_for_test_vaa(), 50, 0); - - // Update the price feeds + + // Update the price feeds let bytes = vector[vector[0u8, 1u8, 2u8]]; let price_identifiers = vector[ x"baa284eaf23edf975b371ba2818772f93dbae72836bbdea28b07d40f3cf8b485", @@ -846,8 +846,8 @@ module pyth::pyth_test { #[test(aptos_framework = @aptos_framework)] fun test_update_price_feeds_if_fresh_fresh_data(aptos_framework: &signer) { let (burn_capability, mint_capability, coins) = setup_test(aptos_framework, 500, 1, x"5d1f252d5de865279b00c84bce362774c2804294ed53299bc4a0389a5defef92", data_sources_for_test_vaa(), 50, 50); - - // Update the price feeds + + // Update the price feeds let bytes = TEST_VAAS; let price_identifiers = vector[ x"c6c75c89f14810ec1c54c03ab8f1864a4c4032791f05747f560faec380a695d1", @@ -883,7 +883,7 @@ module pyth::pyth_test { assert!(coin::balance(signer::address_of(&funder)) == initial_balance, 1); assert!(coin::balance(@pyth) == 0, 1); - // Update the price feeds using the funder + // Update the price feeds using the funder let bytes = TEST_VAAS; let price_identifiers = vector[ x"c6c75c89f14810ec1c54c03ab8f1864a4c4032791f05747f560faec380a695d1", @@ -915,7 +915,7 @@ module pyth::pyth_test { // First populate the cache pyth::update_cache(get_mock_price_infos()); - + // Now attempt to update the price feeds with publish_times that are older than those we have cached // This should abort with error::no_fresh_data() let bytes = TEST_VAAS; diff --git a/aptos/contracts/sources/set.move b/aptos/contracts/sources/set.move index b4a41366..0d4f3c9c 100644 --- a/aptos/contracts/sources/set.move +++ b/aptos/contracts/sources/set.move @@ -41,5 +41,5 @@ module pyth::set { } // TODO: destroy_empty, but this is tricky because std::table doesn't - // have this functionality. + // have this functionality. } diff --git a/aptos/contracts/sources/state.move b/aptos/contracts/sources/state.move index 7bfcb12f..9170c9b2 100644 --- a/aptos/contracts/sources/state.move +++ b/aptos/contracts/sources/state.move @@ -41,8 +41,8 @@ module pyth::state { } /// Mapping of cached price information - /// - /// WARNING: do not directly read out of this table, instead use + /// + /// WARNING: do not directly read out of this table, instead use /// the checked `pyth::get_price` method. This ensures that the price /// is recent enough. struct LatestPriceInfo has key { diff --git a/aptos/examples/fetch_btc_price/sources/example.move b/aptos/examples/fetch_btc_price/sources/example.move index ca9fad2c..6d5456a7 100644 --- a/aptos/examples/fetch_btc_price/sources/example.move +++ b/aptos/examples/fetch_btc_price/sources/example.move @@ -3,11 +3,11 @@ module example::example { use pyth::price::Price; use pyth::price_identifier; use aptos_framework::coin; - - /// Updates the Pyth price feeds using the given pyth_update_data, and then returns + + /// Updates the Pyth price feeds using the given pyth_update_data, and then returns /// the BTC/USD price. - /// - /// https://github.com/pyth-network/pyth-js/tree/main/pyth-aptos-js should be used to + /// + /// https://github.com/pyth-network/pyth-js/tree/main/pyth-aptos-js should be used to /// fetch the pyth_update_data off-chain and pass it in. More information about how this /// works can be found at https://docs.pyth.network/consume-data public fun get_btc_usd_price(user: &signer, pyth_update_data: vector>): Price { diff --git a/aptos/examples/mint_nft/.gitignore b/aptos/examples/mint_nft/.gitignore index 144253fd..86fdc370 100644 --- a/aptos/examples/mint_nft/.gitignore +++ b/aptos/examples/mint_nft/.gitignore @@ -1,2 +1,2 @@ .aptos -build \ No newline at end of file +build diff --git a/aptos/examples/mint_nft/README.md b/aptos/examples/mint_nft/README.md index 43ea6d67..0889bea4 100644 --- a/aptos/examples/mint_nft/README.md +++ b/aptos/examples/mint_nft/README.md @@ -5,18 +5,19 @@ The example contract is deployed at : `0x19f8503273cdb5aa93ffe453927768461524212 The goal of this contract is managing an NFT mint where the mint is paid in native currency but the cost of one NFT is always 1$. This example is intended to be run on Aptos testnet because it depends on Pyth and Wormhole existing onchain. -### Important files : +### Important files : + - `./sources/minting.move` has the smart contract logic (the code that will run onchain) - `./app/src/App.tsx` has the React application. The core logic of how the frontend will interact with the wallet and the blockchain. -Both combined contain the key pieces of code needed to make an Aptos fullstack app using Pyth! + Both combined contain the key pieces of code needed to make an Aptos fullstack app using Pyth! ### How to deploy the smart contract : -- Use `aptos init` with rest_url : `https://testnet.aptoslabs.com/` and faucet `https://faucet.testnet.aptoslabs.com` to generate a new keypair. +- Use `aptos init` with rest_url : `https://testnet.aptoslabs.com/` and faucet `https://faucet.testnet.aptoslabs.com` to generate a new keypair. - Use a faucet to airdrop testnet APT to your newly created account by calling `aptos account fund-with-faucet --account default`. If this doesn't work, I have had success importing my private key from `.aptos/config.yaml` into Petra and clicking the airdrop button. Otherwise send APT from another account. - Get your account address from `.aptos/config.yaml` and replace `mint_nft="0x19f8503273cdb5aa93ffe4539277684615242127aa2e65ef91424136a316c9c7"` by `mint_nft="
"` in `Move.toml` - `aptos move compile` -- `aptos move publish` +- `aptos move publish` ### How to run the webapp : diff --git a/aptos/examples/mint_nft/app/src/App.test.tsx b/aptos/examples/mint_nft/app/src/App.test.tsx index 2a68616d..d76787ed 100644 --- a/aptos/examples/mint_nft/app/src/App.test.tsx +++ b/aptos/examples/mint_nft/app/src/App.test.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from "react"; +import { render, screen } from "@testing-library/react"; +import App from "./App"; -test('renders learn react link', () => { +test("renders learn react link", () => { render(); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); diff --git a/aptos/examples/mint_nft/app/src/App.tsx b/aptos/examples/mint_nft/app/src/App.tsx index 64275d69..416187aa 100644 --- a/aptos/examples/mint_nft/app/src/App.tsx +++ b/aptos/examples/mint_nft/app/src/App.tsx @@ -19,7 +19,8 @@ const APT_USD_TESTNET_PRICE_ID = "0x44a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e"; // Aptos modules : These are testnet addresses https://docs.pyth.network/consume-data/aptos#addresses -const MINT_NFT_MODULE = "0x19f8503273cdb5aa93ffe4539277684615242127aa2e65ef91424136a316c9c7"; +const MINT_NFT_MODULE = + "0x19f8503273cdb5aa93ffe4539277684615242127aa2e65ef91424136a316c9c7"; /// React component that shows the offchain price and confidence interval function PriceText(props: { price: Price | undefined }) { diff --git a/aptos/examples/mint_nft/app/src/index.css b/aptos/examples/mint_nft/app/src/index.css index ec2585e8..4a1df4db 100644 --- a/aptos/examples/mint_nft/app/src/index.css +++ b/aptos/examples/mint_nft/app/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/aptos/examples/mint_nft/app/src/index.tsx b/aptos/examples/mint_nft/app/src/index.tsx index 5c4f7906..62e3448b 100644 --- a/aptos/examples/mint_nft/app/src/index.tsx +++ b/aptos/examples/mint_nft/app/src/index.tsx @@ -1,18 +1,20 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./index.css"; +import App from "./App"; +import reportWebVitals from "./reportWebVitals"; declare global { - interface Window { aptos: any; } + interface Window { + aptos: any; + } } const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById("root") as HTMLElement ); -window.addEventListener('load', () => { +window.addEventListener("load", () => { root.render( diff --git a/aptos/examples/mint_nft/app/src/reportWebVitals.ts b/aptos/examples/mint_nft/app/src/reportWebVitals.ts index 49a2a16e..5fa3583b 100644 --- a/aptos/examples/mint_nft/app/src/reportWebVitals.ts +++ b/aptos/examples/mint_nft/app/src/reportWebVitals.ts @@ -1,8 +1,8 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from "web-vitals"; const reportWebVitals = (onPerfEntry?: ReportHandler) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/aptos/examples/mint_nft/app/src/setupTests.ts b/aptos/examples/mint_nft/app/src/setupTests.ts index 8f2609b7..1dd407a6 100644 --- a/aptos/examples/mint_nft/app/src/setupTests.ts +++ b/aptos/examples/mint_nft/app/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import "@testing-library/jest-dom"; diff --git a/aptos/examples/mint_nft/app/tsconfig.json b/aptos/examples/mint_nft/app/tsconfig.json index a273b0cf..9d379a3c 100644 --- a/aptos/examples/mint_nft/app/tsconfig.json +++ b/aptos/examples/mint_nft/app/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -20,7 +16,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": [ - "src" - ] + "include": ["src"] } diff --git a/aptos/examples/mint_nft/sources/minting.move b/aptos/examples/mint_nft/sources/minting.move index ece658ec..1acf476b 100644 --- a/aptos/examples/mint_nft/sources/minting.move +++ b/aptos/examples/mint_nft/sources/minting.move @@ -17,7 +17,7 @@ module mint_nft::minting { use aptos_token::token::{Self, TokenDataId}; // For the entire list of price_ids head to https://pyth.network/developers/price-feed-ids/#pyth-cross-chain-testnet - const APTOS_USD_PRICE_FEED_IDENTIFIER : vector = x"44a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e"; + const APTOS_USD_PRICE_FEED_IDENTIFIER : vector = x"44a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e"; // This event stores the receiver of the NFT and the TokenDataId of the NFT struct TokenMintingEvent has drop, store { @@ -82,7 +82,7 @@ module mint_nft::minting { /// Mint an edition of the Pythian NFT pay 1 USD in native APT public entry fun mint_nft(receiver : &signer, vaas : vector>) acquires CollectionTokenMinter{ // Fetch the signer capability to mint the NFT - let collection_token_minter = borrow_global_mut(@mint_nft); + let collection_token_minter = borrow_global_mut(@mint_nft); let resource_signer = account::create_signer_with_capability(&collection_token_minter.signer_cap); let token_id = token::mint_token(&resource_signer, collection_token_minter.token_data_id, 1); // Mint the NFT @@ -101,7 +101,7 @@ module mint_nft::minting { fun update_and_fetch_price(receiver : &signer, vaas : vector>) : Price { let coins = coin::withdraw(receiver, pyth::get_update_fee(&vaas)); // Get coins to pay for the update pyth::update_price_feeds(vaas, coins); // Update price feed with the provided vaas - pyth::get_price(price_identifier::from_byte_vec(APTOS_USD_PRICE_FEED_IDENTIFIER)) // Get recent price (will fail if price is too old) + pyth::get_price(price_identifier::from_byte_vec(APTOS_USD_PRICE_FEED_IDENTIFIER)) // Get recent price (will fail if price is too old) } } diff --git a/cosmwasm/.dockerignore b/cosmwasm/.dockerignore index ca1b0e45..4589e1cc 100644 --- a/cosmwasm/.dockerignore +++ b/cosmwasm/.dockerignore @@ -1,3 +1,3 @@ target tools/node_modules -tools/dist \ No newline at end of file +tools/dist diff --git a/cosmwasm/Cargo.toml b/cosmwasm/Cargo.toml index c299d14d..b4376710 100644 --- a/cosmwasm/Cargo.toml +++ b/cosmwasm/Cargo.toml @@ -11,4 +11,3 @@ codegen-units = 1 panic = 'abort' incremental = false overflow-checks = true - diff --git a/cosmwasm/README.md b/cosmwasm/README.md index ea233742..89d66b26 100644 --- a/cosmwasm/README.md +++ b/cosmwasm/README.md @@ -5,10 +5,11 @@ This directory contains The Pyth contract on CosmWasm and utilities to deploy it ## Deployment Deploying the CosmWasm contract has two steps: + 1. Upload the code. This step will give you a code id. 2. Either create a new contract or migrate an existing one: - 1. Create a new contract that has an address with a code id as its program. - 2. Migrating an existing contract code id to the new code id. + 1. Create a new contract that has an address with a code id as its program. + 2. Migrating an existing contract code id to the new code id. This directory includes a script to perform both steps. Read below for the details. @@ -16,7 +17,7 @@ This directory includes a script to perform both steps. Read below for the detai First, build the contracts within [the current directory](./): -``` sh +```sh bash build.sh ``` @@ -24,31 +25,33 @@ This command will build and save the Pyth contract in the `artifact` directory. Then, to deploy the Pyth contract (`pyth_cosmwasm.wasm`), run the following command in the `tools` directory: -``` sh +```sh npm ci # Do it only once to install the required packages npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_cosmwasm.wasm --mnemonic "..." ``` If successful, this command will print something along the lines of: -``` sh +```sh Storing WASM: ../artifacts/pyth_cosmwasm.wasm (367689 bytes) Deploy fee: 88446uluna Code ID: 2435 ``` -If you do not pass any additional arguments to the script, it will only upload the code and return the code id. If you want to create a +If you do not pass any additional arguments to the script, it will only upload the code and return the code id. If you want to create a new contract or upgrade an existing contract you should pass more arguments that are described below. ### Instantiating new contract + If you want to instantiate a new contract after your deployment, pass `--instantiate` to the above command. This command will upload the code and instantiates a new Pyth contract with the resulting code id: -``` sh +```sh npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_cosmwasm.wasm --mnemonic "..." --instantiate ``` If successful, the output should look like so: + ``` Storing WASM: ../artifacts/pyth_cosmwasm.wasm (183749 bytes) Deploy fee: 44682uluna @@ -60,14 +63,16 @@ Deployed Pyth contract at terra123456789yelw23uh22nadqlyjvtl7s5527er97 ``` ### Migrating existing contract + If you want to upgrade an existing contract pass `--migrate --contract terra123456xyzqwe..` to the above command. This command will upload the code, and with the resulting code id, will migrate the existing contract to the new one: -``` sh +```sh npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_cosmwasm.wasm --mnemonic "..." --migrate --contract "terra123..." ``` If successful, the output should look like so: + ``` Storing WASM: ../artifacts/pyth_cosmwasm.wasm (183749 bytes) Deploy fee: 44682uluna @@ -80,14 +85,15 @@ Contract terra1rhjej5gkyelw23uh22nadqlyjvtl7s5527er97 code_id successfully updat ### Common Errors While running the instantiation/migration commands you might get the following errors: + - Gateway timeout: This error means that the request timed out. It is good to double check with terra finder as sometimes transactions succeed despite being timed out. - Account sequence mismatch: Transactions from an account should have an increasing sequence number. This error happens when a transaction from the same sender is not fully synchronized with the terra RPC and an old sequence number is used. This is likely to happen because the deploy script sends two transactions: one to submit the code, and one to do the instantiation/migration. -You can rerun your command if you encounter any of the above errors. If an error occurs after the new code is uploaded, you can avoid re-uploading the code and use the uploaded code for instantiation/migration. You can use the printed code id in the logs +You can rerun your command if you encounter any of the above errors. If an error occurs after the new code is uploaded, you can avoid re-uploading the code and use the uploaded code for instantiation/migration. You can use the printed code id in the logs by passing `--code-id ` instead of `--artifact`. If you do so, the script will skip uploading the code and instantiate/migrate the contract with the given code id. An example command using an existing code id looks like so: -``` sh +```sh npm run deploy-pyth -- --network testnet --code-id 50123 --mnemonic "..." --migrate --contract "terra123..." ``` diff --git a/cosmwasm/contracts/pyth/src/contract.rs b/cosmwasm/contracts/pyth/src/contract.rs index 7117081d..d5f97615 100644 --- a/cosmwasm/contracts/pyth/src/contract.rs +++ b/cosmwasm/contracts/pyth/src/contract.rs @@ -287,7 +287,7 @@ pub fn query_price_feed(deps: Deps, env: Env, address: &[u8]) -> StdResult price_pub_time_sec { env_time_sec - price_pub_time_sec diff --git a/cosmwasm/contracts/pyth/src/error.rs b/cosmwasm/contracts/pyth/src/error.rs index 16a8b649..870c9ec9 100644 --- a/cosmwasm/contracts/pyth/src/error.rs +++ b/cosmwasm/contracts/pyth/src/error.rs @@ -22,7 +22,7 @@ pub enum PythContractError { /// Data source does not exists error (on removing data source) #[error("DataSourceDoesNotExists")] DataSourceDoesNotExists, - + /// Data source already exists error (on adding data source) #[error("DataSourceAlreadyExists")] DataSourceAlreadyExists, diff --git a/cosmwasm/devnet/config/app.toml b/cosmwasm/devnet/config/app.toml index 28b13718..4ddbf6e5 100644 --- a/cosmwasm/devnet/config/app.toml +++ b/cosmwasm/devnet/config/app.toml @@ -60,7 +60,7 @@ inter-block-cache = true # ["message.sender", "message.recipient"] index-events = [] -# IavlCacheSize set the size of the iavl tree cache. +# IavlCacheSize set the size of the iavl tree cache. # Default cache size is 50mb. iavl-cache-size = 781250 diff --git a/cosmwasm/devnet/config/node_key.json b/cosmwasm/devnet/config/node_key.json index f73aff74..d6611a4d 100644 --- a/cosmwasm/devnet/config/node_key.json +++ b/cosmwasm/devnet/config/node_key.json @@ -1 +1,6 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"xkHT1nM10OR4WLbdZNxQzxS5n2XbEUQhrEGS9DSpiS55fPkIkwVyvEqz0Auzv2S9ZcnoVwwAvVjg2uOfy/dlVw=="}} +{ + "priv_key": { + "type": "tendermint/PrivKeyEd25519", + "value": "xkHT1nM10OR4WLbdZNxQzxS5n2XbEUQhrEGS9DSpiS55fPkIkwVyvEqz0Auzv2S9ZcnoVwwAvVjg2uOfy/dlVw==" + } +} diff --git a/cosmwasm/devnet/config/wasm.toml b/cosmwasm/devnet/config/wasm.toml index ef001e29..60edef7a 100644 --- a/cosmwasm/devnet/config/wasm.toml +++ b/cosmwasm/devnet/config/wasm.toml @@ -8,9 +8,9 @@ # so we need to restrict the max usage to prevent DoS attack contract-query-gas-limit = "3000000" -# Storing instances in the LRU will have no effect on the results -# (still deterministic), but should lower execution time at -# the cost of increased memory usage. We cannot pick universal +# Storing instances in the LRU will have no effect on the results +# (still deterministic), but should lower execution time at +# the cost of increased memory usage. We cannot pick universal # parameters for this, so we should allow node operators to set it. lru-size = "0" diff --git a/cosmwasm/tools/deploy-pyth-bridge.js b/cosmwasm/tools/deploy-pyth-bridge.js index b1d02dae..097ac5e6 100644 --- a/cosmwasm/tools/deploy-pyth-bridge.js +++ b/cosmwasm/tools/deploy-pyth-bridge.js @@ -9,52 +9,53 @@ import { Bech32, toHex } from "@cosmjs/encoding"; import { zeroPad } from "ethers/lib/utils.js"; import axios from "axios"; import yargs from "yargs"; -import {hideBin} from "yargs/helpers"; +import { hideBin } from "yargs/helpers"; import assert from "assert"; export const TERRA_GAS_PRICES_URL = "https://fcd.terra.dev/v1/txs/gas_prices"; const argv = yargs(hideBin(process.argv)) - .option('network', { - description: 'Which network to deploy to', - choices: ['mainnet', 'testnet'], - required: true + .option("network", { + description: "Which network to deploy to", + choices: ["mainnet", "testnet"], + required: true, }) - .option('artifact', { - description: 'Path to Pyth artifact', - type: 'string', - required: false - }) - .option('mnemonic', { - description: 'Mnemonic (private key)', - type: 'string', - required: true - }) - .option('instantiate', { - description: 'Instantiate contract if set (default: disabled)', - type: 'boolean', - default: false, - required: false - }) - .option('migrate', { - description: 'Migrate an existing contract if set (default: disabled)', - type: 'boolean', - default: false, - required: false - }) - .option('contract', { - description: 'Contract address, used only for migration', - type: 'string', + .option("artifact", { + description: "Path to Pyth artifact", + type: "string", required: false, - default: '' }) - .option('code-id', { - description: 'Code Id, if provided this will be used for migrate/instantiate and no code will be uploaded', - type: 'number', - requred: false + .option("mnemonic", { + description: "Mnemonic (private key)", + type: "string", + required: true, + }) + .option("instantiate", { + description: "Instantiate contract if set (default: disabled)", + type: "boolean", + default: false, + required: false, + }) + .option("migrate", { + description: "Migrate an existing contract if set (default: disabled)", + type: "boolean", + default: false, + required: false, + }) + .option("contract", { + description: "Contract address, used only for migration", + type: "string", + required: false, + default: "", + }) + .option("code-id", { + description: + "Code Id, if provided this will be used for migrate/instantiate and no code will be uploaded", + type: "number", + requred: false, }) .help() - .alias('help', 'h').argv; + .alias("help", "h").argv; const artifact = argv.artifact; @@ -68,7 +69,8 @@ const CONFIG = { name: "mainnet", }, wormholeContract: "terra1dq03ugtd40zu9hcgdzrsq6z2z4hwhc9tqk2uy5", - pythEmitterAddress: "6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25" + pythEmitterAddress: + "6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25", }, testnet: { terraHost: { @@ -77,14 +79,15 @@ const CONFIG = { name: "testnet", }, wormholeContract: "terra1pd65m0q9tl3v8znnz5f5ltsfegyzah7g42cx5v", - pythEmitterAddress: "f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0" - } -} + pythEmitterAddress: + "f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0", + }, +}; const terraHost = CONFIG[argv.network].terraHost; const wormholeContract = CONFIG[argv.network].wormholeContract; const pythEmitterAddress = CONFIG[argv.network].pythEmitterAddress; - + const lcd = new LCDClient(terraHost); const feeDenoms = ["uluna"]; @@ -95,19 +98,21 @@ const gasPrices = await axios const wallet = lcd.wallet( new MnemonicKey({ - mnemonic: argv.mnemonic + mnemonic: argv.mnemonic, }) ); /* Deploy artifacts */ -var codeId; +var codeId; if (argv.codeId !== undefined) { codeId = argv.codeId; } else { if (argv.artifact === undefined) { - console.error("Artifact is not provided. Please at least provide artifact or code id"); + console.error( + "Artifact is not provided. Please at least provide artifact or code id" + ); process.exit(1); } @@ -142,10 +147,12 @@ if (argv.codeId !== undefined) { try { const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1]; codeId = parseInt(ci); - } catch(e) { - console.error("Encountered an error in parsing deploy code result. Printing raw log") + } catch (e) { + console.error( + "Encountered an error in parsing deploy code result. Printing raw log" + ); console.error(rs.raw_log); - throw(e); + throw e; } console.log("Code ID: ", codeId); @@ -176,13 +183,19 @@ if (argv.instantiate) { .then((rs) => { try { address = /"contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1]; - } catch (e) { - console.error("Encountered an error in parsing instantiation result. Printing raw log") + } catch (e) { + console.error( + "Encountered an error in parsing instantiation result. Printing raw log" + ); console.error(rs.raw_log); - throw(e); + throw e; } }); - console.log(`Instantiated Pyth at ${address} (${convert_terra_address_to_hex(address)})`); + console.log( + `Instantiated Pyth at ${address} (${convert_terra_address_to_hex( + address + )})` + ); return address; } @@ -190,9 +203,7 @@ if (argv.instantiate) { const contractAddress = await instantiate(codeId, { wormhole_contract: wormholeContract, - pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString( - "base64" - ), + pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString("base64"), pyth_emitter_chain: pythChain, }); @@ -200,8 +211,10 @@ if (argv.instantiate) { } if (argv.migrate) { - if (argv.contract === '') { - console.error("Contract address is not provided. Provide it using --contract"); + if (argv.contract === "") { + console.error( + "Contract address is not provided. Provide it using --contract" + ); process.exit(1); } @@ -214,7 +227,7 @@ if (argv.migrate) { argv.contract, codeId, { - "action": "" + action: "", }, { uluna: 1000 } ), @@ -222,19 +235,23 @@ if (argv.migrate) { feeDenoms, gasPrices, }); - + const rs = await lcd.tx.broadcast(tx); var resultCodeId; try { resultCodeId = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1]; - assert.equal(codeId, resultCodeId) + assert.equal(codeId, resultCodeId); } catch (e) { - console.error("Encountered an error in parsing migration result. Printing raw log") + console.error( + "Encountered an error in parsing migration result. Printing raw log" + ); console.error(rs.raw_log); - throw(e); + throw e; } - console.log(`Contract ${argv.contract} code_id successfully updated to ${resultCodeId}`); + console.log( + `Contract ${argv.contract} code_id successfully updated to ${resultCodeId}` + ); } // Terra addresses are "human-readable", but for cross-chain registrations, we @@ -244,5 +261,5 @@ function convert_terra_address_to_hex(human_addr) { } function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} \ No newline at end of file + return new Promise((resolve) => setTimeout(resolve, ms)); +} diff --git a/cosmwasm/tools/deploy.js b/cosmwasm/tools/deploy.js index 6191ddd3..5042df1b 100644 --- a/cosmwasm/tools/deploy.js +++ b/cosmwasm/tools/deploy.js @@ -1,13 +1,10 @@ -// Deploy Wormhole and Pyth contract to Tilt. If you want to +// Deploy Wormhole and Pyth contract to Tilt. If you want to // test the contracts locally you need to build the wormhole contract // as well. You can use Dockerfile.cosmwasm in the root of this repo // to do that. import { LCDClient, MnemonicKey } from "@terra-money/terra.js"; -import { - MsgInstantiateContract, - MsgStoreCode, -} from "@terra-money/terra.js"; +import { MsgInstantiateContract, MsgStoreCode } from "@terra-money/terra.js"; import { readFileSync, readdirSync } from "fs"; import { Bech32, toHex } from "@cosmjs/encoding"; import { zeroPad } from "ethers/lib/utils.js"; @@ -17,10 +14,7 @@ import { zeroPad } from "ethers/lib/utils.js"; contracts must be imported in a deterministic order so their addresses remain deterministic. */ -const artifacts = [ - "wormhole.wasm", - "pyth_cosmwasm.wasm", -]; +const artifacts = ["wormhole.wasm", "pyth_cosmwasm.wasm"]; /* Check that the artifact folder contains all the wasm files we expect and nothing else */ @@ -133,7 +127,11 @@ async function instantiate(contract, inst_msg, label) { .then((rs) => { address = /"_contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1]; }); - console.log(`Instantiated ${contract} at ${address} (${convert_terra_address_to_hex(address)})`); + console.log( + `Instantiated ${contract} at ${address} (${convert_terra_address_to_hex( + address + )})` + ); return address; } @@ -142,36 +140,42 @@ async function instantiate(contract, inst_msg, label) { const addresses = {}; -addresses["wormhole.wasm"] = await instantiate("wormhole.wasm", { - gov_chain: govChain, - gov_address: Buffer.from(govAddress, "hex").toString("base64"), - guardian_set_expirity: 86400, - initial_guardian_set: { - addresses: [ - { - bytes: Buffer.from( - "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe", - "hex" - ).toString("base64"), - }, - ], - expiration_time: 0, +addresses["wormhole.wasm"] = await instantiate( + "wormhole.wasm", + { + gov_chain: govChain, + gov_address: Buffer.from(govAddress, "hex").toString("base64"), + guardian_set_expirity: 86400, + initial_guardian_set: { + addresses: [ + { + bytes: Buffer.from( + "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe", + "hex" + ).toString("base64"), + }, + ], + expiration_time: 0, + }, + chain_id: 18, + fee_denom: "uluna", }, - chain_id: 18, - fee_denom: "uluna", -}, "wormhole"); + "wormhole" +); const pythEmitterAddress = "71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b"; const pythChain = 1; -addresses["pyth_cosmwasm.wasm"] = await instantiate("pyth_cosmwasm.wasm", { - wormhole_contract: addresses["wormhole.wasm"], - pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString( - "base64" - ), - pyth_emitter_chain: pythChain, -}, "pyth"); +addresses["pyth_cosmwasm.wasm"] = await instantiate( + "pyth_cosmwasm.wasm", + { + wormhole_contract: addresses["wormhole.wasm"], + pyth_emitter: Buffer.from(pythEmitterAddress, "hex").toString("base64"), + pyth_emitter_chain: pythChain, + }, + "pyth" +); // Terra addresses are "human-readable", but for cross-chain registrations, we // want the "canonical" version diff --git a/devnet/eth-devnet.yaml b/devnet/eth-devnet.yaml index e99dc90e..6d741afb 100644 --- a/devnet/eth-devnet.yaml +++ b/devnet/eth-devnet.yaml @@ -74,8 +74,8 @@ spec: - /bin/sh - -c - "npm run migrate -- --network development && - npx truffle test test/pyth.js 2>&1 && - nc -lkp 2000 0.0.0.0" + npx truffle test test/pyth.js 2>&1 && + nc -lkp 2000 0.0.0.0" readinessProbe: periodSeconds: 1 failureThreshold: 300 @@ -129,7 +129,7 @@ spec: - /bin/sh - -c - "npm run migrate -- --network development && - nc -lkp 2000 0.0.0.0" + nc -lkp 2000 0.0.0.0" readinessProbe: periodSeconds: 1 failureThreshold: 300 diff --git a/devnet/p2w-attest.yaml b/devnet/p2w-attest.yaml index 8ae8fba9..b88f0185 100644 --- a/devnet/p2w-attest.yaml +++ b/devnet/p2w-attest.yaml @@ -38,10 +38,10 @@ spec: - python3 - /usr/src/pyth/p2w_autoattest.py env: - - name: P2W_INITIALIZE_SOL_CONTRACT - value: "1" - - name: P2W_EXIT_ON_ERROR - value: "true" + - name: P2W_INITIALIZE_SOL_CONTRACT + value: "1" + - name: P2W_EXIT_ON_ERROR + value: "true" tty: true readinessProbe: tcpSocket: diff --git a/devnet/p2w-evm-relay.yaml b/devnet/p2w-evm-relay.yaml index c730d2f8..fe917196 100644 --- a/devnet/p2w-evm-relay.yaml +++ b/devnet/p2w-evm-relay.yaml @@ -45,7 +45,7 @@ spec: protocol: TCP readinessProbe: httpGet: - path: '/health' + path: "/health" port: 4200 command: - node @@ -68,16 +68,16 @@ spec: - name: EVM_VERIFY_PRICE_FEEDS value: "yes" - name: REST_PORT - value: '4200' + value: "4200" - name: PROM_PORT - value: '8081' + value: "8081" - name: BAL_QUERY_INTERVAL - value: '60000' + value: "60000" - name: RETRY_MAX_ATTEMPTS - value: '4' + value: "4" - name: RETRY_DELAY_IN_MS - value: '250' + value: "250" - name: MAX_MSGS_PER_BATCH - value: '1' + value: "1" - name: LOG_LEVEL value: debug diff --git a/devnet/p2w-terra-relay.yaml b/devnet/p2w-terra-relay.yaml index 7e8ce2a4..18026b3d 100644 --- a/devnet/p2w-terra-relay.yaml +++ b/devnet/p2w-terra-relay.yaml @@ -45,7 +45,7 @@ spec: protocol: TCP readinessProbe: httpGet: - path: '/health' + path: "/health" port: 4200 command: - node @@ -71,18 +71,18 @@ spec: - name: TERRA_COIN value: uluna - name: REST_PORT - value: '4200' + value: "4200" - name: PROM_PORT - value: '8081' + value: "8081" - name: BAL_QUERY_INTERVAL - value: '60000' + value: "60000" - name: RETRY_MAX_ATTEMPTS - value: '6' + value: "6" - name: RETRY_DELAY_IN_MS - value: '1000' + value: "1000" - name: MAX_MSGS_PER_BATCH - value: '1' + value: "1" - name: MAX_HEALTHY_NO_RELAY_DURATION_IN_SECONDS - value: '120' + value: "120" - name: LOG_LEVEL value: debug diff --git a/devnet/pyth-evm-watcher.yaml b/devnet/pyth-evm-watcher.yaml index 8b1766e0..23d3c883 100644 --- a/devnet/pyth-evm-watcher.yaml +++ b/devnet/pyth-evm-watcher.yaml @@ -18,6 +18,6 @@ spec: image: pyth-evm-watcher env: - name: WS_ENDPOINT - value: 'ws://eth-devnet:8545' + value: "ws://eth-devnet:8545" - name: PYTH_CONTRACT - value: '0xe982E462b094850F12AF94d21D470e21bE9D0E9C' + value: "0xe982E462b094850F12AF94d21D470e21bE9D0E9C" diff --git a/devnet/pyth-price-service.yaml b/devnet/pyth-price-service.yaml index e8ee0a97..01e7fa6c 100644 --- a/devnet/pyth-price-service.yaml +++ b/devnet/pyth-price-service.yaml @@ -45,14 +45,14 @@ spec: protocol: TCP readinessProbe: httpGet: - path: '/ready' + path: "/ready" port: 4200 initialDelaySeconds: 10 periodSeconds: 1 failureThreshold: 1 livenessProbe: httpGet: - path: '/live' + path: "/live" port: 4200 initialDelaySeconds: 20 periodSeconds: 30 @@ -63,12 +63,12 @@ spec: - name: SPY_SERVICE_FILTERS value: '[{"chain_id":1,"emitter_address":"71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b"}]' - name: REST_PORT - value: '4200' + value: "4200" - name: PROM_PORT - value: '8081' + value: "8081" - name: READINESS_SPY_SYNC_TIME_SECONDS - value: '5' + value: "5" - name: READINESS_NUM_LOADED_SYMBOLS - value: '6' + value: "6" - name: LOG_LEVEL value: debug diff --git a/devnet/spy.yaml b/devnet/spy.yaml index a91c3af8..3bd8aa0e 100644 --- a/devnet/spy.yaml +++ b/devnet/spy.yaml @@ -46,7 +46,7 @@ spec: # Hardcoded devnet bootstrap (generated from deterministic key in guardiand) - --bootstrap - /dns4/guardian-0.guardian/udp/8999/quic/p2p/12D3KooWL3XJ9EMCyZvmmGXL2LMiVBtrVa2BuESsJiXkSj7333Jw -# - --logLevel=debug + # - --logLevel=debug ports: - containerPort: 7072 name: spyrpc diff --git a/ethereum/.dockerignore b/ethereum/.dockerignore index 0364bb2d..a9322782 100644 --- a/ethereum/.dockerignore +++ b/ethereum/.dockerignore @@ -2,4 +2,4 @@ node_modules build .openzeppelin networks -.env \ No newline at end of file +.env diff --git a/ethereum/.env.prod.ethereum b/ethereum/.env.prod.ethereum index c3bd1c72..bd5d9851 100644 --- a/ethereum/.env.prod.ethereum +++ b/ethereum/.env.prod.ethereum @@ -2,4 +2,4 @@ MIGRATIONS_DIR=./migrations/prod MIGRATIONS_NETWORK=ethereum WORMHOLE_CHAIN_NAME=ethereum CLUSTER=mainnet -VALID_TIME_PERIOD_SECONDS=120 \ No newline at end of file +VALID_TIME_PERIOD_SECONDS=120 diff --git a/ethereum/.openzeppelin/goerli.json b/ethereum/.openzeppelin/goerli.json index 10c6a8ce..c4b919b6 100644 --- a/ethereum/.openzeppelin/goerli.json +++ b/ethereum/.openzeppelin/goerli.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/mainnet.json b/ethereum/.openzeppelin/mainnet.json index a63405c2..9211bc35 100644 --- a/ethereum/.openzeppelin/mainnet.json +++ b/ethereum/.openzeppelin/mainnet.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/ropsten.json b/ethereum/.openzeppelin/ropsten.json index dd9d8125..c03a1ab3 100644 --- a/ethereum/.openzeppelin/ropsten.json +++ b/ethereum/.openzeppelin/ropsten.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-10.json b/ethereum/.openzeppelin/unknown-10.json index 05537193..46fb422c 100644 --- a/ethereum/.openzeppelin/unknown-10.json +++ b/ethereum/.openzeppelin/unknown-10.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-1313161554.json b/ethereum/.openzeppelin/unknown-1313161554.json index 86f90e24..dfa2cc9d 100644 --- a/ethereum/.openzeppelin/unknown-1313161554.json +++ b/ethereum/.openzeppelin/unknown-1313161554.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-1313161555.json b/ethereum/.openzeppelin/unknown-1313161555.json index e7af563e..6c543f1c 100644 --- a/ethereum/.openzeppelin/unknown-1313161555.json +++ b/ethereum/.openzeppelin/unknown-1313161555.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-137.json b/ethereum/.openzeppelin/unknown-137.json index 6d6938b0..62fc16bd 100644 --- a/ethereum/.openzeppelin/unknown-137.json +++ b/ethereum/.openzeppelin/unknown-137.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-250.json b/ethereum/.openzeppelin/unknown-250.json index 1ac5921e..b40a1aa3 100644 --- a/ethereum/.openzeppelin/unknown-250.json +++ b/ethereum/.openzeppelin/unknown-250.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-4002.json b/ethereum/.openzeppelin/unknown-4002.json index 25abee2a..d05a045d 100644 --- a/ethereum/.openzeppelin/unknown-4002.json +++ b/ethereum/.openzeppelin/unknown-4002.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-42161.json b/ethereum/.openzeppelin/unknown-42161.json index f87cea32..17c3022d 100644 --- a/ethereum/.openzeppelin/unknown-42161.json +++ b/ethereum/.openzeppelin/unknown-42161.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-43113.json b/ethereum/.openzeppelin/unknown-43113.json index e38af1f0..04fb9fdf 100644 --- a/ethereum/.openzeppelin/unknown-43113.json +++ b/ethereum/.openzeppelin/unknown-43113.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-43114.json b/ethereum/.openzeppelin/unknown-43114.json index 9aeffb91..063d020b 100644 --- a/ethereum/.openzeppelin/unknown-43114.json +++ b/ethereum/.openzeppelin/unknown-43114.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-56.json b/ethereum/.openzeppelin/unknown-56.json index 71ea7d8a..05f4559c 100644 --- a/ethereum/.openzeppelin/unknown-56.json +++ b/ethereum/.openzeppelin/unknown-56.json @@ -230,12 +230,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-80001.json b/ethereum/.openzeppelin/unknown-80001.json index 85b75b30..e322f8f8 100644 --- a/ethereum/.openzeppelin/unknown-80001.json +++ b/ethereum/.openzeppelin/unknown-80001.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/.openzeppelin/unknown-97.json b/ethereum/.openzeppelin/unknown-97.json index 883cea89..89b99954 100644 --- a/ethereum/.openzeppelin/unknown-97.json +++ b/ethereum/.openzeppelin/unknown-97.json @@ -192,12 +192,7 @@ }, "t_enum(PriceStatus)2233": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -435,12 +430,7 @@ }, "t_enum(PriceStatus)2280": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -676,12 +666,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" @@ -925,12 +910,7 @@ }, "t_enum(PriceStatus)2468": { "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] + "members": ["UNKNOWN", "TRADING", "HALTED", "AUCTION"] }, "t_uint32": { "label": "uint32" diff --git a/ethereum/Deploying.md b/ethereum/Deploying.md index 9a08e613..c3521841 100644 --- a/ethereum/Deploying.md +++ b/ethereum/Deploying.md @@ -24,7 +24,7 @@ export MNEMONIC=... npm run receiver-submit-guardian-sets -- --network $MIGRATIONS_NETWORK ``` -As a sanity check, it is recommended to deploy the migrations in `migrations/prod` to the Truffle `development` network first. You can do this by using the configuration values in [`.env.prod.development`](.env.prod.development). +As a sanity check, it is recommended to deploy the migrations in `migrations/prod` to the Truffle `development` network first. You can do this by using the configuration values in [`.env.prod.development`](.env.prod.development). As a result of this process for some files (with the network id in their name) in `networks` and `.openzeppelin` directory might change which need to be committed (if they are result of a production deployment). @@ -33,26 +33,29 @@ If you are deploying to a new network, please add the new contract address to co To do so, add the contract address to both [Pyth Gitbook EVM Page](https://github.com/pyth-network/pyth-gitbook/blob/main/consumers/evm.md) and [pyth-evm-js package](https://github.com/pyth-network/pyth-js/blob/main/pyth-evm-js/src/index.ts#L13). You also need to add the new network address to [pyth-evm-js relaying example](https://github.com/pyth-network/pyth-js/blob/main/pyth-evm-js/src/examples/EvmRelay.ts#L47). ## `networks` directory + Truffle stores the address of the deployed contracts in the build artifacts, which can make local development difficult. We use [`truffle-deploy-registry`](https://github.com/MedXProtocol/truffle-deploy-registry) to store the addresses separately from the artifacts, in the [`networks`](networks) directory. When we need to perform operations on the deployed contracts, such as performing additional migrations, we can run `npx apply-registry` to populate the artifacts with the correct addresses. Each file in the network directory is named after the network id and contains address of Migration contract and PythUpgradable contract (and Wormhole Receiver if we use `prod-receiver`). If you are upgrading the contract it should not change. In case you are deploying to a new network make sure to commit this file. ## `.openzeppelin` directory + In order to handle upgrades safely this directory stores details of the contracts structure, such as implementation addresses -and their respective storage layout in one file per network (the name contains network id). This allows truffle to -check whether the upgrade is causing any memory collision. Please take a look at (this doc)[https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable] +and their respective storage layout in one file per network (the name contains network id). This allows truffle to +check whether the upgrade is causing any memory collision. Please take a look at (this doc)[https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable] for more information. Changes to the files in this directory should be commited as well. # Upgrading the contract + To upgrade the contract you should add a new migration file in the `migrations/*` directories increasing the migration number. It looks like so: ```javascript -require('dotenv').config({ path: "../.env" }); +require("dotenv").config({ path: "../.env" }); const PythUpgradable = artifacts.require("PythUpgradable"); @@ -60,13 +63,13 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version . - * + * * Briefly describe the changelog here. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { deployer }); +}; ``` **When changing the storage, you might need to disable the storage checks because Open Zeppelin is very conservative, @@ -75,9 +78,10 @@ struct that contains all Pyth variables inside it. It is the last variable in th and is safe to append fields inside it. However, Open Zeppelin only allows appending variables in the contract surface and does not allow appending in the nested structs. -To disable security checks, you can add -`unsafeSkipStorageCheck: true` option in `upgradeProxy` call. **If you do such a thing, +To disable security checks, you can add +`unsafeSkipStorageCheck: true` option in `upgradeProxy` call. **If you do such a thing, make sure that your change to the contract won't cause any collision**. For example: + - Renaming a variable is fine. - Changing a variable type to another type with the same size is ok. - Appending to the contract variables is ok. If the last variable is a struct, it is also fine @@ -121,9 +125,9 @@ It will create a new file `PythUpgradable_merged.sol` which you can use in the e # Troubleshooting - Sometimes the truffle might fail during the dry-run (e.g., in Ethereum). It is because openzeppelin does not have the required metadata for forking. To fix it please -follow the suggestion [here](https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/241#issuecomment-1192657444). + follow the suggestion [here](https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/241#issuecomment-1192657444). - Sometimes due to rpc problems or insufficient gas the migration is not executed completely. It is better to avoid doing multiple transactions in one -migration. However, if it happens, you can comment out the part that is already ran (you can double check in the explorer), and re-run the migration. -You can avoid gas problems by choosing a much higher gas than what is showed on the network gas tracker. Also, you can find rpc nodes from -[here](https://chainlist.org/) + migration. However, if it happens, you can comment out the part that is already ran (you can double check in the explorer), and re-run the migration. + You can avoid gas problems by choosing a much higher gas than what is showed on the network gas tracker. Also, you can find rpc nodes from + [here](https://chainlist.org/) diff --git a/ethereum/README.md b/ethereum/README.md index 0e62cf21..181e1c42 100644 --- a/ethereum/README.md +++ b/ethereum/README.md @@ -9,19 +9,20 @@ Run the following command to install required dependencies for the contract: ``` # xc-governance-sdk-js is a local dependency that should be built # it is used in deployment (truffle migrations) to generate/sanity check -# the governance VAAs +# the governance VAAs pushd third_party/pyth/xc-governance-sdk-js && npm ci && popd npm ci ``` ## Deployment + Please refer to [Deploying.md](./Deploying.md) for more information. ## Foundry Foundry can be installed by the official installer, or by running our helper script which will automatically pull the correct installation script individually for Foundry and the Solidity compiler for your current OS. This may work better if you are running into networking/firewall issues using Foundry's Solidity installer. To use helper script, run the command below from this directory: -``` sh +```sh pyth-crosschain/ethereum $ bash ../scripts/install-foundry.sh ``` diff --git a/ethereum/VERIFY.md b/ethereum/VERIFY.md index 9b0ed155..0bf8e684 100644 --- a/ethereum/VERIFY.md +++ b/ethereum/VERIFY.md @@ -13,7 +13,7 @@ be set in the `ETHERSCAN_KEY` environment variable for all APIs (not just etherscan, bit of a misnomer). Our contracts are structured as a separate proxy and an implementation. Both of -these components need to be verified, and truffle handles it. +these components need to be verified, and truffle handles it. ## Verifying the contract @@ -30,12 +30,12 @@ ETHERSCAN_KEY=... npm run verify --module=PythUpgradable --contract_address=0x0e `truffle-plugin-verify/utils.js` to find the key names. # Note + The `npm run verify` script uses the `truffle-plugin-verify` plugin under the -hood. The version of `truffle-plugin-verify` pinned in the repo (`^0.5.11` at +hood. The version of `truffle-plugin-verify` pinned in the repo (`^0.5.11` at the time of writing) doesn't support the avalanche RPC. In later versions of the plugin, support was added, but other stuff has changed as well in the transitive dependencies, so it fails to parse the `HDWallet` arguments in our `truffle-config.json`. As a quick workaround, we backport the patch to `0.5.11` -by applying the `truffle-verify-constants.patch` file, which the `npm run -verify` script does transparently. Once the toolchain has been upgraded and the +by applying the `truffle-verify-constants.patch` file, which the `npm run verify` script does transparently. Once the toolchain has been upgraded and the errors fixed, this patch can be removed. diff --git a/ethereum/contracts/Migrations.sol b/ethereum/contracts/Migrations.sol index e7d1dbcd..7fcd571b 100644 --- a/ethereum/contracts/Migrations.sol +++ b/ethereum/contracts/Migrations.sol @@ -8,7 +8,7 @@ import "@openzeppelin/contracts/access/Ownable.sol"; contract Migrations is Ownable { uint public last_completed_migration; - function setCompleted(uint completed) public onlyOwner { + function setCompleted(uint completed) public onlyOwner { last_completed_migration = completed; } } diff --git a/ethereum/contracts/libraries/external/BytesLib.sol b/ethereum/contracts/libraries/external/BytesLib.sol index 532897a6..71277b6d 100644 --- a/ethereum/contracts/libraries/external/BytesLib.sol +++ b/ethereum/contracts/libraries/external/BytesLib.sol @@ -8,16 +8,11 @@ */ pragma solidity >=0.8.0 <0.9.0; - library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes - ) - internal - pure - returns (bytes memory) - { + ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { @@ -79,16 +74,22 @@ library BytesLib { // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). - mstore(0x40, and( - add(add(end, iszero(add(length, mload(_preBytes)))), 31), - not(31) // Round down to the nearest 32 bytes. - )) + mstore( + 0x40, + and( + add(add(end, iszero(add(length, mload(_preBytes)))), 31), + not(31) // Round down to the nearest 32 bytes. + ) + ) } return tempBytes; } - function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { + function concatStorage( + bytes storage _preBytes, + bytes memory _postBytes + ) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot @@ -101,7 +102,10 @@ library BytesLib { // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. - let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) + let slength := div( + and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), + 2 + ) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array @@ -229,11 +233,7 @@ library BytesLib { bytes memory _bytes, uint256 _start, uint256 _length - ) - internal - pure - returns (bytes memory) - { + ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); @@ -260,13 +260,22 @@ library BytesLib { // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. - let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) + let mc := add( + add(tempBytes, lengthmod), + mul(0x20, iszero(lengthmod)) + ) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. - let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) + let cc := add( + add( + add(_bytes, lengthmod), + mul(0x20, iszero(lengthmod)) + ), + _start + ) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) @@ -294,19 +303,28 @@ library BytesLib { return tempBytes; } - function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { + function toAddress( + bytes memory _bytes, + uint256 _start + ) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { - tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) + tempAddress := div( + mload(add(add(_bytes, 0x20), _start)), + 0x1000000000000000000000000 + ) } return tempAddress; } - function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { - require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); + function toUint8( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint8) { + require(_bytes.length >= _start + 1, "toUint8_outOfBounds"); uint8 tempUint; assembly { @@ -316,7 +334,10 @@ library BytesLib { return tempUint; } - function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { + function toUint16( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; @@ -327,7 +348,10 @@ library BytesLib { return tempUint; } - function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { + function toUint32( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; @@ -338,7 +362,10 @@ library BytesLib { return tempUint; } - function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { + function toUint64( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; @@ -349,7 +376,10 @@ library BytesLib { return tempUint; } - function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { + function toUint96( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; @@ -360,7 +390,10 @@ library BytesLib { return tempUint; } - function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { + function toUint128( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; @@ -371,7 +404,10 @@ library BytesLib { return tempUint; } - function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { + function toUint256( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; @@ -382,7 +418,10 @@ library BytesLib { return tempUint; } - function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { + function toBytes32( + bytes memory _bytes, + uint256 _start + ) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; @@ -393,7 +432,10 @@ library BytesLib { return tempBytes32; } - function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { + function equal( + bytes memory _preBytes, + bytes memory _postBytes + ) internal pure returns (bool) { bool success = true; assembly { @@ -413,8 +455,8 @@ library BytesLib { for { let cc := add(_postBytes, 0x20) - // the next line is the loop condition: - // while(uint256(mc < end) + cb == 2) + // the next line is the loop condition: + // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) @@ -439,18 +481,17 @@ library BytesLib { function equalStorage( bytes storage _preBytes, bytes memory _postBytes - ) - internal - view - returns (bool) - { + ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). - let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) + let slength := div( + and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), + 2 + ) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal @@ -486,7 +527,9 @@ library BytesLib { // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) - for {} eq(add(lt(mc, end), cb), 2) { + for { + + } eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { diff --git a/ethereum/contracts/libraries/external/UnsafeBytesLib.sol b/ethereum/contracts/libraries/external/UnsafeBytesLib.sol index 3a022e68..2c6fdad6 100644 --- a/ethereum/contracts/libraries/external/UnsafeBytesLib.sol +++ b/ethereum/contracts/libraries/external/UnsafeBytesLib.sol @@ -11,16 +11,11 @@ */ pragma solidity >=0.8.0 <0.9.0; - library UnsafeBytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes - ) - internal - pure - returns (bytes memory) - { + ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { @@ -82,16 +77,22 @@ library UnsafeBytesLib { // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). - mstore(0x40, and( - add(add(end, iszero(add(length, mload(_preBytes)))), 31), - not(31) // Round down to the nearest 32 bytes. - )) + mstore( + 0x40, + and( + add(add(end, iszero(add(length, mload(_preBytes)))), 31), + not(31) // Round down to the nearest 32 bytes. + ) + ) } return tempBytes; } - function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { + function concatStorage( + bytes storage _preBytes, + bytes memory _postBytes + ) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot @@ -104,7 +105,10 @@ library UnsafeBytesLib { // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. - let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) + let slength := div( + and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), + 2 + ) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array @@ -232,12 +236,7 @@ library UnsafeBytesLib { bytes memory _bytes, uint256 _start, uint256 _length - ) - internal - pure - returns (bytes memory) - { - + ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { @@ -261,13 +260,22 @@ library UnsafeBytesLib { // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. - let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) + let mc := add( + add(tempBytes, lengthmod), + mul(0x20, iszero(lengthmod)) + ) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. - let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) + let cc := add( + add( + add(_bytes, lengthmod), + mul(0x20, iszero(lengthmod)) + ), + _start + ) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) @@ -295,17 +303,26 @@ library UnsafeBytesLib { return tempBytes; } - function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { + function toAddress( + bytes memory _bytes, + uint256 _start + ) internal pure returns (address) { address tempAddress; assembly { - tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) + tempAddress := div( + mload(add(add(_bytes, 0x20), _start)), + 0x1000000000000000000000000 + ) } return tempAddress; } - function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { + function toUint8( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint8) { uint8 tempUint; assembly { @@ -315,7 +332,10 @@ library UnsafeBytesLib { return tempUint; } - function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { + function toUint16( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint16) { uint16 tempUint; assembly { @@ -325,7 +345,10 @@ library UnsafeBytesLib { return tempUint; } - function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { + function toUint32( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint32) { uint32 tempUint; assembly { @@ -335,7 +358,10 @@ library UnsafeBytesLib { return tempUint; } - function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { + function toUint64( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint64) { uint64 tempUint; assembly { @@ -345,7 +371,10 @@ library UnsafeBytesLib { return tempUint; } - function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { + function toUint96( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint96) { uint96 tempUint; assembly { @@ -355,7 +384,10 @@ library UnsafeBytesLib { return tempUint; } - function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { + function toUint128( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint128) { uint128 tempUint; assembly { @@ -365,7 +397,10 @@ library UnsafeBytesLib { return tempUint; } - function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { + function toUint256( + bytes memory _bytes, + uint256 _start + ) internal pure returns (uint256) { uint256 tempUint; assembly { @@ -375,7 +410,10 @@ library UnsafeBytesLib { return tempUint; } - function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { + function toBytes32( + bytes memory _bytes, + uint256 _start + ) internal pure returns (bytes32) { bytes32 tempBytes32; assembly { @@ -385,7 +423,10 @@ library UnsafeBytesLib { return tempBytes32; } - function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { + function equal( + bytes memory _preBytes, + bytes memory _postBytes + ) internal pure returns (bool) { bool success = true; assembly { @@ -405,8 +446,8 @@ library UnsafeBytesLib { for { let cc := add(_postBytes, 0x20) - // the next line is the loop condition: - // while(uint256(mc < end) + cb == 2) + // the next line is the loop condition: + // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) @@ -431,18 +472,17 @@ library UnsafeBytesLib { function equalStorage( bytes storage _preBytes, bytes memory _postBytes - ) - internal - view - returns (bool) - { + ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). - let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) + let slength := div( + and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), + 2 + ) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal @@ -478,7 +518,9 @@ library UnsafeBytesLib { // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) - for {} eq(add(lt(mc, end), cb), 2) { + for { + + } eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { diff --git a/ethereum/contracts/pyth/Pyth.sol b/ethereum/contracts/pyth/Pyth.sol index a9141b82..14585f1a 100644 --- a/ethereum/contracts/pyth/Pyth.sol +++ b/ethereum/contracts/pyth/Pyth.sol @@ -23,34 +23,48 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { } function updatePriceBatchFromVm(bytes calldata encodedVm) private { - parseAndProcessBatchPriceAttestation(parseAndVerifyBatchAttestationVM(encodedVm)); + parseAndProcessBatchPriceAttestation( + parseAndVerifyBatchAttestationVM(encodedVm) + ); } - function updatePriceFeeds(bytes[] calldata updateData) public override payable { + function updatePriceFeeds( + bytes[] calldata updateData + ) public payable override { uint requiredFee = getUpdateFee(updateData); require(msg.value >= requiredFee, "insufficient paid fee amount"); - - for(uint i = 0; i < updateData.length; ) { + + for (uint i = 0; i < updateData.length; ) { updatePriceBatchFromVm(updateData[i]); - unchecked { i++; } + unchecked { + i++; + } } } /// This method is deprecated, please use the `getUpdateFee(bytes[])` instead. - function getUpdateFee(uint updateDataSize) public view returns (uint feeAmount) { + function getUpdateFee( + uint updateDataSize + ) public view returns (uint feeAmount) { return singleUpdateFeeInWei() * updateDataSize; } - function getUpdateFee(bytes[] calldata updateData) public override view returns (uint feeAmount) { + function getUpdateFee( + bytes[] calldata updateData + ) public view override returns (uint feeAmount) { return singleUpdateFeeInWei() * updateData.length; } - function verifyPythVM(IWormhole.VM memory vm) private view returns (bool valid) { - return isValidDataSource(vm.emitterChainId, vm.emitterAddress); + function verifyPythVM( + IWormhole.VM memory vm + ) private view returns (bool valid) { + return isValidDataSource(vm.emitterChainId, vm.emitterAddress); } - function parseAndProcessBatchPriceAttestation(IWormhole.VM memory vm) internal { + function parseAndProcessBatchPriceAttestation( + IWormhole.VM memory vm + ) internal { // Most of the math operations below are simple additions. // In the places that there is more complex operation there is // a comment explaining why it is safe. Also, byteslib @@ -58,12 +72,22 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { unchecked { bytes memory encoded = vm.payload; - (uint index, uint nAttestations, uint attestationSize) = - parseBatchAttestationHeader(encoded); + ( + uint index, + uint nAttestations, + uint attestationSize + ) = parseBatchAttestationHeader(encoded); // Deserialize each attestation - for (uint j=0; j < nAttestations; j++) { - (PythInternalStructs.PriceInfo memory info, bytes32 priceId) = parseSingleAttestationFromBatch(encoded, index, attestationSize); + for (uint j = 0; j < nAttestations; j++) { + ( + PythInternalStructs.PriceInfo memory info, + bytes32 priceId + ) = parseSingleAttestationFromBatch( + encoded, + index, + attestationSize + ); // Respect specified attestation size for forward-compat index += attestationSize; @@ -71,9 +95,14 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // Store the attestation uint64 latestPublishTime = latestPriceInfoPublishTime(priceId); - if(info.publishTime > latestPublishTime) { + if (info.publishTime > latestPublishTime) { setLatestPriceInfo(priceId, info); - emit PriceFeedUpdate(priceId, info.publishTime, info.price, info.conf); + emit PriceFeedUpdate( + priceId, + info.publishTime, + info.price, + info.conf + ); } } @@ -85,10 +114,11 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { bytes memory encoded, uint index, uint attestationSize - ) internal pure returns ( - PythInternalStructs.PriceInfo memory info, - bytes32 priceId - ) { + ) + internal + pure + returns (PythInternalStructs.PriceInfo memory info, bytes32 priceId) + { unchecked { // NOTE: We don't advance the global index immediately. // attestationIndex is an attestation-local offset used @@ -98,22 +128,37 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // Unused bytes32 product id attestationIndex += 32; - priceId = UnsafeBytesLib.toBytes32(encoded, index + attestationIndex); + priceId = UnsafeBytesLib.toBytes32( + encoded, + index + attestationIndex + ); attestationIndex += 32; - info.price = int64(UnsafeBytesLib.toUint64(encoded, index + attestationIndex)); + info.price = int64( + UnsafeBytesLib.toUint64(encoded, index + attestationIndex) + ); attestationIndex += 8; - info.conf = UnsafeBytesLib.toUint64(encoded, index + attestationIndex); + info.conf = UnsafeBytesLib.toUint64( + encoded, + index + attestationIndex + ); attestationIndex += 8; - info.expo = int32(UnsafeBytesLib.toUint32(encoded, index + attestationIndex)); + info.expo = int32( + UnsafeBytesLib.toUint32(encoded, index + attestationIndex) + ); attestationIndex += 4; - info.emaPrice = int64(UnsafeBytesLib.toUint64(encoded, index + attestationIndex)); + info.emaPrice = int64( + UnsafeBytesLib.toUint64(encoded, index + attestationIndex) + ); attestationIndex += 8; - info.emaConf = UnsafeBytesLib.toUint64(encoded, index + attestationIndex); + info.emaConf = UnsafeBytesLib.toUint64( + encoded, + index + attestationIndex + ); attestationIndex += 8; { @@ -122,7 +167,10 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // 1 = TRADING: The price feed is updating as expected. // 2 = HALTED: The price feed is not currently updating because trading in the product has been halted. // 3 = AUCTION: The price feed is not currently updating because an auction is setting the price. - uint8 status = UnsafeBytesLib.toUint8(encoded, index + attestationIndex); + uint8 status = UnsafeBytesLib.toUint8( + encoded, + index + attestationIndex + ); attestationIndex += 1; // Unused uint32 numPublishers @@ -134,30 +182,48 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // Unused uint64 attestationTime attestationIndex += 8; - info.publishTime = UnsafeBytesLib.toUint64(encoded, index + attestationIndex); + info.publishTime = UnsafeBytesLib.toUint64( + encoded, + index + attestationIndex + ); attestationIndex += 8; - if (status == 1) { // status == TRADING + if (status == 1) { + // status == TRADING attestationIndex += 24; } else { // If status is not trading then the latest available price is // the previous price info that are passed here. // Previous publish time - info.publishTime = UnsafeBytesLib.toUint64(encoded, index + attestationIndex); + info.publishTime = UnsafeBytesLib.toUint64( + encoded, + index + attestationIndex + ); attestationIndex += 8; // Previous price - info.price = int64(UnsafeBytesLib.toUint64(encoded, index + attestationIndex)); + info.price = int64( + UnsafeBytesLib.toUint64( + encoded, + index + attestationIndex + ) + ); attestationIndex += 8; // Previous confidence - info.conf = UnsafeBytesLib.toUint64(encoded, index + attestationIndex); + info.conf = UnsafeBytesLib.toUint64( + encoded, + index + attestationIndex + ); attestationIndex += 8; } } - require(attestationIndex <= attestationSize, "INTERNAL: Consumed more than `attestationSize` bytes"); + require( + attestationIndex <= attestationSize, + "INTERNAL: Consumed more than `attestationSize` bytes" + ); } } @@ -173,7 +239,7 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { "priceIds and publishTimes arrays should have same length" ); - for (uint i = 0; i < priceIds.length;) { + for (uint i = 0; i < priceIds.length; ) { // If the price does not exist, then the publish time is zero and // this condition will work fine. if (latestPriceInfoPublishTime(priceIds[i]) < publishTimes[i]) { @@ -181,7 +247,9 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { return; } - unchecked { i++; } + unchecked { + i++; + } } revert( @@ -202,7 +270,10 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { price.price = info.price; price.conf = info.conf; - require(price.publishTime != 0, "price feed for the given id is not pushed or does not exist"); + require( + price.publishTime != 0, + "price feed for the given id is not pushed or does not exist" + ); } // This is an overwrite of the same method in AbstractPyth.sol @@ -218,16 +289,19 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { price.price = info.emaPrice; price.conf = info.emaConf; - require(price.publishTime != 0, "price feed for the given id is not pushed or does not exist"); + require( + price.publishTime != 0, + "price feed for the given id is not pushed or does not exist" + ); } function parseBatchAttestationHeader( bytes memory encoded - ) internal pure returns ( - uint index, - uint nAttestations, - uint attestationSize - ) { + ) + internal + pure + returns (uint index, uint nAttestations, uint attestationSize) + { unchecked { index = 0; @@ -243,7 +317,10 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { uint16 versionMinor = UnsafeBytesLib.toUint16(encoded, index); index += 2; - require(versionMinor >= 0, "invalid version minor, expected 0 or more"); + require( + versionMinor >= 0, + "invalid version minor, expected 0 or more" + ); uint16 hdrSize = UnsafeBytesLib.toUint16(encoded, index); index += 2; @@ -268,7 +345,10 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { index += hdrSize; // Payload ID of 2 required for batch headerBa - require(payloadId == 2, "invalid payload ID, expected 2 for BatchPriceAttestation"); + require( + payloadId == 2, + "invalid payload ID, expected 2 for BatchPriceAttestation" + ); } // Parse the number of attestations @@ -281,15 +361,16 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // Given the message is valid the arithmetic below should not overflow, and // even if it overflows then the require would fail. - require(encoded.length == (index + (attestationSize * nAttestations)), "invalid BatchPriceAttestation size"); + require( + encoded.length == (index + (attestationSize * nAttestations)), + "invalid BatchPriceAttestation size" + ); } } function parseAndVerifyBatchAttestationVM( bytes calldata encodedVm - ) internal view returns ( - IWormhole.VM memory vm - ) { + ) internal view returns (IWormhole.VM memory vm) { { bool valid; string memory reason; @@ -305,28 +386,41 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime - ) external payable override returns (PythStructs.PriceFeed[] memory priceFeeds) { + ) + external + payable + override + returns (PythStructs.PriceFeed[] memory priceFeeds) + { unchecked { { uint requiredFee = getUpdateFee(updateData); - require(msg.value >= requiredFee, "insufficient paid fee amount"); + require( + msg.value >= requiredFee, + "insufficient paid fee amount" + ); } priceFeeds = new PythStructs.PriceFeed[](priceIds.length); - for(uint i = 0; i < updateData.length; i++) { + for (uint i = 0; i < updateData.length; i++) { bytes memory encoded; { - IWormhole.VM memory vm = parseAndVerifyBatchAttestationVM(updateData[i]); + IWormhole.VM memory vm = parseAndVerifyBatchAttestationVM( + updateData[i] + ); encoded = vm.payload; } - (uint index, uint nAttestations, uint attestationSize) = - parseBatchAttestationHeader(encoded); + ( + uint index, + uint nAttestations, + uint attestationSize + ) = parseBatchAttestationHeader(encoded); // Deserialize each attestation - for (uint j=0; j < nAttestations; j++) { + for (uint j = 0; j < nAttestations; j++) { // NOTE: We don't advance the global index immediately. // attestationIndex is an attestation-local offset used // for readability and easier debugging. @@ -335,11 +429,14 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // Unused bytes32 product id attestationIndex += 32; - bytes32 priceId = UnsafeBytesLib.toBytes32(encoded, index + attestationIndex); + bytes32 priceId = UnsafeBytesLib.toBytes32( + encoded, + index + attestationIndex + ); // Check whether the caller requested for this data. uint k = 0; - for(; k < priceIds.length; k++) { + for (; k < priceIds.length; k++) { if (priceIds[k] == priceId) { break; } @@ -352,8 +449,18 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { continue; } - (PythInternalStructs.PriceInfo memory info, ) = parseSingleAttestationFromBatch(encoded, index, attestationSize); - require(info.publishTime != 0, "price feed for the given id is not pushed or does not exist"); + ( + PythInternalStructs.PriceInfo memory info, + + ) = parseSingleAttestationFromBatch( + encoded, + index, + attestationSize + ); + require( + info.publishTime != 0, + "price feed for the given id is not pushed or does not exist" + ); priceFeeds[k].id = priceId; priceFeeds[k].price.price = info.price; @@ -369,26 +476,35 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { // if it is not, then set the id to 0 to indicate that this price id // still does not have a valid price feed. This will allow other updates // for this price id to be processed. - if (priceFeeds[k].price.publishTime < minPublishTime || - priceFeeds[k].price.publishTime > maxPublishTime) { - priceFeeds[k].id = 0; - } + if ( + priceFeeds[k].price.publishTime < minPublishTime || + priceFeeds[k].price.publishTime > maxPublishTime + ) { + priceFeeds[k].id = 0; + } index += attestationSize; } } for (uint k = 0; k < priceIds.length; k++) { - require(priceFeeds[k].id != 0, - "1 or more price feeds are not found in the updateData or they are out of the given time range"); + require( + priceFeeds[k].id != 0, + "1 or more price feeds are not found in the updateData or they are out of the given time range" + ); } } } - function queryPriceFeed(bytes32 id) public view override returns (PythStructs.PriceFeed memory priceFeed){ + function queryPriceFeed( + bytes32 id + ) public view override returns (PythStructs.PriceFeed memory priceFeed) { // Look up the latest price info for the given ID PythInternalStructs.PriceInfo memory info = latestPriceInfo(id); - require(info.publishTime != 0, "price feed for the given id is not pushed or does not exist"); + require( + info.publishTime != 0, + "price feed for the given id is not pushed or does not exist" + ); priceFeed.id = id; priceFeed.price.price = info.price; @@ -402,11 +518,11 @@ abstract contract Pyth is PythGetters, PythSetters, AbstractPyth { priceFeed.emaPrice.publishTime = uint(info.publishTime); } - function priceFeedExists(bytes32 id) public override view returns (bool) { + function priceFeedExists(bytes32 id) public view override returns (bool) { return (latestPriceInfoPublishTime(id) != 0); } - function getValidTimePeriod() public override view returns (uint) { + function getValidTimePeriod() public view override returns (uint) { return validTimePeriodSeconds(); } diff --git a/ethereum/contracts/pyth/PythDeprecatedStructs.sol b/ethereum/contracts/pyth/PythDeprecatedStructs.sol index fcbca437..4aa4a9fa 100644 --- a/ethereum/contracts/pyth/PythDeprecatedStructs.sol +++ b/ethereum/contracts/pyth/PythDeprecatedStructs.sol @@ -1,4 +1,3 @@ - // contracts/PythDeprecatedStructs.sol // SPDX-License-Identifier: Apache 2 @@ -20,7 +19,7 @@ contract PythDeprecatedStructs { } struct DeprecatedPriceFeedV1 { - // The price ID. + // The price ID. bytes32 id; // Product account key. bytes32 productId; @@ -79,7 +78,6 @@ contract PythDeprecatedStructs { DeprecatedPriceV2 emaPrice; } - struct DeprecatedPriceInfoV2 { uint256 attestationTime; uint256 arrivalTime; diff --git a/ethereum/contracts/pyth/PythGetters.sol b/ethereum/contracts/pyth/PythGetters.sol index 9df74524..7df27cef 100644 --- a/ethereum/contracts/pyth/PythGetters.sol +++ b/ethereum/contracts/pyth/PythGetters.sol @@ -14,34 +14,56 @@ contract PythGetters is PythState { } /// Deprecated, use `validDataSources` instead - function pyth2WormholeChainId() public view returns (uint16){ + function pyth2WormholeChainId() public view returns (uint16) { return _state._deprecatedPyth2WormholeChainId; } /// Deprecated, use `validDataSources` instead - function pyth2WormholeEmitter() public view returns (bytes32){ + function pyth2WormholeEmitter() public view returns (bytes32) { return _state._deprecatedPyth2WormholeEmitter; } - function latestPriceInfo(bytes32 priceId) internal view returns (PythInternalStructs.PriceInfo memory info){ + function latestPriceInfo( + bytes32 priceId + ) internal view returns (PythInternalStructs.PriceInfo memory info) { return _state.latestPriceInfo[priceId]; } - function latestPriceInfoPublishTime(bytes32 priceId) public view returns (uint64) { + function latestPriceInfoPublishTime( + bytes32 priceId + ) public view returns (uint64) { return _state.latestPriceInfo[priceId].publishTime; } - function hashDataSource(PythInternalStructs.DataSource memory ds) public pure returns (bytes32) { + function hashDataSource( + PythInternalStructs.DataSource memory ds + ) public pure returns (bytes32) { return keccak256(abi.encodePacked(ds.chainId, ds.emitterAddress)); } - function isValidDataSource(uint16 dataSourceChainId, bytes32 dataSourceEmitterAddress) public view returns (bool) { - return _state.isValidDataSource[keccak256(abi.encodePacked(dataSourceChainId, dataSourceEmitterAddress))]; + function isValidDataSource( + uint16 dataSourceChainId, + bytes32 dataSourceEmitterAddress + ) public view returns (bool) { + return + _state.isValidDataSource[ + keccak256( + abi.encodePacked( + dataSourceChainId, + dataSourceEmitterAddress + ) + ) + ]; } - function isValidGovernanceDataSource(uint16 governanceChainId, bytes32 governanceEmitterAddress) public view returns (bool) { - return _state.governanceDataSource.chainId == governanceChainId && - _state.governanceDataSource.emitterAddress == governanceEmitterAddress; + function isValidGovernanceDataSource( + uint16 governanceChainId, + bytes32 governanceEmitterAddress + ) public view returns (bool) { + return + _state.governanceDataSource.chainId == governanceChainId && + _state.governanceDataSource.emitterAddress == + governanceEmitterAddress; } function chainId() public view returns (uint16) { @@ -52,11 +74,19 @@ contract PythGetters is PythState { return _state.lastExecutedGovernanceSequence; } - function validDataSources() public view returns (PythInternalStructs.DataSource[] memory) { + function validDataSources() + public + view + returns (PythInternalStructs.DataSource[] memory) + { return _state.validDataSources; } - function governanceDataSource() public view returns (PythInternalStructs.DataSource memory) { + function governanceDataSource() + public + view + returns (PythInternalStructs.DataSource memory) + { return _state.governanceDataSource; } diff --git a/ethereum/contracts/pyth/PythGovernance.sol b/ethereum/contracts/pyth/PythGovernance.sol index 6b4dff26..e1740482 100644 --- a/ethereum/contracts/pyth/PythGovernance.sol +++ b/ethereum/contracts/pyth/PythGovernance.sol @@ -8,27 +8,48 @@ import "./PythInternalStructs.sol"; import "./PythGetters.sol"; import "./PythSetters.sol"; - import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; /** * @dev `Governance` defines a means to enacting changes to the Pyth contract. */ -abstract contract PythGovernance is PythGetters, PythSetters, PythGovernanceInstructions { - event ContractUpgraded(address oldImplementation, address newImplementation); - event GovernanceDataSourceSet(PythInternalStructs.DataSource oldDataSource, PythInternalStructs.DataSource newDataSource, - uint64 initialSequence); - event DataSourcesSet(PythInternalStructs.DataSource[] oldDataSources, PythInternalStructs.DataSource[] newDataSources); +abstract contract PythGovernance is + PythGetters, + PythSetters, + PythGovernanceInstructions +{ + event ContractUpgraded( + address oldImplementation, + address newImplementation + ); + event GovernanceDataSourceSet( + PythInternalStructs.DataSource oldDataSource, + PythInternalStructs.DataSource newDataSource, + uint64 initialSequence + ); + event DataSourcesSet( + PythInternalStructs.DataSource[] oldDataSources, + PythInternalStructs.DataSource[] newDataSources + ); event FeeSet(uint oldFee, uint newFee); event ValidPeriodSet(uint oldValidPeriod, uint newValidPeriod); - function verifyGovernanceVM(bytes memory encodedVM) internal returns (IWormhole.VM memory parsedVM){ - (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVM); + function verifyGovernanceVM( + bytes memory encodedVM + ) internal returns (IWormhole.VM memory parsedVM) { + (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole() + .parseAndVerifyVM(encodedVM); require(valid, reason); - require(isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress), "VAA is not coming from the governance data source"); + require( + isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress), + "VAA is not coming from the governance data source" + ); - require(vm.sequence > lastExecutedGovernanceSequence(), "VAA is older than the last executed governance VAA"); + require( + vm.sequence > lastExecutedGovernanceSequence(), + "VAA is older than the last executed governance VAA" + ); setLastExecutedGovernanceSequence(vm.sequence); @@ -38,23 +59,39 @@ abstract contract PythGovernance is PythGetters, PythSetters, PythGovernanceInst function executeGovernanceInstruction(bytes calldata encodedVM) public { IWormhole.VM memory vm = verifyGovernanceVM(encodedVM); - GovernanceInstruction memory gi = parseGovernanceInstruction(vm.payload); + GovernanceInstruction memory gi = parseGovernanceInstruction( + vm.payload + ); - require(gi.targetChainId == chainId() || gi.targetChainId == 0, "invalid target chain for this governance instruction"); + require( + gi.targetChainId == chainId() || gi.targetChainId == 0, + "invalid target chain for this governance instruction" + ); if (gi.action == GovernanceAction.UpgradeContract) { - require(gi.targetChainId != 0, "upgrade with chain id 0 is not possible"); + require( + gi.targetChainId != 0, + "upgrade with chain id 0 is not possible" + ); upgradeContract(parseUpgradeContractPayload(gi.payload)); - } else if (gi.action == GovernanceAction.AuthorizeGovernanceDataSourceTransfer) { - AuthorizeGovernanceDataSourceTransfer(parseAuthorizeGovernanceDataSourceTransferPayload(gi.payload)); + } else if ( + gi.action == GovernanceAction.AuthorizeGovernanceDataSourceTransfer + ) { + AuthorizeGovernanceDataSourceTransfer( + parseAuthorizeGovernanceDataSourceTransferPayload(gi.payload) + ); } else if (gi.action == GovernanceAction.SetDataSources) { setDataSources(parseSetDataSourcesPayload(gi.payload)); } else if (gi.action == GovernanceAction.SetFee) { setFee(parseSetFeePayload(gi.payload)); } else if (gi.action == GovernanceAction.SetValidPeriod) { setValidPeriod(parseSetValidPeriodPayload(gi.payload)); - } else if (gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer) { - revert("RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message"); + } else if ( + gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer + ) { + revert( + "RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message" + ); } else { revert("invalid governance action"); } @@ -66,45 +103,73 @@ abstract contract PythGovernance is PythGetters, PythSetters, PythGovernanceInst upgradeUpgradableContract(payload); } - function upgradeUpgradableContract(UpgradeContractPayload memory payload) virtual internal; + function upgradeUpgradableContract( + UpgradeContractPayload memory payload + ) internal virtual; // Transfer the governance data source to a new value with sanity checks // to ensure the new governance data source can manage the contract. - function AuthorizeGovernanceDataSourceTransfer(AuthorizeGovernanceDataSourceTransferPayload memory payload) internal { - PythInternalStructs.DataSource memory oldGovernanceDatSource = governanceDataSource(); + function AuthorizeGovernanceDataSourceTransfer( + AuthorizeGovernanceDataSourceTransferPayload memory payload + ) internal { + PythInternalStructs.DataSource + memory oldGovernanceDatSource = governanceDataSource(); // Make sure the claimVaa is a valid VAA with RequestGovernanceDataSourceTransfer governance message // If it's valid then its emitter can take over the governance from the current emitter. // The VAA is checked here to ensure that the new governance data source is valid and can send message // through wormhole. - (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(payload.claimVaa); + (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole() + .parseAndVerifyVM(payload.claimVaa); require(valid, reason); - GovernanceInstruction memory gi = parseGovernanceInstruction(vm.payload); - require(gi.targetChainId == chainId() || gi.targetChainId == 0, "invalid target chain for this governance instruction"); - require(gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer, - "governance data source change inner vaa is not of claim action type"); + GovernanceInstruction memory gi = parseGovernanceInstruction( + vm.payload + ); + require( + gi.targetChainId == chainId() || gi.targetChainId == 0, + "invalid target chain for this governance instruction" + ); + require( + gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer, + "governance data source change inner vaa is not of claim action type" + ); - RequestGovernanceDataSourceTransferPayload memory claimPayload = parseRequestGovernanceDataSourceTransferPayload(gi.payload); + RequestGovernanceDataSourceTransferPayload + memory claimPayload = parseRequestGovernanceDataSourceTransferPayload( + gi.payload + ); // Governance data source index is used to prevent replay attacks, so a claimVaa cannot be used twice. - require(governanceDataSourceIndex() < claimPayload.governanceDataSourceIndex, - "cannot upgrade to an older governance data source"); + require( + governanceDataSourceIndex() < + claimPayload.governanceDataSourceIndex, + "cannot upgrade to an older governance data source" + ); setGovernanceDataSourceIndex(claimPayload.governanceDataSourceIndex); - PythInternalStructs.DataSource memory newGovernanceDS = PythInternalStructs.DataSource(vm.emitterChainId, vm.emitterAddress); + PythInternalStructs.DataSource + memory newGovernanceDS = PythInternalStructs.DataSource( + vm.emitterChainId, + vm.emitterAddress + ); setGovernanceDataSource(newGovernanceDS); // Setting the last executed governance to the claimVaa sequence to avoid using older sequences. setLastExecutedGovernanceSequence(vm.sequence); - emit GovernanceDataSourceSet(oldGovernanceDatSource, governanceDataSource(), lastExecutedGovernanceSequence()); + emit GovernanceDataSourceSet( + oldGovernanceDatSource, + governanceDataSource(), + lastExecutedGovernanceSequence() + ); } function setDataSources(SetDataSourcesPayload memory payload) internal { - PythInternalStructs.DataSource[] memory oldDataSources = validDataSources(); + PythInternalStructs.DataSource[] + memory oldDataSources = validDataSources(); for (uint i = 0; i < oldDataSources.length; i += 1) { _state.isValidDataSource[hashDataSource(oldDataSources[i])] = false; @@ -113,7 +178,9 @@ abstract contract PythGovernance is PythGetters, PythSetters, PythGovernanceInst delete _state.validDataSources; for (uint i = 0; i < payload.dataSources.length; i++) { _state.validDataSources.push(payload.dataSources[i]); - _state.isValidDataSource[hashDataSource(payload.dataSources[i])] = true; + _state.isValidDataSource[ + hashDataSource(payload.dataSources[i]) + ] = true; } emit DataSourcesSet(oldDataSources, validDataSources()); diff --git a/ethereum/contracts/pyth/PythGovernanceInstructions.sol b/ethereum/contracts/pyth/PythGovernanceInstructions.sol index a6b24702..1c7e398c 100644 --- a/ethereum/contracts/pyth/PythGovernanceInstructions.sol +++ b/ethereum/contracts/pyth/PythGovernanceInstructions.sol @@ -11,7 +11,6 @@ import "./PythInternalStructs.sol"; * for Pyth governance instructions. */ contract PythGovernanceInstructions { - using BytesLib for bytes; // Magic is `PTGM` encoded as a 4 byte data: Pyth Governance Message @@ -70,7 +69,9 @@ contract PythGovernanceInstructions { } /// @dev Parse a GovernanceInstruction - function parseGovernanceInstruction(bytes memory encodedInstruction) public pure returns (GovernanceInstruction memory gi) { + function parseGovernanceInstruction( + bytes memory encodedInstruction + ) public pure returns (GovernanceInstruction memory gi) { uint index = 0; uint32 magic = encodedInstruction.toUint32(index); @@ -81,7 +82,10 @@ contract PythGovernanceInstructions { gi.module = GovernanceModule(modNumber); index += 1; - require(gi.module == MODULE, "invalid module for GovernanceInstruction"); + require( + gi.module == MODULE, + "invalid module for GovernanceInstruction" + ); uint8 actionNumber = encodedInstruction.toUint8(index); gi.action = GovernanceAction(actionNumber); @@ -93,46 +97,71 @@ contract PythGovernanceInstructions { // As solidity performs math operations in a checked mode // if the length of the encoded instruction be smaller than index // it will revert. So we don't need any extra check. - gi.payload = encodedInstruction.slice(index, encodedInstruction.length - index); + gi.payload = encodedInstruction.slice( + index, + encodedInstruction.length - index + ); } /// @dev Parse a UpgradeContractPayload (action 1) with minimal validation - function parseUpgradeContractPayload(bytes memory encodedPayload) public pure returns (UpgradeContractPayload memory uc) { + function parseUpgradeContractPayload( + bytes memory encodedPayload + ) public pure returns (UpgradeContractPayload memory uc) { uint index = 0; uc.newImplementation = address(encodedPayload.toAddress(index)); index += 20; - require(encodedPayload.length == index, "invalid length for UpgradeContractPayload"); + require( + encodedPayload.length == index, + "invalid length for UpgradeContractPayload" + ); } /// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation - function parseAuthorizeGovernanceDataSourceTransferPayload(bytes memory encodedPayload) public pure returns (AuthorizeGovernanceDataSourceTransferPayload memory sgds) { + function parseAuthorizeGovernanceDataSourceTransferPayload( + bytes memory encodedPayload + ) + public + pure + returns (AuthorizeGovernanceDataSourceTransferPayload memory sgds) + { sgds.claimVaa = encodedPayload; } /// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation - function parseRequestGovernanceDataSourceTransferPayload(bytes memory encodedPayload) public pure - returns (RequestGovernanceDataSourceTransferPayload memory sgdsClaim) { - + function parseRequestGovernanceDataSourceTransferPayload( + bytes memory encodedPayload + ) + public + pure + returns (RequestGovernanceDataSourceTransferPayload memory sgdsClaim) + { uint index = 0; sgdsClaim.governanceDataSourceIndex = encodedPayload.toUint32(index); index += 4; - require(encodedPayload.length == index, "invalid length for RequestGovernanceDataSourceTransferPayload"); + require( + encodedPayload.length == index, + "invalid length for RequestGovernanceDataSourceTransferPayload" + ); } /// @dev Parse a SetDataSourcesPayload (action 3) with minimal validation - function parseSetDataSourcesPayload(bytes memory encodedPayload) public pure returns (SetDataSourcesPayload memory sds) { + function parseSetDataSourcesPayload( + bytes memory encodedPayload + ) public pure returns (SetDataSourcesPayload memory sds) { uint index = 0; uint8 dataSourcesLength = encodedPayload.toUint8(index); index += 1; - sds.dataSources = new PythInternalStructs.DataSource[](dataSourcesLength); + sds.dataSources = new PythInternalStructs.DataSource[]( + dataSourcesLength + ); - for(uint i = 0; i < dataSourcesLength; i++) { + for (uint i = 0; i < dataSourcesLength; i++) { sds.dataSources[i].chainId = encodedPayload.toUint16(index); index += 2; @@ -140,11 +169,16 @@ contract PythGovernanceInstructions { index += 32; } - require(encodedPayload.length == index, "invalid length for SetDataSourcesPayload"); + require( + encodedPayload.length == index, + "invalid length for SetDataSourcesPayload" + ); } /// @dev Parse a SetFeePayload (action 4) with minimal validation - function parseSetFeePayload(bytes memory encodedPayload) public pure returns (SetFeePayload memory sf) { + function parseSetFeePayload( + bytes memory encodedPayload + ) public pure returns (SetFeePayload memory sf) { uint index = 0; uint64 val = encodedPayload.toUint64(index); @@ -153,18 +187,26 @@ contract PythGovernanceInstructions { uint64 expo = encodedPayload.toUint64(index); index += 8; - sf.newFee = uint256(val) * uint256(10)**uint256(expo); + sf.newFee = uint256(val) * uint256(10) ** uint256(expo); - require(encodedPayload.length == index, "invalid length for SetFeePayload"); + require( + encodedPayload.length == index, + "invalid length for SetFeePayload" + ); } /// @dev Parse a SetValidPeriodPayload (action 5) with minimal validation - function parseSetValidPeriodPayload(bytes memory encodedPayload) public pure returns (SetValidPeriodPayload memory svp) { + function parseSetValidPeriodPayload( + bytes memory encodedPayload + ) public pure returns (SetValidPeriodPayload memory svp) { uint index = 0; svp.newValidPeriod = uint256(encodedPayload.toUint64(index)); index += 8; - require(encodedPayload.length == index, "invalid length for SetValidPeriodPayload"); + require( + encodedPayload.length == index, + "invalid length for SetValidPeriodPayload" + ); } } diff --git a/ethereum/contracts/pyth/PythInternalStructs.sol b/ethereum/contracts/pyth/PythInternalStructs.sol index 5347344e..0a2b5901 100644 --- a/ethereum/contracts/pyth/PythInternalStructs.sol +++ b/ethereum/contracts/pyth/PythInternalStructs.sol @@ -15,7 +15,6 @@ contract PythInternalStructs { int32 expo; int64 price; uint64 conf; - // slot 2 int64 emaPrice; uint64 emaConf; diff --git a/ethereum/contracts/pyth/PythSetters.sol b/ethereum/contracts/pyth/PythSetters.sol index a571fc60..b843bed6 100644 --- a/ethereum/contracts/pyth/PythSetters.sol +++ b/ethereum/contracts/pyth/PythSetters.sol @@ -18,7 +18,10 @@ contract PythSetters is PythState { _state.wormhole = payable(wh); } - function setLatestPriceInfo(bytes32 priceId, PythInternalStructs.PriceInfo memory info) internal { + function setLatestPriceInfo( + bytes32 priceId, + PythInternalStructs.PriceInfo memory info + ) internal { _state.latestPriceInfo[priceId] = info; } @@ -30,7 +33,9 @@ contract PythSetters is PythState { _state.validTimePeriodSeconds = validTimePeriodSeconds; } - function setGovernanceDataSource(PythInternalStructs.DataSource memory newDataSource) internal { + function setGovernanceDataSource( + PythInternalStructs.DataSource memory newDataSource + ) internal { _state.governanceDataSource = newDataSource; } diff --git a/ethereum/contracts/pyth/PythState.sol b/ethereum/contracts/pyth/PythState.sol index 56e34469..ebca604e 100644 --- a/ethereum/contracts/pyth/PythState.sol +++ b/ethereum/contracts/pyth/PythState.sol @@ -11,24 +11,18 @@ contract PythStorage { address wormhole; uint16 _deprecatedPyth2WormholeChainId; // Replaced by validDataSources/isValidDataSource bytes32 _deprecatedPyth2WormholeEmitter; // Ditto - // After a backward-incompatible change in PriceFeed this mapping got deprecated. mapping(bytes32 => PythDeprecatedStructs.DeprecatedPriceInfoV1) _deprecatedLatestPriceInfoV1; - // For tracking all active emitter/chain ID pairs PythInternalStructs.DataSource[] validDataSources; - // (chainId, emitterAddress) => isValid; takes advantage of // constant-time mapping lookup for VM verification mapping(bytes32 => bool) isValidDataSource; - uint singleUpdateFeeInWei; - /// Maximum acceptable time period before price is considered to be stale. /// This includes attestation delay, block time, and potential clock drift /// between the source/target chains. uint validTimePeriodSeconds; - // Governance data source. VAA messages from this source can change this contract // state. e.g., upgrade the contract, change the valid data sources, and more. PythInternalStructs.DataSource governanceDataSource; @@ -36,15 +30,12 @@ contract PythStorage { // with a lower or equal sequence number will be discarded. This prevents double-execution, // and also makes sure that messages are executed in the right order. uint64 lastExecutedGovernanceSequence; - // Mapping of cached price information // priceId => PriceInfo mapping(bytes32 => PythDeprecatedStructs.DeprecatedPriceInfoV2) _deprecatedLatestPriceInfoV2; - // Index of the governance data source, increased each time the governance data source - // changes. + // changes. uint32 governanceDataSourceIndex; - // Mapping of cached price information // priceId => PriceInfo mapping(bytes32 => PythInternalStructs.PriceInfo) latestPriceInfo; diff --git a/ethereum/contracts/pyth/PythUpgradable.sol b/ethereum/contracts/pyth/PythUpgradable.sol index 858b1c54..36d4418c 100644 --- a/ethereum/contracts/pyth/PythUpgradable.sol +++ b/ethereum/contracts/pyth/PythUpgradable.sol @@ -12,13 +12,18 @@ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./PythGovernance.sol"; import "./Pyth.sol"; - -contract PythUpgradable is Initializable, OwnableUpgradeable, UUPSUpgradeable, Pyth, PythGovernance { +contract PythUpgradable is + Initializable, + OwnableUpgradeable, + UUPSUpgradeable, + Pyth, + PythGovernance +{ function initialize( address wormhole, uint16 pyth2WormholeChainId, bytes32 pyth2WormholeEmitter - ) initializer public { + ) public initializer { __Ownable_init(); __UUPSUpgradeable_init(); @@ -26,50 +31,70 @@ contract PythUpgradable is Initializable, OwnableUpgradeable, UUPSUpgradeable, P } /// Privileged function to specify additional data sources in the contract - function addDataSource(uint16 chainId, bytes32 emitter) onlyOwner public { - PythInternalStructs.DataSource memory ds = PythInternalStructs.DataSource(chainId, emitter); - require(!PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress), "Data source already added"); + function addDataSource(uint16 chainId, bytes32 emitter) public onlyOwner { + PythInternalStructs.DataSource memory ds = PythInternalStructs + .DataSource(chainId, emitter); + require( + !PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress), + "Data source already added" + ); _state.isValidDataSource[hashDataSource(ds)] = true; _state.validDataSources.push(ds); } /// Privileged fucntion to remove the specified data source. Assumes _state.validDataSources has no duplicates. - function removeDataSource(uint16 chainId, bytes32 emitter) onlyOwner public { - PythInternalStructs.DataSource memory ds = PythInternalStructs.DataSource(chainId, emitter); - require(PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress), "Data source not found, not removing"); + function removeDataSource( + uint16 chainId, + bytes32 emitter + ) public onlyOwner { + PythInternalStructs.DataSource memory ds = PythInternalStructs + .DataSource(chainId, emitter); + require( + PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress), + "Data source not found, not removing" + ); _state.isValidDataSource[hashDataSource(ds)] = false; - for (uint i = 0; i < _state.validDataSources.length; ++i) { - + for (uint i = 0; i < _state.validDataSources.length; ++i) { // Find the source to remove - if (_state.validDataSources[i].chainId == ds.chainId || _state.validDataSources[i].emitterAddress == ds.emitterAddress) { - + if ( + _state.validDataSources[i].chainId == ds.chainId || + _state.validDataSources[i].emitterAddress == ds.emitterAddress + ) { // Copy last element to overwrite the target data source - _state.validDataSources[i] = _state.validDataSources[_state.validDataSources.length - 1]; + _state.validDataSources[i] = _state.validDataSources[ + _state.validDataSources.length - 1 + ]; // Remove the last element we just preserved _state.validDataSources.pop(); - break; } } } /// Privileged function to update the price update fee - function updateSingleUpdateFeeInWei(uint newFee) onlyOwner public { + function updateSingleUpdateFeeInWei(uint newFee) public onlyOwner { PythSetters.setSingleUpdateFeeInWei(newFee); } /// Privileged function to update the valid time period for a price. - function updateValidTimePeriodSeconds(uint newValidTimePeriodSeconds) onlyOwner public { + function updateValidTimePeriodSeconds( + uint newValidTimePeriodSeconds + ) public onlyOwner { PythSetters.setValidTimePeriodSeconds(newValidTimePeriodSeconds); } // Privileged function to update the governance emitter - function updateGovernanceDataSource(uint16 chainId, bytes32 emitter, uint64 sequence) onlyOwner public { - PythInternalStructs.DataSource memory ds = PythInternalStructs.DataSource(chainId, emitter); + function updateGovernanceDataSource( + uint16 chainId, + bytes32 emitter, + uint64 sequence + ) public onlyOwner { + PythInternalStructs.DataSource memory ds = PythInternalStructs + .DataSource(chainId, emitter); PythSetters.setGovernanceDataSource(ds); PythSetters.setLastExecutedGovernanceSequence(sequence); } @@ -86,13 +111,18 @@ contract PythUpgradable is Initializable, OwnableUpgradeable, UUPSUpgradeable, P } // Execute a UpgradeContract governance message - function upgradeUpgradableContract(UpgradeContractPayload memory payload) override internal { + function upgradeUpgradableContract( + UpgradeContractPayload memory payload + ) internal override { address oldImplementation = _getImplementation(); _upgradeToAndCallUUPS(payload.newImplementation, new bytes(0), false); // Calling a method using `this.` will cause a contract call that will use // the new contract. - require(this.pythUpgradableMagic() == 0x97a6f304, "the new implementation is not a Pyth contract"); + require( + this.pythUpgradableMagic() == 0x97a6f304, + "the new implementation is not a Pyth contract" + ); emit ContractUpgraded(oldImplementation, _getImplementation()); } diff --git a/ethereum/contracts/wormhole-receiver/ReceiverGetters.sol b/ethereum/contracts/wormhole-receiver/ReceiverGetters.sol index b7863e08..73cb3454 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverGetters.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverGetters.sol @@ -8,9 +8,11 @@ import "./ReceiverState.sol"; contract ReceiverGetters is ReceiverState { function owner() public view returns (address) { return _state.owner; - } - - function getGuardianSet(uint32 index) public view returns (ReceiverStructs.GuardianSet memory) { + } + + function getGuardianSet( + uint32 index + ) public view returns (ReceiverStructs.GuardianSet memory) { return _state.guardianSets[index]; } @@ -22,7 +24,9 @@ contract ReceiverGetters is ReceiverState { return _state.guardianSetExpiry; } - function governanceActionIsConsumed(bytes32 hash) public view returns (bool) { + function governanceActionIsConsumed( + bytes32 hash + ) public view returns (bool) { return _state.consumedGovernanceActions[hash]; } @@ -30,11 +34,11 @@ contract ReceiverGetters is ReceiverState { return _state.initializedImplementations[impl]; } - function governanceChainId() public view returns (uint16){ + function governanceChainId() public view returns (uint16) { return _state.provider.governanceChainId; } - function governanceContract() public view returns (bytes32){ + function governanceContract() public view returns (bytes32) { return _state.provider.governanceContract; } } diff --git a/ethereum/contracts/wormhole-receiver/ReceiverGovernance.sol b/ethereum/contracts/wormhole-receiver/ReceiverGovernance.sol index e1fb4fe2..551b33c3 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverGovernance.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverGovernance.sol @@ -10,12 +10,24 @@ import "./ReceiverSetters.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; -abstract contract ReceiverGovernance is ReceiverGovernanceStructs, ReceiverMessages, ReceiverSetters, ERC1967Upgrade { - event ContractUpgraded(address indexed oldContract, address indexed newContract); - event OwnershipTransfered(address indexed oldOwner, address indexed newOwner); +abstract contract ReceiverGovernance is + ReceiverGovernanceStructs, + ReceiverMessages, + ReceiverSetters, + ERC1967Upgrade +{ + event ContractUpgraded( + address indexed oldContract, + address indexed newContract + ); + event OwnershipTransfered( + address indexed oldOwner, + address indexed newOwner + ); // "Core" (left padded) - bytes32 constant module = 0x00000000000000000000000000000000000000000000000000000000436f7265; + bytes32 constant module = + 0x00000000000000000000000000000000000000000000000000000000436f7265; function submitNewGuardianSet(bytes memory _vm) public { ReceiverStructs.VM memory vm = parseVM(_vm); @@ -23,12 +35,19 @@ abstract contract ReceiverGovernance is ReceiverGovernanceStructs, ReceiverMessa (bool isValid, string memory reason) = verifyGovernanceVM(vm); require(isValid, reason); - ReceiverGovernanceStructs.GuardianSetUpgrade memory upgrade = parseGuardianSetUpgrade(vm.payload); + ReceiverGovernanceStructs.GuardianSetUpgrade + memory upgrade = parseGuardianSetUpgrade(vm.payload); require(upgrade.module == module, "invalid Module"); - require(upgrade.newGuardianSet.keys.length > 0, "new guardian set is empty"); - require(upgrade.newGuardianSetIndex == getCurrentGuardianSetIndex() + 1, "index must increase in steps of 1"); + require( + upgrade.newGuardianSet.keys.length > 0, + "new guardian set is empty" + ); + require( + upgrade.newGuardianSetIndex == getCurrentGuardianSetIndex() + 1, + "index must increase in steps of 1" + ); setGovernanceActionConsumed(vm.hash); @@ -43,17 +62,21 @@ abstract contract ReceiverGovernance is ReceiverGovernanceStructs, ReceiverMessa _upgradeTo(newImplementation); // Call initialize function of the new implementation - (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()")); + (bool success, bytes memory reason) = newImplementation.delegatecall( + abi.encodeWithSignature("initialize()") + ); require(success, string(reason)); emit ContractUpgraded(currentImplementation, newImplementation); } - function verifyGovernanceVM(ReceiverStructs.VM memory vm) internal view returns (bool, string memory){ + function verifyGovernanceVM( + ReceiverStructs.VM memory vm + ) internal view returns (bool, string memory) { // validate vm (bool isValid, string memory reason) = verifyVM(vm); - if (!isValid){ + if (!isValid) { return (false, reason); } @@ -71,7 +94,7 @@ abstract contract ReceiverGovernance is ReceiverGovernanceStructs, ReceiverMessa } // prevent re-entry - if (governanceActionIsConsumed(vm.hash)){ + if (governanceActionIsConsumed(vm.hash)) { return (false, "governance action already consumed"); } @@ -82,7 +105,7 @@ abstract contract ReceiverGovernance is ReceiverGovernanceStructs, ReceiverMessa require(newOwner != address(0), "new owner cannot be the zero address"); address currentOwner = owner(); - + setOwner(newOwner); emit OwnershipTransfered(currentOwner, newOwner); diff --git a/ethereum/contracts/wormhole-receiver/ReceiverGovernanceStructs.sol b/ethereum/contracts/wormhole-receiver/ReceiverGovernanceStructs.sol index d0570686..10e5ffab 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverGovernanceStructs.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverGovernanceStructs.sol @@ -18,12 +18,13 @@ contract ReceiverGovernanceStructs { bytes32 module; uint8 action; uint16 chain; - ReceiverStructs.GuardianSet newGuardianSet; uint32 newGuardianSetIndex; } - function parseGuardianSetUpgrade(bytes memory encodedUpgrade) public pure returns (GuardianSetUpgrade memory gsu) { + function parseGuardianSetUpgrade( + bytes memory encodedUpgrade + ) public pure returns (GuardianSetUpgrade memory gsu) { uint index = 0; gsu.module = encodedUpgrade.toBytes32(index); @@ -44,16 +45,15 @@ contract ReceiverGovernanceStructs { index += 1; gsu.newGuardianSet = ReceiverStructs.GuardianSet({ - keys : new address[](guardianLength), - expirationTime : 0 + keys: new address[](guardianLength), + expirationTime: 0 }); - for(uint i = 0; i < guardianLength; i++) { + for (uint i = 0; i < guardianLength; i++) { gsu.newGuardianSet.keys[i] = encodedUpgrade.toAddress(index); index += 20; } require(encodedUpgrade.length == index, "invalid GuardianSetUpgrade"); } - } diff --git a/ethereum/contracts/wormhole-receiver/ReceiverImplementation.sol b/ethereum/contracts/wormhole-receiver/ReceiverImplementation.sol index 283da814..4b2fc3c5 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverImplementation.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverImplementation.sol @@ -9,21 +9,21 @@ import "./ReceiverGovernance.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; contract ReceiverImplementation is ReceiverGovernance { - modifier initializer() { address implementation = ERC1967Upgrade._getImplementation(); - require( - !isInitialized(implementation), - "already initialized" - ); + require(!isInitialized(implementation), "already initialized"); setInitialized(implementation); _; } - fallback() external payable {revert("unsupported");} + fallback() external payable { + revert("unsupported"); + } - receive() external payable {revert("the Wormhole Receiver contract does not accept assets");} + receive() external payable { + revert("the Wormhole Receiver contract does not accept assets"); + } } diff --git a/ethereum/contracts/wormhole-receiver/ReceiverMessages.sol b/ethereum/contracts/wormhole-receiver/ReceiverMessages.sol index 33c45094..f8c6f414 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverMessages.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverMessages.sol @@ -8,56 +8,75 @@ import "./ReceiverGetters.sol"; import "./ReceiverStructs.sol"; import "../libraries/external/BytesLib.sol"; - contract ReceiverMessages is ReceiverGetters { using BytesLib for bytes; /// @dev parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption - function parseAndVerifyVM(bytes calldata encodedVM) public view returns (ReceiverStructs.VM memory vm, bool valid, string memory reason) { + function parseAndVerifyVM( + bytes calldata encodedVM + ) + public + view + returns (ReceiverStructs.VM memory vm, bool valid, string memory reason) + { vm = parseVM(encodedVM); (valid, reason) = verifyVM(vm); } - /** - * @dev `verifyVM` serves to validate an arbitrary vm against a valid Guardian set - * - it aims to make sure the VM is for a known guardianSet - * - it aims to ensure the guardianSet is not expired - * - it aims to ensure the VM has reached quorum - * - it aims to verify the signatures provided against the guardianSet - */ - function verifyVM(ReceiverStructs.VM memory vm) public view returns (bool valid, string memory reason) { + /** + * @dev `verifyVM` serves to validate an arbitrary vm against a valid Guardian set + * - it aims to make sure the VM is for a known guardianSet + * - it aims to ensure the guardianSet is not expired + * - it aims to ensure the VM has reached quorum + * - it aims to verify the signatures provided against the guardianSet + */ + function verifyVM( + ReceiverStructs.VM memory vm + ) public view returns (bool valid, string memory reason) { /// @dev Obtain the current guardianSet for the guardianSetIndex provided - ReceiverStructs.GuardianSet memory guardianSet = getGuardianSet(vm.guardianSetIndex); + ReceiverStructs.GuardianSet memory guardianSet = getGuardianSet( + vm.guardianSetIndex + ); - /** - * @dev Checks whether the guardianSet has zero keys - * WARNING: This keys check is critical to ensure the guardianSet has keys present AND to ensure - * that guardianSet key size doesn't fall to zero and negatively impact quorum assessment. If guardianSet - * key length is 0 and vm.signatures length is 0, this could compromise the integrity of both vm and - * signature verification. - */ - if(guardianSet.keys.length == 0){ + /** + * @dev Checks whether the guardianSet has zero keys + * WARNING: This keys check is critical to ensure the guardianSet has keys present AND to ensure + * that guardianSet key size doesn't fall to zero and negatively impact quorum assessment. If guardianSet + * key length is 0 and vm.signatures length is 0, this could compromise the integrity of both vm and + * signature verification. + */ + if (guardianSet.keys.length == 0) { return (false, "invalid guardian set"); } /// @dev Checks if VM guardian set index matches the current index (unless the current set is expired). - if(vm.guardianSetIndex != getCurrentGuardianSetIndex() && guardianSet.expirationTime < block.timestamp){ + if ( + vm.guardianSetIndex != getCurrentGuardianSetIndex() && + guardianSet.expirationTime < block.timestamp + ) { return (false, "guardian set has expired"); } - /** - * @dev We're using a fixed point number transformation with 1 decimal to deal with rounding. - * WARNING: This quorum check is critical to assessing whether we have enough Guardian signatures to validate a VM - * if making any changes to this, obtain additional peer review. If guardianSet key length is 0 and - * vm.signatures length is 0, this could compromise the integrity of both vm and signature verification. - */ - if(((guardianSet.keys.length * 10 / 3) * 2) / 10 + 1 > vm.signatures.length){ + /** + * @dev We're using a fixed point number transformation with 1 decimal to deal with rounding. + * WARNING: This quorum check is critical to assessing whether we have enough Guardian signatures to validate a VM + * if making any changes to this, obtain additional peer review. If guardianSet key length is 0 and + * vm.signatures length is 0, this could compromise the integrity of both vm and signature verification. + */ + if ( + (((guardianSet.keys.length * 10) / 3) * 2) / 10 + 1 > + vm.signatures.length + ) { return (false, "no quorum"); } /// @dev Verify the proposed vm.signatures against the guardianSet - (bool signaturesValid, string memory invalidReason) = verifySignatures(vm.hash, vm.signatures, guardianSet); - if(!signaturesValid){ + (bool signaturesValid, string memory invalidReason) = verifySignatures( + vm.hash, + vm.signatures, + guardianSet + ); + if (!signaturesValid) { return (false, invalidReason); } @@ -71,17 +90,27 @@ contract ReceiverMessages is ReceiverGetters { * - it intentioanlly does not solve for quorum (you should use verifyVM if you need these protections) * - it intentionally returns true when signatures is an empty set (you should use verifyVM if you need these protections) */ - function verifySignatures(bytes32 hash, ReceiverStructs.Signature[] memory signatures, ReceiverStructs.GuardianSet memory guardianSet) public pure returns (bool valid, string memory reason) { + function verifySignatures( + bytes32 hash, + ReceiverStructs.Signature[] memory signatures, + ReceiverStructs.GuardianSet memory guardianSet + ) public pure returns (bool valid, string memory reason) { uint8 lastIndex = 0; for (uint i = 0; i < signatures.length; i++) { ReceiverStructs.Signature memory sig = signatures[i]; /// Ensure that provided signature indices are ascending only - require(i == 0 || sig.guardianIndex > lastIndex, "signature indices must be ascending"); + require( + i == 0 || sig.guardianIndex > lastIndex, + "signature indices must be ascending" + ); lastIndex = sig.guardianIndex; /// Check to see if the signer of the signature does not match a specific Guardian key at the provided index - if(ecrecover(hash, sig.v, sig.r, sig.s) != guardianSet.keys[sig.guardianIndex]){ + if ( + ecrecover(hash, sig.v, sig.r, sig.s) != + guardianSet.keys[sig.guardianIndex] + ) { return (false, "VM signature invalid"); } } @@ -94,7 +123,9 @@ contract ReceiverMessages is ReceiverGetters { * @dev parseVM serves to parse an encodedVM into a vm struct * - it intentionally performs no validation functions, it simply parses raw into a struct */ - function parseVM(bytes memory encodedVM) public pure virtual returns (ReceiverStructs.VM memory vm) { + function parseVM( + bytes memory encodedVM + ) public pure virtual returns (ReceiverStructs.VM memory vm) { uint index = 0; vm.version = encodedVM.toUint8(index); diff --git a/ethereum/contracts/wormhole-receiver/ReceiverSetters.sol b/ethereum/contracts/wormhole-receiver/ReceiverSetters.sol index f30d6995..b9bcebd3 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverSetters.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverSetters.sol @@ -9,16 +9,21 @@ contract ReceiverSetters is ReceiverState { function setOwner(address owner_) internal { _state.owner = owner_; } - + function updateGuardianSetIndex(uint32 newIndex) internal { _state.guardianSetIndex = newIndex; } function expireGuardianSet(uint32 index) internal { - _state.guardianSets[index].expirationTime = uint32(block.timestamp) + 86400; + _state.guardianSets[index].expirationTime = + uint32(block.timestamp) + + 86400; } - function storeGuardianSet(ReceiverStructs.GuardianSet memory set, uint32 index) internal { + function storeGuardianSet( + ReceiverStructs.GuardianSet memory set, + uint32 index + ) internal { _state.guardianSets[index] = set; } @@ -37,5 +42,4 @@ contract ReceiverSetters is ReceiverState { function setGovernanceContract(bytes32 governanceContract) internal { _state.provider.governanceContract = governanceContract; } - } diff --git a/ethereum/contracts/wormhole-receiver/ReceiverSetup.sol b/ethereum/contracts/wormhole-receiver/ReceiverSetup.sol index d0063e55..8d77a125 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverSetup.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverSetup.sol @@ -19,10 +19,8 @@ contract ReceiverSetup is ReceiverSetters, ERC1967Upgrade { setOwner(msg.sender); - ReceiverStructs.GuardianSet memory initialGuardianSet = ReceiverStructs.GuardianSet({ - keys : initialGuardians, - expirationTime : 0 - }); + ReceiverStructs.GuardianSet memory initialGuardianSet = ReceiverStructs + .GuardianSet({keys: initialGuardians, expirationTime: 0}); storeGuardianSet(initialGuardianSet, 0); // initial guardian set index is 0, which is the default value of the storage slot anyways diff --git a/ethereum/contracts/wormhole-receiver/ReceiverState.sol b/ethereum/contracts/wormhole-receiver/ReceiverState.sol index a7b90a99..202e0ffe 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverState.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverState.sol @@ -21,22 +21,16 @@ contract ReceiverEvents { contract ReceiverStorage { struct WormholeState { ReceiverStructs.Provider provider; - // contract deployer address owner; - // Mapping of guardian_set_index => guardian set mapping(uint32 => ReceiverStructs.GuardianSet) guardianSets; - // Current active guardian set index uint32 guardianSetIndex; - // Period for which a guardian set stays active after it has been replaced uint32 guardianSetExpiry; - // Mapping of consumed governance actions mapping(bytes32 => bool) consumedGovernanceActions; - // Mapping of initialized implementations mapping(address => bool) initializedImplementations; } diff --git a/ethereum/contracts/wormhole-receiver/ReceiverStructs.sol b/ethereum/contracts/wormhole-receiver/ReceiverStructs.sol index 16aef4cb..134f6d3d 100644 --- a/ethereum/contracts/wormhole-receiver/ReceiverStructs.sol +++ b/ethereum/contracts/wormhole-receiver/ReceiverStructs.sol @@ -4,36 +4,34 @@ pragma solidity ^0.8.0; interface ReceiverStructs { - struct Provider { - uint16 governanceChainId; - bytes32 governanceContract; - } + struct Provider { + uint16 governanceChainId; + bytes32 governanceContract; + } - struct GuardianSet { - address[] keys; - uint32 expirationTime; - } + struct GuardianSet { + address[] keys; + uint32 expirationTime; + } - struct Signature { - bytes32 r; - bytes32 s; - uint8 v; - uint8 guardianIndex; - } + struct Signature { + bytes32 r; + bytes32 s; + uint8 v; + uint8 guardianIndex; + } - struct VM { - uint8 version; - uint32 timestamp; - uint32 nonce; - uint16 emitterChainId; - bytes32 emitterAddress; - uint64 sequence; - uint8 consistencyLevel; - bytes payload; - - uint32 guardianSetIndex; - Signature[] signatures; - - bytes32 hash; - } + struct VM { + uint8 version; + uint32 timestamp; + uint32 nonce; + uint16 emitterChainId; + bytes32 emitterAddress; + uint64 sequence; + uint8 consistencyLevel; + bytes payload; + uint32 guardianSetIndex; + Signature[] signatures; + bytes32 hash; + } } diff --git a/ethereum/contracts/wormhole-receiver/WormholeReceiver.sol b/ethereum/contracts/wormhole-receiver/WormholeReceiver.sol index e1f58d38..4c1a923e 100644 --- a/ethereum/contracts/wormhole-receiver/WormholeReceiver.sol +++ b/ethereum/contracts/wormhole-receiver/WormholeReceiver.sol @@ -6,8 +6,8 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract WormholeReceiver is ERC1967Proxy { - constructor (address setup, bytes memory initData) ERC1967Proxy( - setup, - initData - ) { } + constructor( + address setup, + bytes memory initData + ) ERC1967Proxy(setup, initData) {} } diff --git a/ethereum/contracts/wormhole/Getters.sol b/ethereum/contracts/wormhole/Getters.sol index 60d67a78..434d6fa5 100644 --- a/ethereum/contracts/wormhole/Getters.sol +++ b/ethereum/contracts/wormhole/Getters.sol @@ -6,7 +6,9 @@ pragma solidity ^0.8.0; import "./State.sol"; contract Getters is State { - function getGuardianSet(uint32 index) public view returns (Structs.GuardianSet memory) { + function getGuardianSet( + uint32 index + ) public view returns (Structs.GuardianSet memory) { return _state.guardianSets[index]; } @@ -18,7 +20,9 @@ contract Getters is State { return _state.guardianSetExpiry; } - function governanceActionIsConsumed(bytes32 hash) public view returns (bool) { + function governanceActionIsConsumed( + bytes32 hash + ) public view returns (bool) { return _state.consumedGovernanceActions[hash]; } @@ -30,11 +34,11 @@ contract Getters is State { return _state.provider.chainId; } - function governanceChainId() public view returns (uint16){ + function governanceChainId() public view returns (uint16) { return _state.provider.governanceChainId; } - function governanceContract() public view returns (bytes32){ + function governanceContract() public view returns (bytes32) { return _state.provider.governanceContract; } @@ -45,4 +49,4 @@ contract Getters is State { function nextSequence(address emitter) public view returns (uint64) { return _state.sequences[emitter]; } -} \ No newline at end of file +} diff --git a/ethereum/contracts/wormhole/Governance.sol b/ethereum/contracts/wormhole/Governance.sol index 47d4b100..b5ba9830 100644 --- a/ethereum/contracts/wormhole/Governance.sol +++ b/ethereum/contracts/wormhole/Governance.sol @@ -10,12 +10,21 @@ import "./Setters.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; -abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upgrade { - event ContractUpgraded(address indexed oldContract, address indexed newContract); +abstract contract Governance is + GovernanceStructs, + Messages, + Setters, + ERC1967Upgrade +{ + event ContractUpgraded( + address indexed oldContract, + address indexed newContract + ); event GuardianSetAdded(uint32 indexed index); // "Core" (left padded) - bytes32 constant module = 0x00000000000000000000000000000000000000000000000000000000436f7265; + bytes32 constant module = + 0x00000000000000000000000000000000000000000000000000000000436f7265; function submitContractUpgrade(bytes memory _vm) public { Structs.VM memory vm = parseVM(_vm); @@ -23,7 +32,9 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg (bool isValid, string memory reason) = verifyGovernanceVM(vm); require(isValid, reason); - GovernanceStructs.ContractUpgrade memory upgrade = parseContractUpgrade(vm.payload); + GovernanceStructs.ContractUpgrade memory upgrade = parseContractUpgrade( + vm.payload + ); require(upgrade.module == module, "Invalid Module"); require(upgrade.chain == chainId(), "Invalid Chain"); @@ -39,7 +50,9 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg (bool isValid, string memory reason) = verifyGovernanceVM(vm); require(isValid, reason); - GovernanceStructs.SetMessageFee memory upgrade = parseSetMessageFee(vm.payload); + GovernanceStructs.SetMessageFee memory upgrade = parseSetMessageFee( + vm.payload + ); require(upgrade.module == module, "Invalid Module"); require(upgrade.chain == chainId(), "Invalid Chain"); @@ -55,13 +68,23 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg (bool isValid, string memory reason) = verifyGovernanceVM(vm); require(isValid, reason); - GovernanceStructs.GuardianSetUpgrade memory upgrade = parseGuardianSetUpgrade(vm.payload); + GovernanceStructs.GuardianSetUpgrade + memory upgrade = parseGuardianSetUpgrade(vm.payload); require(upgrade.module == module, "invalid Module"); - require(upgrade.chain == chainId() || upgrade.chain == 0, "invalid Chain"); + require( + upgrade.chain == chainId() || upgrade.chain == 0, + "invalid Chain" + ); - require(upgrade.newGuardianSet.keys.length > 0, "new guardian set is empty"); - require(upgrade.newGuardianSetIndex == getCurrentGuardianSetIndex() + 1, "index must increase in steps of 1"); + require( + upgrade.newGuardianSet.keys.length > 0, + "new guardian set is empty" + ); + require( + upgrade.newGuardianSetIndex == getCurrentGuardianSetIndex() + 1, + "index must increase in steps of 1" + ); setGovernanceActionConsumed(vm.hash); @@ -76,14 +99,21 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg (bool isValid, string memory reason) = verifyGovernanceVM(vm); require(isValid, reason); - GovernanceStructs.TransferFees memory transfer = parseTransferFees(vm.payload); + GovernanceStructs.TransferFees memory transfer = parseTransferFees( + vm.payload + ); require(transfer.module == module, "invalid Module"); - require(transfer.chain == chainId() || transfer.chain == 0, "invalid Chain"); + require( + transfer.chain == chainId() || transfer.chain == 0, + "invalid Chain" + ); setGovernanceActionConsumed(vm.hash); - address payable recipient = payable(address(uint160(uint256(transfer.recipient)))); + address payable recipient = payable( + address(uint160(uint256(transfer.recipient))) + ); recipient.transfer(transfer.amount); } @@ -94,17 +124,21 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg _upgradeTo(newImplementation); // Call initialize function of the new implementation - (bool success, bytes memory reason) = newImplementation.delegatecall(abi.encodeWithSignature("initialize()")); + (bool success, bytes memory reason) = newImplementation.delegatecall( + abi.encodeWithSignature("initialize()") + ); require(success, string(reason)); emit ContractUpgraded(currentImplementation, newImplementation); } - function verifyGovernanceVM(Structs.VM memory vm) internal view returns (bool, string memory){ + function verifyGovernanceVM( + Structs.VM memory vm + ) internal view returns (bool, string memory) { // validate vm (bool isValid, string memory reason) = verifyVM(vm); - if (!isValid){ + if (!isValid) { return (false, reason); } @@ -122,10 +156,10 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg } // prevent re-entry - if (governanceActionIsConsumed(vm.hash)){ + if (governanceActionIsConsumed(vm.hash)) { return (false, "governance action already consumed"); } return (true, ""); } -} \ No newline at end of file +} diff --git a/ethereum/contracts/wormhole/GovernanceStructs.sol b/ethereum/contracts/wormhole/GovernanceStructs.sol index 06baa273..f5c0708b 100644 --- a/ethereum/contracts/wormhole/GovernanceStructs.sol +++ b/ethereum/contracts/wormhole/GovernanceStructs.sol @@ -18,7 +18,6 @@ contract GovernanceStructs { bytes32 module; uint8 action; uint16 chain; - address newContract; } @@ -26,7 +25,6 @@ contract GovernanceStructs { bytes32 module; uint8 action; uint16 chain; - Structs.GuardianSet newGuardianSet; uint32 newGuardianSetIndex; } @@ -35,7 +33,6 @@ contract GovernanceStructs { bytes32 module; uint8 action; uint16 chain; - uint256 messageFee; } @@ -43,12 +40,13 @@ contract GovernanceStructs { bytes32 module; uint8 action; uint16 chain; - uint256 amount; bytes32 recipient; } - function parseContractUpgrade(bytes memory encodedUpgrade) public pure returns (ContractUpgrade memory cu) { + function parseContractUpgrade( + bytes memory encodedUpgrade + ) public pure returns (ContractUpgrade memory cu) { uint index = 0; cu.module = encodedUpgrade.toBytes32(index); @@ -62,13 +60,17 @@ contract GovernanceStructs { cu.chain = encodedUpgrade.toUint16(index); index += 2; - cu.newContract = address(uint160(uint256(encodedUpgrade.toBytes32(index)))); + cu.newContract = address( + uint160(uint256(encodedUpgrade.toBytes32(index))) + ); index += 32; require(encodedUpgrade.length == index, "invalid ContractUpgrade"); } - function parseGuardianSetUpgrade(bytes memory encodedUpgrade) public pure returns (GuardianSetUpgrade memory gsu) { + function parseGuardianSetUpgrade( + bytes memory encodedUpgrade + ) public pure returns (GuardianSetUpgrade memory gsu) { uint index = 0; gsu.module = encodedUpgrade.toBytes32(index); @@ -89,11 +91,11 @@ contract GovernanceStructs { index += 1; gsu.newGuardianSet = Structs.GuardianSet({ - keys : new address[](guardianLength), - expirationTime : 0 + keys: new address[](guardianLength), + expirationTime: 0 }); - for(uint i = 0; i < guardianLength; i++) { + for (uint i = 0; i < guardianLength; i++) { gsu.newGuardianSet.keys[i] = encodedUpgrade.toAddress(index); index += 20; } @@ -101,7 +103,9 @@ contract GovernanceStructs { require(encodedUpgrade.length == index, "invalid GuardianSetUpgrade"); } - function parseSetMessageFee(bytes memory encodedSetMessageFee) public pure returns (SetMessageFee memory smf) { + function parseSetMessageFee( + bytes memory encodedSetMessageFee + ) public pure returns (SetMessageFee memory smf) { uint index = 0; smf.module = encodedSetMessageFee.toBytes32(index); @@ -121,7 +125,9 @@ contract GovernanceStructs { require(encodedSetMessageFee.length == index, "invalid SetMessageFee"); } - function parseTransferFees(bytes memory encodedTransferFees) public pure returns (TransferFees memory tf) { + function parseTransferFees( + bytes memory encodedTransferFees + ) public pure returns (TransferFees memory tf) { uint index = 0; tf.module = encodedTransferFees.toBytes32(index); @@ -143,4 +149,4 @@ contract GovernanceStructs { require(encodedTransferFees.length == index, "invalid TransferFees"); } -} \ No newline at end of file +} diff --git a/ethereum/contracts/wormhole/Implementation.sol b/ethereum/contracts/wormhole/Implementation.sol index 474cc2d6..377a325c 100644 --- a/ethereum/contracts/wormhole/Implementation.sol +++ b/ethereum/contracts/wormhole/Implementation.sol @@ -9,7 +9,13 @@ import "./Governance.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; contract Implementation is Governance { - event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); + event LogMessagePublished( + address indexed sender, + uint64 sequence, + uint32 nonce, + bytes payload, + uint8 consistencyLevel + ); // Publish a message to be attested by the Wormhole network function publishMessage( @@ -22,7 +28,13 @@ contract Implementation is Governance { sequence = useSequence(msg.sender); // emit log - emit LogMessagePublished(msg.sender, sequence, nonce, payload, consistencyLevel); + emit LogMessagePublished( + msg.sender, + sequence, + nonce, + payload, + consistencyLevel + ); } function useSequence(address emitter) internal returns (uint64 sequence) { @@ -33,17 +45,18 @@ contract Implementation is Governance { modifier initializer() { address implementation = ERC1967Upgrade._getImplementation(); - require( - !isInitialized(implementation), - "already initialized" - ); + require(!isInitialized(implementation), "already initialized"); setInitialized(implementation); _; } - fallback() external payable {revert("unsupported");} + fallback() external payable { + revert("unsupported"); + } - receive() external payable {revert("the Wormhole contract does not accept assets");} + receive() external payable { + revert("the Wormhole contract does not accept assets"); + } } diff --git a/ethereum/contracts/wormhole/Messages.sol b/ethereum/contracts/wormhole/Messages.sol index e982abf0..43305780 100644 --- a/ethereum/contracts/wormhole/Messages.sol +++ b/ethereum/contracts/wormhole/Messages.sol @@ -8,54 +8,85 @@ import "./Getters.sol"; import "./Structs.sol"; import "../libraries/external/BytesLib.sol"; - contract Messages is Getters { using BytesLib for bytes; - function parseAndVerifyVM(bytes calldata encodedVM) public view returns (Structs.VM memory vm, bool valid, string memory reason) { + function parseAndVerifyVM( + bytes calldata encodedVM + ) + public + view + returns (Structs.VM memory vm, bool valid, string memory reason) + { vm = parseVM(encodedVM); (valid, reason) = verifyVM(vm); } - function verifyVM(Structs.VM memory vm) public view returns (bool valid, string memory reason) { - Structs.GuardianSet memory guardianSet = getGuardianSet(vm.guardianSetIndex); + function verifyVM( + Structs.VM memory vm + ) public view returns (bool valid, string memory reason) { + Structs.GuardianSet memory guardianSet = getGuardianSet( + vm.guardianSetIndex + ); - if(guardianSet.keys.length == 0){ + if (guardianSet.keys.length == 0) { return (false, "invalid guardian set"); } - if(vm.guardianSetIndex != getCurrentGuardianSetIndex() && guardianSet.expirationTime < block.timestamp){ + if ( + vm.guardianSetIndex != getCurrentGuardianSetIndex() && + guardianSet.expirationTime < block.timestamp + ) { return (false, "guardian set has expired"); } // We're using a fixed point number transformation with 1 decimal to deal with rounding. - if(((guardianSet.keys.length * 10 / 3) * 2) / 10 + 1 > vm.signatures.length){ + if ( + (((guardianSet.keys.length * 10) / 3) * 2) / 10 + 1 > + vm.signatures.length + ) { return (false, "no quorum"); } // Verify signatures - (bool signaturesValid, string memory invalidReason) = verifySignatures(vm.hash, vm.signatures, guardianSet); - if(!signaturesValid){ + (bool signaturesValid, string memory invalidReason) = verifySignatures( + vm.hash, + vm.signatures, + guardianSet + ); + if (!signaturesValid) { return (false, invalidReason); } return (true, ""); } - function verifySignatures(bytes32 hash, Structs.Signature[] memory signatures, Structs.GuardianSet memory guardianSet) public pure returns (bool valid, string memory reason) { + function verifySignatures( + bytes32 hash, + Structs.Signature[] memory signatures, + Structs.GuardianSet memory guardianSet + ) public pure returns (bool valid, string memory reason) { uint8 lastIndex = 0; for (uint i = 0; i < signatures.length; i++) { Structs.Signature memory sig = signatures[i]; - require(i == 0 || sig.guardianIndex > lastIndex, "signature indices must be ascending"); + require( + i == 0 || sig.guardianIndex > lastIndex, + "signature indices must be ascending" + ); lastIndex = sig.guardianIndex; - if(ecrecover(hash, sig.v, sig.r, sig.s) != guardianSet.keys[sig.guardianIndex]){ + if ( + ecrecover(hash, sig.v, sig.r, sig.s) != + guardianSet.keys[sig.guardianIndex] + ) { return (false, "VM signature invalid"); } } return (true, ""); } - function parseVM(bytes memory encodedVM) public pure virtual returns (Structs.VM memory vm) { + function parseVM( + bytes memory encodedVM + ) public pure virtual returns (Structs.VM memory vm) { uint index = 0; vm.version = encodedVM.toUint8(index); diff --git a/ethereum/contracts/wormhole/Setters.sol b/ethereum/contracts/wormhole/Setters.sol index 95184b4e..5cacc2f0 100644 --- a/ethereum/contracts/wormhole/Setters.sol +++ b/ethereum/contracts/wormhole/Setters.sol @@ -11,10 +11,15 @@ contract Setters is State { } function expireGuardianSet(uint32 index) internal { - _state.guardianSets[index].expirationTime = uint32(block.timestamp) + 86400; + _state.guardianSets[index].expirationTime = + uint32(block.timestamp) + + 86400; } - function storeGuardianSet(Structs.GuardianSet memory set, uint32 index) internal { + function storeGuardianSet( + Structs.GuardianSet memory set, + uint32 index + ) internal { _state.guardianSets[index] = set; } @@ -45,4 +50,4 @@ contract Setters is State { function setNextSequence(address emitter, uint64 sequence) internal { _state.sequences[emitter] = sequence; } -} \ No newline at end of file +} diff --git a/ethereum/contracts/wormhole/Setup.sol b/ethereum/contracts/wormhole/Setup.sol index 989ffd6f..b30be4ce 100644 --- a/ethereum/contracts/wormhole/Setup.sol +++ b/ethereum/contracts/wormhole/Setup.sol @@ -19,8 +19,8 @@ contract Setup is Setters, ERC1967Upgrade { require(initialGuardians.length > 0, "no guardians specified"); Structs.GuardianSet memory initialGuardianSet = Structs.GuardianSet({ - keys : initialGuardians, - expirationTime : 0 + keys: initialGuardians, + expirationTime: 0 }); storeGuardianSet(initialGuardianSet, 0); diff --git a/ethereum/contracts/wormhole/State.sol b/ethereum/contracts/wormhole/State.sol index 627c8b01..62d82c7c 100644 --- a/ethereum/contracts/wormhole/State.sol +++ b/ethereum/contracts/wormhole/State.sol @@ -21,29 +21,22 @@ contract Events { contract Storage { struct WormholeState { Structs.Provider provider; - // Mapping of guardian_set_index => guardian set mapping(uint32 => Structs.GuardianSet) guardianSets; - // Current active guardian set index uint32 guardianSetIndex; - // Period for which a guardian set stays active after it has been replaced uint32 guardianSetExpiry; - // Sequence numbers per emitter mapping(address => uint64) sequences; - // Mapping of consumed governance actions mapping(bytes32 => bool) consumedGovernanceActions; - // Mapping of initialized implementations mapping(address => bool) initializedImplementations; - uint256 messageFee; } } contract State { Storage.WormholeState _state; -} \ No newline at end of file +} diff --git a/ethereum/contracts/wormhole/Structs.sol b/ethereum/contracts/wormhole/Structs.sol index d61155c5..ad609e36 100644 --- a/ethereum/contracts/wormhole/Structs.sol +++ b/ethereum/contracts/wormhole/Structs.sol @@ -4,37 +4,35 @@ pragma solidity ^0.8.0; interface Structs { - struct Provider { - uint16 chainId; - uint16 governanceChainId; - bytes32 governanceContract; - } + struct Provider { + uint16 chainId; + uint16 governanceChainId; + bytes32 governanceContract; + } - struct GuardianSet { - address[] keys; - uint32 expirationTime; - } + struct GuardianSet { + address[] keys; + uint32 expirationTime; + } - struct Signature { - bytes32 r; - bytes32 s; - uint8 v; - uint8 guardianIndex; - } + struct Signature { + bytes32 r; + bytes32 s; + uint8 v; + uint8 guardianIndex; + } - struct VM { - uint8 version; - uint32 timestamp; - uint32 nonce; - uint16 emitterChainId; - bytes32 emitterAddress; - uint64 sequence; - uint8 consistencyLevel; - bytes payload; - - uint32 guardianSetIndex; - Signature[] signatures; - - bytes32 hash; - } + struct VM { + uint8 version; + uint32 timestamp; + uint32 nonce; + uint16 emitterChainId; + bytes32 emitterAddress; + uint64 sequence; + uint8 consistencyLevel; + bytes payload; + uint32 guardianSetIndex; + Signature[] signatures; + bytes32 hash; + } } diff --git a/ethereum/contracts/wormhole/Wormhole.sol b/ethereum/contracts/wormhole/Wormhole.sol index a0917894..f89deeaa 100644 --- a/ethereum/contracts/wormhole/Wormhole.sol +++ b/ethereum/contracts/wormhole/Wormhole.sol @@ -6,8 +6,8 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract Wormhole is ERC1967Proxy { - constructor (address setup, bytes memory initData) ERC1967Proxy( - setup, - initData - ) { } -} \ No newline at end of file + constructor( + address setup, + bytes memory initData + ) ERC1967Proxy(setup, initData) {} +} diff --git a/ethereum/contracts/wormhole/interfaces/IWormhole.sol b/ethereum/contracts/wormhole/interfaces/IWormhole.sol index 0a3c48fa..69d60a62 100644 --- a/ethereum/contracts/wormhole/interfaces/IWormhole.sol +++ b/ethereum/contracts/wormhole/interfaces/IWormhole.sol @@ -6,7 +6,13 @@ pragma solidity ^0.8.0; import "../Structs.sol"; interface IWormhole is Structs { - event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); + event LogMessagePublished( + address indexed sender, + uint64 sequence, + uint32 nonce, + bytes payload, + uint8 consistencyLevel + ); function publishMessage( uint32 nonce, @@ -14,29 +20,46 @@ interface IWormhole is Structs { uint8 consistencyLevel ) external payable returns (uint64 sequence); - function parseAndVerifyVM(bytes calldata encodedVM) external view returns (Structs.VM memory vm, bool valid, string memory reason); + function parseAndVerifyVM( + bytes calldata encodedVM + ) + external + view + returns (Structs.VM memory vm, bool valid, string memory reason); - function verifyVM(Structs.VM memory vm) external view returns (bool valid, string memory reason); + function verifyVM( + Structs.VM memory vm + ) external view returns (bool valid, string memory reason); - function verifySignatures(bytes32 hash, Structs.Signature[] memory signatures, Structs.GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason) ; + function verifySignatures( + bytes32 hash, + Structs.Signature[] memory signatures, + Structs.GuardianSet memory guardianSet + ) external pure returns (bool valid, string memory reason); - function parseVM(bytes memory encodedVM) external pure returns (Structs.VM memory vm); + function parseVM( + bytes memory encodedVM + ) external pure returns (Structs.VM memory vm); - function getGuardianSet(uint32 index) external view returns (Structs.GuardianSet memory) ; + function getGuardianSet( + uint32 index + ) external view returns (Structs.GuardianSet memory); - function getCurrentGuardianSetIndex() external view returns (uint32) ; + function getCurrentGuardianSetIndex() external view returns (uint32); - function getGuardianSetExpiry() external view returns (uint32) ; + function getGuardianSetExpiry() external view returns (uint32); - function governanceActionIsConsumed(bytes32 hash) external view returns (bool) ; + function governanceActionIsConsumed( + bytes32 hash + ) external view returns (bool); - function isInitialized(address impl) external view returns (bool) ; + function isInitialized(address impl) external view returns (bool); - function chainId() external view returns (uint16) ; + function chainId() external view returns (uint16); function governanceChainId() external view returns (uint16); function governanceContract() external view returns (bytes32); - function messageFee() external view returns (uint256) ; + function messageFee() external view returns (uint256); } diff --git a/ethereum/deploy.sh b/ethereum/deploy.sh index 5a14ae0d..4b79f31a 100755 --- a/ethereum/deploy.sh +++ b/ethereum/deploy.sh @@ -1,7 +1,7 @@ #!/bin/bash # # This script deploys changes to given networks. Usage: -# $ ./deploy.sh <...> +# $ ./deploy.sh <...> # Network names are defined in `truffle-config.js`. # # Example: Deploying to some testnet networks diff --git a/ethereum/forge-test/GasBenchmark.t.sol b/ethereum/forge-test/GasBenchmark.t.sol index 86f96cd6..ce088be3 100644 --- a/ethereum/forge-test/GasBenchmark.t.sol +++ b/ethereum/forge-test/GasBenchmark.t.sol @@ -22,7 +22,7 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils { uint8 constant NUM_PRICES = 5; IPyth public pyth; - + bytes32[] priceIds; // Cached prices are populated in the setUp @@ -45,38 +45,51 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils { pyth = IPyth(setUpPyth(setUpWormhole(NUM_GUARDIANS))); priceIds = new bytes32[](NUM_PRICES); - priceIds[0] = bytes32(0x1000000000000000000000000000000000000000000000000000000000000f00); + priceIds[0] = bytes32( + 0x1000000000000000000000000000000000000000000000000000000000000f00 + ); for (uint i = 1; i < NUM_PRICES; ++i) { - priceIds[i] = bytes32(uint256(priceIds[i-1])+1); + priceIds[i] = bytes32(uint256(priceIds[i - 1]) + 1); } for (uint i = 0; i < NUM_PRICES; ++i) { - uint64 publishTime = uint64(getRand() % 10); - - cachedPrices.push(PythStructs.Price( - int64(uint64(getRand() % 1000)), // Price - uint64(getRand() % 100), // Confidence - -5, // Expo - publishTime - )); + + cachedPrices.push( + PythStructs.Price( + int64(uint64(getRand() % 1000)), // Price + uint64(getRand() % 100), // Confidence + -5, // Expo + publishTime + ) + ); cachedPricesPublishTimes.push(publishTime); publishTime += uint64(getRand() % 10); - freshPrices.push(PythStructs.Price( - int64(uint64(getRand() % 1000)), // Price - uint64(getRand() % 100), // Confidence - -5, // Expo - publishTime - )); + freshPrices.push( + PythStructs.Price( + int64(uint64(getRand() % 1000)), // Price + uint64(getRand() % 100), // Confidence + -5, // Expo + publishTime + ) + ); freshPricesPublishTimes.push(publishTime); } // Populate the contract with the initial prices - (cachedPricesUpdateData, cachedPricesUpdateFee) = generateUpdateDataAndFee(cachedPrices); - pyth.updatePriceFeeds{value: cachedPricesUpdateFee}(cachedPricesUpdateData); + ( + cachedPricesUpdateData, + cachedPricesUpdateFee + ) = generateUpdateDataAndFee(cachedPrices); + pyth.updatePriceFeeds{value: cachedPricesUpdateFee}( + cachedPricesUpdateData + ); - (freshPricesUpdateData, freshPricesUpdateFee) = generateUpdateDataAndFee(freshPrices); + ( + freshPricesUpdateData, + freshPricesUpdateFee + ) = generateUpdateDataAndFee(freshPrices); } function getRand() internal returns (uint val) { @@ -84,7 +97,9 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils { val = uint(keccak256(abi.encode(randSeed))); } - function generateUpdateDataAndFee(PythStructs.Price[] memory prices) internal returns (bytes[] memory updateData, uint updateFee) { + function generateUpdateDataAndFee( + PythStructs.Price[] memory prices + ) internal returns (bytes[] memory updateData, uint updateFee) { bytes memory vaa = generatePriceFeedUpdateVAA( pricesToPriceAttestations(priceIds, prices), sequence, @@ -92,7 +107,7 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils { ); ++sequence; - + updateData = new bytes[](1); updateData[0] = vaa; @@ -100,32 +115,53 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils { } function testBenchmarkUpdatePriceFeedsFresh() public { - pyth.updatePriceFeeds{value: freshPricesUpdateFee}(freshPricesUpdateData); + pyth.updatePriceFeeds{value: freshPricesUpdateFee}( + freshPricesUpdateData + ); } function testBenchmarkUpdatePriceFeedsNotFresh() public { - pyth.updatePriceFeeds{value: cachedPricesUpdateFee}(cachedPricesUpdateData); + pyth.updatePriceFeeds{value: cachedPricesUpdateFee}( + cachedPricesUpdateData + ); } function testBenchmarkUpdatePriceFeedsIfNecessaryFresh() public { // Since the prices have advanced, the publishTimes are newer than one in // the contract and hence, the call should succeed. - pyth.updatePriceFeedsIfNecessary{value: freshPricesUpdateFee}(freshPricesUpdateData, priceIds, freshPricesPublishTimes); + pyth.updatePriceFeedsIfNecessary{value: freshPricesUpdateFee}( + freshPricesUpdateData, + priceIds, + freshPricesPublishTimes + ); } function testBenchmarkUpdatePriceFeedsIfNecessaryNotFresh() public { // Since the price is not advanced, the publishTimes are the same as the // ones in the contract. - vm.expectRevert(bytes("no prices in the submitted batch have fresh prices, so this update will have no effect")); + vm.expectRevert( + bytes( + "no prices in the submitted batch have fresh prices, so this update will have no effect" + ) + ); - pyth.updatePriceFeedsIfNecessary{value: cachedPricesUpdateFee}(cachedPricesUpdateData, priceIds, cachedPricesPublishTimes); + pyth.updatePriceFeedsIfNecessary{value: cachedPricesUpdateFee}( + cachedPricesUpdateData, + priceIds, + cachedPricesPublishTimes + ); } function testBenchmarkParsePriceFeedUpdatesForOnePriceFeed() public { bytes32[] memory ids = new bytes32[](1); ids[0] = priceIds[0]; - pyth.parsePriceFeedUpdates{value: freshPricesUpdateFee}(freshPricesUpdateData, ids, 0, 50); + pyth.parsePriceFeedUpdates{value: freshPricesUpdateFee}( + freshPricesUpdateData, + ids, + 0, + 50 + ); } function testBenchmarkParsePriceFeedUpdatesForTwoPriceFeed() public { @@ -133,28 +169,43 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils { ids[0] = priceIds[0]; ids[1] = priceIds[1]; - pyth.parsePriceFeedUpdates{value: freshPricesUpdateFee}(freshPricesUpdateData, ids, 0, 50); + pyth.parsePriceFeedUpdates{value: freshPricesUpdateFee}( + freshPricesUpdateData, + ids, + 0, + 50 + ); } - function testBenchmarkParsePriceFeedUpdatesForOnePriceFeedNotWithinRange() public { + function testBenchmarkParsePriceFeedUpdatesForOnePriceFeedNotWithinRange() + public + { bytes32[] memory ids = new bytes32[](1); ids[0] = priceIds[0]; - vm.expectRevert(bytes("1 or more price feeds are not found in the updateData or they are out of the given time range")); - pyth.parsePriceFeedUpdates{value: freshPricesUpdateFee}(freshPricesUpdateData, ids, 50, 100); + vm.expectRevert( + bytes( + "1 or more price feeds are not found in the updateData or they are out of the given time range" + ) + ); + pyth.parsePriceFeedUpdates{value: freshPricesUpdateFee}( + freshPricesUpdateData, + ids, + 50, + 100 + ); } function testBenchmarkGetPrice() public { - // Set the block timestamp to 0. As prices have < 10 timestamp and staleness + // Set the block timestamp to 0. As prices have < 10 timestamp and staleness // is set to 60 seconds, the getPrice should work as expected. vm.warp(0); pyth.getPrice(priceIds[0]); } - function testBenchmarkGetEmaPrice() public { - // Set the block timestamp to 0. As prices have < 10 timestamp and staleness + // Set the block timestamp to 0. As prices have < 10 timestamp and staleness // is set to 60 seconds, the getPrice should work as expected. vm.warp(0); diff --git a/ethereum/forge-test/Pyth.t.sol b/ethereum/forge-test/Pyth.t.sol index 689088c7..b288545b 100644 --- a/ethereum/forge-test/Pyth.t.sol +++ b/ethereum/forge-test/Pyth.t.sol @@ -16,23 +16,26 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { // -1 is equal to 0x111111 which is the biggest uint if converted back uint64 constant MAX_UINT64 = uint64(int64(-1)); - + function setUp() public { pyth = IPyth(setUpPyth(setUpWormhole(1))); } function generateRandomPriceAttestations( uint length - ) internal returns ( - bytes32[] memory priceIds, - PriceAttestation[] memory attestations - ) { + ) + internal + returns ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) + { attestations = new PriceAttestation[](length); priceIds = new bytes32[](length); - for(uint i = 0; i < length; i++) { + for (uint i = 0; i < length; i++) { attestations[i].productId = getRandBytes32(); - attestations[i].priceId = bytes32(i+1); // price ids should be non-zero and unique + attestations[i].priceId = bytes32(i + 1); // price ids should be non-zero and unique attestations[i].price = getRandInt64(); attestations[i].conf = getRandUint64(); attestations[i].expo = getRandInt32(); @@ -56,21 +59,22 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { function createBatchedUpdateDataFromAttestations( PriceAttestation[] memory attestations ) internal returns (bytes[] memory updateData, uint updateFee) { - uint batchSize = 1 + getRandUint() % attestations.length; + uint batchSize = 1 + (getRandUint() % attestations.length); uint numBatches = (attestations.length + batchSize - 1) / batchSize; updateData = new bytes[](numBatches); - for(uint i = 0; i < attestations.length; i += batchSize) { + for (uint i = 0; i < attestations.length; i += batchSize) { uint len = batchSize; - if(attestations.length - i < len) { + if (attestations.length - i < len) { len = attestations.length - i; } - - PriceAttestation[] memory batchAttestations = new PriceAttestation[](len); - for(uint j = i; j < i+len; j++) { - batchAttestations[j-i] = attestations[j]; - } + + PriceAttestation[] + memory batchAttestations = new PriceAttestation[](len); + for (uint j = i; j < i + len; j++) { + batchAttestations[j - i] = attestations[j]; + } updateData[i / batchSize] = generatePriceFeedUpdateVAA( batchAttestations, @@ -85,128 +89,186 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { /// Testing parsePriceFeedUpdates method. function testParsePriceFeedUpdatesWorksWithTradingStatus(uint seed) public { setRandSeed(seed); - uint numAttestations = 1 + getRandUint() % 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + uint numAttestations = 1 + (getRandUint() % 10); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); - for(uint i = 0; i < numAttestations; i++) { + for (uint i = 0; i < numAttestations; i++) { attestations[i].status = PriceAttestationStatus.Trading; } - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); - PythStructs.PriceFeed[] memory priceFeeds = - pyth.parsePriceFeedUpdates{value: updateFee}( - updateData, - priceIds, - 0, - MAX_UINT64 - ); + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); + PythStructs.PriceFeed[] memory priceFeeds = pyth.parsePriceFeedUpdates{ + value: updateFee + }(updateData, priceIds, 0, MAX_UINT64); - for(uint i = 0; i < numAttestations; i++) { + for (uint i = 0; i < numAttestations; i++) { assertEq(priceFeeds[i].id, priceIds[i]); assertEq(priceFeeds[i].price.price, attestations[i].price); assertEq(priceFeeds[i].price.conf, attestations[i].conf); assertEq(priceFeeds[i].price.expo, attestations[i].expo); - assertEq(priceFeeds[i].price.publishTime, attestations[i].publishTime); + assertEq( + priceFeeds[i].price.publishTime, + attestations[i].publishTime + ); assertEq(priceFeeds[i].emaPrice.price, attestations[i].emaPrice); assertEq(priceFeeds[i].emaPrice.conf, attestations[i].emaConf); assertEq(priceFeeds[i].emaPrice.expo, attestations[i].expo); - assertEq(priceFeeds[i].emaPrice.publishTime, attestations[i].publishTime); + assertEq( + priceFeeds[i].emaPrice.publishTime, + attestations[i].publishTime + ); } } function testParsePriceFeedUpdatesWorksWithUnknownStatus(uint seed) public { setRandSeed(seed); - uint numAttestations = 1 + getRandUint() % 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + uint numAttestations = 1 + (getRandUint() % 10); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); - for(uint i = 0; i < numAttestations; i++) { + for (uint i = 0; i < numAttestations; i++) { attestations[i].status = PriceAttestationStatus.Unknown; } - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); - PythStructs.PriceFeed[] memory priceFeeds = - pyth.parsePriceFeedUpdates{value: updateFee}( - updateData, - priceIds, - 0, - MAX_UINT64 - ); + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); + PythStructs.PriceFeed[] memory priceFeeds = pyth.parsePriceFeedUpdates{ + value: updateFee + }(updateData, priceIds, 0, MAX_UINT64); - for(uint i = 0; i < numAttestations; i++) { + for (uint i = 0; i < numAttestations; i++) { assertEq(priceFeeds[i].id, priceIds[i]); assertEq(priceFeeds[i].price.price, attestations[i].prevPrice); assertEq(priceFeeds[i].price.conf, attestations[i].prevConf); assertEq(priceFeeds[i].price.expo, attestations[i].expo); - assertEq(priceFeeds[i].price.publishTime, attestations[i].prevPublishTime); + assertEq( + priceFeeds[i].price.publishTime, + attestations[i].prevPublishTime + ); assertEq(priceFeeds[i].emaPrice.price, attestations[i].emaPrice); assertEq(priceFeeds[i].emaPrice.conf, attestations[i].emaConf); assertEq(priceFeeds[i].emaPrice.expo, attestations[i].expo); - assertEq(priceFeeds[i].emaPrice.publishTime, attestations[i].prevPublishTime); + assertEq( + priceFeeds[i].emaPrice.publishTime, + attestations[i].prevPublishTime + ); } } - function testParsePriceFeedUpdatesWorksWithRandomDistinctUpdatesInput(uint seed) public { + function testParsePriceFeedUpdatesWorksWithRandomDistinctUpdatesInput( + uint seed + ) public { setRandSeed(seed); - uint numAttestations = 1 + getRandUint() % 30; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + uint numAttestations = 1 + (getRandUint() % 30); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); // Shuffle the attestations for (uint i = 1; i < numAttestations; i++) { - uint swapWith = getRandUint() % (i+1); - (attestations[i], attestations[swapWith]) = (attestations[swapWith], attestations[i]); - (priceIds[i], priceIds[swapWith]) = (priceIds[swapWith], priceIds[i]); + uint swapWith = getRandUint() % (i + 1); + (attestations[i], attestations[swapWith]) = ( + attestations[swapWith], + attestations[i] + ); + (priceIds[i], priceIds[swapWith]) = ( + priceIds[swapWith], + priceIds[i] + ); } // Select only first numSelectedAttestations. numSelectedAttestations will be in [0, numAttestations] uint numSelectedAttestations = getRandUint() % (numAttestations + 1); - PriceAttestation[] memory selectedAttestations = new PriceAttestation[](numSelectedAttestations); - bytes32[] memory selectedPriceIds = new bytes32[](numSelectedAttestations); + PriceAttestation[] memory selectedAttestations = new PriceAttestation[]( + numSelectedAttestations + ); + bytes32[] memory selectedPriceIds = new bytes32[]( + numSelectedAttestations + ); for (uint i = 0; i < numSelectedAttestations; i++) { selectedAttestations[i] = attestations[i]; selectedPriceIds[i] = priceIds[i]; } - // Only parse selected attestations - PythStructs.PriceFeed[] memory priceFeeds = - pyth.parsePriceFeedUpdates{value: updateFee}( - updateData, - selectedPriceIds, - 0, - MAX_UINT64 - ); + // Only parse selected attestations + PythStructs.PriceFeed[] memory priceFeeds = pyth.parsePriceFeedUpdates{ + value: updateFee + }(updateData, selectedPriceIds, 0, MAX_UINT64); - for(uint i = 0; i < numSelectedAttestations; i++) { + for (uint i = 0; i < numSelectedAttestations; i++) { assertEq(priceFeeds[i].id, selectedPriceIds[i]); assertEq(priceFeeds[i].price.expo, selectedAttestations[i].expo); - assertEq(priceFeeds[i].emaPrice.price, selectedAttestations[i].emaPrice); - assertEq(priceFeeds[i].emaPrice.conf, selectedAttestations[i].emaConf); + assertEq( + priceFeeds[i].emaPrice.price, + selectedAttestations[i].emaPrice + ); + assertEq( + priceFeeds[i].emaPrice.conf, + selectedAttestations[i].emaConf + ); assertEq(priceFeeds[i].emaPrice.expo, selectedAttestations[i].expo); - if (selectedAttestations[i].status == PriceAttestationStatus.Trading) { - assertEq(priceFeeds[i].price.price, selectedAttestations[i].price); - assertEq(priceFeeds[i].price.conf, selectedAttestations[i].conf); - assertEq(priceFeeds[i].price.publishTime, selectedAttestations[i].publishTime); - assertEq(priceFeeds[i].emaPrice.publishTime, selectedAttestations[i].publishTime); + if ( + selectedAttestations[i].status == PriceAttestationStatus.Trading + ) { + assertEq( + priceFeeds[i].price.price, + selectedAttestations[i].price + ); + assertEq( + priceFeeds[i].price.conf, + selectedAttestations[i].conf + ); + assertEq( + priceFeeds[i].price.publishTime, + selectedAttestations[i].publishTime + ); + assertEq( + priceFeeds[i].emaPrice.publishTime, + selectedAttestations[i].publishTime + ); } else { - assertEq(priceFeeds[i].price.price, selectedAttestations[i].prevPrice); - assertEq(priceFeeds[i].price.conf, selectedAttestations[i].prevConf); - assertEq(priceFeeds[i].price.publishTime, selectedAttestations[i].prevPublishTime); - assertEq(priceFeeds[i].emaPrice.publishTime, selectedAttestations[i].prevPublishTime); + assertEq( + priceFeeds[i].price.price, + selectedAttestations[i].prevPrice + ); + assertEq( + priceFeeds[i].price.conf, + selectedAttestations[i].prevConf + ); + assertEq( + priceFeeds[i].price.publishTime, + selectedAttestations[i].prevPublishTime + ); + assertEq( + priceFeeds[i].emaPrice.publishTime, + selectedAttestations[i].prevPublishTime + ); } } } - function testParsePriceFeedUpdatesWorksWithOverlappingWithinTimeRangeUpdates() public { + function testParsePriceFeedUpdatesWorksWithOverlappingWithinTimeRangeUpdates() + public + { PriceAttestation[] memory attestations = new PriceAttestation[](2); attestations[0].priceId = bytes32(uint(1)); @@ -218,31 +280,33 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { attestations[1].status = PriceAttestationStatus.Trading; attestations[1].price = 2000; attestations[1].publishTime = 20; - - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); + + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); bytes32[] memory priceIds = new bytes32[](1); priceIds[0] = bytes32(uint(1)); - PythStructs.PriceFeed[] memory priceFeeds = - pyth.parsePriceFeedUpdates{value: updateFee}( - updateData, - priceIds, - 0, - 20 - ); - + PythStructs.PriceFeed[] memory priceFeeds = pyth.parsePriceFeedUpdates{ + value: updateFee + }(updateData, priceIds, 0, 20); + assertEq(priceFeeds.length, 1); assertEq(priceFeeds[0].id, bytes32(uint(1))); - + assertTrue( - (priceFeeds[0].price.price == 1000 && priceFeeds[0].price.publishTime == 10) || - (priceFeeds[0].price.price == 2000 && priceFeeds[0].price.publishTime == 20) + (priceFeeds[0].price.price == 1000 && + priceFeeds[0].price.publishTime == 10) || + (priceFeeds[0].price.price == 2000 && + priceFeeds[0].price.publishTime == 20) ); } - function testParsePriceFeedUpdatesWorksWithOverlappingMixedTimeRangeUpdates() public { + function testParsePriceFeedUpdatesWorksWithOverlappingMixedTimeRangeUpdates() + public + { PriceAttestation[] memory attestations = new PriceAttestation[](2); attestations[0].priceId = bytes32(uint(1)); @@ -254,34 +318,31 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { attestations[1].status = PriceAttestationStatus.Trading; attestations[1].price = 2000; attestations[1].publishTime = 20; - - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); + + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); bytes32[] memory priceIds = new bytes32[](1); priceIds[0] = bytes32(uint(1)); - PythStructs.PriceFeed[] memory priceFeeds = - pyth.parsePriceFeedUpdates{value: updateFee}( - updateData, - priceIds, - 5, - 15 - ); - + PythStructs.PriceFeed[] memory priceFeeds = pyth.parsePriceFeedUpdates{ + value: updateFee + }(updateData, priceIds, 5, 15); + assertEq(priceFeeds.length, 1); assertEq(priceFeeds[0].id, bytes32(uint(1))); assertEq(priceFeeds[0].price.price, 1000); assertEq(priceFeeds[0].price.publishTime, 10); - priceFeeds = - pyth.parsePriceFeedUpdates{value: updateFee}( - updateData, - priceIds, - 15, - 25 - ); - + priceFeeds = pyth.parsePriceFeedUpdates{value: updateFee}( + updateData, + priceIds, + 15, + 25 + ); + assertEq(priceFeeds.length, 1); assertEq(priceFeeds[0].id, bytes32(uint(1))); assertEq(priceFeeds[0].price.price, 2000); @@ -290,18 +351,22 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { function testParsePriceFeedUpdatesRevertsIfUpdateFeeIsNotPaid() public { uint numAttestations = 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); - // Since attestations are not empty the fee should be at least 1 + // Since attestations are not empty the fee should be at least 1 assertGe(updateFee, 1); vm.expectRevert(bytes("insufficient paid fee amount")); - pyth.parsePriceFeedUpdates{value: updateFee-1}( + pyth.parsePriceFeedUpdates{value: updateFee - 1}( updateData, priceIds, 0, @@ -309,19 +374,25 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { ); } - function testParsePriceFeedUpdatesRevertsIfUpdateVAAIsInvalid(uint seed) public { + function testParsePriceFeedUpdatesRevertsIfUpdateVAAIsInvalid( + uint seed + ) public { setRandSeed(seed); - uint numAttestations = 1 + getRandUint() % 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + uint numAttestations = 1 + (getRandUint() % 10); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); + + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); - uint mutPos = getRandUint() % updateData[0].length; - + // mutate the random position by 1 bit - updateData[0][mutPos] = bytes1(uint8(updateData[0][mutPos])^1); + updateData[0][mutPos] = bytes1(uint8(updateData[0][mutPos]) ^ 1); // It might revert due to different wormhole errors vm.expectRevert(); @@ -333,10 +404,14 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { ); } - function testParsePriceFeedUpdatesRevertsIfUpdateSourceChainIsInvalid() public { + function testParsePriceFeedUpdatesRevertsIfUpdateSourceChainIsInvalid() + public + { uint numAttestations = 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); bytes[] memory updateData = new bytes[](1); updateData[0] = generateVaa( @@ -349,7 +424,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { ); uint updateFee = pyth.getUpdateFee(updateData); - + vm.expectRevert(bytes("invalid data source chain/emitter ID")); pyth.parsePriceFeedUpdates{value: updateFee}( updateData, @@ -359,10 +434,14 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { ); } - function testParsePriceFeedUpdatesRevertsIfUpdateSourceAddressIsInvalid() public { + function testParsePriceFeedUpdatesRevertsIfUpdateSourceAddressIsInvalid() + public + { uint numAttestations = 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); bytes[] memory updateData = new bytes[](1); updateData[0] = generateVaa( @@ -375,7 +454,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { ); uint updateFee = pyth.getUpdateFee(updateData); - + vm.expectRevert(bytes("invalid data source chain/emitter ID")); pyth.parsePriceFeedUpdates{value: updateFee}( updateData, @@ -385,7 +464,6 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { ); } - function testParsePriceFeedUpdatesRevertsIfPriceIdNotIncluded() public { PriceAttestation[] memory attestations = new PriceAttestation[](1); @@ -394,14 +472,19 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { attestations[0].price = 1000; attestations[0].publishTime = 10; + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); - bytes32[] memory priceIds = new bytes32[](1); priceIds[0] = bytes32(uint(2)); - vm.expectRevert(bytes("1 or more price feeds are not found in the updateData or they are out of the given time range")); + vm.expectRevert( + bytes( + "1 or more price feeds are not found in the updateData or they are out of the given time range" + ) + ); pyth.parsePriceFeedUpdates{value: updateFee}( updateData, priceIds, @@ -412,17 +495,21 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { function testParsePriceFeedUpdateRevertsIfPricesOutOfTimeRange() public { uint numAttestations = 10; - (bytes32[] memory priceIds, PriceAttestation[] memory attestations) = - generateRandomPriceAttestations(numAttestations); + ( + bytes32[] memory priceIds, + PriceAttestation[] memory attestations + ) = generateRandomPriceAttestations(numAttestations); - for(uint i = 0; i < numAttestations; i++) { + for (uint i = 0; i < numAttestations; i++) { // Set status to Trading so publishTime is used attestations[i].status = PriceAttestationStatus.Trading; - attestations[i].publishTime = uint64(100 + getRandUint() % 101); // All between [100, 200] + attestations[i].publishTime = uint64(100 + (getRandUint() % 101)); // All between [100, 200] } - (bytes[] memory updateData, uint updateFee) = - createBatchedUpdateDataFromAttestations(attestations); + ( + bytes[] memory updateData, + uint updateFee + ) = createBatchedUpdateDataFromAttestations(attestations); // Request for parse within the given time range should work pyth.parsePriceFeedUpdates{value: updateFee}( @@ -431,9 +518,13 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils, RandTestUtils { 100, 200 ); - + // Request for parse after the time range should revert. - vm.expectRevert(bytes("1 or more price feeds are not found in the updateData or they are out of the given time range")); + vm.expectRevert( + bytes( + "1 or more price feeds are not found in the updateData or they are out of the given time range" + ) + ); pyth.parsePriceFeedUpdates{value: updateFee}( updateData, priceIds, diff --git a/ethereum/forge-test/utils/PythTestUtils.t.sol b/ethereum/forge-test/utils/PythTestUtils.t.sol index 771a1365..4e76d8f1 100644 --- a/ethereum/forge-test/utils/PythTestUtils.t.sol +++ b/ethereum/forge-test/utils/PythTestUtils.t.sol @@ -9,20 +9,24 @@ import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; import "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol"; import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; - import "forge-std/Test.sol"; import "./WormholeTestUtils.t.sol"; abstract contract PythTestUtils is Test, WormholeTestUtils { uint16 constant SOURCE_EMITTER_CHAIN_ID = 0x1; - bytes32 constant SOURCE_EMITTER_ADDRESS = 0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b; + bytes32 constant SOURCE_EMITTER_ADDRESS = + 0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b; uint16 constant GOVERNANCE_EMITTER_CHAIN_ID = 0x1; - bytes32 constant GOVERNANCE_EMITTER_ADDRESS = 0x0000000000000000000000000000000000000000000000000000000000000011; + bytes32 constant GOVERNANCE_EMITTER_ADDRESS = + 0x0000000000000000000000000000000000000000000000000000000000000011; function setUpPyth(address wormhole) public returns (address) { PythUpgradable implementation = new PythUpgradable(); - ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), new bytes(0)); + ERC1967Proxy proxy = new ERC1967Proxy( + address(implementation), + new bytes(0) + ); PythUpgradable pyth = PythUpgradable(address(proxy)); pyth.initialize( wormhole, @@ -31,18 +35,11 @@ abstract contract PythTestUtils is Test, WormholeTestUtils { ); // TODO: All the logic below should be moved to the initializer - pyth.addDataSource( - SOURCE_EMITTER_CHAIN_ID, - SOURCE_EMITTER_ADDRESS - ); + pyth.addDataSource(SOURCE_EMITTER_CHAIN_ID, SOURCE_EMITTER_ADDRESS); - pyth.updateSingleUpdateFeeInWei( - 1 - ); + pyth.updateSingleUpdateFeeInWei(1); - pyth.updateValidTimePeriodSeconds( - 60 - ); + pyth.updateValidTimePeriodSeconds(60); pyth.updateGovernanceDataSource( GOVERNANCE_EMITTER_CHAIN_ID, @@ -133,10 +130,8 @@ abstract contract PythTestUtils is Test, WormholeTestUtils { uint64 sequence, uint8 numSigners ) public returns (bytes memory vaa) { - bytes memory payload = generatePriceFeedUpdatePayload( - attestations - ); - + bytes memory payload = generatePriceFeedUpdatePayload(attestations); + vaa = generateVaa( uint32(block.timestamp), SOURCE_EMITTER_CHAIN_ID, @@ -178,14 +173,25 @@ abstract contract PythTestUtils is Test, WormholeTestUtils { } } -contract PythTestUtilsTest is Test, WormholeTestUtils, PythTestUtils, IPythEvents { +contract PythTestUtilsTest is + Test, + WormholeTestUtils, + PythTestUtils, + IPythEvents +{ function testGeneratePriceFeedUpdateVAAWorks() public { - IPyth pyth = IPyth(setUpPyth(setUpWormhole( - 1 // Number of guardians - ))); + IPyth pyth = IPyth( + setUpPyth( + setUpWormhole( + 1 // Number of guardians + ) + ) + ); bytes32[] memory priceIds = new bytes32[](1); - priceIds[0] = 0x0000000000000000000000000000000000000000000000000000000000000222; + priceIds[ + 0 + ] = 0x0000000000000000000000000000000000000000000000000000000000000222; PythStructs.Price[] memory prices = new PythStructs.Price[](1); prices[0] = PythStructs.Price( diff --git a/ethereum/forge-test/utils/RandTestUtils.t.sol b/ethereum/forge-test/utils/RandTestUtils.t.sol index 2dd660c0..b6524466 100644 --- a/ethereum/forge-test/utils/RandTestUtils.t.sol +++ b/ethereum/forge-test/utils/RandTestUtils.t.sol @@ -13,10 +13,12 @@ contract RandTestUtils is Test { } function getRandBytes32() internal returns (bytes32) { - unchecked { randSeed++; } + unchecked { + randSeed++; + } return keccak256(abi.encode(randSeed)); } - + function getRandUint() internal returns (uint) { return uint(getRandBytes32()); } diff --git a/ethereum/forge-test/utils/WormholeTestUtils.t.sol b/ethereum/forge-test/utils/WormholeTestUtils.t.sol index 462661e8..f291942c 100644 --- a/ethereum/forge-test/utils/WormholeTestUtils.t.sol +++ b/ethereum/forge-test/utils/WormholeTestUtils.t.sol @@ -97,7 +97,10 @@ contract WormholeTestUtilsTest is Test, WormholeTestUtils { assertEq(vm.timestamp, 112); assertEq(vm.emitterChainId, 7); - assertEq(vm.emitterAddress, 0x0000000000000000000000000000000000000000000000000000000000000bad); + assertEq( + vm.emitterAddress, + 0x0000000000000000000000000000000000000000000000000000000000000bad + ); assertEq(vm.payload, hex"deadbeaf"); assertEq(vm.signatures.length, 4); } diff --git a/ethereum/migrations/prod-receiver/10_pyth_enable_governance.js b/ethereum/migrations/prod-receiver/10_pyth_enable_governance.js index f5950407..c8b24f8e 100644 --- a/ethereum/migrations/prod-receiver/10_pyth_enable_governance.js +++ b/ethereum/migrations/prod-receiver/10_pyth_enable_governance.js @@ -12,12 +12,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 1.0.0 - * + * * This change: * - Add Governance coming from the Wormhole to manage the contract. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); - await proxy.updateGovernanceDataSource(governanceChainId, governanceEmitter, 0); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); + await proxy.updateGovernanceDataSource( + governanceChainId, + governanceEmitter, + 0 + ); +}; diff --git a/ethereum/migrations/prod-receiver/11_pyth_make_interface_simpler.js b/ethereum/migrations/prod-receiver/11_pyth_make_interface_simpler.js index d9e1dea9..30022ba1 100644 --- a/ethereum/migrations/prod-receiver/11_pyth_make_interface_simpler.js +++ b/ethereum/migrations/prod-receiver/11_pyth_make_interface_simpler.js @@ -12,11 +12,14 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 1.1.0 - * + * * This change: * - Use pyth-sdk-solidity 1.0.0 which simplifies the PriceFeed interface */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod-receiver/1_initial_migration.js b/ethereum/migrations/prod-receiver/1_initial_migration.js index ec354c0e..67ced9da 100644 --- a/ethereum/migrations/prod-receiver/1_initial_migration.js +++ b/ethereum/migrations/prod-receiver/1_initial_migration.js @@ -1,12 +1,12 @@ const Migrations = artifacts.require("Migrations"); -const tdr = require('truffle-deploy-registry'); +const tdr = require("truffle-deploy-registry"); module.exports = async function (deployer, network) { await deployer.deploy(Migrations); let migrationsInstance = await Migrations.deployed(); if (!tdr.isDryRunNetworkName(network)) { - await tdr.appendInstance(migrationsInstance); + await tdr.appendInstance(migrationsInstance); } }; diff --git a/ethereum/migrations/prod-receiver/2_deploy_wormhole_receiver.js b/ethereum/migrations/prod-receiver/2_deploy_wormhole_receiver.js index c4b88b08..adce8178 100644 --- a/ethereum/migrations/prod-receiver/2_deploy_wormhole_receiver.js +++ b/ethereum/migrations/prod-receiver/2_deploy_wormhole_receiver.js @@ -1,7 +1,7 @@ const loadEnv = require("../../scripts/loadEnv"); loadEnv("../../"); -const tdr = require('truffle-deploy-registry'); +const tdr = require("truffle-deploy-registry"); const ReceiverSetup = artifacts.require("ReceiverSetup"); const ReceiverImplementation = artifacts.require("ReceiverImplementation"); @@ -31,7 +31,11 @@ module.exports = async function (deployer, network) { .encodeABI(); // deploy proxy - const wormholeReceiver = await deployer.deploy(WormholeReceiver, ReceiverSetup.address, initData); + const wormholeReceiver = await deployer.deploy( + WormholeReceiver, + ReceiverSetup.address, + initData + ); if (!tdr.isDryRunNetworkName(network)) { await tdr.appendInstance(wormholeReceiver); diff --git a/ethereum/migrations/prod-receiver/3_deploy_pyth.js b/ethereum/migrations/prod-receiver/3_deploy_pyth.js index dfa31ff0..b90e6d25 100644 --- a/ethereum/migrations/prod-receiver/3_deploy_pyth.js +++ b/ethereum/migrations/prod-receiver/3_deploy_pyth.js @@ -8,27 +8,29 @@ const pyth2WormholeChainId = process.env.SOLANA_CHAIN_ID; const pyth2WormholeEmitter = process.env.SOLANA_EMITTER; const { deployProxy } = require("@openzeppelin/truffle-upgrades"); -const tdr = require('truffle-deploy-registry'); +const tdr = require("truffle-deploy-registry"); -console.log("pyth2WormholeEmitter: " + pyth2WormholeEmitter) -console.log("pyth2WormholeChainId: " + pyth2WormholeChainId) +console.log("pyth2WormholeEmitter: " + pyth2WormholeEmitter); +console.log("pyth2WormholeChainId: " + pyth2WormholeChainId); module.exports = async function (deployer, network) { - // Deploy the proxy. This will return an instance of PythUpgradable, - // with the address field corresponding to the fronting ERC1967Proxy. - let proxyInstance = await deployProxy(PythUpgradable, - [ - (await WormholeReceiver.deployed()).address, - pyth2WormholeChainId, - pyth2WormholeEmitter - ], - { deployer }); + // Deploy the proxy. This will return an instance of PythUpgradable, + // with the address field corresponding to the fronting ERC1967Proxy. + let proxyInstance = await deployProxy( + PythUpgradable, + [ + (await WormholeReceiver.deployed()).address, + pyth2WormholeChainId, + pyth2WormholeEmitter, + ], + { deployer } + ); - // Add the ERC1967Proxy address to the PythUpgradable contract's - // entry in the registry. This allows us to call upgradeProxy - // functions with the value of PythUpgradable.deployed().address: - // e.g. upgradeProxy(PythUpgradable.deployed().address, NewImplementation) - if (!tdr.isDryRunNetworkName(network)) { - await tdr.appendInstance(proxyInstance); - } + // Add the ERC1967Proxy address to the PythUpgradable contract's + // entry in the registry. This allows us to call upgradeProxy + // functions with the value of PythUpgradable.deployed().address: + // e.g. upgradeProxy(PythUpgradable.deployed().address, NewImplementation) + if (!tdr.isDryRunNetworkName(network)) { + await tdr.appendInstance(proxyInstance); + } }; diff --git a/ethereum/migrations/prod-receiver/4_pyth_multiple_emitters.js b/ethereum/migrations/prod-receiver/4_pyth_multiple_emitters.js index acc9b06b..4aafc675 100644 --- a/ethereum/migrations/prod-receiver/4_pyth_multiple_emitters.js +++ b/ethereum/migrations/prod-receiver/4_pyth_multiple_emitters.js @@ -9,10 +9,13 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * Adds multiple emitter/chain ID support */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); - await proxy.addDataSource( - await proxy.pyth2WormholeChainId(), - await proxy.pyth2WormholeEmitter() - ); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); + await proxy.addDataSource( + await proxy.pyth2WormholeChainId(), + await proxy.pyth2WormholeEmitter() + ); }; diff --git a/ethereum/migrations/prod-receiver/5_pyth_add_events_and_update_fee.js b/ethereum/migrations/prod-receiver/5_pyth_add_events_and_update_fee.js index 09199bd1..576f8ef1 100644 --- a/ethereum/migrations/prod-receiver/5_pyth_add_events_and_update_fee.js +++ b/ethereum/migrations/prod-receiver/5_pyth_add_events_and_update_fee.js @@ -12,6 +12,9 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * the contract activity. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod-receiver/6_pyth_update_interface_add_latest_methods.js b/ethereum/migrations/prod-receiver/6_pyth_update_interface_add_latest_methods.js index cd971f82..f78477bd 100644 --- a/ethereum/migrations/prod-receiver/6_pyth_update_interface_add_latest_methods.js +++ b/ethereum/migrations/prod-receiver/6_pyth_update_interface_add_latest_methods.js @@ -12,6 +12,9 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * to replace its behaviour in a more elegant way. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod-receiver/7_pyth_make_valid_time_period_configurable.js b/ethereum/migrations/prod-receiver/7_pyth_make_valid_time_period_configurable.js index 27bfef75..7ca71710 100644 --- a/ethereum/migrations/prod-receiver/7_pyth_make_valid_time_period_configurable.js +++ b/ethereum/migrations/prod-receiver/7_pyth_make_valid_time_period_configurable.js @@ -11,16 +11,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * - Makes validTimePeriodSeconds configurable and sets its value. * The value depends on the network latency and block time. So * it is read from the network env file. - * + * * During this upgrade two transaction will be sent and in between validTimePeriodSeconds * will be zero and `getCurrentPrice` will reject. At the time of doing this migration * Pyth is not deployed on mainnet and current hard-coded value is large for some * networks and it's better to reject rather than accept a price old in the past. - * + * */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); - await proxy.updateValidTimePeriodSeconds(validTimePeriodSeconds); -} + await proxy.updateValidTimePeriodSeconds(validTimePeriodSeconds); +}; diff --git a/ethereum/migrations/prod-receiver/8_pyth_update_interface_add_update_if_necessary.js b/ethereum/migrations/prod-receiver/8_pyth_update_interface_add_update_if_necessary.js index 229d02f1..c69d6961 100644 --- a/ethereum/migrations/prod-receiver/8_pyth_update_interface_add_update_if_necessary.js +++ b/ethereum/migrations/prod-receiver/8_pyth_update_interface_add_update_if_necessary.js @@ -7,16 +7,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 0.1.0 - * + * * This change: * - Updates the interface, adds `updatePriceFeedsIfNecessary` that wraps - * `updatePriceFeeds` and rejects if the price update is not necessary. + * `updatePriceFeeds` and rejects if the price update is not necessary. * - Changes some memory modifiers to improve gas efficiency. * - Changes staleness logic to be included in the sdk and bring * more clarity to the existing code. * - Adds version to the contract (which is hard coded) */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod-receiver/9_pyth_add_pythnet_datasource.js b/ethereum/migrations/prod-receiver/9_pyth_add_pythnet_datasource.js index b3c385fa..b9c83941 100644 --- a/ethereum/migrations/prod-receiver/9_pyth_add_pythnet_datasource.js +++ b/ethereum/migrations/prod-receiver/9_pyth_add_pythnet_datasource.js @@ -14,9 +14,6 @@ console.log("pythnetChainId: " + pythnetChainId); * - Adds PythNet data source. */ module.exports = async function (_deployer) { - const proxy = await PythUpgradable.deployed(); - await proxy.addDataSource( - pythnetChainId, - pythnetEmitter, - ); -} + const proxy = await PythUpgradable.deployed(); + await proxy.addDataSource(pythnetChainId, pythnetEmitter); +}; diff --git a/ethereum/migrations/prod/10_pyth_make_interface_simpler.js b/ethereum/migrations/prod/10_pyth_make_interface_simpler.js index 61437129..a73a19ae 100644 --- a/ethereum/migrations/prod/10_pyth_make_interface_simpler.js +++ b/ethereum/migrations/prod/10_pyth_make_interface_simpler.js @@ -7,34 +7,37 @@ const PythUpgradable = artifacts.require("PythUpgradable"); const wormholeChainName = process.env.WORMHOLE_CHAIN_NAME; const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); -const { assert } = require('chai'); +const { assert } = require("chai"); /** * Version 1.1.0 - * + * * This change: * - Use pyth-sdk-solidity 1.0.0 which simplifies the PriceFeed interface */ module.exports = async function (deployer) { - assert(governance.CHAINS[wormholeChainName] !== undefined); + assert(governance.CHAINS[wormholeChainName] !== undefined); - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); - // This step is not needed in new contracts as the contract up to this step is up to date. - // The code is left here to be an example of how to create a governance instruction for upgrade. - // If you wish to create an upgrade step, do it in 2 migration steps. First step should be like below - // that deploys a new contract and creates the governance instruction payload. Second step should - // take the VAA as an env variable and execute it. - - // const proxy = await PythUpgradable.deployed(); - // const newImpl = (await deployProxyImpl(PythUpgradable, { deployer, unsafeSkipStorageCheck: true }, proxy.address)).impl; - // console.log(`New implementation address is: ${newImpl}. Please sign and execute the following encoded ` + - // `governance instruction to upgrade it.`); + // This step is not needed in new contracts as the contract up to this step is up to date. + // The code is left here to be an example of how to create a governance instruction for upgrade. + // If you wish to create an upgrade step, do it in 2 migration steps. First step should be like below + // that deploys a new contract and creates the governance instruction payload. Second step should + // take the VAA as an env variable and execute it. - // const instructionBuffer = new governance.EthereumUpgradeContractInstruction( - // governance.CHAINS[wormholeChainName], - // new governance.HexString20Bytes(newImpl) - // ).serialize(); - // console.log(`Governance instruction: 0x${instructionBuffer.toString('hex')}`); -} + // const proxy = await PythUpgradable.deployed(); + // const newImpl = (await deployProxyImpl(PythUpgradable, { deployer, unsafeSkipStorageCheck: true }, proxy.address)).impl; + // console.log(`New implementation address is: ${newImpl}. Please sign and execute the following encoded ` + + // `governance instruction to upgrade it.`); + + // const instructionBuffer = new governance.EthereumUpgradeContractInstruction( + // governance.CHAINS[wormholeChainName], + // new governance.HexString20Bytes(newImpl) + // ).serialize(); + // console.log(`Governance instruction: 0x${instructionBuffer.toString('hex')}`); +}; diff --git a/ethereum/migrations/prod/11_pyth_renounce_ownership.js b/ethereum/migrations/prod/11_pyth_renounce_ownership.js index ea4311d6..c5dfa24a 100644 --- a/ethereum/migrations/prod/11_pyth_renounce_ownership.js +++ b/ethereum/migrations/prod/11_pyth_renounce_ownership.js @@ -5,11 +5,11 @@ const PythUpgradable = artifacts.require("PythUpgradable"); /** * Version 1.0.0 - 2nd step - * + * * This change: * - Renounce single ownership, the contract will be managed by only the governance */ module.exports = async function (_deployer) { - const proxy = await PythUpgradable.deployed(); - await proxy.renounceOwnership(); -} + const proxy = await PythUpgradable.deployed(); + await proxy.renounceOwnership(); +}; diff --git a/ethereum/migrations/prod/12_pyth_set_fee_1_wei.js b/ethereum/migrations/prod/12_pyth_set_fee_1_wei.js index 115beaad..950d3ae7 100644 --- a/ethereum/migrations/prod/12_pyth_set_fee_1_wei.js +++ b/ethereum/migrations/prod/12_pyth_set_fee_1_wei.js @@ -11,24 +11,24 @@ console.log("Set fee vaa: ", setFeeVaa); const PythUpgradable = artifacts.require("PythUpgradable"); /** - * + * * This change: * - Executes the VAA to set the fee to 1 wei */ module.exports = async function (_deployer) { - const proxy = await PythUpgradable.deployed(); + const proxy = await PythUpgradable.deployed(); - const setFeeInstruction = new governance.SetFeeInstruction( - governance.CHAINS.unset, // All the chains - BigInt(1), - BigInt(0), - ).serialize(); + const setFeeInstruction = new governance.SetFeeInstruction( + governance.CHAINS.unset, // All the chains + BigInt(1), + BigInt(0) + ).serialize(); - console.log("SetFeeInstruction: 0x", setFeeInstruction.toString('hex')); + console.log("SetFeeInstruction: 0x", setFeeInstruction.toString("hex")); - assertVaaPayloadEquals(setFeeVaa, setFeeInstruction); + assertVaaPayloadEquals(setFeeVaa, setFeeInstruction); - await proxy.executeGovernanceInstruction(setFeeVaa); + await proxy.executeGovernanceInstruction(setFeeVaa); - assert.equal((await proxy.singleUpdateFeeInWei()).toString(), "1"); -} + assert.equal((await proxy.singleUpdateFeeInWei()).toString(), "1"); +}; diff --git a/ethereum/migrations/prod/1_initial_migration.js b/ethereum/migrations/prod/1_initial_migration.js index ec354c0e..67ced9da 100644 --- a/ethereum/migrations/prod/1_initial_migration.js +++ b/ethereum/migrations/prod/1_initial_migration.js @@ -1,12 +1,12 @@ const Migrations = artifacts.require("Migrations"); -const tdr = require('truffle-deploy-registry'); +const tdr = require("truffle-deploy-registry"); module.exports = async function (deployer, network) { await deployer.deploy(Migrations); let migrationsInstance = await Migrations.deployed(); if (!tdr.isDryRunNetworkName(network)) { - await tdr.appendInstance(migrationsInstance); + await tdr.appendInstance(migrationsInstance); } }; diff --git a/ethereum/migrations/prod/2_deploy_pyth.js b/ethereum/migrations/prod/2_deploy_pyth.js index 711052d1..8508b3de 100644 --- a/ethereum/migrations/prod/2_deploy_pyth.js +++ b/ethereum/migrations/prod/2_deploy_pyth.js @@ -7,39 +7,38 @@ const pyth2WormholeChainId = process.env.SOLANA_CHAIN_ID; const pyth2WormholeEmitter = process.env.SOLANA_EMITTER; const { deployProxy } = require("@openzeppelin/truffle-upgrades"); -const tdr = require('truffle-deploy-registry'); -const { CONTRACTS } = require('@certusone/wormhole-sdk'); +const tdr = require("truffle-deploy-registry"); +const { CONTRACTS } = require("@certusone/wormhole-sdk"); const { assert } = require("chai"); -console.log("pyth2WormholeEmitter: " + pyth2WormholeEmitter) -console.log("pyth2WormholeChainId: " + pyth2WormholeChainId) +console.log("pyth2WormholeEmitter: " + pyth2WormholeEmitter); +console.log("pyth2WormholeChainId: " + pyth2WormholeChainId); module.exports = async function (deployer, network) { - const cluster = process.env.CLUSTER; - const chainName = process.env.WORMHOLE_CHAIN_NAME; + const cluster = process.env.CLUSTER; + const chainName = process.env.WORMHOLE_CHAIN_NAME; - assert(cluster !== undefined && chainName !== undefined); + assert(cluster !== undefined && chainName !== undefined); - const wormholeBridgeAddress = CONTRACTS[cluster.toUpperCase()][chainName].core; - assert(wormholeBridgeAddress !== undefined); + const wormholeBridgeAddress = + CONTRACTS[cluster.toUpperCase()][chainName].core; + assert(wormholeBridgeAddress !== undefined); - console.log("Wormhole bridge address: " + wormholeBridgeAddress) + console.log("Wormhole bridge address: " + wormholeBridgeAddress); - // Deploy the proxy. This will return an instance of PythUpgradable, - // with the address field corresponding to the fronting ERC1967Proxy. - let proxyInstance = await deployProxy(PythUpgradable, - [ - wormholeBridgeAddress, - pyth2WormholeChainId, - pyth2WormholeEmitter - ], - { deployer }); + // Deploy the proxy. This will return an instance of PythUpgradable, + // with the address field corresponding to the fronting ERC1967Proxy. + let proxyInstance = await deployProxy( + PythUpgradable, + [wormholeBridgeAddress, pyth2WormholeChainId, pyth2WormholeEmitter], + { deployer } + ); - // Add the ERC1967Proxy address to the PythUpgradable contract's - // entry in the registry. This allows us to call upgradeProxy - // functions with the value of PythUpgradable.deployed().address: - // e.g. upgradeProxy(PythUpgradable.deployed().address, NewImplementation) - if (!tdr.isDryRunNetworkName(network)) { - await tdr.appendInstance(proxyInstance); - } + // Add the ERC1967Proxy address to the PythUpgradable contract's + // entry in the registry. This allows us to call upgradeProxy + // functions with the value of PythUpgradable.deployed().address: + // e.g. upgradeProxy(PythUpgradable.deployed().address, NewImplementation) + if (!tdr.isDryRunNetworkName(network)) { + await tdr.appendInstance(proxyInstance); + } }; diff --git a/ethereum/migrations/prod/3_pyth_multiple_emitters.js b/ethereum/migrations/prod/3_pyth_multiple_emitters.js index acc9b06b..4aafc675 100644 --- a/ethereum/migrations/prod/3_pyth_multiple_emitters.js +++ b/ethereum/migrations/prod/3_pyth_multiple_emitters.js @@ -9,10 +9,13 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * Adds multiple emitter/chain ID support */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); - await proxy.addDataSource( - await proxy.pyth2WormholeChainId(), - await proxy.pyth2WormholeEmitter() - ); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); + await proxy.addDataSource( + await proxy.pyth2WormholeChainId(), + await proxy.pyth2WormholeEmitter() + ); }; diff --git a/ethereum/migrations/prod/4_pyth_add_events_and_update_fee.js b/ethereum/migrations/prod/4_pyth_add_events_and_update_fee.js index 09199bd1..576f8ef1 100644 --- a/ethereum/migrations/prod/4_pyth_add_events_and_update_fee.js +++ b/ethereum/migrations/prod/4_pyth_add_events_and_update_fee.js @@ -12,6 +12,9 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * the contract activity. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod/5_pyth_update_interface_add_latest_methods.js b/ethereum/migrations/prod/5_pyth_update_interface_add_latest_methods.js index cd971f82..f78477bd 100644 --- a/ethereum/migrations/prod/5_pyth_update_interface_add_latest_methods.js +++ b/ethereum/migrations/prod/5_pyth_update_interface_add_latest_methods.js @@ -12,6 +12,9 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * to replace its behaviour in a more elegant way. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod/6_pyth_make_valid_time_period_configurable.js b/ethereum/migrations/prod/6_pyth_make_valid_time_period_configurable.js index 27bfef75..7ca71710 100644 --- a/ethereum/migrations/prod/6_pyth_make_valid_time_period_configurable.js +++ b/ethereum/migrations/prod/6_pyth_make_valid_time_period_configurable.js @@ -11,16 +11,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * - Makes validTimePeriodSeconds configurable and sets its value. * The value depends on the network latency and block time. So * it is read from the network env file. - * + * * During this upgrade two transaction will be sent and in between validTimePeriodSeconds * will be zero and `getCurrentPrice` will reject. At the time of doing this migration * Pyth is not deployed on mainnet and current hard-coded value is large for some * networks and it's better to reject rather than accept a price old in the past. - * + * */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); - await proxy.updateValidTimePeriodSeconds(validTimePeriodSeconds); -} + await proxy.updateValidTimePeriodSeconds(validTimePeriodSeconds); +}; diff --git a/ethereum/migrations/prod/7_pyth_update_interface_add_update_if_necessary.js b/ethereum/migrations/prod/7_pyth_update_interface_add_update_if_necessary.js index 229d02f1..c69d6961 100644 --- a/ethereum/migrations/prod/7_pyth_update_interface_add_update_if_necessary.js +++ b/ethereum/migrations/prod/7_pyth_update_interface_add_update_if_necessary.js @@ -7,16 +7,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 0.1.0 - * + * * This change: * - Updates the interface, adds `updatePriceFeedsIfNecessary` that wraps - * `updatePriceFeeds` and rejects if the price update is not necessary. + * `updatePriceFeeds` and rejects if the price update is not necessary. * - Changes some memory modifiers to improve gas efficiency. * - Changes staleness logic to be included in the sdk and bring * more clarity to the existing code. * - Adds version to the contract (which is hard coded) */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/prod/8_pyth_add_pythnet_datasource.js b/ethereum/migrations/prod/8_pyth_add_pythnet_datasource.js index b3c385fa..b9c83941 100644 --- a/ethereum/migrations/prod/8_pyth_add_pythnet_datasource.js +++ b/ethereum/migrations/prod/8_pyth_add_pythnet_datasource.js @@ -14,9 +14,6 @@ console.log("pythnetChainId: " + pythnetChainId); * - Adds PythNet data source. */ module.exports = async function (_deployer) { - const proxy = await PythUpgradable.deployed(); - await proxy.addDataSource( - pythnetChainId, - pythnetEmitter, - ); -} + const proxy = await PythUpgradable.deployed(); + await proxy.addDataSource(pythnetChainId, pythnetEmitter); +}; diff --git a/ethereum/migrations/prod/9_pyth_enable_governance.js b/ethereum/migrations/prod/9_pyth_enable_governance.js index fed814b5..923f1380 100644 --- a/ethereum/migrations/prod/9_pyth_enable_governance.js +++ b/ethereum/migrations/prod/9_pyth_enable_governance.js @@ -12,13 +12,20 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 1.0.0 - 1st step - * + * * This change: * - Moves away single ownership to Governance coming from the Wormhole to * manage the contract. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); - await proxy.updateGovernanceDataSource(governanceChainId, governanceEmitter, 0); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); + await proxy.updateGovernanceDataSource( + governanceChainId, + governanceEmitter, + 0 + ); +}; diff --git a/ethereum/migrations/test/10_pyth_renounce_ownership.js b/ethereum/migrations/test/10_pyth_renounce_ownership.js index 2d2e5043..76c23554 100644 --- a/ethereum/migrations/test/10_pyth_renounce_ownership.js +++ b/ethereum/migrations/test/10_pyth_renounce_ownership.js @@ -12,11 +12,11 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 1.0.0 - 2nd step - * + * * This change: * - Renounce single ownership, the contract will be managed by only the governance */ module.exports = async function (_deployer) { - const proxy = await PythUpgradable.deployed(); - await proxy.renounceOwnership(); -} + const proxy = await PythUpgradable.deployed(); + await proxy.renounceOwnership(); +}; diff --git a/ethereum/migrations/test/11_pyth_make_interface_simpler.js b/ethereum/migrations/test/11_pyth_make_interface_simpler.js index c7672a99..87694f95 100644 --- a/ethereum/migrations/test/11_pyth_make_interface_simpler.js +++ b/ethereum/migrations/test/11_pyth_make_interface_simpler.js @@ -11,26 +11,34 @@ const governanceEmitter = process.env.GOVERNANCE_EMITTER; console.log("governanceEmitter: " + governanceEmitter); console.log("governanceChainId: " + governanceChainId); -const { deployProxyImpl } = require('@openzeppelin/truffle-upgrades/dist/utils'); +const { + deployProxyImpl, +} = require("@openzeppelin/truffle-upgrades/dist/utils"); /** * Version 1.1.0 - * + * * This change: * - Use pyth-sdk-solidity 1.0.0 which simplifies the PriceFeed interface */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - const newImpl = (await deployProxyImpl(PythUpgradable, { deployer, unsafeSkipStorageCheck: true }, proxy.address)).impl; - console.log(newImpl); + const proxy = await PythUpgradable.deployed(); + const newImpl = ( + await deployProxyImpl( + PythUpgradable, + { deployer, unsafeSkipStorageCheck: true }, + proxy.address + ) + ).impl; + console.log(newImpl); - await proxy.executeGovernanceInstruction( - createLocalnetGovernanceVaa( - new governance.EthereumUpgradeContractInstruction( - governance.CHAINS.ethereum, - new governance.HexString20Bytes(newImpl) - ).serialize(), - 1, - ) - ); -} + await proxy.executeGovernanceInstruction( + createLocalnetGovernanceVaa( + new governance.EthereumUpgradeContractInstruction( + governance.CHAINS.ethereum, + new governance.HexString20Bytes(newImpl) + ).serialize(), + 1 + ) + ); +}; diff --git a/ethereum/migrations/test/12_pyth_set_fee_1_wei.js b/ethereum/migrations/test/12_pyth_set_fee_1_wei.js index 16ef5152..1b3ba51d 100644 --- a/ethereum/migrations/test/12_pyth_set_fee_1_wei.js +++ b/ethereum/migrations/test/12_pyth_set_fee_1_wei.js @@ -6,32 +6,28 @@ const { assert } = require("chai"); const loadEnv = require("../../scripts/loadEnv"); loadEnv("../../"); - const PythUpgradable = artifacts.require("PythUpgradable"); /** - * + * * This change: * - Executes the VAA to set the fee to 1 wei */ module.exports = async function (_deployer) { - const setFeeInstruction = new governance.SetFeeInstruction( - governance.CHAINS.unset, // All the chains - BigInt(1), - BigInt(0), - ).serialize(); + const setFeeInstruction = new governance.SetFeeInstruction( + governance.CHAINS.unset, // All the chains + BigInt(1), + BigInt(0) + ).serialize(); - console.log("SetFeeInstruction: 0x", setFeeInstruction.toString('hex')); + console.log("SetFeeInstruction: 0x", setFeeInstruction.toString("hex")); - const setFeeVaa = createLocalnetGovernanceVaa( - setFeeInstruction, - 2 - ); + const setFeeVaa = createLocalnetGovernanceVaa(setFeeInstruction, 2); - assertVaaPayloadEquals(setFeeVaa, setFeeInstruction); + assertVaaPayloadEquals(setFeeVaa, setFeeInstruction); - const proxy = await PythUpgradable.deployed(); - await proxy.executeGovernanceInstruction(setFeeVaa); + const proxy = await PythUpgradable.deployed(); + await proxy.executeGovernanceInstruction(setFeeVaa); - assert.equal((await proxy.singleUpdateFeeInWei()).toString(), "1"); -} + assert.equal((await proxy.singleUpdateFeeInWei()).toString(), "1"); +}; diff --git a/ethereum/migrations/test/1_initial_migration.js b/ethereum/migrations/test/1_initial_migration.js index c8e518d8..6fc7cd72 100644 --- a/ethereum/migrations/test/1_initial_migration.js +++ b/ethereum/migrations/test/1_initial_migration.js @@ -1,6 +1,6 @@ var Migrations = artifacts.require("Migrations"); -module.exports = function(deployer) { - // Deploy the Migrations contract as our only task - deployer.deploy(Migrations); -}; \ No newline at end of file +module.exports = function (deployer) { + // Deploy the Migrations contract as our only task + deployer.deploy(Migrations); +}; diff --git a/ethereum/migrations/test/2_deploy_wormhole.js b/ethereum/migrations/test/2_deploy_wormhole.js index e222e55c..a17cf64b 100644 --- a/ethereum/migrations/test/2_deploy_wormhole.js +++ b/ethereum/migrations/test/2_deploy_wormhole.js @@ -12,22 +12,24 @@ const governanceChainId = process.env.INIT_GOV_CHAIN_ID; const governanceContract = process.env.INIT_GOV_CONTRACT; // bytes32 module.exports = async function (deployer) { - // deploy setup - await deployer.deploy(Setup); + // deploy setup + await deployer.deploy(Setup); - // deploy implementation - await deployer.deploy(Implementation); + // deploy implementation + await deployer.deploy(Implementation); - // encode initialisation data - const setup = new web3.eth.Contract(Setup.abi, Setup.address); - const initData = setup.methods.setup( - Implementation.address, - initialSigners, - chainId, - governanceChainId, - governanceContract - ).encodeABI(); + // encode initialisation data + const setup = new web3.eth.Contract(Setup.abi, Setup.address); + const initData = setup.methods + .setup( + Implementation.address, + initialSigners, + chainId, + governanceChainId, + governanceContract + ) + .encodeABI(); - // deploy proxy - await deployer.deploy(Wormhole, Setup.address, initData); + // deploy proxy + await deployer.deploy(Wormhole, Setup.address, initData); }; diff --git a/ethereum/migrations/test/3_deploy_pyth.js b/ethereum/migrations/test/3_deploy_pyth.js index ccaaaf5d..8cc5db54 100644 --- a/ethereum/migrations/test/3_deploy_pyth.js +++ b/ethereum/migrations/test/3_deploy_pyth.js @@ -11,15 +11,20 @@ const pyth2WormholeEmitter = process.env.SOLANA_EMITTER; const { deployProxy } = require("@openzeppelin/truffle-upgrades"); -console.log("Deploying Pyth with emitter", pyth2WormholeEmitter.toString("hex")) +console.log( + "Deploying Pyth with emitter", + pyth2WormholeEmitter.toString("hex") +); module.exports = async function (deployer) { - // Deploy the proxy script - await deployProxy(PythUpgradable, - [ - (await Wormhole.deployed()).address, - pyth2WormholeChainId, - pyth2WormholeEmitter - ], - { deployer }); + // Deploy the proxy script + await deployProxy( + PythUpgradable, + [ + (await Wormhole.deployed()).address, + pyth2WormholeChainId, + pyth2WormholeEmitter, + ], + { deployer } + ); }; diff --git a/ethereum/migrations/test/4_pyth_multiple_emitters.js b/ethereum/migrations/test/4_pyth_multiple_emitters.js index acc9b06b..4aafc675 100644 --- a/ethereum/migrations/test/4_pyth_multiple_emitters.js +++ b/ethereum/migrations/test/4_pyth_multiple_emitters.js @@ -9,10 +9,13 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * Adds multiple emitter/chain ID support */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); - await proxy.addDataSource( - await proxy.pyth2WormholeChainId(), - await proxy.pyth2WormholeEmitter() - ); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); + await proxy.addDataSource( + await proxy.pyth2WormholeChainId(), + await proxy.pyth2WormholeEmitter() + ); }; diff --git a/ethereum/migrations/test/5_pyth_add_events_and_update_fee.js b/ethereum/migrations/test/5_pyth_add_events_and_update_fee.js index 09199bd1..576f8ef1 100644 --- a/ethereum/migrations/test/5_pyth_add_events_and_update_fee.js +++ b/ethereum/migrations/test/5_pyth_add_events_and_update_fee.js @@ -12,6 +12,9 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * the contract activity. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/test/6_pyth_update_interface_add_latest_methods.js b/ethereum/migrations/test/6_pyth_update_interface_add_latest_methods.js index cd971f82..f78477bd 100644 --- a/ethereum/migrations/test/6_pyth_update_interface_add_latest_methods.js +++ b/ethereum/migrations/test/6_pyth_update_interface_add_latest_methods.js @@ -12,6 +12,9 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * to replace its behaviour in a more elegant way. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/test/7_pyth_make_valid_time_period_configurable.js b/ethereum/migrations/test/7_pyth_make_valid_time_period_configurable.js index 27bfef75..7ca71710 100644 --- a/ethereum/migrations/test/7_pyth_make_valid_time_period_configurable.js +++ b/ethereum/migrations/test/7_pyth_make_valid_time_period_configurable.js @@ -11,16 +11,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); * - Makes validTimePeriodSeconds configurable and sets its value. * The value depends on the network latency and block time. So * it is read from the network env file. - * + * * During this upgrade two transaction will be sent and in between validTimePeriodSeconds * will be zero and `getCurrentPrice` will reject. At the time of doing this migration * Pyth is not deployed on mainnet and current hard-coded value is large for some * networks and it's better to reject rather than accept a price old in the past. - * + * */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); - await proxy.updateValidTimePeriodSeconds(validTimePeriodSeconds); -} + await proxy.updateValidTimePeriodSeconds(validTimePeriodSeconds); +}; diff --git a/ethereum/migrations/test/8_pyth_update_interface_add_update_if_necessary.js b/ethereum/migrations/test/8_pyth_update_interface_add_update_if_necessary.js index 229d02f1..c69d6961 100644 --- a/ethereum/migrations/test/8_pyth_update_interface_add_update_if_necessary.js +++ b/ethereum/migrations/test/8_pyth_update_interface_add_update_if_necessary.js @@ -7,16 +7,19 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 0.1.0 - * + * * This change: * - Updates the interface, adds `updatePriceFeedsIfNecessary` that wraps - * `updatePriceFeeds` and rejects if the price update is not necessary. + * `updatePriceFeeds` and rejects if the price update is not necessary. * - Changes some memory modifiers to improve gas efficiency. * - Changes staleness logic to be included in the sdk and bring * more clarity to the existing code. * - Adds version to the contract (which is hard coded) */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); +}; diff --git a/ethereum/migrations/test/9_pyth_enable_governance.js b/ethereum/migrations/test/9_pyth_enable_governance.js index fed814b5..923f1380 100644 --- a/ethereum/migrations/test/9_pyth_enable_governance.js +++ b/ethereum/migrations/test/9_pyth_enable_governance.js @@ -12,13 +12,20 @@ const { upgradeProxy } = require("@openzeppelin/truffle-upgrades"); /** * Version 1.0.0 - 1st step - * + * * This change: * - Moves away single ownership to Governance coming from the Wormhole to * manage the contract. */ module.exports = async function (deployer) { - const proxy = await PythUpgradable.deployed(); - await upgradeProxy(proxy.address, PythUpgradable, { deployer, unsafeSkipStorageCheck: true }); - await proxy.updateGovernanceDataSource(governanceChainId, governanceEmitter, 0); -} + const proxy = await PythUpgradable.deployed(); + await upgradeProxy(proxy.address, PythUpgradable, { + deployer, + unsafeSkipStorageCheck: true, + }); + await proxy.updateGovernanceDataSource( + governanceChainId, + governanceEmitter, + 0 + ); +}; diff --git a/ethereum/mine.js b/ethereum/mine.js index d151c73c..88a21544 100644 --- a/ethereum/mine.js +++ b/ethereum/mine.js @@ -4,33 +4,36 @@ */ advanceBlock = () => { - return new Promise((resolve, reject) => { - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "evm_mine", - id: new Date().getTime() - }, (err, result) => { - if (err) { - return reject(err); - } - const newBlockHash = web3.eth.getBlock('latest').hash; + return new Promise((resolve, reject) => { + web3.currentProvider.send( + { + jsonrpc: "2.0", + method: "evm_mine", + id: new Date().getTime(), + }, + (err, result) => { + if (err) { + return reject(err); + } + const newBlockHash = web3.eth.getBlock("latest").hash; - return resolve(newBlockHash) - }); - }); -} + return resolve(newBlockHash); + } + ); + }); +}; function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } -module.exports = function(callback) { - const fn = async () => { - while (true) { - console.log(await advanceBlock()); - await sleep(1000); - } +module.exports = function (callback) { + const fn = async () => { + while (true) { + console.log(await advanceBlock()); + await sleep(1000); } + }; - fn().catch(reason => console.error(reason)) -} + fn().catch((reason) => console.error(reason)); +}; diff --git a/ethereum/networks/1.json b/ethereum/networks/1.json index 3539d238..9af9bdc0 100644 --- a/ethereum/networks/1.json +++ b/ethereum/networks/1.json @@ -8,4 +8,4 @@ "address": "0x4305FB66699C3B2702D4d05CF36551390A4c69C6", "transactionHash": "0xa5d57f2a33f7890850ffe9ce867ffb169d59c6ec2e96d1902363d1f670302892" } -] \ No newline at end of file +] diff --git a/ethereum/networks/10.json b/ethereum/networks/10.json index e9c2fb53..c73f2209 100644 --- a/ethereum/networks/10.json +++ b/ethereum/networks/10.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0xfa85e9031cc6f186079eb1721376cad2f71a3bc8dffdc40b22875be38b2629f8" } -] \ No newline at end of file +] diff --git a/ethereum/networks/1313161554.json b/ethereum/networks/1313161554.json index bc2d06b1..c2936fc2 100644 --- a/ethereum/networks/1313161554.json +++ b/ethereum/networks/1313161554.json @@ -8,4 +8,4 @@ "address": "0xF89C7b475821EC3fDC2dC8099032c05c6c0c9AB9", "transactionHash": "0x450d5c254a196cf2432f742f3b74e4a8d93b0e32794f9c8ed725d6e7d515fdef" } -] \ No newline at end of file +] diff --git a/ethereum/networks/1313161555.json b/ethereum/networks/1313161555.json index 5a0f8e91..9892f552 100644 --- a/ethereum/networks/1313161555.json +++ b/ethereum/networks/1313161555.json @@ -8,4 +8,4 @@ "address": "0x4305FB66699C3B2702D4d05CF36551390A4c69C6", "transactionHash": "0xcb2ad36f327e73f0aa55c8b18fd87881c5d5d83c324fdbfe133c471759a54825" } -] \ No newline at end of file +] diff --git a/ethereum/networks/137.json b/ethereum/networks/137.json index d31b54d3..a06133bb 100644 --- a/ethereum/networks/137.json +++ b/ethereum/networks/137.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0xb90ac65ea4fbfa6f9f6c5a3652bd0a2f29f185283212f9510f20b8ad7a3f3be1" } -] \ No newline at end of file +] diff --git a/ethereum/networks/250.json b/ethereum/networks/250.json index 95232058..351438c4 100644 --- a/ethereum/networks/250.json +++ b/ethereum/networks/250.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0xcdf870767c72e384c9cc70d8843e6b2eb5d412058bd3040c6a6cf3711c1297f9" } -] \ No newline at end of file +] diff --git a/ethereum/networks/3.json b/ethereum/networks/3.json index dd8c7439..ab61ac45 100644 --- a/ethereum/networks/3.json +++ b/ethereum/networks/3.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0x78f8960b670a27f63a846ff99f25dc64f7c2fc8b843c7f166abe64f24a5cb87e" } -] \ No newline at end of file +] diff --git a/ethereum/networks/4002.json b/ethereum/networks/4002.json index 562a7e59..315d9d94 100644 --- a/ethereum/networks/4002.json +++ b/ethereum/networks/4002.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0x0261874d2b5cd39e4a6b49276d13089d80e0a5a43efa82fc9cab9986633bd67e" } -] \ No newline at end of file +] diff --git a/ethereum/networks/420.json b/ethereum/networks/420.json index 17fef08e..c7a748e6 100644 --- a/ethereum/networks/420.json +++ b/ethereum/networks/420.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0x89c663594a3d7468ab799b75b6424586c6bc150720584a952d8610165ba6c302" } -] \ No newline at end of file +] diff --git a/ethereum/networks/42161.json b/ethereum/networks/42161.json index ab6dd427..9751ad4c 100644 --- a/ethereum/networks/42161.json +++ b/ethereum/networks/42161.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0x79273fba06b87496db4ceccd65ff2106c1807ff82ec4a53f75ba83d48f8fe3e1" } -] \ No newline at end of file +] diff --git a/ethereum/networks/43113.json b/ethereum/networks/43113.json index 92f2d7ac..52ab69f2 100644 --- a/ethereum/networks/43113.json +++ b/ethereum/networks/43113.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0xf9f70f6671e8a5cbfcc04a93344260674aeb129cf6b3d7278f8c4712aea04f77" } -] \ No newline at end of file +] diff --git a/ethereum/networks/43114.json b/ethereum/networks/43114.json index 36636e94..6364c36d 100644 --- a/ethereum/networks/43114.json +++ b/ethereum/networks/43114.json @@ -8,4 +8,4 @@ "address": "0x4305FB66699C3B2702D4d05CF36551390A4c69C6", "transactionHash": "0xf843fe900c4d2e412830c42949d39dd52200918a20394d3661fd1b5980112c08" } -] \ No newline at end of file +] diff --git a/ethereum/networks/5.json b/ethereum/networks/5.json index a0c42954..05d01747 100644 --- a/ethereum/networks/5.json +++ b/ethereum/networks/5.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0x04cfb919fca33bf75dc7626a1ede69fde0a409e9eb26f1e6dac1b7702f92d567" } -] \ No newline at end of file +] diff --git a/ethereum/networks/56.json b/ethereum/networks/56.json index dee5aec9..a419a50f 100644 --- a/ethereum/networks/56.json +++ b/ethereum/networks/56.json @@ -8,4 +8,4 @@ "address": "0x4D7E825f80bDf85e913E0DD2A2D54927e9dE1594", "transactionHash": "0x2529280562720c28983eefbb9cb6d3d9334b2c315aaf43ff5d81e7914f097c85" } -] \ No newline at end of file +] diff --git a/ethereum/networks/80001.json b/ethereum/networks/80001.json index cf469672..913bc378 100644 --- a/ethereum/networks/80001.json +++ b/ethereum/networks/80001.json @@ -8,4 +8,4 @@ "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", "transactionHash": "0xad07603dc3bdf109bdffb95097303b5cb6c254e9cd13538d8f73edcebc525ebf" } -] \ No newline at end of file +] diff --git a/ethereum/networks/97.json b/ethereum/networks/97.json index 537a24de..830fcd1c 100644 --- a/ethereum/networks/97.json +++ b/ethereum/networks/97.json @@ -8,4 +8,4 @@ "address": "0xd7308b14BF4008e7C7196eC35610B1427C5702EA", "transactionHash": "0xaf87d230967901c4122ae191647efb5016033d2b4130e3d174ea136633f2fb8f" } -] \ No newline at end of file +] diff --git a/ethereum/scripts/assertVaaPayloadEquals.js b/ethereum/scripts/assertVaaPayloadEquals.js index 81bd325d..30971816 100644 --- a/ethereum/scripts/assertVaaPayloadEquals.js +++ b/ethereum/scripts/assertVaaPayloadEquals.js @@ -1,16 +1,26 @@ - -const { importCoreWasm, setDefaultWasm } = require("@certusone/wormhole-sdk-wasm"); +const { + importCoreWasm, + setDefaultWasm, +} = require("@certusone/wormhole-sdk-wasm"); setDefaultWasm("node"); const { assert } = require("chai"); -module.exports = async function assertVaaPayloadEquals(vaaHexString, expectedPayloadBuffer) { +module.exports = async function assertVaaPayloadEquals( + vaaHexString, + expectedPayloadBuffer +) { const { parse_vaa } = await importCoreWasm(); if (vaaHexString.startsWith("0x")) { vaaHexString = vaaHexString.substring(2); } - const vaaPayload = Buffer.from(parse_vaa(Buffer.from(vaaHexString, 'hex')).payload); + const vaaPayload = Buffer.from( + parse_vaa(Buffer.from(vaaHexString, "hex")).payload + ); - assert(expectedPayloadBuffer.equals(vaaPayload), "The VAA payload is not equal to the expected payload"); -} + assert( + expectedPayloadBuffer.equals(vaaPayload), + "The VAA payload is not equal to the expected payload" + ); +}; diff --git a/ethereum/scripts/createLocalnetGovernanceVaa.js b/ethereum/scripts/createLocalnetGovernanceVaa.js index d50c6e42..525ac81e 100644 --- a/ethereum/scripts/createLocalnetGovernanceVaa.js +++ b/ethereum/scripts/createLocalnetGovernanceVaa.js @@ -2,111 +2,102 @@ const abi = require("web3-eth-abi"); const utils = require("web3-utils"); const elliptic = require("elliptic"); -const testSigner1PK = "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"; +const testSigner1PK = + "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"; const testGovernanceChain = "1"; // ethereum -const testGovernanceEmitter = "0x0000000000000000000000000000000000000000000000000000000000001234"; +const testGovernanceEmitter = + "0x0000000000000000000000000000000000000000000000000000000000001234"; function zeroPadBytes(value, length) { - while (value.length < 2 * length) { - value = "0" + value; - } - return value; + while (value.length < 2 * length) { + value = "0" + value; + } + return value; } const signAndEncodeVM = function ( - timestamp, - nonce, - emitterChainId, - emitterAddress, - sequence, - data, - signers, - guardianSetIndex, - consistencyLevel + timestamp, + nonce, + emitterChainId, + emitterAddress, + sequence, + data, + signers, + guardianSetIndex, + consistencyLevel ) { - const body = [ - abi - .encodeParameter("uint32", timestamp) - .substring(2 + (64 - 8)), - abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)), - abi - .encodeParameter("uint16", emitterChainId) - .substring(2 + (64 - 4)), - abi.encodeParameter("bytes32", emitterAddress).substring(2), - abi - .encodeParameter("uint64", sequence) - .substring(2 + (64 - 16)), - abi - .encodeParameter("uint8", consistencyLevel) - .substring(2 + (64 - 2)), - data.substr(2), + const body = [ + abi.encodeParameter("uint32", timestamp).substring(2 + (64 - 8)), + abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)), + abi.encodeParameter("uint16", emitterChainId).substring(2 + (64 - 4)), + abi.encodeParameter("bytes32", emitterAddress).substring(2), + abi.encodeParameter("uint64", sequence).substring(2 + (64 - 16)), + abi.encodeParameter("uint8", consistencyLevel).substring(2 + (64 - 2)), + data.substr(2), + ]; + + const hash = utils.soliditySha3(utils.soliditySha3("0x" + body.join(""))); + + let signatures = ""; + + for (let i in signers) { + const ec = new elliptic.ec("secp256k1"); + const key = ec.keyFromPrivate(signers[i]); + const signature = key.sign(hash.substr(2), { canonical: true }); + + const packSig = [ + abi.encodeParameter("uint8", i).substring(2 + (64 - 2)), + zeroPadBytes(signature.r.toString(16), 32), + zeroPadBytes(signature.s.toString(16), 32), + abi + .encodeParameter("uint8", signature.recoveryParam) + .substr(2 + (64 - 2)), ]; - const hash = utils.soliditySha3( - utils.soliditySha3("0x" + body.join("")) - ); + signatures += packSig.join(""); + } - let signatures = ""; + const vm = [ + abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)), + abi.encodeParameter("uint32", guardianSetIndex).substring(2 + (64 - 8)), + abi.encodeParameter("uint8", signers.length).substring(2 + (64 - 2)), - for (let i in signers) { - const ec = new elliptic.ec("secp256k1"); - const key = ec.keyFromPrivate(signers[i]); - const signature = key.sign(hash.substr(2), { canonical: true }); + signatures, + body.join(""), + ].join(""); - const packSig = [ - abi.encodeParameter("uint8", i).substring(2 + (64 - 2)), - zeroPadBytes(signature.r.toString(16), 32), - zeroPadBytes(signature.s.toString(16), 32), - abi - .encodeParameter("uint8", signature.recoveryParam) - .substr(2 + (64 - 2)), - ]; - - signatures += packSig.join(""); - } - - const vm = [ - abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)), - abi - .encodeParameter("uint32", guardianSetIndex) - .substring(2 + (64 - 8)), - abi - .encodeParameter("uint8", signers.length) - .substring(2 + (64 - 2)), - - signatures, - body.join(""), - ].join(""); - - return vm; + return vm; }; function createVAAFromUint8Array( - dataBuffer, - emitterChainId, - emitterAddress, - sequence, + dataBuffer, + emitterChainId, + emitterAddress, + sequence ) { - const dataHex = "0x" + dataBuffer.toString("hex"); - return "0x" + signAndEncodeVM( - 0, - 0, - emitterChainId, - emitterAddress, - sequence, - dataHex, - [testSigner1PK], - 0, - 0 - ); + const dataHex = "0x" + dataBuffer.toString("hex"); + return ( + "0x" + + signAndEncodeVM( + 0, + 0, + emitterChainId, + emitterAddress, + sequence, + dataHex, + [testSigner1PK], + 0, + 0 + ) + ); } module.exports = function createLocalnetGovernanceVAA(dataBuffer, sequence) { - return createVAAFromUint8Array( - dataBuffer, - testGovernanceChain, - testGovernanceEmitter, - sequence - ); -} + return createVAAFromUint8Array( + dataBuffer, + testGovernanceChain, + testGovernanceEmitter, + sequence + ); +}; diff --git a/ethereum/scripts/loadEnv.js b/ethereum/scripts/loadEnv.js index 1c58fac9..27f85018 100644 --- a/ethereum/scripts/loadEnv.js +++ b/ethereum/scripts/loadEnv.js @@ -1,10 +1,11 @@ const dotenv = require("dotenv"); -var path = require('path'); +var path = require("path"); module.exports = function loadEnv(rootPath) { dotenv.config({ path: path.join(rootPath, ".env") }); if (process.env.CLUSTER !== undefined) { - dotenv.config({ path: path.join(rootPath, - `.env.cluster.${process.env.CLUSTER}`) }); + dotenv.config({ + path: path.join(rootPath, `.env.cluster.${process.env.CLUSTER}`), + }); } -} +}; diff --git a/ethereum/test/pyth.js b/ethereum/test/pyth.js index e680e782..3b079f1f 100644 --- a/ethereum/test/pyth.js +++ b/ethereum/test/pyth.js @@ -6,9 +6,15 @@ const governance = require("@pythnetwork/xc-governance-sdk"); const PythStructs = artifacts.require("PythStructs"); const { deployProxy, upgradeProxy } = require("@openzeppelin/truffle-upgrades"); -const { expectRevert, expectEvent, time } = require("@openzeppelin/test-helpers"); +const { + expectRevert, + expectEvent, + time, +} = require("@openzeppelin/test-helpers"); const { assert, expect } = require("chai"); -const { deployProxyImpl } = require("@openzeppelin/truffle-upgrades/dist/utils"); +const { + deployProxyImpl, +} = require("@openzeppelin/truffle-upgrades/dist/utils"); // Use "WormholeReceiver" if you are testing with Wormhole Receiver const Wormhole = artifacts.require("Wormhole"); @@ -18,1291 +24,1370 @@ const MockPythUpgrade = artifacts.require("MockPythUpgrade"); const MockUpgradeableProxy = artifacts.require("MockUpgradeableProxy"); const testSigner1PK = - "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"; + "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"; const testSigner2PK = - "892330666a850761e7370376430bb8c2aa1494072d3bfeaed0c4fa3d5a9135fe"; + "892330666a850761e7370376430bb8c2aa1494072d3bfeaed0c4fa3d5a9135fe"; contract("Pyth", function () { - const testSigner1 = web3.eth.accounts.privateKeyToAccount(testSigner1PK); - const testSigner2 = web3.eth.accounts.privateKeyToAccount(testSigner2PK); - const testGovernanceChainId = "1"; - const testGovernanceEmitter = - "0x0000000000000000000000000000000000000000000000000000000000001234"; - const testPyth2WormholeChainId = "1"; - const testPyth2WormholeEmitter = - "0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b"; - const notOwnerError = - "Ownable: caller is not the owner -- Reason given: Ownable: caller is not the owner."; - const insufficientFeeError = - "insufficient paid fee amount"; - - // Place all atomic operations that are done within migrations here. - beforeEach(async function () { - this.pythProxy = await deployProxy(PythUpgradable, [ - (await Wormhole.deployed()).address, - testPyth2WormholeChainId, - testPyth2WormholeEmitter, - ]); - - await this.pythProxy.addDataSource( - testPyth2WormholeChainId, - testPyth2WormholeEmitter - ); - - // Setting the validity time to 60 seconds - await this.pythProxy.updateValidTimePeriodSeconds(60); - - // Setting the governance data source to 0x1 (solana) and some random emitter address - await this.pythProxy.updateGovernanceDataSource(testGovernanceChainId, testGovernanceEmitter, 0); - }); - - it("should be initialized with the correct signers and values", async function () { - await this.pythProxy.isValidDataSource(testPyth2WormholeChainId, testPyth2WormholeEmitter); - }); - - it("should allow upgrades from the owner", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. upgradeProxy will send - // transactions from the default account. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - const owner = await this.pythProxy.owner(); - assert.equal(owner, defaultAccount); - - // Try and upgrade the proxy - const newImplementation = await upgradeProxy( - this.pythProxy.address, - MockPythUpgrade - ); - - // Check that the new upgrade is successful - assert.equal(await newImplementation.isUpgradeActive(), true); - assert.equal(this.pythProxy.address, newImplementation.address); - }); - - it("should allow ownership transfer", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check that another account can't transfer the ownership - await expectRevert( - this.pythProxy.transferOwnership(accounts[1], { - from: accounts[1], - }), - notOwnerError - ); - - // Transfer the ownership to another account - await this.pythProxy.transferOwnership(accounts[2], { - from: defaultAccount, - }); - assert.equal(await this.pythProxy.owner(), accounts[2]); - - // Check that the original account can't transfer the ownership back to itself - await expectRevert( - this.pythProxy.transferOwnership(defaultAccount, { - from: defaultAccount, - }), - notOwnerError - ); - - // Check that the new owner can transfer the ownership back to the original account - await this.pythProxy.transferOwnership(defaultAccount, { - from: accounts[2], - }); - assert.equal(await this.pythProxy.owner(), defaultAccount); - }); - - it("should not allow upgrades from the another account", async function () { - // This test is slightly convoluted as, due to a limitation of Truffle, - // we cannot specify which account upgradeProxy send transactions from: - // it will always use the default account. - // - // Therefore, we transfer the ownership to another account first, - // and then attempt an upgrade using the default account. - - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Transfer the ownership to another account - const newOwnerAccount = accounts[1]; - await this.pythProxy.transferOwnership(newOwnerAccount, { - from: defaultAccount, - }); - assert.equal(await this.pythProxy.owner(), newOwnerAccount); - - // Try and upgrade using the default account, which will fail - // because we are no longer the owner. - await expectRevert( - upgradeProxy(this.pythProxy.address, MockPythUpgrade), - notOwnerError - ); - }); - - it("should allow updating singleUpdateFeeInWei by owner", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check initial fee is zero - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); - - // Set fee - await this.pythProxy.updateSingleUpdateFeeInWei(10); - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); - }); - - it("should not allow updating singleUpdateFeeInWei by another account", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check initial valid time period is zero - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); - - // Checks setting valid time period using another account reverts. - await expectRevert( - this.pythProxy.updateSingleUpdateFeeInWei(10, {from: accounts[1]}), - notOwnerError, - ); - }); - - it("should allow updating validTimePeriodSeconds by owner", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check valid time period is 60 (set in beforeEach) - assert.equal(await this.pythProxy.validTimePeriodSeconds(), 60); - - // Set valid time period - await this.pythProxy.updateValidTimePeriodSeconds(30); - assert.equal(await this.pythProxy.validTimePeriodSeconds(), 30); - }); - - it("should not allow updating validTimePeriodSeconds by another account", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check valid time period is 60 (set in beforeEach) - assert.equal(await this.pythProxy.validTimePeriodSeconds(), 60); - - // Checks setting validity time using another account reverts. - await expectRevert( - this.pythProxy.updateValidTimePeriodSeconds(30, {from: accounts[1]}), - notOwnerError, - ); - }); - - // NOTE(2022-05-02): Raw hex payload obtained from format serialization unit tests in `p2w-sdk/rust` - // Latest known addition: wire format v3 - // - // Tests rely on a p2w-sdk mock price/prod ID generation rule: - // nthProdByte(n) = n % 256, starting with n=1 - // nthPriceByte(n) = 255 - (n % 256), starting with n=1 - // - // Examples: - // 1st prod = "0x010101[...]" - // 1st price = "0xFEFEFE[...]" - // 2nd prod = "0x020202[...]" - // 2nd price = "0xFDFDFD[...]" - // 3rd prod = "0x030303[...]" - // 3rd price = "0xFCFCFC[...]" - const RAW_BATCH_ATTESTATION_TIME_REGEX = /DEADBEEFFADEDEED/g; - const RAW_BATCH_PUBLISH_TIME_REGEX = /00000000DADEBEEF/g; - const RAW_BATCH_PRICE_REGEX = /0000002BAD2FEED7/g; - const RAW_BATCH_PREV_PRICE_REGEX = /0000DEADFACEBEEF/g; - const RAW_BATCH_PREV_PUBLISH_TIME_REGEX = /00000000DEADBABE/g; - const RAW_BATCH_EMA_PRICE_REGEX = /FFFFFFFFFFFFFFD6/g; - const RAW_PRICE_ATTESTATION_SIZE = 149; - const RAW_BATCH_ATTESTATION_COUNT = 10; - const RAW_BATCH = - "0x" + - "5032574800030000000102000A00950101010101010101010101010101010101010101010101010101010101010101FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0202020202020202020202020202020202020202020202020202020202020202FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0303030303030303030303030303030303030303030303030303030303030303FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0404040404040404040404040404040404040404040404040404040404040404FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0505050505050505050505050505050505050505050505050505050505050505FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0606060606060606060606060606060606060606060606060606060606060606F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F90000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0707070707070707070707070707070707070707070707070707070707070707F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F80000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0808080808080808080808080808080808080808080808080808080808080808F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F70000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0909090909090909090909090909090909090909090909090909090909090909F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F60000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AF5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F50000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF"; - const RAW_UNKNOWN_BATCH_ATTESTATION_COUNT = 3; - const RAW_UNKNOWN_BATCH = - "0x" + - "5032574800030000000102000300950101010101010101010101010101010101010101010101010101010101010101FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A000001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0202020202020202020202020202020202020202020202020202020202020202FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A000001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0303030303030303030303030303030303030303030303030303030303030303FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A000001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF"; - - // Takes an unsigned 64-bit integer, converts it to hex with 0-padding - function u64ToHex(timestamp) { - // u64 -> 8 bytes -> 16 hex bytes - return timestamp.toString(16).padStart(16, "0"); - } - - function generateRawBatchAttestation( - publishTime, - attestationTime, - priceVal, - emaPriceVal, - ) { - const pubTs = u64ToHex(publishTime); - const attTs = u64ToHex(attestationTime); - const price = u64ToHex(priceVal); - const emaPrice = u64ToHex(emaPriceVal || priceVal); - const replaced = RAW_BATCH.replace(RAW_BATCH_PUBLISH_TIME_REGEX, pubTs) - .replace(RAW_BATCH_ATTESTATION_TIME_REGEX, attTs) - .replace(RAW_BATCH_PRICE_REGEX, price) - .replace(RAW_BATCH_EMA_PRICE_REGEX, emaPrice); - return replaced; - } - - function generateRawUnknownBatchAttestation( - publishTime, - attestationTime, - priceVal, - emaPriceVal, - prevPublishTime, - prevPriceVal, - ) { - const pubTs = u64ToHex(publishTime); - const attTs = u64ToHex(attestationTime); - const price = u64ToHex(priceVal); - const emaPrice = u64ToHex(emaPriceVal); - const prevPubTs = u64ToHex(prevPublishTime); - const prevPrice = u64ToHex(prevPriceVal); - - const replaced = RAW_UNKNOWN_BATCH.replace(RAW_BATCH_PUBLISH_TIME_REGEX, pubTs) - .replace(RAW_BATCH_ATTESTATION_TIME_REGEX, attTs) - .replace(RAW_BATCH_PRICE_REGEX, price) - .replace(RAW_BATCH_EMA_PRICE_REGEX, emaPrice) - .replace(RAW_BATCH_PREV_PUBLISH_TIME_REGEX, prevPubTs) - .replace(RAW_BATCH_PREV_PRICE_REGEX, prevPrice); - return replaced; - } - - it("should parse batch price attestation correctly", async function () { - let attestationTime = 1647273460; // re-used for publishTime - let publishTime = 1647273465; // re-used for publishTime - let priceVal = 1337; - let emaPriceVal = 2022; - let rawBatch = generateRawBatchAttestation( - publishTime, - attestationTime, - priceVal, - emaPriceVal - ); - - const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); - - expectEventMultipleTimes(receipt, 'PriceFeedUpdate', { - price: "1337", - }, 10); - - for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - - const price = await this.pythProxy.getPriceUnsafe(price_id); - assert.equal(price.price, priceVal.toString()); - assert.equal(price.conf, "101"); // The value is hardcoded in the RAW_BATCH. - assert.equal(price.publishTime, publishTime.toString()); - assert.equal(price.expo, "-3"); // The value is hardcoded in the RAW_BATCH. - - const emaPrice = await this.pythProxy.getEmaPriceUnsafe(price_id); - assert.equal(emaPrice.price, emaPriceVal.toString()); - assert.equal(emaPrice.conf, "42"); // The value is hardcoded in the RAW_BATCH. - assert.equal(emaPrice.publishTime, publishTime.toString()); - assert.equal(emaPrice.expo, "-3"); // The value is hardcoded in the RAW_BATCH. - } - }); - - async function updatePriceFeeds(contract, batches, valueInWei, chainId, emitter) { - let updateData = []; - for (let data of batches) { - const vm = await signAndEncodeVM( - 1, - 1, - chainId || testPyth2WormholeChainId, - emitter || testPyth2WormholeEmitter, - 0, - data, - [testSigner1PK], - 0, - 0 - ); - updateData.push("0x" + vm); - } - return await contract.updatePriceFeeds(updateData, {value: valueInWei}); - } - - it("should attest price updates over wormhole", async function () { - let ts = 1647273460; - let rawBatch = generateRawBatchAttestation(ts - 5, ts, 1337); - await updatePriceFeeds(this.pythProxy, [rawBatch]); - }); - - it("should attest price updates empty", async function () { - const receipt = await updatePriceFeeds(this.pythProxy, []); - expectEvent.notEmitted(receipt, 'PriceFeedUpdate'); - expectEvent.notEmitted(receipt, 'BatchPriceFeedUpdate'); - }); - - it("should attest price updates with multiple batches of correct order", async function () { - let ts = 1647273460; - let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); - let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2]); - expectEvent(receipt, 'PriceFeedUpdate', { - publishTime: (ts - 5).toString(), - }); - expectEvent(receipt, 'PriceFeedUpdate', { - publishTime: (ts + 5).toString(), - }); - expectEventMultipleTimes(receipt, 'BatchPriceFeedUpdate', {}, 2); - }); - - it("should attest price updates with multiple batches of wrong order", async function () { - let ts = 1647273460; - let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); - let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch2, rawBatch1]); - expectEvent(receipt, 'PriceFeedUpdate', { - publishTime: (ts + 5).toString(), - }); - expectEventMultipleTimes(receipt, 'BatchPriceFeedUpdate', {}, 2); - expectEventNotEmittedWithArgs(receipt, 'PriceFeedUpdate', { - publishTime: (ts - 5).toString(), - }); - }); - - it("should not attest price updates with when required fee is not given", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check initial fee is zero - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); - - // Set fee - await this.pythProxy.updateSingleUpdateFeeInWei(10); - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); - - let ts = 1647273460; - let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); - let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - - // Getting the fee from the contract - let feeInWei = await this.pythProxy.methods["getUpdateFee(bytes[])"]([rawBatch1, rawBatch2]); - assert.equal(feeInWei, 20); - - // When a smaller fee is payed it reverts - await expectRevert( - updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2], feeInWei - 1), - insufficientFeeError - ); - }); - - it("should attest price updates with when required fee is given", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check initial fee is zero - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); - - // Set fee - await this.pythProxy.updateSingleUpdateFeeInWei(10); - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); - - let ts = 1647273460; - let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); - let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - - // Getting the fee from the contract - let feeInWei = await this.pythProxy.methods["getUpdateFee(bytes[])"]([rawBatch1, rawBatch2]); - assert.equal(feeInWei, 20); - - await updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2], feeInWei); - const pythBalance = await web3.eth.getBalance(this.pythProxy.address); - assert.equal(pythBalance, feeInWei); - }); - - it("should attest price updates with required fee even if more fee is given", async function () { - // Check that the owner is the default account Truffle - // has configured for the network. - const accounts = await web3.eth.getAccounts(); - const defaultAccount = accounts[0]; - assert.equal(await this.pythProxy.owner(), defaultAccount); - - // Check initial fee is zero - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); - - // Set fee - await this.pythProxy.updateSingleUpdateFeeInWei(10); - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); - - let ts = 1647273460; - let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); - let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - - // Paying the fee works and extra fee is not paid back. - let feeInWei = await this.pythProxy.methods["getUpdateFee(bytes[])"]([rawBatch1, rawBatch2]); - assert.equal(feeInWei, 20); - - await updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2], feeInWei + 10); - const pythBalance = await web3.eth.getBalance(this.pythProxy.address); - assert.equal(pythBalance, feeInWei + 10); - }); - - it("should cache price updates", async function () { - let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; - let priceVal = 521; - let rawBatch = generateRawBatchAttestation( - currentTimestamp - 5, - currentTimestamp, - priceVal - ); - let receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); - expectEvent(receipt, 'PriceFeedUpdate', { - price: priceVal.toString(), - publishTime: (currentTimestamp - 5).toString() - }); - expectEvent(receipt, 'BatchPriceFeedUpdate'); - - - let first_prod_id = "0x" + "01".repeat(32); - let first_price_id = "0x" + "fe".repeat(32); - let second_prod_id = "0x" + "02".repeat(32); - let second_price_id = "0x" + "fd".repeat(32); - - // Confirm that previously non-existent feeds are created - let first = await this.pythProxy.queryPriceFeed(first_price_id); - console.debug(`first is ${JSON.stringify(first)}`); - assert.equal(first.price.price, priceVal); - - let second = await this.pythProxy.queryPriceFeed(second_price_id); - assert.equal(second.price.price, priceVal); - - // Confirm the price is bumped after a new attestation updates each record - let nextTimestamp = currentTimestamp + 1; - let rawBatch2 = generateRawBatchAttestation( - nextTimestamp - 5, - nextTimestamp, - priceVal + 5 - ); - receipt = await updatePriceFeeds(this.pythProxy, [rawBatch2]); - expectEvent(receipt, 'PriceFeedUpdate', { - price: (priceVal+5).toString(), - publishTime: (nextTimestamp - 5).toString() - }); - expectEvent(receipt, 'BatchPriceFeedUpdate'); - - first = await this.pythProxy.queryPriceFeed(first_price_id); - assert.equal(first.price.price, priceVal + 5); - - second = await this.pythProxy.queryPriceFeed(second_price_id); - assert.equal(second.price.price, priceVal + 5); - - // Confirm that only strictly larger timestamps trigger updates - let rawBatch3 = generateRawBatchAttestation( - nextTimestamp - 5, - nextTimestamp, - priceVal + 10 - ); - receipt = await updatePriceFeeds(this.pythProxy, [rawBatch3]); - expectEvent.notEmitted(receipt, 'PriceFeedUpdate'); - expectEvent(receipt, 'BatchPriceFeedUpdate'); - - first = await this.pythProxy.queryPriceFeed(first_price_id); - assert.equal(first.price.price, priceVal + 5); - assert.notEqual(first.price.price, priceVal + 10); - - second = await this.pythProxy.queryPriceFeed(second_price_id); - assert.equal(second.price.price, priceVal + 5); - assert.notEqual(second.price.price, priceVal + 10); - }); - - it("should fail transaction if a price is not found", async function () { - await expectRevert( - this.pythProxy.queryPriceFeed( - "0xdeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeed" - ), - "price feed for the given id is not pushed or does not exist" - ); - }); - - it("should revert on getting stale current prices", async function () { - let smallestTimestamp = 1; - let rawBatch = generateRawBatchAttestation( - smallestTimestamp, - smallestTimestamp + 5, - 1337 - ); - await updatePriceFeeds(this.pythProxy, [rawBatch]); - - for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - expectRevert( - this.pythProxy.getPrice(price_id), - "no price available which is recent enough" - ); - } - }); - - it("should revert on getting current prices too far into the future as they are considered unknown", async function () { - let largestTimestamp = 4294967295; - let rawBatch = generateRawBatchAttestation( - largestTimestamp - 5, - largestTimestamp, - 1337 - ); - await updatePriceFeeds(this.pythProxy, [rawBatch]); - - for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - expectRevert( - this.pythProxy.getPrice(price_id), - "no price available which is recent enough" - ); - } - }); - - it("changing validity time works", async function() { - const latestTime = await time.latest(); - let rawBatch = generateRawBatchAttestation( - latestTime, - latestTime, - 1337 - ); - - await updatePriceFeeds(this.pythProxy, [rawBatch]); - - // Setting the validity time to 30 seconds - await this.pythProxy.updateValidTimePeriodSeconds(30); - - // Then prices should be available - for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - - // Expect getPrice to work (not revert) - await this.pythProxy.getPrice(price_id); - } - - // One minute passes - await time.increase(time.duration.minutes(1)); - - // The prices should become unavailable now. - for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - - expectRevert( - this.pythProxy.getPrice(price_id), - "no price available which is recent enough" - ); - } - - // Setting the validity time to 120 seconds - await this.pythProxy.updateValidTimePeriodSeconds(120); - - // Then prices should be available because the valid period is now 120 seconds - for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - let priceFeedResult = await this.pythProxy.queryPriceFeed(price_id); - - // Expect getPrice to work (not revert) - await this.pythProxy.getPrice(price_id); - } - }); - - it("should use prev price and timestamp on unknown attestation status", async function () { - const latestTime = await time.latest(); - let rawBatch = generateRawUnknownBatchAttestation( - latestTime, - latestTime, - 1337, // price - 1500, // ema price - latestTime - 10, - 1000, // prev price - ); - - const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); - expectEvent(receipt, 'PriceFeedUpdate', { - price: "1000", - }); - - // Then prices should be available because the valid period is now 120 seconds - for (var i = 1; i <= RAW_UNKNOWN_BATCH_ATTESTATION_COUNT; i++) { - const price_id = - "0x" + - (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); - - const price = await this.pythProxy.getPrice(price_id); - assert.equal(price.price, "1000"); - assert.equal(price.publishTime, (latestTime - 10).toString()); - - const emaPrice = await this.pythProxy.getEmaPrice(price_id); - assert.equal(emaPrice.price, "1500"); - assert.equal(emaPrice.publishTime, (latestTime - 10).toString()); - } - }); - - it("should accept a VM after adding its data source", async function () { - let newChainId = "42424"; - let newEmitter = testPyth2WormholeEmitter.replace("a", "f"); - - await this.pythProxy.addDataSource(newChainId, newEmitter); - - let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; - let rawBatch = generateRawBatchAttestation( - currentTimestamp - 5, - currentTimestamp, - 1337 - ); - let vm = await signAndEncodeVM( - 1, - 1, - newChainId, - newEmitter, - 0, - rawBatch, - [testSigner1PK], - 0, - 0 - ); - - await this.pythProxy.updatePriceFeeds(["0x" + vm]); - }); - - it("should reject a VM after removing its data source", async function () { - // Add 2 new data sources to produce a non-trivial data source state. - let newChainId = "42424"; - let newEmitter = testPyth2WormholeEmitter.replace("a", "f"); - await this.pythProxy.addDataSource(newChainId, newEmitter); - - let newChainId2 = "42425"; - let newEmitter2 = testPyth2WormholeEmitter.replace("a", "e"); - await this.pythProxy.addDataSource(newChainId2, newEmitter2); - - // Remove the first one added - await this.pythProxy.removeDataSource(newChainId, newEmitter); - - // Sign a batch with the removed data source - let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; - let rawBatch = generateRawBatchAttestation( - currentTimestamp - 5, - currentTimestamp, - 1337 - ); - let vm = await signAndEncodeVM( - 1, - 1, - newChainId, - newEmitter, - 0, - rawBatch, - [testSigner1PK], - 0, - 0 - ); - - await expectRevert( - this.pythProxy.updatePriceFeeds(["0x" + vm]), - "invalid data source chain/emitter ID" - ); - }); - - // Governance - - // Logics that apply to all governance messages - it("Make sure invalid magic and module won't work", async function () { - // First 4 bytes of data are magic and the second byte after that is module - const data = new governance.SetValidPeriodInstruction(governance.CHAINS.ethereum, BigInt(10)).serialize(); - - const wrongMagic = Buffer.from(data); - wrongMagic[1] = 0; - - const vaaWrongMagic = await createVAAFromUint8Array(wrongMagic, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaWrongMagic), - "invalid magic for GovernanceInstruction" - ); - - const wrongModule = Buffer.from(data); - wrongModule[4] = 0; - - const vaaWrongModule = await createVAAFromUint8Array(wrongModule, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaWrongModule), - "invalid module for GovernanceInstruction" - ); - - const outOfBoundModule = Buffer.from(data); - outOfBoundModule[4] = 20; - - const vaaOutOfBoundModule = await createVAAFromUint8Array(outOfBoundModule, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaOutOfBoundModule), - "Panic: Enum value out of bounds.", - ); - }); - - it("Make sure governance with wrong sender won't work", async function () { - const data = new governance.SetValidPeriodInstruction(governance.CHAINS.ethereum, BigInt(10)).serialize(); - - const vaaWrongEmitter = await createVAAFromUint8Array(data, - testGovernanceChainId, - "0x0000000000000000000000000000000000000000000000000000000000001111", - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaWrongEmitter), - "VAA is not coming from the governance data source" - ); - - const vaaWrongChain = await createVAAFromUint8Array(data, - governance.CHAINS.karura, - testGovernanceEmitter, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaWrongChain), - "VAA is not coming from the governance data source" - ); - }); - - it("Make sure governance with only target chain id and 0 work", async function () { - const wrongChainData = new governance.SetValidPeriodInstruction(governance.CHAINS.solana, BigInt(10)).serialize(); - - const wrongChainVaa = await createVAAFromUint8Array(wrongChainData, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(wrongChainVaa), - "invalid target chain for this governance instruction" - ); - - const dataForAllChains = new governance.SetValidPeriodInstruction(governance.CHAINS.unset, BigInt(10)).serialize(); - - const vaaForAllChains = await createVAAFromUint8Array(dataForAllChains, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await this.pythProxy.executeGovernanceInstruction(vaaForAllChains); - - const dataForEth = new governance.SetValidPeriodInstruction(governance.CHAINS.ethereum, BigInt(10)).serialize(); - - const vaaForEth = await createVAAFromUint8Array(dataForEth, - testGovernanceChainId, - testGovernanceEmitter, - 2, - ); - - await this.pythProxy.executeGovernanceInstruction(vaaForEth); - }); - - it("Make sure that governance messages are executed in order and cannot be reused", async function () { - const data = new governance.SetValidPeriodInstruction(governance.CHAINS.ethereum, BigInt(10)).serialize(); - - const vaaSeq1 = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await this.pythProxy.executeGovernanceInstruction(vaaSeq1), - - // Replaying shouldn't work - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaSeq1), - "VAA is older than the last executed governance VAA", - ) - - const vaaSeq2 = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 2 - ); - - await this.pythProxy.executeGovernanceInstruction(vaaSeq2), - - // Replaying shouldn't work - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaSeq1), - "VAA is older than the last executed governance VAA", - ) - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaaSeq2), - "VAA is older than the last executed governance VAA", - ) - }); - - // Per governance type logic - it("Upgrading the contract with chain id 0 is invalid", async function () { - const newImplementation = await PythUpgradable.new(); - - const data = new governance.EthereumUpgradeContractInstruction( - governance.CHAINS.unset, // 0 - new governance.HexString20Bytes(newImplementation.address), - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaa), - "upgrade with chain id 0 is not possible" - ); - }); - - - it("Upgrading the contract should work", async function () { - const newImplementation = await PythUpgradable.new(); - - const data = new governance.EthereumUpgradeContractInstruction( - governance.CHAINS.ethereum, - new governance.HexString20Bytes(newImplementation.address), - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); - - // Couldn't get the oldImplementation address. - expectEvent(receipt, 'ContractUpgraded', { - newImplementation: newImplementation.address, - }); - expectEvent(receipt, 'Upgraded', { - implementation: newImplementation.address - }); - }); - - it("Upgrading the contract to a non-pyth contract won't work", async function () { - const newImplementation = await MockUpgradeableProxy.new(); - - const data = new governance.EthereumUpgradeContractInstruction( - governance.CHAINS.ethereum, - new governance.HexString20Bytes(newImplementation.address), - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - // Calling a non-existing method will cause a revert with no explanation. - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaa), - "revert" - ); - }); - - it("Transferring governance data source should work", async function () { - const newEmitterAddress = "0x0000000000000000000000000000000000000000000000000000000000001111"; - const newEmitterChain = governance.CHAINS.acala; - - const claimInstructionData = new governance.RequestGovernanceDataSourceTransferInstruction( - governance.CHAINS.unset, - 1 - ).serialize(); - - const claimVaaHexString = await createVAAFromUint8Array( - claimInstructionData, - newEmitterChain, - newEmitterAddress, - 1 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(claimVaaHexString), - "VAA is not coming from the governance data source" - ); - - const claimVaa = Buffer.from(claimVaaHexString.substring(2), 'hex'); - - const data = new governance.AuthorizeGovernanceDataSourceTransferInstruction( - governance.CHAINS.unset, - claimVaa - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - const oldGovernanceDataSource = await this.pythProxy.governanceDataSource(); - - const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); - - const newGovernanceDataSource = await this.pythProxy.governanceDataSource(); - - expectEvent(receipt, 'GovernanceDataSourceSet', { - oldDataSource: oldGovernanceDataSource, - newDataSource: newGovernanceDataSource, - }); - - expect(newGovernanceDataSource.chainId).equal(newEmitterChain.toString()); - expect(newGovernanceDataSource.emitterAddress).equal(newEmitterAddress); - - // Verifies the data source has changed. - await expectRevert( - this.pythProxy.executeGovernanceInstruction(vaa), - "VAA is not coming from the governance data source" - ); - - // Make sure a claim vaa does not get executed - - const claimLonely = new governance.RequestGovernanceDataSourceTransferInstruction( - governance.CHAINS.unset, - 2 - ).serialize(); - - const claimLonelyVaa = await createVAAFromUint8Array( - claimLonely, - newEmitterChain, - newEmitterAddress, - 2 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(claimLonelyVaa), - "RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message" - ); - - // Transfer back the ownership to the old governance data source without increasing - // the governance index should not work - - // A wrong vaa that does not move the governance index - const transferBackClaimInstructionDataWrong = new governance.RequestGovernanceDataSourceTransferInstruction( - governance.CHAINS.unset, - 1 // The same governance data source index => Should fail - ).serialize(); - - const transferBackClaimVaaHexStringWrong = await createVAAFromUint8Array( - transferBackClaimInstructionDataWrong, - testGovernanceChainId, - testGovernanceEmitter, - 2 - ); - - const transferBackClaimVaaWrong = Buffer.from(transferBackClaimVaaHexStringWrong.substring(2), 'hex'); - - const transferBackDataWrong = new governance.AuthorizeGovernanceDataSourceTransferInstruction( - governance.CHAINS.unset, - transferBackClaimVaaWrong - ).serialize(); - - const transferBackVaaWrong = await createVAAFromUint8Array(transferBackDataWrong, - newEmitterChain, - newEmitterAddress, - 2 - ); - - await expectRevert( - this.pythProxy.executeGovernanceInstruction(transferBackVaaWrong), - "cannot upgrade to an older governance data source" - ); - }); - - it("Setting data sources should work", async function () { - const data = new governance.SetDataSourcesInstruction( - governance.CHAINS.ethereum, - [new governance.DataSource( - governance.CHAINS.acala, - new governance.HexString32Bytes( - "0x0000000000000000000000000000000000000000000000000000000000001111", - ) - )], - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - const oldDataSources = await this.pythProxy.validDataSources(); - - const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); - expectEvent(receipt, 'DataSourcesSet', { - oldDataSources: oldDataSources, - newDataSources: await this.pythProxy.validDataSources(), - }); - - assert.isTrue(await this.pythProxy.isValidDataSource(governance.CHAINS.acala, - "0x0000000000000000000000000000000000000000000000000000000000001111")); - assert.isFalse(await this.pythProxy.isValidDataSource(testPyth2WormholeChainId, - testPyth2WormholeEmitter)); - - let rawBatch = generateRawBatchAttestation( - 100, - 100, - 1337 - ); - await expectRevert( - updatePriceFeeds(this.pythProxy, [rawBatch]), - "invalid data source chain/emitter ID" - ); - - await updatePriceFeeds(this.pythProxy, [rawBatch], 0, governance.CHAINS.acala, - "0x0000000000000000000000000000000000000000000000000000000000001111"); - }); - - it("Setting fee should work", async function () { - const data = new governance.SetFeeInstruction( - governance.CHAINS.ethereum, - BigInt(5), BigInt(3) // 5*10**3 = 5000 - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - const oldFee = await this.pythProxy.singleUpdateFeeInWei(); - - const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); - expectEvent(receipt, 'FeeSet', { - oldFee: oldFee, - newFee: await this.pythProxy.singleUpdateFeeInWei(), - }); - - assert.equal(await this.pythProxy.singleUpdateFeeInWei(), "5000"); - - let rawBatch = generateRawBatchAttestation( - 100, - 100, - 1337 - ); - await expectRevert( - updatePriceFeeds(this.pythProxy, [rawBatch], 0), - insufficientFeeError - ); - - await updatePriceFeeds(this.pythProxy, [rawBatch], 5000); - }); - - it("Setting valid period should work", async function () { - const data = new governance.SetValidPeriodInstruction( - governance.CHAINS.ethereum, - BigInt(0), - ).serialize(); - - const vaa = await createVAAFromUint8Array(data, - testGovernanceChainId, - testGovernanceEmitter, - 1 - ); - - const oldValidPeriod = await this.pythProxy.validTimePeriodSeconds(); - - const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); - expectEvent(receipt, 'ValidPeriodSet', { - oldValidPeriod: oldValidPeriod, - newValidPeriod: await this.pythProxy.validTimePeriodSeconds(), - }); - - assert.equal(await this.pythProxy.validTimePeriodSeconds(), "0"); - - // The behaviour of valid time period is extensively tested before, - // and adding it here will cause more complexity (and is not so short). - }); - - // Renounce ownership works - it("Renouncing ownership should work", async function () { - await this.pythProxy.updateValidTimePeriodSeconds(100); - await this.pythProxy.renounceOwnership(); - await expectRevert( - this.pythProxy.updateValidTimePeriodSeconds(60), - "Ownable: caller is not the owner", - ) - }); - - // Version - - it("Make sure version is the npm package version", async function () { - const contractVersion = await this.pythProxy.version(); - const { version } = require('../package.json'); - - expect(contractVersion).equal(version); - }); -}); - -const signAndEncodeVM = async function ( - timestamp, - nonce, - emitterChainId, - emitterAddress, - sequence, - data, - signers, - guardianSetIndex, - consistencyLevel -) { - const body = [ - web3.eth.abi - .encodeParameter("uint32", timestamp) - .substring(2 + (64 - 8)), - web3.eth.abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)), - web3.eth.abi - .encodeParameter("uint16", emitterChainId) - .substring(2 + (64 - 4)), - web3.eth.abi.encodeParameter("bytes32", emitterAddress).substring(2), - web3.eth.abi - .encodeParameter("uint64", sequence) - .substring(2 + (64 - 16)), - web3.eth.abi - .encodeParameter("uint8", consistencyLevel) - .substring(2 + (64 - 2)), - data.substr(2), - ]; - - const hash = web3.utils.soliditySha3( - web3.utils.soliditySha3("0x" + body.join("")) + const testSigner1 = web3.eth.accounts.privateKeyToAccount(testSigner1PK); + const testSigner2 = web3.eth.accounts.privateKeyToAccount(testSigner2PK); + const testGovernanceChainId = "1"; + const testGovernanceEmitter = + "0x0000000000000000000000000000000000000000000000000000000000001234"; + const testPyth2WormholeChainId = "1"; + const testPyth2WormholeEmitter = + "0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b"; + const notOwnerError = + "Ownable: caller is not the owner -- Reason given: Ownable: caller is not the owner."; + const insufficientFeeError = "insufficient paid fee amount"; + + // Place all atomic operations that are done within migrations here. + beforeEach(async function () { + this.pythProxy = await deployProxy(PythUpgradable, [ + (await Wormhole.deployed()).address, + testPyth2WormholeChainId, + testPyth2WormholeEmitter, + ]); + + await this.pythProxy.addDataSource( + testPyth2WormholeChainId, + testPyth2WormholeEmitter ); - let signatures = ""; + // Setting the validity time to 60 seconds + await this.pythProxy.updateValidTimePeriodSeconds(60); - for (let i in signers) { - const ec = new elliptic.ec("secp256k1"); - const key = ec.keyFromPrivate(signers[i]); - const signature = key.sign(hash.substr(2), { canonical: true }); + // Setting the governance data source to 0x1 (solana) and some random emitter address + await this.pythProxy.updateGovernanceDataSource( + testGovernanceChainId, + testGovernanceEmitter, + 0 + ); + }); - const packSig = [ - web3.eth.abi.encodeParameter("uint8", i).substring(2 + (64 - 2)), - zeroPadBytes(signature.r.toString(16), 32), - zeroPadBytes(signature.s.toString(16), 32), - web3.eth.abi - .encodeParameter("uint8", signature.recoveryParam) - .substr(2 + (64 - 2)), - ]; + it("should be initialized with the correct signers and values", async function () { + await this.pythProxy.isValidDataSource( + testPyth2WormholeChainId, + testPyth2WormholeEmitter + ); + }); - signatures += packSig.join(""); + it("should allow upgrades from the owner", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. upgradeProxy will send + // transactions from the default account. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + const owner = await this.pythProxy.owner(); + assert.equal(owner, defaultAccount); + + // Try and upgrade the proxy + const newImplementation = await upgradeProxy( + this.pythProxy.address, + MockPythUpgrade + ); + + // Check that the new upgrade is successful + assert.equal(await newImplementation.isUpgradeActive(), true); + assert.equal(this.pythProxy.address, newImplementation.address); + }); + + it("should allow ownership transfer", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check that another account can't transfer the ownership + await expectRevert( + this.pythProxy.transferOwnership(accounts[1], { + from: accounts[1], + }), + notOwnerError + ); + + // Transfer the ownership to another account + await this.pythProxy.transferOwnership(accounts[2], { + from: defaultAccount, + }); + assert.equal(await this.pythProxy.owner(), accounts[2]); + + // Check that the original account can't transfer the ownership back to itself + await expectRevert( + this.pythProxy.transferOwnership(defaultAccount, { + from: defaultAccount, + }), + notOwnerError + ); + + // Check that the new owner can transfer the ownership back to the original account + await this.pythProxy.transferOwnership(defaultAccount, { + from: accounts[2], + }); + assert.equal(await this.pythProxy.owner(), defaultAccount); + }); + + it("should not allow upgrades from the another account", async function () { + // This test is slightly convoluted as, due to a limitation of Truffle, + // we cannot specify which account upgradeProxy send transactions from: + // it will always use the default account. + // + // Therefore, we transfer the ownership to another account first, + // and then attempt an upgrade using the default account. + + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Transfer the ownership to another account + const newOwnerAccount = accounts[1]; + await this.pythProxy.transferOwnership(newOwnerAccount, { + from: defaultAccount, + }); + assert.equal(await this.pythProxy.owner(), newOwnerAccount); + + // Try and upgrade using the default account, which will fail + // because we are no longer the owner. + await expectRevert( + upgradeProxy(this.pythProxy.address, MockPythUpgrade), + notOwnerError + ); + }); + + it("should allow updating singleUpdateFeeInWei by owner", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check initial fee is zero + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); + + // Set fee + await this.pythProxy.updateSingleUpdateFeeInWei(10); + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); + }); + + it("should not allow updating singleUpdateFeeInWei by another account", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check initial valid time period is zero + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); + + // Checks setting valid time period using another account reverts. + await expectRevert( + this.pythProxy.updateSingleUpdateFeeInWei(10, { from: accounts[1] }), + notOwnerError + ); + }); + + it("should allow updating validTimePeriodSeconds by owner", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check valid time period is 60 (set in beforeEach) + assert.equal(await this.pythProxy.validTimePeriodSeconds(), 60); + + // Set valid time period + await this.pythProxy.updateValidTimePeriodSeconds(30); + assert.equal(await this.pythProxy.validTimePeriodSeconds(), 30); + }); + + it("should not allow updating validTimePeriodSeconds by another account", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check valid time period is 60 (set in beforeEach) + assert.equal(await this.pythProxy.validTimePeriodSeconds(), 60); + + // Checks setting validity time using another account reverts. + await expectRevert( + this.pythProxy.updateValidTimePeriodSeconds(30, { from: accounts[1] }), + notOwnerError + ); + }); + + // NOTE(2022-05-02): Raw hex payload obtained from format serialization unit tests in `p2w-sdk/rust` + // Latest known addition: wire format v3 + // + // Tests rely on a p2w-sdk mock price/prod ID generation rule: + // nthProdByte(n) = n % 256, starting with n=1 + // nthPriceByte(n) = 255 - (n % 256), starting with n=1 + // + // Examples: + // 1st prod = "0x010101[...]" + // 1st price = "0xFEFEFE[...]" + // 2nd prod = "0x020202[...]" + // 2nd price = "0xFDFDFD[...]" + // 3rd prod = "0x030303[...]" + // 3rd price = "0xFCFCFC[...]" + const RAW_BATCH_ATTESTATION_TIME_REGEX = /DEADBEEFFADEDEED/g; + const RAW_BATCH_PUBLISH_TIME_REGEX = /00000000DADEBEEF/g; + const RAW_BATCH_PRICE_REGEX = /0000002BAD2FEED7/g; + const RAW_BATCH_PREV_PRICE_REGEX = /0000DEADFACEBEEF/g; + const RAW_BATCH_PREV_PUBLISH_TIME_REGEX = /00000000DEADBABE/g; + const RAW_BATCH_EMA_PRICE_REGEX = /FFFFFFFFFFFFFFD6/g; + const RAW_PRICE_ATTESTATION_SIZE = 149; + const RAW_BATCH_ATTESTATION_COUNT = 10; + const RAW_BATCH = + "0x" + + "5032574800030000000102000A00950101010101010101010101010101010101010101010101010101010101010101FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0202020202020202020202020202020202020202020202020202020202020202FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0303030303030303030303030303030303030303030303030303030303030303FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0404040404040404040404040404040404040404040404040404040404040404FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0505050505050505050505050505050505050505050505050505050505050505FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0606060606060606060606060606060606060606060606060606060606060606F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F90000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0707070707070707070707070707070707070707070707070707070707070707F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F80000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0808080808080808080808080808080808080808080808080808080808080808F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F70000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0909090909090909090909090909090909090909090909090909090909090909F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F60000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0AF5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F50000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A010001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF"; + const RAW_UNKNOWN_BATCH_ATTESTATION_COUNT = 3; + const RAW_UNKNOWN_BATCH = + "0x" + + "5032574800030000000102000300950101010101010101010101010101010101010101010101010101010101010101FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A000001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0202020202020202020202020202020202020202020202020202020202020202FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A000001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF0303030303030303030303030303030303030303030303030303030303030303FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC0000002BAD2FEED70000000000000065FFFFFFFDFFFFFFFFFFFFFFD6000000000000002A000001E14C0004E6D0DEADBEEFFADEDEED00000000DADEBEEF00000000DEADBABE0000DEADFACEBEEF000000BADBADBEEF"; + + // Takes an unsigned 64-bit integer, converts it to hex with 0-padding + function u64ToHex(timestamp) { + // u64 -> 8 bytes -> 16 hex bytes + return timestamp.toString(16).padStart(16, "0"); + } + + function generateRawBatchAttestation( + publishTime, + attestationTime, + priceVal, + emaPriceVal + ) { + const pubTs = u64ToHex(publishTime); + const attTs = u64ToHex(attestationTime); + const price = u64ToHex(priceVal); + const emaPrice = u64ToHex(emaPriceVal || priceVal); + const replaced = RAW_BATCH.replace(RAW_BATCH_PUBLISH_TIME_REGEX, pubTs) + .replace(RAW_BATCH_ATTESTATION_TIME_REGEX, attTs) + .replace(RAW_BATCH_PRICE_REGEX, price) + .replace(RAW_BATCH_EMA_PRICE_REGEX, emaPrice); + return replaced; + } + + function generateRawUnknownBatchAttestation( + publishTime, + attestationTime, + priceVal, + emaPriceVal, + prevPublishTime, + prevPriceVal + ) { + const pubTs = u64ToHex(publishTime); + const attTs = u64ToHex(attestationTime); + const price = u64ToHex(priceVal); + const emaPrice = u64ToHex(emaPriceVal); + const prevPubTs = u64ToHex(prevPublishTime); + const prevPrice = u64ToHex(prevPriceVal); + + const replaced = RAW_UNKNOWN_BATCH.replace( + RAW_BATCH_PUBLISH_TIME_REGEX, + pubTs + ) + .replace(RAW_BATCH_ATTESTATION_TIME_REGEX, attTs) + .replace(RAW_BATCH_PRICE_REGEX, price) + .replace(RAW_BATCH_EMA_PRICE_REGEX, emaPrice) + .replace(RAW_BATCH_PREV_PUBLISH_TIME_REGEX, prevPubTs) + .replace(RAW_BATCH_PREV_PRICE_REGEX, prevPrice); + return replaced; + } + + it("should parse batch price attestation correctly", async function () { + let attestationTime = 1647273460; // re-used for publishTime + let publishTime = 1647273465; // re-used for publishTime + let priceVal = 1337; + let emaPriceVal = 2022; + let rawBatch = generateRawBatchAttestation( + publishTime, + attestationTime, + priceVal, + emaPriceVal + ); + + const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); + + expectEventMultipleTimes( + receipt, + "PriceFeedUpdate", + { + price: "1337", + }, + 10 + ); + + for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + + const price = await this.pythProxy.getPriceUnsafe(price_id); + assert.equal(price.price, priceVal.toString()); + assert.equal(price.conf, "101"); // The value is hardcoded in the RAW_BATCH. + assert.equal(price.publishTime, publishTime.toString()); + assert.equal(price.expo, "-3"); // The value is hardcoded in the RAW_BATCH. + + const emaPrice = await this.pythProxy.getEmaPriceUnsafe(price_id); + assert.equal(emaPrice.price, emaPriceVal.toString()); + assert.equal(emaPrice.conf, "42"); // The value is hardcoded in the RAW_BATCH. + assert.equal(emaPrice.publishTime, publishTime.toString()); + assert.equal(emaPrice.expo, "-3"); // The value is hardcoded in the RAW_BATCH. } + }); - const vm = [ - web3.eth.abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)), - web3.eth.abi - .encodeParameter("uint32", guardianSetIndex) - .substring(2 + (64 - 8)), - web3.eth.abi - .encodeParameter("uint8", signers.length) - .substring(2 + (64 - 2)), - - signatures, - body.join(""), - ].join(""); - - return vm; -}; - -function zeroPadBytes(value, length) { - while (value.length < 2 * length) { - value = "0" + value; - } - return value; -} - -async function createVAAFromUint8Array( - dataBuffer, - emitterChainId, - emitterAddress, - sequence, -) { - const dataHex = "0x" + dataBuffer.toString("hex"); - return "0x" + await signAndEncodeVM( + async function updatePriceFeeds( + contract, + batches, + valueInWei, + chainId, + emitter + ) { + let updateData = []; + for (let data of batches) { + const vm = await signAndEncodeVM( + 1, + 1, + chainId || testPyth2WormholeChainId, + emitter || testPyth2WormholeEmitter, 0, - 0, - emitterChainId.toString(), - emitterAddress, - sequence, - dataHex, + data, [testSigner1PK], 0, 0 + ); + updateData.push("0x" + vm); + } + return await contract.updatePriceFeeds(updateData, { value: valueInWei }); + } + + it("should attest price updates over wormhole", async function () { + let ts = 1647273460; + let rawBatch = generateRawBatchAttestation(ts - 5, ts, 1337); + await updatePriceFeeds(this.pythProxy, [rawBatch]); + }); + + it("should attest price updates empty", async function () { + const receipt = await updatePriceFeeds(this.pythProxy, []); + expectEvent.notEmitted(receipt, "PriceFeedUpdate"); + expectEvent.notEmitted(receipt, "BatchPriceFeedUpdate"); + }); + + it("should attest price updates with multiple batches of correct order", async function () { + let ts = 1647273460; + let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); + let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); + const receipt = await updatePriceFeeds(this.pythProxy, [ + rawBatch1, + rawBatch2, + ]); + expectEvent(receipt, "PriceFeedUpdate", { + publishTime: (ts - 5).toString(), + }); + expectEvent(receipt, "PriceFeedUpdate", { + publishTime: (ts + 5).toString(), + }); + expectEventMultipleTimes(receipt, "BatchPriceFeedUpdate", {}, 2); + }); + + it("should attest price updates with multiple batches of wrong order", async function () { + let ts = 1647273460; + let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); + let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); + const receipt = await updatePriceFeeds(this.pythProxy, [ + rawBatch2, + rawBatch1, + ]); + expectEvent(receipt, "PriceFeedUpdate", { + publishTime: (ts + 5).toString(), + }); + expectEventMultipleTimes(receipt, "BatchPriceFeedUpdate", {}, 2); + expectEventNotEmittedWithArgs(receipt, "PriceFeedUpdate", { + publishTime: (ts - 5).toString(), + }); + }); + + it("should not attest price updates with when required fee is not given", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check initial fee is zero + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); + + // Set fee + await this.pythProxy.updateSingleUpdateFeeInWei(10); + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); + + let ts = 1647273460; + let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); + let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); + + // Getting the fee from the contract + let feeInWei = await this.pythProxy.methods["getUpdateFee(bytes[])"]([ + rawBatch1, + rawBatch2, + ]); + assert.equal(feeInWei, 20); + + // When a smaller fee is payed it reverts + await expectRevert( + updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2], feeInWei - 1), + insufficientFeeError ); + }); + + it("should attest price updates with when required fee is given", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check initial fee is zero + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); + + // Set fee + await this.pythProxy.updateSingleUpdateFeeInWei(10); + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); + + let ts = 1647273460; + let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); + let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); + + // Getting the fee from the contract + let feeInWei = await this.pythProxy.methods["getUpdateFee(bytes[])"]([ + rawBatch1, + rawBatch2, + ]); + assert.equal(feeInWei, 20); + + await updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2], feeInWei); + const pythBalance = await web3.eth.getBalance(this.pythProxy.address); + assert.equal(pythBalance, feeInWei); + }); + + it("should attest price updates with required fee even if more fee is given", async function () { + // Check that the owner is the default account Truffle + // has configured for the network. + const accounts = await web3.eth.getAccounts(); + const defaultAccount = accounts[0]; + assert.equal(await this.pythProxy.owner(), defaultAccount); + + // Check initial fee is zero + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 0); + + // Set fee + await this.pythProxy.updateSingleUpdateFeeInWei(10); + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), 10); + + let ts = 1647273460; + let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); + let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); + + // Paying the fee works and extra fee is not paid back. + let feeInWei = await this.pythProxy.methods["getUpdateFee(bytes[])"]([ + rawBatch1, + rawBatch2, + ]); + assert.equal(feeInWei, 20); + + await updatePriceFeeds( + this.pythProxy, + [rawBatch1, rawBatch2], + feeInWei + 10 + ); + const pythBalance = await web3.eth.getBalance(this.pythProxy.address); + assert.equal(pythBalance, feeInWei + 10); + }); + + it("should cache price updates", async function () { + let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; + let priceVal = 521; + let rawBatch = generateRawBatchAttestation( + currentTimestamp - 5, + currentTimestamp, + priceVal + ); + let receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); + expectEvent(receipt, "PriceFeedUpdate", { + price: priceVal.toString(), + publishTime: (currentTimestamp - 5).toString(), + }); + expectEvent(receipt, "BatchPriceFeedUpdate"); + + let first_prod_id = "0x" + "01".repeat(32); + let first_price_id = "0x" + "fe".repeat(32); + let second_prod_id = "0x" + "02".repeat(32); + let second_price_id = "0x" + "fd".repeat(32); + + // Confirm that previously non-existent feeds are created + let first = await this.pythProxy.queryPriceFeed(first_price_id); + console.debug(`first is ${JSON.stringify(first)}`); + assert.equal(first.price.price, priceVal); + + let second = await this.pythProxy.queryPriceFeed(second_price_id); + assert.equal(second.price.price, priceVal); + + // Confirm the price is bumped after a new attestation updates each record + let nextTimestamp = currentTimestamp + 1; + let rawBatch2 = generateRawBatchAttestation( + nextTimestamp - 5, + nextTimestamp, + priceVal + 5 + ); + receipt = await updatePriceFeeds(this.pythProxy, [rawBatch2]); + expectEvent(receipt, "PriceFeedUpdate", { + price: (priceVal + 5).toString(), + publishTime: (nextTimestamp - 5).toString(), + }); + expectEvent(receipt, "BatchPriceFeedUpdate"); + + first = await this.pythProxy.queryPriceFeed(first_price_id); + assert.equal(first.price.price, priceVal + 5); + + second = await this.pythProxy.queryPriceFeed(second_price_id); + assert.equal(second.price.price, priceVal + 5); + + // Confirm that only strictly larger timestamps trigger updates + let rawBatch3 = generateRawBatchAttestation( + nextTimestamp - 5, + nextTimestamp, + priceVal + 10 + ); + receipt = await updatePriceFeeds(this.pythProxy, [rawBatch3]); + expectEvent.notEmitted(receipt, "PriceFeedUpdate"); + expectEvent(receipt, "BatchPriceFeedUpdate"); + + first = await this.pythProxy.queryPriceFeed(first_price_id); + assert.equal(first.price.price, priceVal + 5); + assert.notEqual(first.price.price, priceVal + 10); + + second = await this.pythProxy.queryPriceFeed(second_price_id); + assert.equal(second.price.price, priceVal + 5); + assert.notEqual(second.price.price, priceVal + 10); + }); + + it("should fail transaction if a price is not found", async function () { + await expectRevert( + this.pythProxy.queryPriceFeed( + "0xdeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeeddeadfeed" + ), + "price feed for the given id is not pushed or does not exist" + ); + }); + + it("should revert on getting stale current prices", async function () { + let smallestTimestamp = 1; + let rawBatch = generateRawBatchAttestation( + smallestTimestamp, + smallestTimestamp + 5, + 1337 + ); + await updatePriceFeeds(this.pythProxy, [rawBatch]); + + for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + expectRevert( + this.pythProxy.getPrice(price_id), + "no price available which is recent enough" + ); + } + }); + + it("should revert on getting current prices too far into the future as they are considered unknown", async function () { + let largestTimestamp = 4294967295; + let rawBatch = generateRawBatchAttestation( + largestTimestamp - 5, + largestTimestamp, + 1337 + ); + await updatePriceFeeds(this.pythProxy, [rawBatch]); + + for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + expectRevert( + this.pythProxy.getPrice(price_id), + "no price available which is recent enough" + ); + } + }); + + it("changing validity time works", async function () { + const latestTime = await time.latest(); + let rawBatch = generateRawBatchAttestation(latestTime, latestTime, 1337); + + await updatePriceFeeds(this.pythProxy, [rawBatch]); + + // Setting the validity time to 30 seconds + await this.pythProxy.updateValidTimePeriodSeconds(30); + + // Then prices should be available + for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + + // Expect getPrice to work (not revert) + await this.pythProxy.getPrice(price_id); + } + + // One minute passes + await time.increase(time.duration.minutes(1)); + + // The prices should become unavailable now. + for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + + expectRevert( + this.pythProxy.getPrice(price_id), + "no price available which is recent enough" + ); + } + + // Setting the validity time to 120 seconds + await this.pythProxy.updateValidTimePeriodSeconds(120); + + // Then prices should be available because the valid period is now 120 seconds + for (var i = 1; i <= RAW_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + let priceFeedResult = await this.pythProxy.queryPriceFeed(price_id); + + // Expect getPrice to work (not revert) + await this.pythProxy.getPrice(price_id); + } + }); + + it("should use prev price and timestamp on unknown attestation status", async function () { + const latestTime = await time.latest(); + let rawBatch = generateRawUnknownBatchAttestation( + latestTime, + latestTime, + 1337, // price + 1500, // ema price + latestTime - 10, + 1000 // prev price + ); + + const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); + expectEvent(receipt, "PriceFeedUpdate", { + price: "1000", + }); + + // Then prices should be available because the valid period is now 120 seconds + for (var i = 1; i <= RAW_UNKNOWN_BATCH_ATTESTATION_COUNT; i++) { + const price_id = + "0x" + (255 - (i % 256)).toString(16).padStart(2, "0").repeat(32); + + const price = await this.pythProxy.getPrice(price_id); + assert.equal(price.price, "1000"); + assert.equal(price.publishTime, (latestTime - 10).toString()); + + const emaPrice = await this.pythProxy.getEmaPrice(price_id); + assert.equal(emaPrice.price, "1500"); + assert.equal(emaPrice.publishTime, (latestTime - 10).toString()); + } + }); + + it("should accept a VM after adding its data source", async function () { + let newChainId = "42424"; + let newEmitter = testPyth2WormholeEmitter.replace("a", "f"); + + await this.pythProxy.addDataSource(newChainId, newEmitter); + + let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; + let rawBatch = generateRawBatchAttestation( + currentTimestamp - 5, + currentTimestamp, + 1337 + ); + let vm = await signAndEncodeVM( + 1, + 1, + newChainId, + newEmitter, + 0, + rawBatch, + [testSigner1PK], + 0, + 0 + ); + + await this.pythProxy.updatePriceFeeds(["0x" + vm]); + }); + + it("should reject a VM after removing its data source", async function () { + // Add 2 new data sources to produce a non-trivial data source state. + let newChainId = "42424"; + let newEmitter = testPyth2WormholeEmitter.replace("a", "f"); + await this.pythProxy.addDataSource(newChainId, newEmitter); + + let newChainId2 = "42425"; + let newEmitter2 = testPyth2WormholeEmitter.replace("a", "e"); + await this.pythProxy.addDataSource(newChainId2, newEmitter2); + + // Remove the first one added + await this.pythProxy.removeDataSource(newChainId, newEmitter); + + // Sign a batch with the removed data source + let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; + let rawBatch = generateRawBatchAttestation( + currentTimestamp - 5, + currentTimestamp, + 1337 + ); + let vm = await signAndEncodeVM( + 1, + 1, + newChainId, + newEmitter, + 0, + rawBatch, + [testSigner1PK], + 0, + 0 + ); + + await expectRevert( + this.pythProxy.updatePriceFeeds(["0x" + vm]), + "invalid data source chain/emitter ID" + ); + }); + + // Governance + + // Logics that apply to all governance messages + it("Make sure invalid magic and module won't work", async function () { + // First 4 bytes of data are magic and the second byte after that is module + const data = new governance.SetValidPeriodInstruction( + governance.CHAINS.ethereum, + BigInt(10) + ).serialize(); + + const wrongMagic = Buffer.from(data); + wrongMagic[1] = 0; + + const vaaWrongMagic = await createVAAFromUint8Array( + wrongMagic, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaWrongMagic), + "invalid magic for GovernanceInstruction" + ); + + const wrongModule = Buffer.from(data); + wrongModule[4] = 0; + + const vaaWrongModule = await createVAAFromUint8Array( + wrongModule, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaWrongModule), + "invalid module for GovernanceInstruction" + ); + + const outOfBoundModule = Buffer.from(data); + outOfBoundModule[4] = 20; + + const vaaOutOfBoundModule = await createVAAFromUint8Array( + outOfBoundModule, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaOutOfBoundModule), + "Panic: Enum value out of bounds." + ); + }); + + it("Make sure governance with wrong sender won't work", async function () { + const data = new governance.SetValidPeriodInstruction( + governance.CHAINS.ethereum, + BigInt(10) + ).serialize(); + + const vaaWrongEmitter = await createVAAFromUint8Array( + data, + testGovernanceChainId, + "0x0000000000000000000000000000000000000000000000000000000000001111", + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaWrongEmitter), + "VAA is not coming from the governance data source" + ); + + const vaaWrongChain = await createVAAFromUint8Array( + data, + governance.CHAINS.karura, + testGovernanceEmitter, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaWrongChain), + "VAA is not coming from the governance data source" + ); + }); + + it("Make sure governance with only target chain id and 0 work", async function () { + const wrongChainData = new governance.SetValidPeriodInstruction( + governance.CHAINS.solana, + BigInt(10) + ).serialize(); + + const wrongChainVaa = await createVAAFromUint8Array( + wrongChainData, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(wrongChainVaa), + "invalid target chain for this governance instruction" + ); + + const dataForAllChains = new governance.SetValidPeriodInstruction( + governance.CHAINS.unset, + BigInt(10) + ).serialize(); + + const vaaForAllChains = await createVAAFromUint8Array( + dataForAllChains, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await this.pythProxy.executeGovernanceInstruction(vaaForAllChains); + + const dataForEth = new governance.SetValidPeriodInstruction( + governance.CHAINS.ethereum, + BigInt(10) + ).serialize(); + + const vaaForEth = await createVAAFromUint8Array( + dataForEth, + testGovernanceChainId, + testGovernanceEmitter, + 2 + ); + + await this.pythProxy.executeGovernanceInstruction(vaaForEth); + }); + + it("Make sure that governance messages are executed in order and cannot be reused", async function () { + const data = new governance.SetValidPeriodInstruction( + governance.CHAINS.ethereum, + BigInt(10) + ).serialize(); + + const vaaSeq1 = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await this.pythProxy.executeGovernanceInstruction(vaaSeq1), + // Replaying shouldn't work + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaSeq1), + "VAA is older than the last executed governance VAA" + ); + + const vaaSeq2 = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 2 + ); + + await this.pythProxy.executeGovernanceInstruction(vaaSeq2), + // Replaying shouldn't work + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaSeq1), + "VAA is older than the last executed governance VAA" + ); + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaaSeq2), + "VAA is older than the last executed governance VAA" + ); + }); + + // Per governance type logic + it("Upgrading the contract with chain id 0 is invalid", async function () { + const newImplementation = await PythUpgradable.new(); + + const data = new governance.EthereumUpgradeContractInstruction( + governance.CHAINS.unset, // 0 + new governance.HexString20Bytes(newImplementation.address) + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaa), + "upgrade with chain id 0 is not possible" + ); + }); + + it("Upgrading the contract should work", async function () { + const newImplementation = await PythUpgradable.new(); + + const data = new governance.EthereumUpgradeContractInstruction( + governance.CHAINS.ethereum, + new governance.HexString20Bytes(newImplementation.address) + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); + + // Couldn't get the oldImplementation address. + expectEvent(receipt, "ContractUpgraded", { + newImplementation: newImplementation.address, + }); + expectEvent(receipt, "Upgraded", { + implementation: newImplementation.address, + }); + }); + + it("Upgrading the contract to a non-pyth contract won't work", async function () { + const newImplementation = await MockUpgradeableProxy.new(); + + const data = new governance.EthereumUpgradeContractInstruction( + governance.CHAINS.ethereum, + new governance.HexString20Bytes(newImplementation.address) + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + // Calling a non-existing method will cause a revert with no explanation. + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaa), + "revert" + ); + }); + + it("Transferring governance data source should work", async function () { + const newEmitterAddress = + "0x0000000000000000000000000000000000000000000000000000000000001111"; + const newEmitterChain = governance.CHAINS.acala; + + const claimInstructionData = + new governance.RequestGovernanceDataSourceTransferInstruction( + governance.CHAINS.unset, + 1 + ).serialize(); + + const claimVaaHexString = await createVAAFromUint8Array( + claimInstructionData, + newEmitterChain, + newEmitterAddress, + 1 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(claimVaaHexString), + "VAA is not coming from the governance data source" + ); + + const claimVaa = Buffer.from(claimVaaHexString.substring(2), "hex"); + + const data = + new governance.AuthorizeGovernanceDataSourceTransferInstruction( + governance.CHAINS.unset, + claimVaa + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + const oldGovernanceDataSource = await this.pythProxy.governanceDataSource(); + + const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); + + const newGovernanceDataSource = await this.pythProxy.governanceDataSource(); + + expectEvent(receipt, "GovernanceDataSourceSet", { + oldDataSource: oldGovernanceDataSource, + newDataSource: newGovernanceDataSource, + }); + + expect(newGovernanceDataSource.chainId).equal(newEmitterChain.toString()); + expect(newGovernanceDataSource.emitterAddress).equal(newEmitterAddress); + + // Verifies the data source has changed. + await expectRevert( + this.pythProxy.executeGovernanceInstruction(vaa), + "VAA is not coming from the governance data source" + ); + + // Make sure a claim vaa does not get executed + + const claimLonely = + new governance.RequestGovernanceDataSourceTransferInstruction( + governance.CHAINS.unset, + 2 + ).serialize(); + + const claimLonelyVaa = await createVAAFromUint8Array( + claimLonely, + newEmitterChain, + newEmitterAddress, + 2 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(claimLonelyVaa), + "RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message" + ); + + // Transfer back the ownership to the old governance data source without increasing + // the governance index should not work + + // A wrong vaa that does not move the governance index + const transferBackClaimInstructionDataWrong = + new governance.RequestGovernanceDataSourceTransferInstruction( + governance.CHAINS.unset, + 1 // The same governance data source index => Should fail + ).serialize(); + + const transferBackClaimVaaHexStringWrong = await createVAAFromUint8Array( + transferBackClaimInstructionDataWrong, + testGovernanceChainId, + testGovernanceEmitter, + 2 + ); + + const transferBackClaimVaaWrong = Buffer.from( + transferBackClaimVaaHexStringWrong.substring(2), + "hex" + ); + + const transferBackDataWrong = + new governance.AuthorizeGovernanceDataSourceTransferInstruction( + governance.CHAINS.unset, + transferBackClaimVaaWrong + ).serialize(); + + const transferBackVaaWrong = await createVAAFromUint8Array( + transferBackDataWrong, + newEmitterChain, + newEmitterAddress, + 2 + ); + + await expectRevert( + this.pythProxy.executeGovernanceInstruction(transferBackVaaWrong), + "cannot upgrade to an older governance data source" + ); + }); + + it("Setting data sources should work", async function () { + const data = new governance.SetDataSourcesInstruction( + governance.CHAINS.ethereum, + [ + new governance.DataSource( + governance.CHAINS.acala, + new governance.HexString32Bytes( + "0x0000000000000000000000000000000000000000000000000000000000001111" + ) + ), + ] + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + const oldDataSources = await this.pythProxy.validDataSources(); + + const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); + expectEvent(receipt, "DataSourcesSet", { + oldDataSources: oldDataSources, + newDataSources: await this.pythProxy.validDataSources(), + }); + + assert.isTrue( + await this.pythProxy.isValidDataSource( + governance.CHAINS.acala, + "0x0000000000000000000000000000000000000000000000000000000000001111" + ) + ); + assert.isFalse( + await this.pythProxy.isValidDataSource( + testPyth2WormholeChainId, + testPyth2WormholeEmitter + ) + ); + + let rawBatch = generateRawBatchAttestation(100, 100, 1337); + await expectRevert( + updatePriceFeeds(this.pythProxy, [rawBatch]), + "invalid data source chain/emitter ID" + ); + + await updatePriceFeeds( + this.pythProxy, + [rawBatch], + 0, + governance.CHAINS.acala, + "0x0000000000000000000000000000000000000000000000000000000000001111" + ); + }); + + it("Setting fee should work", async function () { + const data = new governance.SetFeeInstruction( + governance.CHAINS.ethereum, + BigInt(5), + BigInt(3) // 5*10**3 = 5000 + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + const oldFee = await this.pythProxy.singleUpdateFeeInWei(); + + const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); + expectEvent(receipt, "FeeSet", { + oldFee: oldFee, + newFee: await this.pythProxy.singleUpdateFeeInWei(), + }); + + assert.equal(await this.pythProxy.singleUpdateFeeInWei(), "5000"); + + let rawBatch = generateRawBatchAttestation(100, 100, 1337); + await expectRevert( + updatePriceFeeds(this.pythProxy, [rawBatch], 0), + insufficientFeeError + ); + + await updatePriceFeeds(this.pythProxy, [rawBatch], 5000); + }); + + it("Setting valid period should work", async function () { + const data = new governance.SetValidPeriodInstruction( + governance.CHAINS.ethereum, + BigInt(0) + ).serialize(); + + const vaa = await createVAAFromUint8Array( + data, + testGovernanceChainId, + testGovernanceEmitter, + 1 + ); + + const oldValidPeriod = await this.pythProxy.validTimePeriodSeconds(); + + const receipt = await this.pythProxy.executeGovernanceInstruction(vaa); + expectEvent(receipt, "ValidPeriodSet", { + oldValidPeriod: oldValidPeriod, + newValidPeriod: await this.pythProxy.validTimePeriodSeconds(), + }); + + assert.equal(await this.pythProxy.validTimePeriodSeconds(), "0"); + + // The behaviour of valid time period is extensively tested before, + // and adding it here will cause more complexity (and is not so short). + }); + + // Renounce ownership works + it("Renouncing ownership should work", async function () { + await this.pythProxy.updateValidTimePeriodSeconds(100); + await this.pythProxy.renounceOwnership(); + await expectRevert( + this.pythProxy.updateValidTimePeriodSeconds(60), + "Ownable: caller is not the owner" + ); + }); + + // Version + + it("Make sure version is the npm package version", async function () { + const contractVersion = await this.pythProxy.version(); + const { version } = require("../package.json"); + + expect(contractVersion).equal(version); + }); +}); + +const signAndEncodeVM = async function ( + timestamp, + nonce, + emitterChainId, + emitterAddress, + sequence, + data, + signers, + guardianSetIndex, + consistencyLevel +) { + const body = [ + web3.eth.abi.encodeParameter("uint32", timestamp).substring(2 + (64 - 8)), + web3.eth.abi.encodeParameter("uint32", nonce).substring(2 + (64 - 8)), + web3.eth.abi + .encodeParameter("uint16", emitterChainId) + .substring(2 + (64 - 4)), + web3.eth.abi.encodeParameter("bytes32", emitterAddress).substring(2), + web3.eth.abi.encodeParameter("uint64", sequence).substring(2 + (64 - 16)), + web3.eth.abi + .encodeParameter("uint8", consistencyLevel) + .substring(2 + (64 - 2)), + data.substr(2), + ]; + + const hash = web3.utils.soliditySha3( + web3.utils.soliditySha3("0x" + body.join("")) + ); + + let signatures = ""; + + for (let i in signers) { + const ec = new elliptic.ec("secp256k1"); + const key = ec.keyFromPrivate(signers[i]); + const signature = key.sign(hash.substr(2), { canonical: true }); + + const packSig = [ + web3.eth.abi.encodeParameter("uint8", i).substring(2 + (64 - 2)), + zeroPadBytes(signature.r.toString(16), 32), + zeroPadBytes(signature.s.toString(16), 32), + web3.eth.abi + .encodeParameter("uint8", signature.recoveryParam) + .substr(2 + (64 - 2)), + ]; + + signatures += packSig.join(""); + } + + const vm = [ + web3.eth.abi.encodeParameter("uint8", 1).substring(2 + (64 - 2)), + web3.eth.abi + .encodeParameter("uint32", guardianSetIndex) + .substring(2 + (64 - 8)), + web3.eth.abi + .encodeParameter("uint8", signers.length) + .substring(2 + (64 - 2)), + + signatures, + body.join(""), + ].join(""); + + return vm; +}; + +function zeroPadBytes(value, length) { + while (value.length < 2 * length) { + value = "0" + value; + } + return value; +} + +async function createVAAFromUint8Array( + dataBuffer, + emitterChainId, + emitterAddress, + sequence +) { + const dataHex = "0x" + dataBuffer.toString("hex"); + return ( + "0x" + + (await signAndEncodeVM( + 0, + 0, + emitterChainId.toString(), + emitterAddress, + sequence, + dataHex, + [testSigner1PK], + 0, + 0 + )) + ); } // There is no way to check event with given args has not emitted with expectEvent // or how many times an event was emitted. This function is implemented to count // the matching events and is used for the mentioned purposes. function getNumMatchingEvents(receipt, eventName, args) { - let matchCnt = 0; - for (let log of receipt.logs) { - if (log.event === eventName) { - let match = true; - for (let argKey in args) { - if (log.args[argKey].toString() !== args[argKey].toString()) { - match = false; - break; - } - } - if (match) { - matchCnt ++; - } + let matchCnt = 0; + for (let log of receipt.logs) { + if (log.event === eventName) { + let match = true; + for (let argKey in args) { + if (log.args[argKey].toString() !== args[argKey].toString()) { + match = false; + break; } + } + if (match) { + matchCnt++; + } } - return matchCnt; + } + return matchCnt; } function expectEventNotEmittedWithArgs(receipt, eventName, args) { - const matches = getNumMatchingEvents(receipt, eventName, args); - assert(matches === 0, `Expected no matching emitted event. But found ${matches}.`); + const matches = getNumMatchingEvents(receipt, eventName, args); + assert( + matches === 0, + `Expected no matching emitted event. But found ${matches}.` + ); } function expectEventMultipleTimes(receipt, eventName, args, cnt) { - const matches = getNumMatchingEvents(receipt, eventName, args); - assert(matches === cnt, `Expected ${cnt} event matches, found ${matches}.`); + const matches = getNumMatchingEvents(receipt, eventName, args); + assert(matches === cnt, `Expected ${cnt} event matches, found ${matches}.`); } diff --git a/ethereum/truffle-config.js b/ethereum/truffle-config.js index d8f6a278..327045e1 100644 --- a/ethereum/truffle-config.js +++ b/ethereum/truffle-config.js @@ -70,10 +70,11 @@ module.exports = { gasPrice: 5500000000, }, bnb_testnet: { - provider: () => new HDWalletProvider( - process.env.MNEMONIC, - "https://data-seed-prebsc-1-s1.binance.org:8545" - ), + provider: () => + new HDWalletProvider( + process.env.MNEMONIC, + "https://data-seed-prebsc-1-s1.binance.org:8545" + ), network_id: "97", confirmations: 10, networkCheckTimeout: 1000000, @@ -95,7 +96,8 @@ module.exports = { provider: () => { return new HDWalletProvider( process.env.MNEMONIC, - "https://polygon-testnet-rpc.allthatnode.com:8545") + "https://polygon-testnet-rpc.allthatnode.com:8545" + ); }, network_id: "80001", }, @@ -111,10 +113,11 @@ module.exports = { gasPrice: 30000000000, }, fuji: { - provider: () => new HDWalletProvider( - process.env.MNEMONIC, - "https://api.avax-test.network/ext/bc/C/rpc" - ), + provider: () => + new HDWalletProvider( + process.env.MNEMONIC, + "https://api.avax-test.network/ext/bc/C/rpc" + ), network_id: "43113", }, oasis: { @@ -146,7 +149,7 @@ module.exports = { return new HDWalletProvider( process.env.MNEMONIC, "https://testnet.aurora.dev" - ) + ); }, network_id: 0x4e454153, gas: 10000000, @@ -165,10 +168,7 @@ module.exports = { }, optimism: { provider: () => { - return new HDWalletProvider( - process.env.MNEMONIC, - "https://1rpc.io/op" - ); + return new HDWalletProvider(process.env.MNEMONIC, "https://1rpc.io/op"); }, network_id: 10, }, @@ -186,7 +186,7 @@ module.exports = { return new HDWalletProvider( process.env.MNEMONIC, "https://rpc.ftm.tools/" - ) + ); }, network_id: 250, gas: 8000000, @@ -198,7 +198,7 @@ module.exports = { return new HDWalletProvider( process.env.MNEMONIC, "https://rpc.testnet.fantom.network/" - ) + ); }, network_id: 0xfa2, gas: 8000000, @@ -209,16 +209,16 @@ module.exports = { return new HDWalletProvider( process.env.MNEMONIC, "https://forno.celo.org" - ) + ); }, network_id: 42220, - }, + }, celo_alfajores_testnet: { provider: () => { return new HDWalletProvider( process.env.MNEMONIC, "https://alfajores-forno.celo-testnet.org" - ) + ); }, network_id: 44787, }, diff --git a/ethereum/truffle-verify-constants.patch b/ethereum/truffle-verify-constants.patch index fb291117..68e19a83 100644 --- a/ethereum/truffle-verify-constants.patch +++ b/ethereum/truffle-verify-constants.patch @@ -23,7 +23,7 @@ + 421611: 'https://api-testnet.arbiscan.io/api', 80001: 'https://api-testnet.polygonscan.com/api' } - + @@ -18,16 +28,25 @@ 3: 'https://ropsten.etherscan.io/address', 4: 'https://rinkeby.etherscan.io/address', diff --git a/solana/keys/p2w_owner.json b/solana/keys/p2w_owner.json index 2e0e3842..5c7a38f0 100644 --- a/solana/keys/p2w_owner.json +++ b/solana/keys/p2w_owner.json @@ -1 +1,6 @@ -[39,20,181,104,82,27,70,145,227,136,168,14,170,24,33,88,145,152,180,229,219,142,247,114,237,79,52,97,84,65,213,172,49,165,99,116,254,135,110,132,214,114,59,200,109,253,45,43,74,172,107,84,162,223,23,15,78,167,240,137,234,123,4,231] \ No newline at end of file +[ + 39, 20, 181, 104, 82, 27, 70, 145, 227, 136, 168, 14, 170, 24, 33, 88, 145, + 152, 180, 229, 219, 142, 247, 114, 237, 79, 52, 97, 84, 65, 213, 172, 49, 165, + 99, 116, 254, 135, 110, 132, 214, 114, 59, 200, 109, 253, 45, 43, 74, 172, + 107, 84, 162, 223, 23, 15, 78, 167, 240, 137, 234, 123, 4, 231 +] diff --git a/solana/keys/pyth_program.json b/solana/keys/pyth_program.json index e46168f6..1c13dad7 100644 --- a/solana/keys/pyth_program.json +++ b/solana/keys/pyth_program.json @@ -1 +1,6 @@ -[151,156,152,229,131,186,5,254,107,42,234,87,191,209,182,237,170,57,174,150,37,14,5,58,100,237,114,141,46,22,155,104,10,20,225,112,227,95,250,0,102,170,119,34,187,74,144,163,181,123,233,253,191,6,2,70,127,227,138,51,98,209,205,172] \ No newline at end of file +[ + 151, 156, 152, 229, 131, 186, 5, 254, 107, 42, 234, 87, 191, 209, 182, 237, + 170, 57, 174, 150, 37, 14, 5, 58, 100, 237, 114, 141, 46, 22, 155, 104, 10, + 20, 225, 112, 227, 95, 250, 0, 102, 170, 119, 34, 187, 74, 144, 163, 181, 123, + 233, 253, 191, 6, 2, 70, 127, 227, 138, 51, 98, 209, 205, 172 +] diff --git a/solana/keys/pyth_publisher.json b/solana/keys/pyth_publisher.json index 60eb8789..cd159a05 100644 --- a/solana/keys/pyth_publisher.json +++ b/solana/keys/pyth_publisher.json @@ -1 +1,6 @@ -[62,189,176,181,215,49,125,17,130,43,109,83,115,112,151,110,117,239,235,54,205,209,6,255,76,27,210,115,206,166,217,165,250,48,211,191,77,246,195,18,170,246,162,103,141,129,14,143,127,4,243,114,79,112,11,46,90,174,215,2,63,42,134,56] \ No newline at end of file +[ + 62, 189, 176, 181, 215, 49, 125, 17, 130, 43, 109, 83, 115, 112, 151, 110, + 117, 239, 235, 54, 205, 209, 6, 255, 76, 27, 210, 115, 206, 166, 217, 165, + 250, 48, 211, 191, 77, 246, 195, 18, 170, 246, 162, 103, 141, 129, 14, 143, + 127, 4, 243, 114, 79, 112, 11, 46, 90, 174, 215, 2, 63, 42, 134, 56 +] diff --git a/solana/keys/solana-devnet.json b/solana/keys/solana-devnet.json index 4867babe..491cad05 100644 --- a/solana/keys/solana-devnet.json +++ b/solana/keys/solana-devnet.json @@ -1 +1,6 @@ -[14,173,153,4,176,224,201,111,32,237,183,185,159,247,22,161,89,84,215,209,212,137,10,92,157,49,29,192,101,164,152,70,87,65,8,174,214,157,175,126,98,90,54,24,100,177,247,77,19,112,47,44,165,109,233,102,14,86,109,29,134,145,132,141] +[ + 14, 173, 153, 4, 176, 224, 201, 111, 32, 237, 183, 185, 159, 247, 22, 161, 89, + 84, 215, 209, 212, 137, 10, 92, 157, 49, 29, 192, 101, 164, 152, 70, 87, 65, + 8, 174, 214, 157, 175, 126, 98, 90, 54, 24, 100, 177, 247, 77, 19, 112, 47, + 44, 165, 109, 233, 102, 14, 86, 109, 29, 134, 145, 132, 141 +] diff --git a/solana/pyth2wormhole/Cargo.lock b/solana/pyth2wormhole/Cargo.lock index 165dff9a..37bb0154 100644 --- a/solana/pyth2wormhole/Cargo.lock +++ b/solana/pyth2wormhole/Cargo.lock @@ -2642,7 +2642,7 @@ dependencies = [ [[package]] name = "pyth2wormhole-client" -version = "1.0.0-rc3" +version = "1.0.0" dependencies = [ "borsh", "clap 3.1.18", diff --git a/solana/pyth2wormhole/client/src/main.rs b/solana/pyth2wormhole/client/src/main.rs index 2112a63f..e945c970 100644 --- a/solana/pyth2wormhole/client/src/main.rs +++ b/solana/pyth2wormhole/client/src/main.rs @@ -10,11 +10,9 @@ use std::{ }; use clap::Parser; -use futures::{ - future::{ - Future, - TryFutureExt, - }, +use futures::future::{ + Future, + TryFutureExt, }; use generic_array::GenericArray; use log::{ @@ -24,7 +22,10 @@ use log::{ warn, LevelFilter, }; -use sha3::{Digest, Sha3_256}; +use sha3::{ + Digest, + Sha3_256, +}; use solana_client::{ nonblocking::rpc_client::RpcClient, rpc_config::RpcTransactionConfig, @@ -32,9 +33,7 @@ use solana_client::{ use solana_program::pubkey::Pubkey; use solana_sdk::{ commitment_config::CommitmentConfig, - signature::{ - read_keypair_file, - }, + signature::read_keypair_file, signer::keypair::Keypair, }; use solana_transaction_status::UiTransactionEncoding; @@ -204,13 +203,7 @@ async fn main() -> Result<(), ErrBox> { )); if daemon { - handle_attest_daemon_mode( - rpc_cfg, - payer, - p2w_addr, - attestation_cfg, - ) - .await?; + handle_attest_daemon_mode(rpc_cfg, payer, p2w_addr, attestation_cfg).await?; } else { handle_attest_non_daemon_mode( attestation_cfg, @@ -326,7 +319,7 @@ async fn handle_attest_daemon_mode( &rpc_cfg, &p2w_addr, &payer, - message_q_mtx.clone() + message_q_mtx.clone(), )); // Quit old sched futures @@ -344,7 +337,7 @@ async fn handle_attest_daemon_mode( &rpc_cfg, &p2w_addr, &payer, - message_q_mtx.clone() + message_q_mtx.clone(), )), new_cfg_hash, )); @@ -358,7 +351,7 @@ async fn handle_attest_daemon_mode( if remaining == Duration::from_secs(0) { warn!( - "Processing took more than desired mapping lookup interval of {} seconds, not sleeping. Consider increasing {}", + "Processing took more than desired mapping lookup interval of {} seconds, not sleeping. Consider increasing {}", target.as_secs(), // stringify prints the up-to-date setting name automatically stringify!(attestation_cfg.mapping_reload_interval_mins) @@ -498,7 +491,6 @@ fn prepare_attestation_sched_jobs( let batch_count = batches.len(); - // Create attestation scheduling routines; see attestation_sched_job() for details let attestation_sched_futs = batches.into_iter().enumerate().map(|(idx, batch)| { attestation_sched_job(AttestationSchedJobArgs { diff --git a/solana/pyth2wormhole/client/tests/test_set_is_active.rs b/solana/pyth2wormhole/client/tests/test_set_is_active.rs index 6571e47a..54756fef 100644 --- a/solana/pyth2wormhole/client/tests/test_set_is_active.rs +++ b/solana/pyth2wormhole/client/tests/test_set_is_active.rs @@ -78,15 +78,20 @@ async fn test_setting_is_active_works() -> Result<(), p2wc::ErrBoxSend> { clone_keypair(&ops_owner), false, ctx.last_blockhash, - ).map_err(|e| e.to_string())?; + ) + .map_err(|e| e.to_string())?; - ctx.banks_client.process_transaction(set_is_active_false_tx).await?; + ctx.banks_client + .process_transaction(set_is_active_false_tx) + .await?; + + let config = ctx + .banks_client + .get_account_data_with_borsh::(p2w_config_addr) + .await?; - let config = ctx.banks_client. - get_account_data_with_borsh::(p2w_config_addr).await?; - assert!(!config.is_active); - + // Setting to true should work let set_is_active_true_tx = p2wc::gen_set_is_active_tx( clone_keypair(&ctx.payer), @@ -94,13 +99,18 @@ async fn test_setting_is_active_works() -> Result<(), p2wc::ErrBoxSend> { clone_keypair(&ops_owner), true, ctx.last_blockhash, - ).map_err(|e| e.to_string())?; + ) + .map_err(|e| e.to_string())?; - ctx.banks_client.process_transaction(set_is_active_true_tx).await?; + ctx.banks_client + .process_transaction(set_is_active_true_tx) + .await?; + + let config = ctx + .banks_client + .get_account_data_with_borsh::(p2w_config_addr) + .await?; - let config = ctx.banks_client. - get_account_data_with_borsh::(p2w_config_addr).await?; - assert!(config.is_active); // A wrong signer cannot handle it @@ -111,9 +121,14 @@ async fn test_setting_is_active_works() -> Result<(), p2wc::ErrBoxSend> { clone_keypair(&ctx.payer), true, ctx.last_blockhash, - ).map_err(|e| e.to_string())?; + ) + .map_err(|e| e.to_string())?; - assert!(ctx.banks_client.process_transaction(set_is_active_true_tx).await.is_err()); + assert!(ctx + .banks_client + .process_transaction(set_is_active_true_tx) + .await + .is_err()); Ok(()) } @@ -161,7 +176,7 @@ async fn test_setting_is_active_does_not_work_without_ops_owner() -> Result<(), let mut ctx = p2w_test.start_with_context().await; - // No one could should be able to handle + // No one could should be able to handle // For example pyth_owner is used here. let set_is_active_true_tx = p2wc::gen_set_is_active_tx( clone_keypair(&ctx.payer), @@ -169,9 +184,14 @@ async fn test_setting_is_active_does_not_work_without_ops_owner() -> Result<(), pyth_owner, true, ctx.last_blockhash, - ).map_err(|e| e.to_string())?; + ) + .map_err(|e| e.to_string())?; - assert!(ctx.banks_client.process_transaction(set_is_active_true_tx).await.is_err()); + assert!(ctx + .banks_client + .process_transaction(set_is_active_true_tx) + .await + .is_err()); Ok(()) } diff --git a/solana/pyth2wormhole/governance/Cargo.toml b/solana/pyth2wormhole/governance/Cargo.toml index 85a3b82d..68143d0a 100644 --- a/solana/pyth2wormhole/governance/Cargo.toml +++ b/solana/pyth2wormhole/governance/Cargo.toml @@ -11,4 +11,4 @@ solana-sdk = "=1.10.31" pyth2wormhole-client = {path = "../client/"} hex = "0.4.3" remote-executor = {path = "../../../pythnet/remote-executor/programs/remote-executor/"} -borsh = "0.9.3" \ No newline at end of file +borsh = "0.9.3" diff --git a/solana/pyth2wormhole/program/src/migrate.rs b/solana/pyth2wormhole/program/src/migrate.rs index 3ad1666d..171fbc8f 100644 --- a/solana/pyth2wormhole/program/src/migrate.rs +++ b/solana/pyth2wormhole/program/src/migrate.rs @@ -1,19 +1,19 @@ //! Instruction used to migrate on-chain configuration from an older format use solana_program::{ + program::invoke, program_error::ProgramError, pubkey::Pubkey, rent::Rent, system_instruction, system_program, sysvar::Sysvar, - program::invoke, }; use solitaire::{ trace, - AccountState, AccountSize, + AccountState, CreationLamports, ExecutionContext, FromAccounts, @@ -80,7 +80,7 @@ pub fn migrate(ctx: &ExecutionContext, accs: &mut Migrate, data: ()) -> SoliResu .create(ctx, accs.payer.info().key, CreationLamports::Exempt)?; accs.new_config.1 = Pyth2WormholeConfig::from(old_config.clone()); - // Adjust new config lamports + // Adjust new config lamports // NOTE(2022-09-29): Necessary due to PythNet rent calculation // differences, remove when solitaire supports Rent::get()? let mut acc_lamports = accs.new_config.info().lamports(); diff --git a/solana/pyth2wormhole/program/src/set_is_active.rs b/solana/pyth2wormhole/program/src/set_is_active.rs index e6e9e875..4071e1e3 100644 --- a/solana/pyth2wormhole/program/src/set_is_active.rs +++ b/solana/pyth2wormhole/program/src/set_is_active.rs @@ -34,7 +34,7 @@ pub fn set_is_active( new_is_active: bool, ) -> SoliResult<()> { let cfg_struct: &mut Pyth2WormholeConfig = &mut accs.config; // unpack Data via nested Deref impls - match &cfg_struct.ops_owner { + match &cfg_struct.ops_owner { None => Err(SolitaireError::InvalidOwner(*accs.ops_owner.info().key)), Some(current_ops_owner) => { if current_ops_owner != accs.ops_owner.info().key { @@ -42,13 +42,11 @@ pub fn set_is_active( "Ops owner account mismatch (expected {:?})", current_ops_owner ); - return Err(SolitaireError::InvalidOwner( - *accs.ops_owner.info().key, - )); + return Err(SolitaireError::InvalidOwner(*accs.ops_owner.info().key)); } - + cfg_struct.is_active = new_is_active; - + Ok(()) } } diff --git a/solana/rust-toolchain b/solana/pyth2wormhole/rust-toolchain similarity index 91% rename from solana/rust-toolchain rename to solana/pyth2wormhole/rust-toolchain index 48511633..34123a90 100644 --- a/solana/rust-toolchain +++ b/solana/pyth2wormhole/rust-toolchain @@ -3,4 +3,4 @@ # with the version we're using. [toolchain] channel = "nightly-2022-02-24" -profile = "minimal" \ No newline at end of file +profile = "minimal" diff --git a/solana/rustfmt.toml b/solana/pyth2wormhole/rustfmt.toml similarity index 100% rename from solana/rustfmt.toml rename to solana/pyth2wormhole/rustfmt.toml diff --git a/third_party/pyth/evm-watcher/jest.config.js b/third_party/pyth/evm-watcher/jest.config.js index e86e13ba..21a1e973 100644 --- a/third_party/pyth/evm-watcher/jest.config.js +++ b/third_party/pyth/evm-watcher/jest.config.js @@ -1,5 +1,5 @@ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', + preset: "ts-jest", + testEnvironment: "node", }; diff --git a/third_party/pyth/evm-watcher/src/events.ts b/third_party/pyth/evm-watcher/src/events.ts index bfccfcb0..e7388e36 100644 --- a/third_party/pyth/evm-watcher/src/events.ts +++ b/third_party/pyth/evm-watcher/src/events.ts @@ -1,48 +1,48 @@ -import { HexString, NumberString, UnixTimestampString } from "./utils" +import { HexString, NumberString, UnixTimestampString } from "./utils"; export type PriceFeedUpdateEventValues = { - id: HexString, - fresh: boolean, - chainId: NumberString, - sequenceNumber: NumberString, - lastPublishTime: UnixTimestampString, - publishTime: UnixTimestampString, - price: NumberString, - conf: NumberString -} + id: HexString; + fresh: boolean; + chainId: NumberString; + sequenceNumber: NumberString; + lastPublishTime: UnixTimestampString; + publishTime: UnixTimestampString; + price: NumberString; + conf: NumberString; +}; export type PriceFeedInfo = PriceFeedUpdateEventValues; export type BatchPriceFeedUpdateEventValues = { - chainId: NumberString, - sequenceNumber: NumberString, - batchSize: NumberString, - freshPricesInBatch: NumberString, -} + chainId: NumberString; + sequenceNumber: NumberString; + batchSize: NumberString; + freshPricesInBatch: NumberString; +}; export type BatchPriceFeedInfo = BatchPriceFeedUpdateEventValues & { priceUpdates: PriceFeedUpdateEventValues[]; -} +}; export type UpdatePriceFeedsEventValues = { - sender: HexString, - batchCount: NumberString, - fee: NumberString, + sender: HexString; + batchCount: NumberString; + fee: NumberString; }; export type UpdatePriceFeedsInfo = UpdatePriceFeedsEventValues & { batchUpdates: BatchPriceFeedInfo[]; -} +}; export type UpdatePriceFeedsAggregateInfo = { - txHash: HexString, - txFrom: HexString, - txTo?: HexString, - block: number, - timestamp: UnixTimestampString, - rawInput: string, - gasUsage: number, - gasPrice: NumberString, - effectiveGasPrice?: number, - updatePriceFeedsInfo: UpdatePriceFeedsInfo, // Assuming there is only one UpdatePriceFeeds Event in a transaction -} + txHash: HexString; + txFrom: HexString; + txTo?: HexString; + block: number; + timestamp: UnixTimestampString; + rawInput: string; + gasUsage: number; + gasPrice: NumberString; + effectiveGasPrice?: number; + updatePriceFeedsInfo: UpdatePriceFeedsInfo; // Assuming there is only one UpdatePriceFeeds Event in a transaction +}; diff --git a/third_party/pyth/evm-watcher/src/handler.ts b/third_party/pyth/evm-watcher/src/handler.ts index b821cf45..ed024f5d 100644 --- a/third_party/pyth/evm-watcher/src/handler.ts +++ b/third_party/pyth/evm-watcher/src/handler.ts @@ -2,7 +2,7 @@ import { UpdatePriceFeedsAggregateInfo } from "./events"; import { Watcher } from "./watcher"; export class Handler { - private watchers: Watcher[]; + private watchers: Watcher[]; constructor() { this.watchers = []; diff --git a/third_party/pyth/evm-watcher/src/index.ts b/third_party/pyth/evm-watcher/src/index.ts index ff847704..02b4c1e8 100644 --- a/third_party/pyth/evm-watcher/src/index.ts +++ b/third_party/pyth/evm-watcher/src/index.ts @@ -7,10 +7,13 @@ console.log("Loading config file .env"); require("dotenv").config(); const handler = new Handler(); -const listener = new Listener({ - wsEndpoint: envOrErr('WS_ENDPOINT'), - pythContract: envOrErr('PYTH_CONTRACT'), -}, handler); +const listener = new Listener( + { + wsEndpoint: envOrErr("WS_ENDPOINT"), + pythContract: envOrErr("PYTH_CONTRACT"), + }, + handler +); // Initialize Watchers const jsonLogger = new JsonLogger(); diff --git a/third_party/pyth/evm-watcher/src/listener.ts b/third_party/pyth/evm-watcher/src/listener.ts index b181ee17..f7c25902 100644 --- a/third_party/pyth/evm-watcher/src/listener.ts +++ b/third_party/pyth/evm-watcher/src/listener.ts @@ -6,16 +6,32 @@ import { AbiItem } from "web3-utils"; import IPythABI from "@pythnetwork/pyth-sdk-solidity/abis/IPyth.json"; import { Handler } from "./handler"; import LRUCache from "lru-cache"; -import { HexString, NumberString, sleep, UnixTimestampString, waitForCondition } from "./utils"; -import { BatchPriceFeedInfo, BatchPriceFeedUpdateEventValues, PriceFeedInfo, UpdatePriceFeedsAggregateInfo, UpdatePriceFeedsEventValues, UpdatePriceFeedsInfo } from "./events"; +import { + HexString, + NumberString, + sleep, + UnixTimestampString, + waitForCondition, +} from "./utils"; +import { + BatchPriceFeedInfo, + BatchPriceFeedUpdateEventValues, + PriceFeedInfo, + UpdatePriceFeedsAggregateInfo, + UpdatePriceFeedsEventValues, + UpdatePriceFeedsInfo, +} from "./events"; type ListenerConfig = { - wsEndpoint: string, - pythContract: string + wsEndpoint: string; + pythContract: string; }; type BatchHash = string; -function getBatchId(chainId: NumberString, sequenceNumber: NumberString): BatchHash { +function getBatchId( + chainId: NumberString, + sequenceNumber: NumberString +): BatchHash { return `${chainId}-${sequenceNumber}`; } @@ -32,21 +48,24 @@ export class Listener { const wsProvider = new WebsocketProvider(config.wsEndpoint, { clientConfig: { keepalive: true, - keepaliveInterval: 30000 + keepaliveInterval: 30000, }, reconnect: { auto: true, delay: 1000, onTimeout: true, - } + }, }); this.web3 = new Web3(wsProvider); - this.pythContract = new this.web3.eth.Contract(IPythABI as AbiItem[], config.pythContract); + this.pythContract = new this.web3.eth.Contract( + IPythABI as AbiItem[], + config.pythContract + ); this.handler = handler; - this.blockToTimestamp = new LRUCache({max: 10000}); - this.batchPrices = new LRUCache({max: 10000}); - this.txBatches = new LRUCache({max: 10000}); + this.blockToTimestamp = new LRUCache({ max: 10000 }); + this.batchPrices = new LRUCache({ max: 10000 }); + this.txBatches = new LRUCache({ max: 10000 }); } async getEffectiveGasPrice(txhash: string): Promise { @@ -60,115 +79,149 @@ export class Listener { } start() { - this.web3.eth.subscribe('newBlockHeaders', (_error: Error, blockHeader) => { - this.blockToTimestamp.set(blockHeader.number, blockHeader.timestamp.toString()); + this.web3.eth.subscribe("newBlockHeaders", (_error: Error, blockHeader) => { + this.blockToTimestamp.set( + blockHeader.number, + blockHeader.timestamp.toString() + ); }); - this.pythContract.events.PriceFeedUpdate(undefined, async (_error: Error, event: EventData) => { - const priceFeedInfo: PriceFeedInfo = { - id: event.returnValues.id, - fresh: event.returnValues.fresh, - chainId: event.returnValues.chainId, - sequenceNumber: event.returnValues.sequenceNumber, - lastPublishTime: event.returnValues.lastPublishTime, - publishTime: event.returnValues.publishTime, - price: event.returnValues.price, - conf: event.returnValues.conf, + this.pythContract.events.PriceFeedUpdate( + undefined, + async (_error: Error, event: EventData) => { + const priceFeedInfo: PriceFeedInfo = { + id: event.returnValues.id, + fresh: event.returnValues.fresh, + chainId: event.returnValues.chainId, + sequenceNumber: event.returnValues.sequenceNumber, + lastPublishTime: event.returnValues.lastPublishTime, + publishTime: event.returnValues.publishTime, + price: event.returnValues.price, + conf: event.returnValues.conf, + }; + + const batchHash = getBatchId( + priceFeedInfo.chainId, + priceFeedInfo.sequenceNumber + ); + if (this.batchPrices.has(batchHash) === false) { + this.batchPrices.set(batchHash, []); + } + this.batchPrices.get(batchHash)!.push(priceFeedInfo); } + ); - const batchHash = getBatchId(priceFeedInfo.chainId, priceFeedInfo.sequenceNumber); - if (this.batchPrices.has(batchHash) === false) { - this.batchPrices.set(batchHash, []) + this.pythContract.events.BatchPriceFeedUpdate( + undefined, + async (_error: Error, event: EventData) => { + const batchValues: BatchPriceFeedUpdateEventValues = { + chainId: event.returnValues.chainId, + sequenceNumber: event.returnValues.sequenceNumber, + batchSize: event.returnValues.batchSize, + freshPricesInBatch: event.returnValues.freshPricesInBatch, + }; + + const batchHash = getBatchId( + batchValues.chainId, + batchValues.sequenceNumber + ); + if (this.batchPrices.has(batchHash) === false) { + this.batchPrices.set(batchHash, []); + } + + const batchSize = Number(batchValues.batchSize); + const waitForPricesCondition = () => + this.batchPrices.has(batchHash) && + this.batchPrices.get(batchHash)!.length == batchSize; + const result = await waitForCondition(waitForPricesCondition, 5000); + if (result === false) { + console.error( + `The price list for ${batchHash} didn't complete. Reason: Timeout` + ); + return; + } + + const batchInfo: BatchPriceFeedInfo = { + priceUpdates: this.batchPrices.get(batchHash)!, + ...batchValues, + }; + + const txHash = event.transactionHash; + if (this.txBatches.has(txHash) === false) { + this.txBatches.set(txHash, []); + } + this.txBatches.get(txHash)!.push(batchInfo); } - this.batchPrices.get(batchHash)!.push(priceFeedInfo); - }); + ); - this.pythContract.events.BatchPriceFeedUpdate(undefined, async (_error: Error, event: EventData) => { - const batchValues: BatchPriceFeedUpdateEventValues = { - chainId: event.returnValues.chainId, - sequenceNumber: event.returnValues.sequenceNumber, - batchSize: event.returnValues.batchSize, - freshPricesInBatch: event.returnValues.freshPricesInBatch, - }; + this.pythContract.events.UpdatePriceFeeds( + undefined, + async (_error: Error, event: EventData) => { + const updateValues: UpdatePriceFeedsEventValues = { + sender: event.returnValues.sender, + batchCount: event.returnValues.batchCount, + fee: event.returnValues.fee, + }; - const batchHash = getBatchId(batchValues.chainId, batchValues.sequenceNumber); - if (this.batchPrices.has(batchHash) === false) { - this.batchPrices.set(batchHash, []) + const txHash = event.transactionHash; + + if (this.txBatches.has(txHash) === false) { + this.txBatches.set(txHash, []); + } + + const batchCount = Number(updateValues.batchCount); + const waitForBatchesCondition = () => + this.txBatches.has(txHash) && + this.txBatches.get(txHash)!.length == batchCount; + const waitForBatchesResult = await waitForCondition( + waitForBatchesCondition, + 5000 + ); + if (waitForBatchesResult === false) { + console.error( + `Couldn't fetch all batches in transaction ${txHash}. Reason: Timeout` + ); + return; + } + + const updatePriceFeedsInfo: UpdatePriceFeedsInfo = { + batchUpdates: this.txBatches.get(txHash)!, + ...updateValues, + }; + + const waitForTimestampCondition = () => + this.blockToTimestamp.has(event.blockNumber); + const waitForTimestampResult = await waitForCondition( + waitForTimestampCondition, + 5000 + ); + if (waitForTimestampResult === false) { + console.error( + `Couldn't fetch timestamp of transaction ${txHash}. Reason: Timeout` + ); + return; + } + + const blockTimestamp = this.blockToTimestamp.get(event.blockNumber)!; + + const tx = await this.web3.eth.getTransaction(txHash); + + const updatePriceFeedsAggregateInfo: UpdatePriceFeedsAggregateInfo = { + block: event.blockNumber, + gasPrice: tx.gasPrice, + effectiveGasPrice: await this.getEffectiveGasPrice(txHash), + gasUsage: tx.gas, + rawInput: tx.input, + timestamp: blockTimestamp, + txFrom: tx.from, + txTo: tx.to || undefined, + txHash: txHash, + updatePriceFeedsInfo: updatePriceFeedsInfo, + }; + + this.handler.dispatchEvent(updatePriceFeedsAggregateInfo); } - - const batchSize = Number(batchValues.batchSize) - const waitForPricesCondition = () => this.batchPrices.has(batchHash) && this.batchPrices.get(batchHash)!.length == batchSize; - const result = await waitForCondition(waitForPricesCondition, 5000); - if (result === false) { - console.error(`The price list for ${batchHash} didn't complete. Reason: Timeout`); - return; - } - - const batchInfo: BatchPriceFeedInfo = { - priceUpdates: this.batchPrices.get(batchHash)!, - ...batchValues, - } - - const txHash = event.transactionHash; - if (this.txBatches.has(txHash) === false) { - this.txBatches.set(txHash, []) - } - this.txBatches.get(txHash)!.push(batchInfo); - }); - - this.pythContract.events.UpdatePriceFeeds(undefined, async (_error: Error, event: EventData) => { - const updateValues: UpdatePriceFeedsEventValues = { - sender: event.returnValues.sender, - batchCount: event.returnValues.batchCount, - fee: event.returnValues.fee, - }; - - const txHash = event.transactionHash; - - if (this.txBatches.has(txHash) === false) { - this.txBatches.set(txHash, []) - } - - const batchCount = Number(updateValues.batchCount); - const waitForBatchesCondition = () => this.txBatches.has(txHash) && this.txBatches.get(txHash)!.length == batchCount; - const waitForBatchesResult = await waitForCondition(waitForBatchesCondition, 5000); - if (waitForBatchesResult === false) { - console.error(`Couldn't fetch all batches in transaction ${txHash}. Reason: Timeout`); - return; - } - - const updatePriceFeedsInfo: UpdatePriceFeedsInfo = { - batchUpdates: this.txBatches.get(txHash)!, - ...updateValues, - } - - const waitForTimestampCondition = () => this.blockToTimestamp.has(event.blockNumber); - const waitForTimestampResult = await waitForCondition(waitForTimestampCondition, 5000); - if (waitForTimestampResult === false) { - console.error(`Couldn't fetch timestamp of transaction ${txHash}. Reason: Timeout`); - return; - } - - const blockTimestamp = this.blockToTimestamp.get(event.blockNumber)!; - - const tx = await this.web3.eth.getTransaction(txHash); - - const updatePriceFeedsAggregateInfo: UpdatePriceFeedsAggregateInfo = { - block: event.blockNumber, - gasPrice: tx.gasPrice, - effectiveGasPrice: await this.getEffectiveGasPrice(txHash), - gasUsage: tx.gas, - rawInput: tx.input, - timestamp: blockTimestamp, - txFrom: tx.from, - txTo: tx.to || undefined, - txHash: txHash, - updatePriceFeedsInfo: updatePriceFeedsInfo, - } - - this.handler.dispatchEvent(updatePriceFeedsAggregateInfo); - }); - + ); } stop() { diff --git a/third_party/pyth/evm-watcher/src/utils.ts b/third_party/pyth/evm-watcher/src/utils.ts index a158a98a..cd047f5d 100644 --- a/third_party/pyth/evm-watcher/src/utils.ts +++ b/third_party/pyth/evm-watcher/src/utils.ts @@ -15,12 +15,17 @@ export function envOrErr(env: string): string { return String(process.env[env]); } -export async function waitForCondition(cond: () => boolean, timeoutInMs: number): Promise { +export async function waitForCondition( + cond: () => boolean, + timeoutInMs: number +): Promise { var timedOut = false; - setTimeout(() => {timedOut = true;}, timeoutInMs); + setTimeout(() => { + timedOut = true; + }, timeoutInMs); - while(timedOut === false && !cond()) { + while (timedOut === false && !cond()) { await sleep(100); } diff --git a/third_party/pyth/multisig-wh-message-builder/.eslintrc.js b/third_party/pyth/multisig-wh-message-builder/.eslintrc.js index 05ed88b2..fa1d1eb6 100644 --- a/third_party/pyth/multisig-wh-message-builder/.eslintrc.js +++ b/third_party/pyth/multisig-wh-message-builder/.eslintrc.js @@ -3,6 +3,5 @@ module.exports = { parser: "@typescript-eslint/parser", plugins: ["@typescript-eslint"], extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - rules: { - }, + rules: {}, }; diff --git a/third_party/pyth/multisig-wh-message-builder/.gitignore b/third_party/pyth/multisig-wh-message-builder/.gitignore index 1b4d4984..ed27b66d 100644 --- a/third_party/pyth/multisig-wh-message-builder/.gitignore +++ b/third_party/pyth/multisig-wh-message-builder/.gitignore @@ -2,4 +2,4 @@ node_modules lib .dccache -keys/ \ No newline at end of file +keys/ diff --git a/third_party/pyth/multisig-wh-message-builder/jest.config.js b/third_party/pyth/multisig-wh-message-builder/jest.config.js index e86e13ba..21a1e973 100644 --- a/third_party/pyth/multisig-wh-message-builder/jest.config.js +++ b/third_party/pyth/multisig-wh-message-builder/jest.config.js @@ -1,5 +1,5 @@ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', + preset: "ts-jest", + testEnvironment: "node", }; diff --git a/third_party/pyth/multisig-wh-message-builder/src/index.ts b/third_party/pyth/multisig-wh-message-builder/src/index.ts index 76dc9dd1..d87e25b5 100644 --- a/third_party/pyth/multisig-wh-message-builder/src/index.ts +++ b/third_party/pyth/multisig-wh-message-builder/src/index.ts @@ -29,22 +29,22 @@ type Cluster = "devnet" | "mainnet"; type WormholeNetwork = "TESTNET" | "MAINNET"; type Config = { - wormholeClusterName: WormholeNetwork, - wormholeRpcEndpoint: string, - vault: PublicKey, + wormholeClusterName: WormholeNetwork; + wormholeRpcEndpoint: string; + vault: PublicKey; }; const CONFIG: Record = { devnet: { wormholeClusterName: "TESTNET", vault: new PublicKey("6baWtW1zTUVMSJHJQVxDUXWzqrQeYBr6mu31j3bTKwY3"), - wormholeRpcEndpoint: "https://wormhole-v2-testnet-api.certus.one" + wormholeRpcEndpoint: "https://wormhole-v2-testnet-api.certus.one", }, mainnet: { wormholeClusterName: "MAINNET", vault: new PublicKey("FVQyHcooAtThJ83XFrNnv74BcinbRH3bRmfFamAHBfuj"), - wormholeRpcEndpoint: "https://wormhole-v2-mainnet-api.certus.one" - } + wormholeRpcEndpoint: "https://wormhole-v2-mainnet-api.certus.one", + }, }; program @@ -122,7 +122,7 @@ program squad, CONFIG[cluster].vault, new PublicKey(options.txPda), - options.payload, + options.payload ); }); @@ -169,10 +169,7 @@ program msAccount.authorityIndex ); const attesterProgramId = new PublicKey(options.attester); - const txKey = await createTx( - squad, - vaultPubkey - ); + const txKey = await createTx(squad, vaultPubkey); let isActive = undefined; if (options.isActive === "true") { @@ -381,10 +378,7 @@ async function getSquadsClient( return squad; } -async function createTx( - squad: Squads, - vault: PublicKey -): Promise { +async function createTx(squad: Squads, vault: PublicKey): Promise { const msAccount = await squad.getMultisig(vault); console.log("Creating new transaction..."); @@ -432,7 +426,8 @@ async function addInstructionsToTx( await squad.approveTransaction(txKey); console.log("Transaction approved."); console.log( - `Tx URL: https://mesh${cluster === "devnet" ? "-devnet" : "" + `Tx URL: https://mesh${ + cluster === "devnet" ? "-devnet" : "" }.squads.so/transactions/${vault.toBase58()}/tx/${txKey.toBase58()}` ); } @@ -486,7 +481,8 @@ async function getWormholeMessageIx( ) { const wormholeClusterName: WormholeNetwork = CONFIG[cluster].wormholeClusterName; - const wormholeAddress = wormholeUtils.CONTRACTS[wormholeClusterName].solana.core; + const wormholeAddress = + wormholeUtils.CONTRACTS[wormholeClusterName].solana.core; const { post_message_ix, fee_collector_address, state_address, parse_state } = await importCoreWasm(); const feeCollector = new PublicKey(fee_collector_address(wormholeAddress)); @@ -575,7 +571,7 @@ async function verifyWormholePayload( squad: Squads, vault: PublicKey, txPubkey: PublicKey, - payload: string, + payload: string ) { const msAccount = await squad.getMultisig(vault); const emitter = squad.getAuthorityPDA( @@ -587,18 +583,33 @@ async function verifyWormholePayload( const tx = await squad.getTransaction(txPubkey); if (tx.instructionIndex !== 2) { - throw new Error(`Expected 2 instructions in the transaction, found ${tx.instructionIndex + 1}`) + throw new Error( + `Expected 2 instructions in the transaction, found ${ + tx.instructionIndex + 1 + }` + ); } - const [ix1PubKey,] = getIxPDA(txPubkey, new anchor.BN(1), squad.multisigProgramId); - const [ix2PubKey,] = getIxPDA(txPubkey, new anchor.BN(2), squad.multisigProgramId); + const [ix1PubKey] = getIxPDA( + txPubkey, + new anchor.BN(1), + squad.multisigProgramId + ); + const [ix2PubKey] = getIxPDA( + txPubkey, + new anchor.BN(2), + squad.multisigProgramId + ); - const onChainInstructions = await squad.getInstructions([ix1PubKey, ix2PubKey]); + const onChainInstructions = await squad.getInstructions([ + ix1PubKey, + ix2PubKey, + ]); console.log(onChainInstructions[0]); console.log(onChainInstructions[1]); - const [messagePDA,] = getIxAuthorityPDA( + const [messagePDA] = getIxAuthorityPDA( txPubkey, new anchor.BN(1), squad.multisigProgramId @@ -614,15 +625,26 @@ async function verifyWormholePayload( ); console.log("Checking equality of the 1st instruction..."); - verifyOnChainInstruction(wormholeIxs[0], onChainInstructions[0] as InstructionAccount); + verifyOnChainInstruction( + wormholeIxs[0], + onChainInstructions[0] as InstructionAccount + ); console.log("Checking equality of the 2nd instruction..."); - verifyOnChainInstruction(wormholeIxs[1], onChainInstructions[1] as InstructionAccount); + verifyOnChainInstruction( + wormholeIxs[1], + onChainInstructions[1] as InstructionAccount + ); - console.log("✅ The transaction is verified to be created with the given payload."); + console.log( + "✅ The transaction is verified to be created with the given payload." + ); } -function verifyOnChainInstruction(instruction: TransactionInstruction, onChainInstruction: InstructionAccount) { +function verifyOnChainInstruction( + instruction: TransactionInstruction, + onChainInstruction: InstructionAccount +) { if (!instruction.programId.equals(onChainInstruction.programId)) { throw new Error( `Program id mismatch: Expected ${instruction.programId.toBase58()}, found ${onChainInstruction.programId.toBase58()}` @@ -638,8 +660,10 @@ function verifyOnChainInstruction(instruction: TransactionInstruction, onChainIn const onChainData = onChainInstruction.data as Buffer; if (!instruction.data.equals(onChainData)) { throw new Error( - `Instruction data mismatch. Expected ${instruction.data.toString('hex')}, Found ${onChainData.toString('hex')}` - ) + `Instruction data mismatch. Expected ${instruction.data.toString( + "hex" + )}, Found ${onChainData.toString("hex")}` + ); } } @@ -696,7 +720,8 @@ async function executeMultisigTx( const signature = await provider.sendAndConfirm(executeTx); console.log( - `Executed tx: https://explorer.solana.com/tx/${signature}${cluster === "devnet" ? "?cluster=devnet" : "" + `Executed tx: https://explorer.solana.com/tx/${signature}${ + cluster === "devnet" ? "?cluster=devnet" : "" }` ); diff --git a/third_party/pyth/p2w-relay/.dockerignore b/third_party/pyth/p2w-relay/.dockerignore index bbf96f0a..847a92af 100644 --- a/third_party/pyth/p2w-relay/.dockerignore +++ b/third_party/pyth/p2w-relay/.dockerignore @@ -1,3 +1,3 @@ /lib /node_modules -/src/evm \ No newline at end of file +/src/evm diff --git a/third_party/pyth/p2w-relay/.env.sample b/third_party/pyth/p2w-relay/.env.sample index 7337a7f2..f525a879 100644 --- a/third_party/pyth/p2w-relay/.env.sample +++ b/third_party/pyth/p2w-relay/.env.sample @@ -39,4 +39,4 @@ MAX_HEALTHY_NO_RELAY_DURATION_IN_SECONDS=120 # The default is to log the console with level info. LOG_DIR=/var/pyth_relay/logs -#LOG_LEVEL=debug \ No newline at end of file +#LOG_LEVEL=debug diff --git a/third_party/pyth/p2w-relay/.gitignore b/third_party/pyth/p2w-relay/.gitignore index a3385fc4..4751a6c3 100644 --- a/third_party/pyth/p2w-relay/.gitignore +++ b/third_party/pyth/p2w-relay/.gitignore @@ -1,4 +1,4 @@ /lib # EVM artifacts -/src/evm \ No newline at end of file +/src/evm diff --git a/third_party/pyth/p2w-relay/Dockerfile.pyth_relay b/third_party/pyth/p2w-relay/Dockerfile.pyth_relay index 14856001..b1f04e13 100644 --- a/third_party/pyth/p2w-relay/Dockerfile.pyth_relay +++ b/third_party/pyth/p2w-relay/Dockerfile.pyth_relay @@ -29,7 +29,7 @@ RUN npm ci && npm run build && npm cache clean --force # Add the code and compile ARG P2W_RELAY_REL_PATH=third_party/pyth/p2w-relay -WORKDIR ${P2W_BASE_PATH}/${P2W_RELAY_REL_PATH} +WORKDIR ${P2W_BASE_PATH}/${P2W_RELAY_REL_PATH} ADD --chown=pyth:pyth ${P2W_RELAY_REL_PATH} . RUN npm ci && npm run build && npm cache clean --force diff --git a/third_party/pyth/p2w-relay/src/listen.ts b/third_party/pyth/p2w-relay/src/listen.ts index bfaa88d4..a8f58bfd 100644 --- a/third_party/pyth/p2w-relay/src/listen.ts +++ b/third_party/pyth/p2w-relay/src/listen.ts @@ -14,7 +14,10 @@ import { subscribeSignedVAA, } from "@certusone/wormhole-spydk"; -import { parseBatchPriceAttestation, getBatchSummary } from "@pythnetwork/p2w-sdk-js"; +import { + parseBatchPriceAttestation, + getBatchSummary, +} from "@pythnetwork/p2w-sdk-js"; import { importCoreWasm } from "@certusone/wormhole-sdk/lib/cjs/solana/wasm"; @@ -153,7 +156,7 @@ async function processVaa(vaaBytes: string) { let batchAttestation; try { - batchAttestation = await parseBatchPriceAttestation( + batchAttestation = await parseBatchPriceAttestation( Buffer.from(parsedVAA.payload) ); } catch (e: any) { diff --git a/third_party/pyth/p2w-relay/src/relay/evm.ts b/third_party/pyth/p2w-relay/src/relay/evm.ts index 4cdf7b59..caeec87d 100644 --- a/third_party/pyth/p2w-relay/src/relay/evm.ts +++ b/third_party/pyth/p2w-relay/src/relay/evm.ts @@ -46,7 +46,9 @@ export class EvmRelay implements Relay { : null; const updateData = ["0x" + signedVAAs[i]]; - const updateFee = await this.p2wContract["getUpdateFee(bytes[])"](updateData); + const updateFee = await this.p2wContract["getUpdateFee(bytes[])"]( + updateData + ); let tx = this.p2wContract .updatePriceFeeds(updateData, { gasLimit: 2000000, value: updateFee }) diff --git a/third_party/pyth/p2w-relay/src/relay/terra.ts b/third_party/pyth/p2w-relay/src/relay/terra.ts index a93203e1..50e24ebc 100644 --- a/third_party/pyth/p2w-relay/src/relay/terra.ts +++ b/third_party/pyth/p2w-relay/src/relay/terra.ts @@ -175,11 +175,7 @@ export class TerraRelay implements Relay { } async query(priceId: PriceId) { - logger.info( - "Querying terra for price info for priceId [" + - priceId + - "]" - ); + logger.info("Querying terra for price info for priceId [" + priceId + "]"); const lcdClient = new LCDClient(this.lcdConfig); diff --git a/third_party/pyth/p2w-relay/src/worker.ts b/third_party/pyth/p2w-relay/src/worker.ts index 7de2c5b1..559f6fc1 100644 --- a/third_party/pyth/p2w-relay/src/worker.ts +++ b/third_party/pyth/p2w-relay/src/worker.ts @@ -8,7 +8,11 @@ import { Relay, RelayResult, RelayRetcode } from "./relay/iface"; import * as helpers from "./helpers"; import { logger } from "./helpers"; import { PromHelper } from "./promHelpers"; -import { BatchPriceAttestation, getBatchAttestationHashKey, getBatchSummary } from "@pythnetwork/p2w-sdk-js"; +import { + BatchPriceAttestation, + getBatchAttestationHashKey, + getBatchSummary, +} from "@pythnetwork/p2w-sdk-js"; const mutex = new Mutex(); let condition = new CondVar(); @@ -239,9 +243,7 @@ async function getPendingEventsAlreadyLocked( const first = pendingMap.entries().next(); logger.debug("processing event with key [" + first.value[0] + "]"); const pendingValue: PendingPayload = first.value[1]; - let pendingKey = getBatchAttestationHashKey( - pendingValue.batchAttestation - ); + let pendingKey = getBatchAttestationHashKey(pendingValue.batchAttestation); let currObj = productMap.get(pendingKey); if (currObj) { currObj.lastBatchAttestation = pendingValue.batchAttestation; diff --git a/third_party/pyth/p2w-sdk/js/.gitignore b/third_party/pyth/p2w-sdk/js/.gitignore index 4b2b9ce8..90d09611 100644 --- a/third_party/pyth/p2w-sdk/js/.gitignore +++ b/third_party/pyth/p2w-sdk/js/.gitignore @@ -30,4 +30,4 @@ yarn-error.log* /src/proto # build -/lib \ No newline at end of file +/lib diff --git a/third_party/pyth/p2w-sdk/js/README.md b/third_party/pyth/p2w-sdk/js/README.md index b4b79075..61d4d545 100644 --- a/third_party/pyth/p2w-sdk/js/README.md +++ b/third_party/pyth/p2w-sdk/js/README.md @@ -1,7 +1,9 @@ # Pyth2wormhole SDK + This project contains a library for interacting with pyth2wormhole and adjacent APIs. # Install + For now, the in-house dependencies are referenced by relative path. The commands below will build those. For an automated version of this process, please refer to `p2w-integration-observer`'s Dockerfile and/or our [Tilt](https://tilt.dev) diff --git a/third_party/pyth/p2w-sdk/js/package-lock.json b/third_party/pyth/p2w-sdk/js/package-lock.json index bc2c5788..91d9b912 100644 --- a/third_party/pyth/p2w-sdk/js/package-lock.json +++ b/third_party/pyth/p2w-sdk/js/package-lock.json @@ -1,4621 +1,4621 @@ { - "name": "@pythnetwork/p2w-sdk-js", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@pythnetwork/p2w-sdk-js", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@certusone/wormhole-sdk": "0.2.1", - "@improbable-eng/grpc-web-node-http-transport": "^0.14.1", - "@pythnetwork/pyth-sdk-js": "^1.1.0" - }, - "devDependencies": { - "@openzeppelin/contracts": "^4.2.0", - "@typechain/ethers-v5": "^7.1.2", - "@types/long": "^4.0.1", - "@types/node": "^16.6.1", - "copy-dir": "^1.3.0", - "find": "^0.3.0", - "prettier": "^2.3.2", - "tslint": "^6.1.3", - "tslint-config-prettier": "^1.18.0", - "typescript": "^4.3.5" - }, - "peerDependencies": { - "@solana/web3.js": "^1.24.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@certusone/wormhole-sdk": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.2.1.tgz", - "integrity": "sha512-L85tiUHwnH4nbUEDgQtS2hNm3Q0IsUP29Z/DGbN2zggdvR0KTC6nLQ+LufCM6IcdUQYpYuwXjOYKD1Et8qc0mw==", - "dependencies": { - "@improbable-eng/grpc-web": "^0.14.0", - "@solana/spl-token": "^0.1.8", - "@solana/web3.js": "^1.24.0", - "@terra-money/terra.js": "^3.0.7", - "axios": "^0.24.0", - "bech32": "^2.0.0", - "js-base64": "^3.6.1", - "protobufjs": "^6.11.2", - "rxjs": "^7.3.0" - } - }, - "node_modules/@certusone/wormhole-sdk/node_modules/@improbable-eng/grpc-web": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", - "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", - "dependencies": { - "browser-headers": "^0.4.1" - }, - "peerDependencies": { - "google-protobuf": "^3.14.0" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.1.tgz", - "integrity": "sha512-0cqssYh6FXjlwKWBmLm3+zH2BNARoS5u/hxbz+LpQmcDB3w0W553h2btWui1/uZp2GBM/SI3KniTuMcYyHpA5w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz", - "integrity": "sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/networks": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/web": "^5.6.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz", - "integrity": "sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz", - "integrity": "sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/rlp": "^5.6.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz", - "integrity": "sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.0.tgz", - "integrity": "sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/properties": "^5.6.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz", - "integrity": "sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "bn.js": "^4.11.9" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz", - "integrity": "sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz", - "integrity": "sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.6.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.0.tgz", - "integrity": "sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abi": "^5.6.0", - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/transactions": "^5.6.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz", - "integrity": "sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.0.tgz", - "integrity": "sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/basex": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/pbkdf2": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/sha2": "^5.6.0", - "@ethersproject/signing-key": "^5.6.0", - "@ethersproject/strings": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/wordlists": "^5.6.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz", - "integrity": "sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hdnode": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/pbkdf2": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.0", - "@ethersproject/strings": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz", - "integrity": "sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", - "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.2.tgz", - "integrity": "sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz", - "integrity": "sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/sha2": "^5.6.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", - "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.4.tgz", - "integrity": "sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/basex": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/networks": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.0", - "@ethersproject/rlp": "^5.6.0", - "@ethersproject/sha2": "^5.6.0", - "@ethersproject/strings": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/web": "^5.6.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true, - "peer": true - }, - "node_modules/@ethersproject/random": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.0.tgz", - "integrity": "sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz", - "integrity": "sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.0.tgz", - "integrity": "sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", - "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.0.tgz", - "integrity": "sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/sha2": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz", - "integrity": "sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz", - "integrity": "sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/rlp": "^5.6.0", - "@ethersproject/signing-key": "^5.6.0" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.0.tgz", - "integrity": "sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.0.tgz", - "integrity": "sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/hdnode": "^5.6.0", - "@ethersproject/json-wallets": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.0", - "@ethersproject/signing-key": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/wordlists": "^5.6.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz", - "integrity": "sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/base64": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.0.tgz", - "integrity": "sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "node_modules/@improbable-eng/grpc-web": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", - "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", - "peer": true, - "dependencies": { - "browser-headers": "^0.4.1" - }, - "peerDependencies": { - "google-protobuf": "^3.14.0" - } - }, - "node_modules/@improbable-eng/grpc-web-node-http-transport": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.1.tgz", - "integrity": "sha512-ZsCTzI1iKUbmQjB5DNZSI5/hvdliuaPpS2h8mVj1QzynL3IFb5NrNnHVHbfcH1wbm26Ka6Z1CrKFGvKLrmbFIg==", - "peerDependencies": { - "@improbable-eng/grpc-web": ">=0.13.0" - } - }, - "node_modules/@openzeppelin/contracts": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", - "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==", - "dev": true - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" - }, - "node_modules/@pythnetwork/pyth-sdk-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-js/-/pyth-sdk-js-1.1.0.tgz", - "integrity": "sha512-IfZI/D+7HiA01TfzuA7Fh0SMhsE+hZWoI1pt48G+XMbNkXhiZG4lSQJRsnquSEY06YAFcAX2D66cFtV6BHy8IA==" - }, - "node_modules/@solana/buffer-layout": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz", - "integrity": "sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ==", - "dependencies": { - "buffer": "~6.0.3" - }, - "engines": { - "node": ">=5.10" - } - }, - "node_modules/@solana/spl-token": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz", - "integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==", - "dependencies": { - "@babel/runtime": "^7.10.5", - "@solana/web3.js": "^1.21.0", - "bn.js": "^5.1.0", - "buffer": "6.0.3", - "buffer-layout": "^1.2.0", - "dotenv": "10.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@solana/spl-token/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, - "node_modules/@solana/web3.js": { - "version": "1.39.1", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.39.1.tgz", - "integrity": "sha512-Q7XnWTAiU7n7GcoINDAAMLO7CJHpm5kPK46HKwJi2x0cusHQ3WFa7QEp6aPzH7tuf7yl/Kw1lYitcwTVOvqARA==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "@ethersproject/sha2": "^5.5.0", - "@solana/buffer-layout": "^4.0.0", - "bn.js": "^5.0.0", - "borsh": "^0.7.0", - "bs58": "^4.0.1", - "buffer": "6.0.1", - "cross-fetch": "^3.1.4", - "jayson": "^3.4.4", - "js-sha3": "^0.8.0", - "rpc-websockets": "^7.4.2", - "secp256k1": "^4.0.2", - "superstruct": "^0.14.2", - "tweetnacl": "^1.0.0" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/@solana/web3.js/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, - "node_modules/@solana/web3.js/node_modules/buffer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", - "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/@terra-money/terra.js": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.0.11.tgz", - "integrity": "sha512-qabXxsycWF1tEcFE3dG7FFXuIcXPlSeYgha5IYU+x4QNKiZuxT9Asi84HrCUSajQkZZ3N7ORfr+aGGE84HD+uw==", - "dependencies": { - "@terra-money/terra.proto": "^0.1.7", - "axios": "^0.26.1", - "bech32": "^2.0.0", - "bip32": "^2.0.6", - "bip39": "^3.0.3", - "bufferutil": "^4.0.3", - "decimal.js": "^10.2.1", - "jscrypto": "^1.0.1", - "readable-stream": "^3.6.0", - "secp256k1": "^4.0.2", - "tmp": "^0.2.1", - "utf-8-validate": "^5.0.5", - "ws": "^7.5.5" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@terra-money/terra.js/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/@terra-money/terra.js/node_modules/ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@terra-money/terra.proto": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", - "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", - "dependencies": { - "google-protobuf": "^3.17.3", - "long": "^4.0.0", - "protobufjs": "~6.11.2" - } - }, - "node_modules/@typechain/ethers-v5": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz", - "integrity": "sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - }, - "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/bytes": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^5.0.0", - "typescript": ">=4.0.0" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/lodash": { - "version": "4.14.182", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", - "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" - }, - "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "node_modules/@types/node": { - "version": "16.11.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.27.tgz", - "integrity": "sha512-C1pD3kgLoZ56Uuy5lhfOxie4aZlA3UMGLX9rXteq4WitEZH6Rl80mwactt9QG0w0gLFlN/kLBTFnGXtDVWvWQw==" - }, - "node_modules/@types/prettier": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", - "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", - "dev": true, - "peer": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", - "dev": true, - "peer": true - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "peer": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "dependencies": { - "follow-redirects": "^1.14.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, - "node_modules/bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - } - }, - "node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" - }, - "node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/borsh": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", - "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", - "dependencies": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" - } - }, - "node_modules/borsh/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "node_modules/browser-headers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", - "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-layout": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", - "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", - "engines": { - "node": ">=4.5" - } - }, - "node_modules/bufferutil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", - "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "deprecated": "CircularJSON is in maintenance only, flatted is its successor." - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/command-line-args": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", - "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", - "dev": true, - "peer": true, - "dependencies": { - "array-back": "^2.0.0", - "find-replace": "^1.0.3", - "typical": "^2.6.1" - }, - "bin": { - "command-line-args": "bin/cli.js" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/copy-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", - "dev": true - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "peer": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" - }, - "node_modules/delay": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "engines": { - "node": ">=10" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dependencies": { - "es6-promise": "^4.0.3" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ethers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.4.tgz", - "integrity": "sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "peer": true, - "dependencies": { - "@ethersproject/abi": "5.6.1", - "@ethersproject/abstract-provider": "5.6.0", - "@ethersproject/abstract-signer": "5.6.0", - "@ethersproject/address": "5.6.0", - "@ethersproject/base64": "5.6.0", - "@ethersproject/basex": "5.6.0", - "@ethersproject/bignumber": "5.6.0", - "@ethersproject/bytes": "5.6.1", - "@ethersproject/constants": "5.6.0", - "@ethersproject/contracts": "5.6.0", - "@ethersproject/hash": "5.6.0", - "@ethersproject/hdnode": "5.6.0", - "@ethersproject/json-wallets": "5.6.0", - "@ethersproject/keccak256": "5.6.0", - "@ethersproject/logger": "5.6.0", - "@ethersproject/networks": "5.6.2", - "@ethersproject/pbkdf2": "5.6.0", - "@ethersproject/properties": "5.6.0", - "@ethersproject/providers": "5.6.4", - "@ethersproject/random": "5.6.0", - "@ethersproject/rlp": "5.6.0", - "@ethersproject/sha2": "5.6.0", - "@ethersproject/signing-key": "5.6.0", - "@ethersproject/solidity": "5.6.0", - "@ethersproject/strings": "5.6.0", - "@ethersproject/transactions": "5.6.0", - "@ethersproject/units": "5.6.0", - "@ethersproject/wallet": "5.6.0", - "@ethersproject/web": "5.6.0", - "@ethersproject/wordlists": "5.6.0" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", - "engines": { - "node": "> 0.1.90" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/find": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", - "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", - "dev": true, - "dependencies": { - "traverse-chain": "~0.1.0" - } - }, - "node_modules/find-replace": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", - "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", - "dev": true, - "peer": true, - "dependencies": { - "array-back": "^1.0.4", - "test-value": "^2.1.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-replace/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "peer": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/google-protobuf": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.20.1.tgz", - "integrity": "sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw==" - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "peer": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/jayson": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.6.6.tgz", - "integrity": "sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ==", - "dependencies": { - "@types/connect": "^3.4.33", - "@types/express-serve-static-core": "^4.17.9", - "@types/lodash": "^4.14.159", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", - "lodash": "^4.17.20", - "uuid": "^8.3.2", - "ws": "^7.4.5" - }, - "bin": { - "jayson": "bin/jayson.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jayson/node_modules/@types/node": { - "version": "12.20.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.48.tgz", - "integrity": "sha512-4kxzqkrpwYtn6okJUcb2lfUu9ilnb3yhUOH6qX3nug8D2DupZ2drIkff2yJzYcNJVl3begnlcaBJ7tqiTTzjnQ==" - }, - "node_modules/js-base64": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", - "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jscrypto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.3.tgz", - "integrity": "sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ==", - "bin": { - "jscrypto": "bin/cli.js" - } - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "peer": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "peer": true - }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" - }, - "node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp-build": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", - "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/prettier": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", - "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rpc-websockets": { - "version": "7.4.17", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.17.tgz", - "integrity": "sha512-eolVi/qlXS13viIUH9aqrde902wzSLAai0IjmOZSRefp5I3CSG/vCnD0c0fDSYCWuEyUoRL1BHQA8K1baEUyow==", - "dependencies": { - "@babel/runtime": "^7.11.2", - "circular-json": "^0.5.9", - "eventemitter3": "^4.0.7", - "uuid": "^8.3.0", - "ws": "^7.4.5" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/kozjak" - }, - "optionalDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - } - }, - "node_modules/rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true, - "peer": true - }, - "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "hasInstallScript": true, - "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/superstruct": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", - "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "peer": true, - "dependencies": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/test-value/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "peer": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/text-encoding-utf-8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/traverse-chain": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", - "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", - "dev": true - }, - "node_modules/ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "peerDependencies": { - "typescript": ">=3.7.0" - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, - "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" - } - }, - "node_modules/tslint-config-prettier": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", - "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", - "dev": true, - "bin": { - "tslint-config-prettier-check": "bin/check.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/tslint/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/typechain": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-5.2.0.tgz", - "integrity": "sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw==", - "dev": true, - "peer": true, - "dependencies": { - "@types/prettier": "^2.1.1", - "command-line-args": "^4.0.7", - "debug": "^4.1.1", - "fs-extra": "^7.0.0", - "glob": "^7.1.6", - "js-sha3": "^0.8.0", - "lodash": "^4.17.15", - "mkdirp": "^1.0.4", - "prettier": "^2.1.2", - "ts-essentials": "^7.0.1" - }, - "bin": { - "typechain": "dist/cli/cli.js" - }, - "peerDependencies": { - "typescript": ">=4.1.0" - } - }, - "node_modules/typechain/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "node_modules/typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true, - "peer": true - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/utf-8-validate": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", - "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } + "name": "@pythnetwork/p2w-sdk-js", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@pythnetwork/p2w-sdk-js", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@certusone/wormhole-sdk": "0.2.1", + "@improbable-eng/grpc-web-node-http-transport": "^0.14.1", + "@pythnetwork/pyth-sdk-js": "^1.1.0" + }, + "devDependencies": { + "@openzeppelin/contracts": "^4.2.0", + "@typechain/ethers-v5": "^7.1.2", + "@types/long": "^4.0.1", + "@types/node": "^16.6.1", + "copy-dir": "^1.3.0", + "find": "^0.3.0", + "prettier": "^2.3.2", + "tslint": "^6.1.3", + "tslint-config-prettier": "^1.18.0", + "typescript": "^4.3.5" + }, + "peerDependencies": { + "@solana/web3.js": "^1.24.0" + } }, - "dependencies": { - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@certusone/wormhole-sdk": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.2.1.tgz", - "integrity": "sha512-L85tiUHwnH4nbUEDgQtS2hNm3Q0IsUP29Z/DGbN2zggdvR0KTC6nLQ+LufCM6IcdUQYpYuwXjOYKD1Et8qc0mw==", - "requires": { - "@improbable-eng/grpc-web": "^0.14.0", - "@solana/spl-token": "^0.1.8", - "@solana/web3.js": "^1.24.0", - "@terra-money/terra.js": "^3.0.7", - "axios": "^0.24.0", - "bech32": "^2.0.0", - "js-base64": "^3.6.1", - "protobufjs": "^6.11.2", - "rxjs": "^7.3.0" - }, - "dependencies": { - "@improbable-eng/grpc-web": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", - "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", - "requires": { - "browser-headers": "^0.4.1" - } - } - } - }, - "@ethersproject/abi": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.1.tgz", - "integrity": "sha512-0cqssYh6FXjlwKWBmLm3+zH2BNARoS5u/hxbz+LpQmcDB3w0W553h2btWui1/uZp2GBM/SI3KniTuMcYyHpA5w==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "@ethersproject/abstract-provider": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz", - "integrity": "sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/networks": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/web": "^5.6.0" - } - }, - "@ethersproject/abstract-signer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz", - "integrity": "sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0" - } - }, - "@ethersproject/address": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz", - "integrity": "sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/rlp": "^5.6.0" - } - }, - "@ethersproject/base64": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz", - "integrity": "sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0" - } - }, - "@ethersproject/basex": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.0.tgz", - "integrity": "sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/properties": "^5.6.0" - } - }, - "@ethersproject/bignumber": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz", - "integrity": "sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "bn.js": "^4.11.9" - } - }, - "@ethersproject/bytes": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz", - "integrity": "sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==", - "requires": { - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/constants": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz", - "integrity": "sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bignumber": "^5.6.0" - } - }, - "@ethersproject/contracts": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.0.tgz", - "integrity": "sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abi": "^5.6.0", - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/transactions": "^5.6.0" - } - }, - "@ethersproject/hash": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz", - "integrity": "sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "@ethersproject/hdnode": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.0.tgz", - "integrity": "sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/basex": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/pbkdf2": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/sha2": "^5.6.0", - "@ethersproject/signing-key": "^5.6.0", - "@ethersproject/strings": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/wordlists": "^5.6.0" - } - }, - "@ethersproject/json-wallets": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz", - "integrity": "sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hdnode": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/pbkdf2": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.0", - "@ethersproject/strings": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "@ethersproject/keccak256": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz", - "integrity": "sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "js-sha3": "0.8.0" - } - }, - "@ethersproject/logger": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", - "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==" - }, - "@ethersproject/networks": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.2.tgz", - "integrity": "sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/pbkdf2": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz", - "integrity": "sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/sha2": "^5.6.0" - } - }, - "@ethersproject/properties": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", - "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/providers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.4.tgz", - "integrity": "sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/basex": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/networks": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.0", - "@ethersproject/rlp": "^5.6.0", - "@ethersproject/sha2": "^5.6.0", - "@ethersproject/strings": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/web": "^5.6.0", - "bech32": "1.1.4", - "ws": "7.4.6" - }, - "dependencies": { - "bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true, - "peer": true - } - } - }, - "@ethersproject/random": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.0.tgz", - "integrity": "sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/rlp": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz", - "integrity": "sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/sha2": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.0.tgz", - "integrity": "sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA==", - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "hash.js": "1.1.7" - } - }, - "@ethersproject/signing-key": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", - "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "@ethersproject/solidity": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.0.tgz", - "integrity": "sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/sha2": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "@ethersproject/strings": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz", - "integrity": "sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/transactions": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz", - "integrity": "sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/rlp": "^5.6.0", - "@ethersproject/signing-key": "^5.6.0" - } - }, - "@ethersproject/units": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.0.tgz", - "integrity": "sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/constants": "^5.6.0", - "@ethersproject/logger": "^5.6.0" - } - }, - "@ethersproject/wallet": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.0.tgz", - "integrity": "sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abstract-provider": "^5.6.0", - "@ethersproject/abstract-signer": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/hdnode": "^5.6.0", - "@ethersproject/json-wallets": "^5.6.0", - "@ethersproject/keccak256": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/random": "^5.6.0", - "@ethersproject/signing-key": "^5.6.0", - "@ethersproject/transactions": "^5.6.0", - "@ethersproject/wordlists": "^5.6.0" - } - }, - "@ethersproject/web": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz", - "integrity": "sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/base64": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "@ethersproject/wordlists": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.0.tgz", - "integrity": "sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" - } - }, - "@improbable-eng/grpc-web": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", - "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", - "peer": true, - "requires": { - "browser-headers": "^0.4.1" - } - }, - "@improbable-eng/grpc-web-node-http-transport": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.1.tgz", - "integrity": "sha512-ZsCTzI1iKUbmQjB5DNZSI5/hvdliuaPpS2h8mVj1QzynL3IFb5NrNnHVHbfcH1wbm26Ka6Z1CrKFGvKLrmbFIg==", - "requires": {} - }, - "@openzeppelin/contracts": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", - "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==", - "dev": true - }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" - }, - "@pythnetwork/pyth-sdk-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-js/-/pyth-sdk-js-1.1.0.tgz", - "integrity": "sha512-IfZI/D+7HiA01TfzuA7Fh0SMhsE+hZWoI1pt48G+XMbNkXhiZG4lSQJRsnquSEY06YAFcAX2D66cFtV6BHy8IA==" - }, - "@solana/buffer-layout": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz", - "integrity": "sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ==", - "requires": { - "buffer": "~6.0.3" - } - }, - "@solana/spl-token": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz", - "integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==", - "requires": { - "@babel/runtime": "^7.10.5", - "@solana/web3.js": "^1.21.0", - "bn.js": "^5.1.0", - "buffer": "6.0.3", - "buffer-layout": "^1.2.0", - "dotenv": "10.0.0" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } - } - }, - "@solana/web3.js": { - "version": "1.39.1", - "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.39.1.tgz", - "integrity": "sha512-Q7XnWTAiU7n7GcoINDAAMLO7CJHpm5kPK46HKwJi2x0cusHQ3WFa7QEp6aPzH7tuf7yl/Kw1lYitcwTVOvqARA==", - "requires": { - "@babel/runtime": "^7.12.5", - "@ethersproject/sha2": "^5.5.0", - "@solana/buffer-layout": "^4.0.0", - "bn.js": "^5.0.0", - "borsh": "^0.7.0", - "bs58": "^4.0.1", - "buffer": "6.0.1", - "cross-fetch": "^3.1.4", - "jayson": "^3.4.4", - "js-sha3": "^0.8.0", - "rpc-websockets": "^7.4.2", - "secp256k1": "^4.0.2", - "superstruct": "^0.14.2", - "tweetnacl": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - }, - "buffer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", - "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - } - } - }, - "@terra-money/terra.js": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.0.11.tgz", - "integrity": "sha512-qabXxsycWF1tEcFE3dG7FFXuIcXPlSeYgha5IYU+x4QNKiZuxT9Asi84HrCUSajQkZZ3N7ORfr+aGGE84HD+uw==", - "requires": { - "@terra-money/terra.proto": "^0.1.7", - "axios": "^0.26.1", - "bech32": "^2.0.0", - "bip32": "^2.0.6", - "bip39": "^3.0.3", - "bufferutil": "^4.0.3", - "decimal.js": "^10.2.1", - "jscrypto": "^1.0.1", - "readable-stream": "^3.6.0", - "secp256k1": "^4.0.2", - "tmp": "^0.2.1", - "utf-8-validate": "^5.0.5", - "ws": "^7.5.5" - }, - "dependencies": { - "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "requires": { - "follow-redirects": "^1.14.8" - } - }, - "ws": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", - "requires": {} - } - } - }, - "@terra-money/terra.proto": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", - "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", - "requires": { - "google-protobuf": "^3.17.3", - "long": "^4.0.0", - "protobufjs": "~6.11.2" - } - }, - "@typechain/ethers-v5": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz", - "integrity": "sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==", - "dev": true, - "requires": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/lodash": { - "version": "4.14.182", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", - "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" - }, - "@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "@types/node": { - "version": "16.11.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.27.tgz", - "integrity": "sha512-C1pD3kgLoZ56Uuy5lhfOxie4aZlA3UMGLX9rXteq4WitEZH6Rl80mwactt9QG0w0gLFlN/kLBTFnGXtDVWvWQw==" - }, - "@types/prettier": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", - "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", - "dev": true, - "peer": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "requires": { - "@types/node": "*" - } - }, - "aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", - "dev": true, - "peer": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "peer": true, - "requires": { - "typical": "^2.6.1" - } - }, - "axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "requires": { - "follow-redirects": "^1.14.4" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "requires": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "dependencies": { - "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - } - } - }, - "bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "requires": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - }, - "dependencies": { - "@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" - } - } - }, - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "borsh": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", - "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", - "requires": { - "bn.js": "^5.2.0", - "bs58": "^4.0.0", - "text-encoding-utf-8": "^1.0.2" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-headers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", - "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "requires": { - "base-x": "^3.0.2" - } - }, - "bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "requires": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "buffer-layout": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", - "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==" - }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@certusone/wormhole-sdk": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.2.1.tgz", + "integrity": "sha512-L85tiUHwnH4nbUEDgQtS2hNm3Q0IsUP29Z/DGbN2zggdvR0KTC6nLQ+LufCM6IcdUQYpYuwXjOYKD1Et8qc0mw==", + "dependencies": { + "@improbable-eng/grpc-web": "^0.14.0", + "@solana/spl-token": "^0.1.8", + "@solana/web3.js": "^1.24.0", + "@terra-money/terra.js": "^3.0.7", + "axios": "^0.24.0", + "bech32": "^2.0.0", + "js-base64": "^3.6.1", + "protobufjs": "^6.11.2", + "rxjs": "^7.3.0" + } + }, + "node_modules/@certusone/wormhole-sdk/node_modules/@improbable-eng/grpc-web": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.1.tgz", + "integrity": "sha512-0cqssYh6FXjlwKWBmLm3+zH2BNARoS5u/hxbz+LpQmcDB3w0W553h2btWui1/uZp2GBM/SI3KniTuMcYyHpA5w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz", + "integrity": "sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/web": "^5.6.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz", + "integrity": "sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz", + "integrity": "sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz", + "integrity": "sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.0.tgz", + "integrity": "sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/properties": "^5.6.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz", + "integrity": "sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "bn.js": "^4.11.9" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz", + "integrity": "sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz", + "integrity": "sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.0.tgz", + "integrity": "sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.6.0", + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz", + "integrity": "sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.0.tgz", + "integrity": "sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/basex": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/pbkdf2": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/sha2": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0", + "@ethersproject/strings": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/wordlists": "^5.6.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz", + "integrity": "sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hdnode": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/pbkdf2": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.0", + "@ethersproject/strings": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz", + "integrity": "sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", + "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, + "node_modules/@ethersproject/networks": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.2.tgz", + "integrity": "sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz", + "integrity": "sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/sha2": "^5.6.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", + "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.4.tgz", + "integrity": "sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/basex": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", + "@ethersproject/sha2": "^5.6.0", + "@ethersproject/strings": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/web": "^5.6.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/providers/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true, + "peer": true + }, + "node_modules/@ethersproject/random": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.0.tgz", + "integrity": "sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz", + "integrity": "sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.0.tgz", + "integrity": "sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", + "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.0.tgz", + "integrity": "sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/sha2": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz", + "integrity": "sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz", + "integrity": "sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.0.tgz", + "integrity": "sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.0.tgz", + "integrity": "sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/hdnode": "^5.6.0", + "@ethersproject/json-wallets": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/wordlists": "^5.6.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz", + "integrity": "sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/base64": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.0.tgz", + "integrity": "sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@improbable-eng/grpc-web": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", + "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", + "peer": true, + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, + "node_modules/@improbable-eng/grpc-web-node-http-transport": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.1.tgz", + "integrity": "sha512-ZsCTzI1iKUbmQjB5DNZSI5/hvdliuaPpS2h8mVj1QzynL3IFb5NrNnHVHbfcH1wbm26Ka6Z1CrKFGvKLrmbFIg==", + "peerDependencies": { + "@improbable-eng/grpc-web": ">=0.13.0" + } + }, + "node_modules/@openzeppelin/contracts": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", + "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==", + "dev": true + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "node_modules/@pythnetwork/pyth-sdk-js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-js/-/pyth-sdk-js-1.1.0.tgz", + "integrity": "sha512-IfZI/D+7HiA01TfzuA7Fh0SMhsE+hZWoI1pt48G+XMbNkXhiZG4lSQJRsnquSEY06YAFcAX2D66cFtV6BHy8IA==" + }, + "node_modules/@solana/buffer-layout": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz", + "integrity": "sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ==", + "dependencies": { + "buffer": "~6.0.3" + }, + "engines": { + "node": ">=5.10" + } + }, + "node_modules/@solana/spl-token": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz", + "integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==", + "dependencies": { + "@babel/runtime": "^7.10.5", + "@solana/web3.js": "^1.21.0", + "bn.js": "^5.1.0", + "buffer": "6.0.3", + "buffer-layout": "^1.2.0", + "dotenv": "10.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@solana/spl-token/node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/@solana/web3.js": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.39.1.tgz", + "integrity": "sha512-Q7XnWTAiU7n7GcoINDAAMLO7CJHpm5kPK46HKwJi2x0cusHQ3WFa7QEp6aPzH7tuf7yl/Kw1lYitcwTVOvqARA==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@ethersproject/sha2": "^5.5.0", + "@solana/buffer-layout": "^4.0.0", + "bn.js": "^5.0.0", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.1", + "cross-fetch": "^3.1.4", + "jayson": "^3.4.4", + "js-sha3": "^0.8.0", + "rpc-websockets": "^7.4.2", + "secp256k1": "^4.0.2", + "superstruct": "^0.14.2", + "tweetnacl": "^1.0.0" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@solana/web3.js/node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/@solana/web3.js/node_modules/buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", + "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/@terra-money/terra.js": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.0.11.tgz", + "integrity": "sha512-qabXxsycWF1tEcFE3dG7FFXuIcXPlSeYgha5IYU+x4QNKiZuxT9Asi84HrCUSajQkZZ3N7ORfr+aGGE84HD+uw==", + "dependencies": { + "@terra-money/terra.proto": "^0.1.7", + "axios": "^0.26.1", + "bech32": "^2.0.0", + "bip32": "^2.0.6", + "bip39": "^3.0.3", + "bufferutil": "^4.0.3", + "decimal.js": "^10.2.1", + "jscrypto": "^1.0.1", + "readable-stream": "^3.6.0", + "secp256k1": "^4.0.2", + "tmp": "^0.2.1", + "utf-8-validate": "^5.0.5", + "ws": "^7.5.5" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@terra-money/terra.js/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/@terra-money/terra.js/node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { "bufferutil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", - "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", - "requires": { - "node-gyp-build": "^4.3.0" - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==" - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "command-line-args": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", - "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", - "dev": true, - "peer": true, - "requires": { - "array-back": "^2.0.0", - "find-replace": "^1.0.3", - "typical": "^2.6.1" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "copy-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", - "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", - "dev": true - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "requires": { - "node-fetch": "2.6.7" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "peer": true, - "requires": { - "ms": "2.1.2" - } - }, - "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" - }, - "delay": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==" - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "ethers": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.4.tgz", - "integrity": "sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ==", - "dev": true, - "peer": true, - "requires": { - "@ethersproject/abi": "5.6.1", - "@ethersproject/abstract-provider": "5.6.0", - "@ethersproject/abstract-signer": "5.6.0", - "@ethersproject/address": "5.6.0", - "@ethersproject/base64": "5.6.0", - "@ethersproject/basex": "5.6.0", - "@ethersproject/bignumber": "5.6.0", - "@ethersproject/bytes": "5.6.1", - "@ethersproject/constants": "5.6.0", - "@ethersproject/contracts": "5.6.0", - "@ethersproject/hash": "5.6.0", - "@ethersproject/hdnode": "5.6.0", - "@ethersproject/json-wallets": "5.6.0", - "@ethersproject/keccak256": "5.6.0", - "@ethersproject/logger": "5.6.0", - "@ethersproject/networks": "5.6.2", - "@ethersproject/pbkdf2": "5.6.0", - "@ethersproject/properties": "5.6.0", - "@ethersproject/providers": "5.6.4", - "@ethersproject/random": "5.6.0", - "@ethersproject/rlp": "5.6.0", - "@ethersproject/sha2": "5.6.0", - "@ethersproject/signing-key": "5.6.0", - "@ethersproject/solidity": "5.6.0", - "@ethersproject/strings": "5.6.0", - "@ethersproject/transactions": "5.6.0", - "@ethersproject/units": "5.6.0", - "@ethersproject/wallet": "5.6.0", - "@ethersproject/web": "5.6.0", - "@ethersproject/wordlists": "5.6.0" - } - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "find": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", - "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", - "dev": true, - "requires": { - "traverse-chain": "~0.1.0" - } - }, - "find-replace": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", - "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", - "dev": true, - "peer": true, - "requires": { - "array-back": "^1.0.4", - "test-value": "^2.1.0" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "peer": true, - "requires": { - "typical": "^2.6.0" - } - } - } - }, - "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "peer": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "google-protobuf": { - "version": "3.20.1", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.20.1.tgz", - "integrity": "sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw==" - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "peer": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "requires": {} - }, - "jayson": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.6.6.tgz", - "integrity": "sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ==", - "requires": { - "@types/connect": "^3.4.33", - "@types/express-serve-static-core": "^4.17.9", - "@types/lodash": "^4.14.159", - "@types/node": "^12.12.54", - "@types/ws": "^7.4.4", - "commander": "^2.20.3", - "delay": "^5.0.0", - "es6-promisify": "^5.0.0", - "eyes": "^0.1.8", - "isomorphic-ws": "^4.0.1", - "json-stringify-safe": "^5.0.1", - "JSONStream": "^1.3.5", - "lodash": "^4.17.20", - "uuid": "^8.3.2", - "ws": "^7.4.5" - }, - "dependencies": { - "@types/node": { - "version": "12.20.48", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.48.tgz", - "integrity": "sha512-4kxzqkrpwYtn6okJUcb2lfUu9ilnb3yhUOH6qX3nug8D2DupZ2drIkff2yJzYcNJVl3begnlcaBJ7tqiTTzjnQ==" - } - } - }, - "js-base64": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", - "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" - }, - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jscrypto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.3.tgz", - "integrity": "sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "peer": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "peer": true - }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" - }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-gyp-build": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", - "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "prettier": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", - "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", - "dev": true - }, - "protobufjs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", - "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "rpc-websockets": { - "version": "7.4.17", - "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.17.tgz", - "integrity": "sha512-eolVi/qlXS13viIUH9aqrde902wzSLAai0IjmOZSRefp5I3CSG/vCnD0c0fDSYCWuEyUoRL1BHQA8K1baEUyow==", - "requires": { - "@babel/runtime": "^7.11.2", - "bufferutil": "^4.0.1", - "circular-json": "^0.5.9", - "eventemitter3": "^4.0.7", - "utf-8-validate": "^5.0.2", - "uuid": "^8.3.0", - "ws": "^7.4.5" - } - }, - "rxjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", - "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true, - "peer": true - }, - "secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "requires": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "superstruct": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", - "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "peer": true, - "requires": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "peer": true, - "requires": { - "typical": "^2.6.0" - } - } - } - }, - "text-encoding-utf-8": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", - "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "requires": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - } - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "requires": { - "rimraf": "^3.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "traverse-chain": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", - "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", - "dev": true - }, - "ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "requires": {} - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tslint-config-prettier": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", - "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", - "dev": true - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "typechain": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-5.2.0.tgz", - "integrity": "sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw==", - "dev": true, - "peer": true, - "requires": { - "@types/prettier": "^2.1.1", - "command-line-args": "^4.0.7", - "debug": "^4.1.1", - "fs-extra": "^7.0.0", - "glob": "^7.1.6", - "js-sha3": "^0.8.0", - "lodash": "^4.17.15", - "mkdirp": "^1.0.4", - "prettier": "^2.1.2", - "ts-essentials": "^7.0.1" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "peer": true - } - } - }, - "typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", - "dev": true - }, - "typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true, - "peer": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "peer": true + "optional": true }, "utf-8-validate": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", - "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", - "requires": { - "node-gyp-build": "^4.3.0" - } + "optional": true + } + } + }, + "node_modules/@terra-money/terra.proto": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", + "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", + "dependencies": { + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@typechain/ethers-v5": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz", + "integrity": "sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "@ethersproject/abi": "^5.0.0", + "@ethersproject/bytes": "^5.0.0", + "@ethersproject/providers": "^5.0.0", + "ethers": "^5.1.3", + "typechain": "^5.0.0", + "typescript": ">=4.0.0" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "node_modules/@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "node_modules/@types/node": { + "version": "16.11.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.27.tgz", + "integrity": "sha512-C1pD3kgLoZ56Uuy5lhfOxie4aZlA3UMGLX9rXteq4WitEZH6Rl80mwactt9QG0w0gLFlN/kLBTFnGXtDVWvWQw==" + }, + "node_modules/@types/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", + "dev": true, + "peer": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", + "dev": true, + "peer": true + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "peer": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bip32": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", + "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", + "dependencies": { + "@types/node": "10.12.18", + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "tiny-secp256k1": "^1.1.3", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bip32/node_modules/@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + }, + "node_modules/bip39": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", + "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", + "dependencies": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + } + }, + "node_modules/bip39/node_modules/@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "dependencies": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + } + }, + "node_modules/borsh/node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "node_modules/browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, + "node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "engines": { + "node": ">=4.5" + } + }, + "node_modules/bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "deprecated": "CircularJSON is in maintenance only, flatted is its successor." + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/command-line-args": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", + "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^2.0.0", + "find-replace": "^1.0.3", + "typical": "^2.6.1" + }, + "bin": { + "command-line-args": "bin/cli.js" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/copy-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", + "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ethers": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.4.tgz", + "integrity": "sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" }, - "wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", - "requires": { - "bs58check": "<3.0.0" - } + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/abi": "5.6.1", + "@ethersproject/abstract-provider": "5.6.0", + "@ethersproject/abstract-signer": "5.6.0", + "@ethersproject/address": "5.6.0", + "@ethersproject/base64": "5.6.0", + "@ethersproject/basex": "5.6.0", + "@ethersproject/bignumber": "5.6.0", + "@ethersproject/bytes": "5.6.1", + "@ethersproject/constants": "5.6.0", + "@ethersproject/contracts": "5.6.0", + "@ethersproject/hash": "5.6.0", + "@ethersproject/hdnode": "5.6.0", + "@ethersproject/json-wallets": "5.6.0", + "@ethersproject/keccak256": "5.6.0", + "@ethersproject/logger": "5.6.0", + "@ethersproject/networks": "5.6.2", + "@ethersproject/pbkdf2": "5.6.0", + "@ethersproject/properties": "5.6.0", + "@ethersproject/providers": "5.6.4", + "@ethersproject/random": "5.6.0", + "@ethersproject/rlp": "5.6.0", + "@ethersproject/sha2": "5.6.0", + "@ethersproject/signing-key": "5.6.0", + "@ethersproject/solidity": "5.6.0", + "@ethersproject/strings": "5.6.0", + "@ethersproject/transactions": "5.6.0", + "@ethersproject/units": "5.6.0", + "@ethersproject/wallet": "5.6.0", + "@ethersproject/web": "5.6.0", + "@ethersproject/wordlists": "5.6.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/find": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", + "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", + "dev": true, + "dependencies": { + "traverse-chain": "~0.1.0" + } + }, + "node_modules/find-replace": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", + "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^1.0.4", + "test-value": "^2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "peer": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-protobuf": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.20.1.tgz", + "integrity": "sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw==" + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jayson": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.6.6.tgz", + "integrity": "sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ==", + "dependencies": { + "@types/connect": "^3.4.33", + "@types/express-serve-static-core": "^4.17.9", + "@types/lodash": "^4.14.159", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "lodash": "^4.17.20", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "bin": { + "jayson": "bin/jayson.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jayson/node_modules/@types/node": { + "version": "12.20.48", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.48.tgz", + "integrity": "sha512-4kxzqkrpwYtn6okJUcb2lfUu9ilnb3yhUOH6qX3nug8D2DupZ2drIkff2yJzYcNJVl3begnlcaBJ7tqiTTzjnQ==" + }, + "node_modules/js-base64": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", + "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jscrypto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.3.tgz", + "integrity": "sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ==", + "bin": { + "jscrypto": "bin/cli.js" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "peer": true + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rpc-websockets": { + "version": "7.4.17", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.17.tgz", + "integrity": "sha512-eolVi/qlXS13viIUH9aqrde902wzSLAai0IjmOZSRefp5I3CSG/vCnD0c0fDSYCWuEyUoRL1BHQA8K1baEUyow==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "circular-json": "^0.5.9", + "eventemitter3": "^4.0.7", + "uuid": "^8.3.0", + "ws": "^7.4.5" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + }, + "optionalDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + } + }, + "node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true, + "peer": true + }, + "node_modules/secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "hasInstallScript": true, + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/superstruct": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", + "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "peer": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "peer": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/tiny-secp256k1": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", + "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0", + "bn.js": "^4.11.8", + "create-hmac": "^1.1.7", + "elliptic": "^6.4.0", + "nan": "^2.13.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/traverse-chain": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", + "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", + "dev": true + }, + "node_modules/ts-essentials": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", + "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", + "dev": true, + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true, + "bin": { + "tslint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "node_modules/typechain": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-5.2.0.tgz", + "integrity": "sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/prettier": "^2.1.1", + "command-line-args": "^4.0.7", + "debug": "^4.1.1", + "fs-extra": "^7.0.0", + "glob": "^7.1.6", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.1.2", + "ts-essentials": "^7.0.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + }, + "peerDependencies": { + "typescript": ">=4.1.0" + } + }, + "node_modules/typechain/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + }, + "node_modules/typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true, + "peer": true + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", + "dependencies": { + "bs58check": "<3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/runtime": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@certusone/wormhole-sdk": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@certusone/wormhole-sdk/-/wormhole-sdk-0.2.1.tgz", + "integrity": "sha512-L85tiUHwnH4nbUEDgQtS2hNm3Q0IsUP29Z/DGbN2zggdvR0KTC6nLQ+LufCM6IcdUQYpYuwXjOYKD1Et8qc0mw==", + "requires": { + "@improbable-eng/grpc-web": "^0.14.0", + "@solana/spl-token": "^0.1.8", + "@solana/web3.js": "^1.24.0", + "@terra-money/terra.js": "^3.0.7", + "axios": "^0.24.0", + "bech32": "^2.0.0", + "js-base64": "^3.6.1", + "protobufjs": "^6.11.2", + "rxjs": "^7.3.0" + }, + "dependencies": { + "@improbable-eng/grpc-web": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz", + "integrity": "sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==", + "requires": { + "browser-headers": "^0.4.1" + } + } + } + }, + "@ethersproject/abi": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.6.1.tgz", + "integrity": "sha512-0cqssYh6FXjlwKWBmLm3+zH2BNARoS5u/hxbz+LpQmcDB3w0W553h2btWui1/uZp2GBM/SI3KniTuMcYyHpA5w==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.6.0.tgz", + "integrity": "sha512-oPMFlKLN+g+y7a79cLK3WiLcjWFnZQtXWgnLAbHZcN3s7L4v90UHpTOrLk+m3yr0gt+/h9STTM6zrr7PM8uoRw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/web": "^5.6.0" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.6.0.tgz", + "integrity": "sha512-WOqnG0NJKtI8n0wWZPReHtaLkDByPL67tn4nBaDAhmVq8sjHTPbCdz4DRhVu/cfTOvfy9w3iq5QZ7BX7zw56BQ==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0" + } + }, + "@ethersproject/address": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.0.tgz", + "integrity": "sha512-6nvhYXjbXsHPS+30sHZ+U4VMagFC/9zAk6Gd/h3S21YW4+yfb0WfRtaAIZ4kfM4rrVwqiy284LP0GtL5HXGLxQ==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.0" + } + }, + "@ethersproject/base64": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.6.0.tgz", + "integrity": "sha512-2Neq8wxJ9xHxCF9TUgmKeSh9BXJ6OAxWfeGWvbauPh8FuHEjamgHilllx8KkSd5ErxyHIX7Xv3Fkcud2kY9ezw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0" + } + }, + "@ethersproject/basex": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.6.0.tgz", + "integrity": "sha512-qN4T+hQd/Md32MoJpc69rOwLYRUXwjTlhHDIeUkUmiN/JyWkkLLMoG0TqvSQKNqZOMgN5stbUYN6ILC+eD7MEQ==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/properties": "^5.6.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.6.0.tgz", + "integrity": "sha512-VziMaXIUHQlHJmkv1dlcd6GY2PmT0khtAqaMctCIDogxkrarMzA9L94KN1NeXqqOfFD6r0sJT3vCTOFSmZ07DA==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "bn.js": "^4.11.9" + } + }, + "@ethersproject/bytes": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.6.1.tgz", + "integrity": "sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==", + "requires": { + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/constants": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.6.0.tgz", + "integrity": "sha512-SrdaJx2bK0WQl23nSpV/b1aq293Lh0sUaZT/yYKPDKn4tlAbkH96SPJwIhwSwTsoQQZxuh1jnqsKwyymoiBdWA==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bignumber": "^5.6.0" + } + }, + "@ethersproject/contracts": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.6.0.tgz", + "integrity": "sha512-74Ge7iqTDom0NX+mux8KbRUeJgu1eHZ3iv6utv++sLJG80FVuU9HnHeKVPfjd9s3woFhaFoQGf3B3iH/FrQmgw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abi": "^5.6.0", + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/transactions": "^5.6.0" + } + }, + "@ethersproject/hash": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.6.0.tgz", + "integrity": "sha512-fFd+k9gtczqlr0/BruWLAu7UAOas1uRRJvOR84uDf4lNZ+bTkGl366qvniUZHKtlqxBRU65MkOobkmvmpHU+jA==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "@ethersproject/hdnode": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.6.0.tgz", + "integrity": "sha512-61g3Jp3nwDqJcL/p4nugSyLrpl/+ChXIOtCEM8UDmWeB3JCAt5FoLdOMXQc3WWkc0oM2C0aAn6GFqqMcS/mHTw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/basex": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/pbkdf2": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/sha2": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0", + "@ethersproject/strings": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/wordlists": "^5.6.0" + } + }, + "@ethersproject/json-wallets": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.6.0.tgz", + "integrity": "sha512-fmh86jViB9r0ibWXTQipxpAGMiuxoqUf78oqJDlCAJXgnJF024hOOX7qVgqsjtbeoxmcLwpPsXNU0WEe/16qPQ==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hdnode": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/pbkdf2": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.0", + "@ethersproject/strings": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "@ethersproject/keccak256": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.6.0.tgz", + "integrity": "sha512-tk56BJ96mdj/ksi7HWZVWGjCq0WVl/QvfhFQNeL8fxhBlGoP+L80uDCiQcpJPd+2XxkivS3lwRm3E0CXTfol0w==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "js-sha3": "0.8.0" + } + }, + "@ethersproject/logger": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.6.0.tgz", + "integrity": "sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==" + }, + "@ethersproject/networks": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.6.2.tgz", + "integrity": "sha512-9uEzaJY7j5wpYGTojGp8U89mSsgQLc40PCMJLMCnFXTs7nhBveZ0t7dbqWUNrepWTszDbFkYD6WlL8DKx5huHA==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/pbkdf2": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.6.0.tgz", + "integrity": "sha512-Wu1AxTgJo3T3H6MIu/eejLFok9TYoSdgwRr5oGY1LTLfmGesDoSx05pemsbrPT2gG4cQME+baTSCp5sEo2erZQ==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/sha2": "^5.6.0" + } + }, + "@ethersproject/properties": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.6.0.tgz", + "integrity": "sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/providers": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.6.4.tgz", + "integrity": "sha512-WAdknnaZ52hpHV3qPiJmKx401BLpup47h36Axxgre9zT+doa/4GC/Ne48ICPxTm0BqndpToHjpLP1ZnaxyE+vw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/basex": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/networks": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", + "@ethersproject/sha2": "^5.6.0", + "@ethersproject/strings": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/web": "^5.6.0", + "bech32": "1.1.4", + "ws": "7.4.6" + }, + "dependencies": { + "bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "dev": true, + "peer": true + } + } + }, + "@ethersproject/random": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.6.0.tgz", + "integrity": "sha512-si0PLcLjq+NG/XHSZz90asNf+YfKEqJGVdxoEkSukzbnBgC8rydbgbUgBbBGLeHN4kAJwUFEKsu3sCXT93YMsw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/rlp": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.6.0.tgz", + "integrity": "sha512-dz9WR1xpcTL+9DtOT/aDO+YyxSSdO8YIS0jyZwHHSlAmnxA6cKU3TrTd4Xc/bHayctxTgGLYNuVVoiXE4tTq1g==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/sha2": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.6.0.tgz", + "integrity": "sha512-1tNWCPFLu1n3JM9t4/kytz35DkuF9MxqkGGEHNauEbaARdm2fafnOyw1s0tIQDPKF/7bkP1u3dbrmjpn5CelyA==", + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "hash.js": "1.1.7" + } + }, + "@ethersproject/signing-key": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.6.0.tgz", + "integrity": "sha512-S+njkhowmLeUu/r7ir8n78OUKx63kBdMCPssePS89So1TH4hZqnWFsThEd/GiXYp9qMxVrydf7KdM9MTGPFukA==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "@ethersproject/solidity": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.6.0.tgz", + "integrity": "sha512-YwF52vTNd50kjDzqKaoNNbC/r9kMDPq3YzDWmsjFTRBcIF1y4JCQJ8gB30wsTfHbaxgxelI5BfxQSxD/PbJOww==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/sha2": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "@ethersproject/strings": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.6.0.tgz", + "integrity": "sha512-uv10vTtLTZqrJuqBZR862ZQjTIa724wGPWQqZrofaPI/kUsf53TBG0I0D+hQ1qyNtllbNzaW+PDPHHUI6/65Mg==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/transactions": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.6.0.tgz", + "integrity": "sha512-4HX+VOhNjXHZyGzER6E/LVI2i6lf9ejYeWD6l4g50AdmimyuStKc39kvKf1bXWQMg7QNVh+uC7dYwtaZ02IXeg==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/rlp": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0" + } + }, + "@ethersproject/units": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.6.0.tgz", + "integrity": "sha512-tig9x0Qmh8qbo1w8/6tmtyrm/QQRviBh389EQ+d8fP4wDsBrJBf08oZfoiz1/uenKK9M78yAP4PoR7SsVoTjsw==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/constants": "^5.6.0", + "@ethersproject/logger": "^5.6.0" + } + }, + "@ethersproject/wallet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.6.0.tgz", + "integrity": "sha512-qMlSdOSTyp0MBeE+r7SUhr1jjDlC1zAXB8VD84hCnpijPQiSNbxr6GdiLXxpUs8UKzkDiNYYC5DRI3MZr+n+tg==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abstract-provider": "^5.6.0", + "@ethersproject/abstract-signer": "^5.6.0", + "@ethersproject/address": "^5.6.0", + "@ethersproject/bignumber": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/hdnode": "^5.6.0", + "@ethersproject/json-wallets": "^5.6.0", + "@ethersproject/keccak256": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/random": "^5.6.0", + "@ethersproject/signing-key": "^5.6.0", + "@ethersproject/transactions": "^5.6.0", + "@ethersproject/wordlists": "^5.6.0" + } + }, + "@ethersproject/web": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.6.0.tgz", + "integrity": "sha512-G/XHj0hV1FxI2teHRfCGvfBUHFmU+YOSbCxlAMqJklxSa7QMiHFQfAxvwY2PFqgvdkxEKwRNr/eCjfAPEm2Ctg==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/base64": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "@ethersproject/wordlists": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.6.0.tgz", + "integrity": "sha512-q0bxNBfIX3fUuAo9OmjlEYxP40IB8ABgb7HjEZCL5IKubzV3j30CWi2rqQbjTS2HfoyQbfINoKcTVWP4ejwR7Q==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "@improbable-eng/grpc-web": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", + "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", + "peer": true, + "requires": { + "browser-headers": "^0.4.1" + } + }, + "@improbable-eng/grpc-web-node-http-transport": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web-node-http-transport/-/grpc-web-node-http-transport-0.14.1.tgz", + "integrity": "sha512-ZsCTzI1iKUbmQjB5DNZSI5/hvdliuaPpS2h8mVj1QzynL3IFb5NrNnHVHbfcH1wbm26Ka6Z1CrKFGvKLrmbFIg==", + "requires": {} + }, + "@openzeppelin/contracts": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz", + "integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==", + "dev": true + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@pythnetwork/pyth-sdk-js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-js/-/pyth-sdk-js-1.1.0.tgz", + "integrity": "sha512-IfZI/D+7HiA01TfzuA7Fh0SMhsE+hZWoI1pt48G+XMbNkXhiZG4lSQJRsnquSEY06YAFcAX2D66cFtV6BHy8IA==" + }, + "@solana/buffer-layout": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.0.tgz", + "integrity": "sha512-lR0EMP2HC3+Mxwd4YcnZb0smnaDw7Bl2IQWZiTevRH5ZZBZn6VRWn3/92E3qdU4SSImJkA6IDHawOHAnx/qUvQ==", + "requires": { + "buffer": "~6.0.3" + } + }, + "@solana/spl-token": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@solana/spl-token/-/spl-token-0.1.8.tgz", + "integrity": "sha512-LZmYCKcPQDtJgecvWOgT/cnoIQPWjdH+QVyzPcFvyDUiT0DiRjZaam4aqNUyvchLFhzgunv3d9xOoyE34ofdoQ==", + "requires": { + "@babel/runtime": "^7.10.5", + "@solana/web3.js": "^1.21.0", + "bn.js": "^5.1.0", + "buffer": "6.0.3", + "buffer-layout": "^1.2.0", + "dotenv": "10.0.0" + }, + "dependencies": { + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + } + } + }, + "@solana/web3.js": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.39.1.tgz", + "integrity": "sha512-Q7XnWTAiU7n7GcoINDAAMLO7CJHpm5kPK46HKwJi2x0cusHQ3WFa7QEp6aPzH7tuf7yl/Kw1lYitcwTVOvqARA==", + "requires": { + "@babel/runtime": "^7.12.5", + "@ethersproject/sha2": "^5.5.0", + "@solana/buffer-layout": "^4.0.0", + "bn.js": "^5.0.0", + "borsh": "^0.7.0", + "bs58": "^4.0.1", + "buffer": "6.0.1", + "cross-fetch": "^3.1.4", + "jayson": "^3.4.4", + "js-sha3": "^0.8.0", + "rpc-websockets": "^7.4.2", + "secp256k1": "^4.0.2", + "superstruct": "^0.14.2", + "tweetnacl": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.1.tgz", + "integrity": "sha512-rVAXBwEcEoYtxnHSO5iWyhzV/O1WMtkUYWlfdLS7FjU4PnSJJHEfHXi/uHPI5EwltmOA794gN3bm3/pzuctWjQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + } + } + }, + "@terra-money/terra.js": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-3.0.11.tgz", + "integrity": "sha512-qabXxsycWF1tEcFE3dG7FFXuIcXPlSeYgha5IYU+x4QNKiZuxT9Asi84HrCUSajQkZZ3N7ORfr+aGGE84HD+uw==", + "requires": { + "@terra-money/terra.proto": "^0.1.7", + "axios": "^0.26.1", + "bech32": "^2.0.0", + "bip32": "^2.0.6", + "bip39": "^3.0.3", + "bufferutil": "^4.0.3", + "decimal.js": "^10.2.1", + "jscrypto": "^1.0.1", + "readable-stream": "^3.6.0", + "secp256k1": "^4.0.2", + "tmp": "^0.2.1", + "utf-8-validate": "^5.0.5", + "ws": "^7.5.5" + }, + "dependencies": { + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } }, "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "requires": {} + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "requires": {} } + } + }, + "@terra-money/terra.proto": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz", + "integrity": "sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ==", + "requires": { + "google-protobuf": "^3.17.3", + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "@typechain/ethers-v5": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-7.2.0.tgz", + "integrity": "sha512-jfcmlTvaaJjng63QsT49MT6R1HFhtO/TBMWbyzPFSzMmVIqb2tL6prnKBs4ZJrSvmgIXWy+ttSjpaxCTq8D/Tw==", + "dev": true, + "requires": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "@types/node": { + "version": "16.11.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.27.tgz", + "integrity": "sha512-C1pD3kgLoZ56Uuy5lhfOxie4aZlA3UMGLX9rXteq4WitEZH6Rl80mwactt9QG0w0gLFlN/kLBTFnGXtDVWvWQw==" + }, + "@types/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", + "dev": true, + "peer": true + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "requires": { + "@types/node": "*" + } + }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=", + "dev": true, + "peer": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "peer": true, + "requires": { + "typical": "^2.6.1" + } + }, + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "requires": { + "follow-redirects": "^1.14.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bip32": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", + "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", + "requires": { + "@types/node": "10.12.18", + "bs58check": "^2.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "tiny-secp256k1": "^1.1.3", + "typeforce": "^1.11.5", + "wif": "^2.0.6" + }, + "dependencies": { + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + } + } + }, + "bip39": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", + "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", + "requires": { + "@types/node": "11.11.6", + "create-hash": "^1.1.0", + "pbkdf2": "^3.0.9", + "randombytes": "^2.0.1" + }, + "dependencies": { + "@types/node": { + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + } + } + }, + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "borsh": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz", + "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==", + "requires": { + "bn.js": "^5.2.0", + "bs58": "^4.0.0", + "text-encoding-utf-8": "^1.0.2" + }, + "dependencies": { + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==" + }, + "bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "command-line-args": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", + "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", + "dev": true, + "peer": true, + "requires": { + "array-back": "^2.0.0", + "find-replace": "^1.0.3", + "typical": "^2.6.1" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "copy-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", + "integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==", + "dev": true + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "peer": true, + "requires": { + "ms": "2.1.2" + } + }, + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" + }, + "delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "ethers": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.6.4.tgz", + "integrity": "sha512-62UIfxAQXdf67TeeOaoOoPctm5hUlYgfd0iW3wxfj7qRYKDcvvy0f+sJ3W2/Pyx77R8dblvejA8jokj+lS+ATQ==", + "dev": true, + "peer": true, + "requires": { + "@ethersproject/abi": "5.6.1", + "@ethersproject/abstract-provider": "5.6.0", + "@ethersproject/abstract-signer": "5.6.0", + "@ethersproject/address": "5.6.0", + "@ethersproject/base64": "5.6.0", + "@ethersproject/basex": "5.6.0", + "@ethersproject/bignumber": "5.6.0", + "@ethersproject/bytes": "5.6.1", + "@ethersproject/constants": "5.6.0", + "@ethersproject/contracts": "5.6.0", + "@ethersproject/hash": "5.6.0", + "@ethersproject/hdnode": "5.6.0", + "@ethersproject/json-wallets": "5.6.0", + "@ethersproject/keccak256": "5.6.0", + "@ethersproject/logger": "5.6.0", + "@ethersproject/networks": "5.6.2", + "@ethersproject/pbkdf2": "5.6.0", + "@ethersproject/properties": "5.6.0", + "@ethersproject/providers": "5.6.4", + "@ethersproject/random": "5.6.0", + "@ethersproject/rlp": "5.6.0", + "@ethersproject/sha2": "5.6.0", + "@ethersproject/signing-key": "5.6.0", + "@ethersproject/solidity": "5.6.0", + "@ethersproject/strings": "5.6.0", + "@ethersproject/transactions": "5.6.0", + "@ethersproject/units": "5.6.0", + "@ethersproject/wallet": "5.6.0", + "@ethersproject/web": "5.6.0", + "@ethersproject/wordlists": "5.6.0" + } + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "find": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz", + "integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==", + "dev": true, + "requires": { + "traverse-chain": "~0.1.0" + } + }, + "find-replace": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", + "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", + "dev": true, + "peer": true, + "requires": { + "array-back": "^1.0.4", + "test-value": "^2.1.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "peer": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "google-protobuf": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.20.1.tgz", + "integrity": "sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw==" + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "requires": {} + }, + "jayson": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.6.6.tgz", + "integrity": "sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ==", + "requires": { + "@types/connect": "^3.4.33", + "@types/express-serve-static-core": "^4.17.9", + "@types/lodash": "^4.14.159", + "@types/node": "^12.12.54", + "@types/ws": "^7.4.4", + "commander": "^2.20.3", + "delay": "^5.0.0", + "es6-promisify": "^5.0.0", + "eyes": "^0.1.8", + "isomorphic-ws": "^4.0.1", + "json-stringify-safe": "^5.0.1", + "JSONStream": "^1.3.5", + "lodash": "^4.17.20", + "uuid": "^8.3.2", + "ws": "^7.4.5" + }, + "dependencies": { + "@types/node": { + "version": "12.20.48", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.48.tgz", + "integrity": "sha512-4kxzqkrpwYtn6okJUcb2lfUu9ilnb3yhUOH6qX3nug8D2DupZ2drIkff2yJzYcNJVl3begnlcaBJ7tqiTTzjnQ==" + } + } + }, + "js-base64": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz", + "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==" + }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jscrypto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.3.tgz", + "integrity": "sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "peer": true + }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true + }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rpc-websockets": { + "version": "7.4.17", + "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.4.17.tgz", + "integrity": "sha512-eolVi/qlXS13viIUH9aqrde902wzSLAai0IjmOZSRefp5I3CSG/vCnD0c0fDSYCWuEyUoRL1BHQA8K1baEUyow==", + "requires": { + "@babel/runtime": "^7.11.2", + "bufferutil": "^4.0.1", + "circular-json": "^0.5.9", + "eventemitter3": "^4.0.7", + "utf-8-validate": "^5.0.2", + "uuid": "^8.3.0", + "ws": "^7.4.5" + } + }, + "rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "scrypt-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "dev": true, + "peer": true + }, + "secp256k1": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", + "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "requires": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "superstruct": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.14.2.tgz", + "integrity": "sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "peer": true, + "requires": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "peer": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "text-encoding-utf-8": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz", + "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "tiny-secp256k1": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", + "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", + "requires": { + "bindings": "^1.3.0", + "bn.js": "^4.11.8", + "create-hmac": "^1.1.7", + "elliptic": "^6.4.0", + "nan": "^2.13.2" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "requires": { + "rimraf": "^3.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "traverse-chain": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz", + "integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE=", + "dev": true + }, + "ts-essentials": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", + "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", + "dev": true, + "requires": {} + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, + "typechain": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-5.2.0.tgz", + "integrity": "sha512-0INirvQ+P+MwJOeMct+WLkUE4zov06QxC96D+i3uGFEHoiSkZN70MKDQsaj8zkL86wQwByJReI2e7fOUwECFuw==", + "dev": true, + "peer": true, + "requires": { + "@types/prettier": "^2.1.1", + "command-line-args": "^4.0.7", + "debug": "^4.1.1", + "fs-extra": "^7.0.0", + "glob": "^7.1.6", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.1.2", + "ts-essentials": "^7.0.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "peer": true + } + } + }, + "typeforce": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", + "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" + }, + "typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true, + "peer": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "peer": true + }, + "utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wif": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", + "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", + "requires": { + "bs58check": "<3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "requires": {} } + } } diff --git a/third_party/pyth/p2w-sdk/js/package.json b/third_party/pyth/p2w-sdk/js/package.json index 4e47a05e..9bdeb804 100644 --- a/third_party/pyth/p2w-sdk/js/package.json +++ b/third_party/pyth/p2w-sdk/js/package.json @@ -1,51 +1,51 @@ { - "name": "@pythnetwork/p2w-sdk-js", - "version": "1.0.0", - "description": "TypeScript library for interacting with Pyth2Wormhole", - "types": "lib/index.d.ts", - "main": "lib/index.js", - "files": [ - "lib/**/*" - ], - "scripts": { - "build": "npm run build-lib", - "build-lib": "npm run copy-artifacts && tsc", - "build-watch": "npm run copy-artifacts && tsc --watch", - "format": "prettier --write \"src/**/*.ts\"", - "copy-artifacts": "node scripts/copyWasm.cjs", - "lint": "tslint -p tsconfig.json", - "postversion": "git push && git push --tags", - "preversion": "npm run lint", - "version": "npm run format && git add -A src" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/pyth-network/pyth-crosschain.git" - }, - "author": "https://certus.one", - "license": "MIT", - "devDependencies": { - "@openzeppelin/contracts": "^4.2.0", - "@typechain/ethers-v5": "^7.1.2", - "@types/long": "^4.0.1", - "@types/node": "^16.6.1", - "copy-dir": "^1.3.0", - "find": "^0.3.0", - "prettier": "^2.3.2", - "tslint": "^6.1.3", - "tslint-config-prettier": "^1.18.0", - "typescript": "^4.3.5" - }, - "peerDependencies": { - "@solana/web3.js": "^1.24.0" - }, - "dependencies": { - "@certusone/wormhole-sdk": "0.2.1", - "@improbable-eng/grpc-web-node-http-transport": "^0.14.1", - "@pythnetwork/pyth-sdk-js": "^1.1.0" - }, - "bugs": { - "url": "https://github.com/pyth-network/pyth-crosschain/issues" - }, - "homepage": "https://github.com/pyth-network/pyth-crosschain#readme" + "name": "@pythnetwork/p2w-sdk-js", + "version": "1.0.0", + "description": "TypeScript library for interacting with Pyth2Wormhole", + "types": "lib/index.d.ts", + "main": "lib/index.js", + "files": [ + "lib/**/*" + ], + "scripts": { + "build": "npm run build-lib", + "build-lib": "npm run copy-artifacts && tsc", + "build-watch": "npm run copy-artifacts && tsc --watch", + "format": "prettier --write \"src/**/*.ts\"", + "copy-artifacts": "node scripts/copyWasm.cjs", + "lint": "tslint -p tsconfig.json", + "postversion": "git push && git push --tags", + "preversion": "npm run lint", + "version": "npm run format && git add -A src" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/pyth-network/pyth-crosschain.git" + }, + "author": "https://certus.one", + "license": "MIT", + "devDependencies": { + "@openzeppelin/contracts": "^4.2.0", + "@typechain/ethers-v5": "^7.1.2", + "@types/long": "^4.0.1", + "@types/node": "^16.6.1", + "copy-dir": "^1.3.0", + "find": "^0.3.0", + "prettier": "^2.3.2", + "tslint": "^6.1.3", + "tslint-config-prettier": "^1.18.0", + "typescript": "^4.3.5" + }, + "peerDependencies": { + "@solana/web3.js": "^1.24.0" + }, + "dependencies": { + "@certusone/wormhole-sdk": "0.2.1", + "@improbable-eng/grpc-web-node-http-transport": "^0.14.1", + "@pythnetwork/pyth-sdk-js": "^1.1.0" + }, + "bugs": { + "url": "https://github.com/pyth-network/pyth-crosschain/issues" + }, + "homepage": "https://github.com/pyth-network/pyth-crosschain#readme" } diff --git a/third_party/pyth/p2w-sdk/js/scripts/copyWasm.cjs b/third_party/pyth/p2w-sdk/js/scripts/copyWasm.cjs index 069bf304..c7cc026c 100644 --- a/third_party/pyth/p2w-sdk/js/scripts/copyWasm.cjs +++ b/third_party/pyth/p2w-sdk/js/scripts/copyWasm.cjs @@ -5,13 +5,12 @@ const path = require("path"); const SOURCE_ROOT = "src"; const TARGET_ROOT = "lib"; -find.eachfile(/\.wasm(\..*)?/, SOURCE_ROOT, fname => { +find.eachfile(/\.wasm(\..*)?/, SOURCE_ROOT, (fname) => { + fname_copy = fname.replace(SOURCE_ROOT, TARGET_ROOT); - fname_copy = fname.replace(SOURCE_ROOT, TARGET_ROOT); + console.log("copyWasm:", fname, "to", fname_copy); - console.log("copyWasm:", fname, "to", fname_copy); + fs.mkdirSync(path.dirname(fname_copy), { recursive: true }); - fs.mkdirSync(path.dirname(fname_copy), {recursive: true}); - - fs.copyFileSync(fname, fname_copy); + fs.copyFileSync(fname, fname_copy); }); diff --git a/third_party/pyth/p2w-sdk/js/tsconfig.json b/third_party/pyth/p2w-sdk/js/tsconfig.json index 891f53e6..b3111cb6 100644 --- a/third_party/pyth/p2w-sdk/js/tsconfig.json +++ b/third_party/pyth/p2w-sdk/js/tsconfig.json @@ -1,17 +1,17 @@ { - "compilerOptions": { - "target": "esnext", - "module": "commonjs", - "moduleResolution": "node", - "declaration": true, - "outDir": "./lib", - "strict": true, - "skipLibCheck": true, - "esModuleInterop": true, - "downlevelIteration": true, - "allowJs": true, - }, - "types": [], - "include": ["src", "types"], - "exclude": ["node_modules", "**/__tests__/*"] + "compilerOptions": { + "target": "esnext", + "module": "commonjs", + "moduleResolution": "node", + "declaration": true, + "outDir": "./lib", + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "downlevelIteration": true, + "allowJs": true + }, + "types": [], + "include": ["src", "types"], + "exclude": ["node_modules", "**/__tests__/*"] } diff --git a/third_party/pyth/p2w-sdk/js/tslint.json b/third_party/pyth/p2w-sdk/js/tslint.json index 95772682..d2b69dde 100644 --- a/third_party/pyth/p2w-sdk/js/tslint.json +++ b/third_party/pyth/p2w-sdk/js/tslint.json @@ -1,9 +1,6 @@ - { "extends": ["tslint:recommended", "tslint-config-prettier"], "linterOptions": { - "exclude": [ - "src/proto/**" - ] + "exclude": ["src/proto/**"] } -} \ No newline at end of file +} diff --git a/third_party/pyth/p2w-sdk/rust/README.md b/third_party/pyth/p2w-sdk/rust/README.md index 30394a74..acfb8a8a 100644 --- a/third_party/pyth/p2w-sdk/rust/README.md +++ b/third_party/pyth/p2w-sdk/rust/README.md @@ -1,4 +1,5 @@ # P2W SDK ## Development -This crate requires rust nightly to compile. \ No newline at end of file + +This crate requires rust nightly to compile. diff --git a/third_party/pyth/p2w_autoattest.py b/third_party/pyth/p2w_autoattest.py index eda98169..c0e3f6b8 100755 --- a/third_party/pyth/p2w_autoattest.py +++ b/third_party/pyth/p2w_autoattest.py @@ -314,7 +314,7 @@ while True: # Keep listening for seqnos until the program exits while p2w_client_process.poll() is None: line = p2w_client_process.stdout.readline() - + # Always pass output to the debug level logging.debug(f"pyth2wormhole-client: {line}") @@ -326,7 +326,7 @@ while True: # trim back to specified maximum if len(saved_log_lines) > P2W_MAX_LOG_LINES: saved_log_lines.pop(0) - + # Yell if the supposedly non-stop attestation process exits logging.warn(f"pyth2wormhole-client stopped unexpectedly with code {p2w_client_process.retcode}") diff --git a/third_party/pyth/price-service/README.md b/third_party/pyth/price-service/README.md index ad02aa86..6cd0a930 100644 --- a/third_party/pyth/price-service/README.md +++ b/third_party/pyth/price-service/README.md @@ -48,7 +48,6 @@ pyth_price_service Or, run docker compose in the `third_party/pyth/price-service` directory using the commands below. It will run a spy listening to the Wormhole testnet network and a price service that connects to it. Then the price service will serve the Pyth prices published to the Wormhole testnet network. - ``` $ cd third_party/pyth/price-service $ docker compose up diff --git a/third_party/pyth/price-service/jest.config.js b/third_party/pyth/price-service/jest.config.js index e86e13ba..21a1e973 100644 --- a/third_party/pyth/price-service/jest.config.js +++ b/third_party/pyth/price-service/jest.config.js @@ -1,5 +1,5 @@ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', + preset: "ts-jest", + testEnvironment: "node", }; diff --git a/third_party/pyth/price-service/tsconfig.json b/third_party/pyth/price-service/tsconfig.json index c920ebda..db413064 100644 --- a/third_party/pyth/price-service/tsconfig.json +++ b/third_party/pyth/price-service/tsconfig.json @@ -14,7 +14,7 @@ "resolveJsonModule": true, "isolatedModules": true, "downlevelIteration": true, - "esModuleInterop": true, + "esModuleInterop": true }, "include": ["src"], "exclude": ["node_modules"] diff --git a/third_party/pyth/price-service/tslint.json b/third_party/pyth/price-service/tslint.json index d2ce6a4f..faea87cd 100644 --- a/third_party/pyth/price-service/tslint.json +++ b/third_party/pyth/price-service/tslint.json @@ -1,4 +1,3 @@ - { "extends": ["tslint:recommended", "tslint-config-prettier"], "rules": { @@ -6,4 +5,4 @@ "severity": "off" } } -} \ No newline at end of file +} diff --git a/third_party/pyth/pyth_publisher.py b/third_party/pyth/pyth_publisher.py index a55ed1e0..be1b2fe8 100644 --- a/third_party/pyth/pyth_publisher.py +++ b/third_party/pyth/pyth_publisher.py @@ -84,7 +84,7 @@ def add_symbol(num: int): capture_output=True) print(f"{symbol_name}: Added publisher {publisher_pubkey}") - # Update the prices as the newly added publisher + # Update the prices as the newly added publisher publisher_random_update(price_pubkey) sym = { @@ -127,7 +127,7 @@ publisher_pubkey = sol_run_or_die("address", args=[ with ThreadPoolExecutor(max_workers=PYTH_TEST_SYMBOL_COUNT) as executor: add_symbol_futures = {executor.submit(add_symbol, sym_id) for sym_id in range(PYTH_TEST_SYMBOL_COUNT)} - + for future in as_completed(add_symbol_futures): print(f"Completed {future.result()}") diff --git a/third_party/pyth/pyth_utils.py b/third_party/pyth/pyth_utils.py index 2ba96ee5..452e28ea 100644 --- a/third_party/pyth/pyth_utils.py +++ b/third_party/pyth/pyth_utils.py @@ -20,7 +20,7 @@ PYTH_TEST_SYMBOL_COUNT = int(os.environ.get("PYTH_TEST_SYMBOL_COUNT", "11")) # If above 0, adds a new test symbol periodically, waiting at least # the given number of seconds in between -# +# # NOTE: the new symbols are added in the HTTP endpoint used by the # p2w-attest service in Tilt. You may need to wait to see p2w-attest # pick up brand new symbols diff --git a/third_party/pyth/xc-governance-sdk-js/jest.config.js b/third_party/pyth/xc-governance-sdk-js/jest.config.js index e86e13ba..21a1e973 100644 --- a/third_party/pyth/xc-governance-sdk-js/jest.config.js +++ b/third_party/pyth/xc-governance-sdk-js/jest.config.js @@ -1,5 +1,5 @@ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', + preset: "ts-jest", + testEnvironment: "node", }; diff --git a/third_party/pyth/xc-governance-sdk-js/src/index.ts b/third_party/pyth/xc-governance-sdk-js/src/index.ts index 4793fdf6..35612d76 100644 --- a/third_party/pyth/xc-governance-sdk-js/src/index.ts +++ b/third_party/pyth/xc-governance-sdk-js/src/index.ts @@ -8,10 +8,7 @@ export { SetFeeInstruction, SetValidPeriodInstruction, RequestGovernanceDataSourceTransferInstruction, - AuthorizeGovernanceDataSourceTransferInstruction -} from "./instructions" + AuthorizeGovernanceDataSourceTransferInstruction, +} from "./instructions"; -export { - CHAINS, - ChainId -} from "@certusone/wormhole-sdk" +export { CHAINS, ChainId } from "@certusone/wormhole-sdk"; diff --git a/third_party/pyth/xc-governance-sdk-js/src/instructions.ts b/third_party/pyth/xc-governance-sdk-js/src/instructions.ts index b03c3c5b..1de67e77 100644 --- a/third_party/pyth/xc-governance-sdk-js/src/instructions.ts +++ b/third_party/pyth/xc-governance-sdk-js/src/instructions.ts @@ -1,6 +1,6 @@ import { ChainId, CHAINS } from "@certusone/wormhole-sdk"; -import { Serializable, BufferBuilder } from "./serialize"; +import { Serializable, BufferBuilder } from "./serialize"; enum Module { Executor = 0, @@ -24,7 +24,9 @@ abstract class HexString implements Serializable { address = address.substring(2); } if (address.length !== 2 * byteLen) { - throw new Error(`Expected address of length ${2 * byteLen}, found ${address.length}`); + throw new Error( + `Expected address of length ${2 * byteLen}, found ${address.length}` + ); } this.addressBuffer = Buffer.from(address, "hex"); if (this.addressBuffer.length === 0) { @@ -52,8 +54,8 @@ export class HexString32Bytes extends HexString { export class DataSource implements Serializable { constructor( private readonly emitterChain: ChainId, - private readonly emitterAddress: HexString32Bytes, - ) { }; + private readonly emitterAddress: HexString32Bytes + ) {} serialize(): Buffer { return new BufferBuilder() @@ -70,8 +72,8 @@ abstract class Instruction implements Serializable { constructor( private module: Module, private action: number, - private targetChainId: ChainId, - ) { }; + private targetChainId: ChainId + ) {} protected abstract serializePayload(): Buffer; @@ -93,19 +95,13 @@ abstract class Instruction implements Serializable { } abstract class TargetInstruction extends Instruction { - constructor( - action: TargetAction, - targetChainId: ChainId - ) { + constructor(action: TargetAction, targetChainId: ChainId) { super(Module.Target, Number(action), targetChainId); } } export class AptosAuthorizeUpgradeContractInstruction extends TargetInstruction { - constructor( - targetChainId: ChainId, - private hash: HexString32Bytes, - ) { + constructor(targetChainId: ChainId, private hash: HexString32Bytes) { super(TargetAction.UpgradeContract, targetChainId); } @@ -115,10 +111,7 @@ export class AptosAuthorizeUpgradeContractInstruction extends TargetInstruction } export class EthereumUpgradeContractInstruction extends TargetInstruction { - constructor( - targetChainId: ChainId, - private address: HexString20Bytes, - ) { + constructor(targetChainId: ChainId, private address: HexString20Bytes) { super(TargetAction.UpgradeContract, targetChainId); } @@ -128,10 +121,7 @@ export class EthereumUpgradeContractInstruction extends TargetInstruction { } export class AuthorizeGovernanceDataSourceTransferInstruction extends TargetInstruction { - constructor( - targetChainId: ChainId, - private claimVaa: Buffer, - ) { + constructor(targetChainId: ChainId, private claimVaa: Buffer) { super(TargetAction.AuthorizeGovernanceDataSourceTransfer, targetChainId); } @@ -141,17 +131,14 @@ export class AuthorizeGovernanceDataSourceTransferInstruction extends TargetInst } export class SetDataSourcesInstruction extends TargetInstruction { - constructor( - targetChainId: ChainId, - private dataSources: DataSource[], - ) { + constructor(targetChainId: ChainId, private dataSources: DataSource[]) { super(TargetAction.SetDataSources, targetChainId); } protected serializePayload(): Buffer { - const builder = new BufferBuilder() + const builder = new BufferBuilder(); builder.addUint8(this.dataSources.length); - this.dataSources.forEach(datasource => builder.addObject(datasource)); + this.dataSources.forEach((datasource) => builder.addObject(datasource)); return builder.build(); } } @@ -160,7 +147,7 @@ export class SetFeeInstruction extends TargetInstruction { constructor( targetChainId: ChainId, private newFeeValue: bigint, - private newFeeExpo: bigint, + private newFeeExpo: bigint ) { super(TargetAction.SetFee, targetChainId); } @@ -174,24 +161,19 @@ export class SetFeeInstruction extends TargetInstruction { } export class SetValidPeriodInstruction extends TargetInstruction { - constructor( - targetChainId: ChainId, - private newValidPeriod: bigint, - ) { + constructor(targetChainId: ChainId, private newValidPeriod: bigint) { super(TargetAction.SetValidPeriod, targetChainId); } protected serializePayload(): Buffer { - return new BufferBuilder() - .addBigUint64(this.newValidPeriod) - .build(); + return new BufferBuilder().addBigUint64(this.newValidPeriod).build(); } } export class RequestGovernanceDataSourceTransferInstruction extends TargetInstruction { constructor( targetChainId: ChainId, - private governanceDataSourceIndex: number, + private governanceDataSourceIndex: number ) { super(TargetAction.RequestGovernanceDataSourceTransfer, targetChainId); } diff --git a/third_party/pyth/xc-governance-sdk-js/src/serialize.ts b/third_party/pyth/xc-governance-sdk-js/src/serialize.ts index da7eacb7..3aaf1ca8 100644 --- a/third_party/pyth/xc-governance-sdk-js/src/serialize.ts +++ b/third_party/pyth/xc-governance-sdk-js/src/serialize.ts @@ -48,7 +48,7 @@ export class BufferBuilder { } build(): Buffer { - const totalLength = this.items.reduce((prev, cur) => (prev + cur.length), 0); + const totalLength = this.items.reduce((prev, cur) => prev + cur.length, 0); const result = Buffer.alloc(totalLength); diff --git a/tilt_modules/extensions.json b/tilt_modules/extensions.json index aac34fa0..b9c5aff7 100644 --- a/tilt_modules/extensions.json +++ b/tilt_modules/extensions.json @@ -11,4 +11,4 @@ "TimeFetched": "2021-07-01T15:08:09.818136358-05:00" } ] -} \ No newline at end of file +} diff --git a/tilt_modules/namespace/test/deployment.yaml b/tilt_modules/namespace/test/deployment.yaml index 2cea480d..8924006f 100644 --- a/tilt_modules/namespace/test/deployment.yaml +++ b/tilt_modules/namespace/test/deployment.yaml @@ -12,15 +12,20 @@ spec: app: namespace-test-busybox spec: containers: - - name: busybox - image: busybox - ports: - - containerPort: 8000 - command: ["sh", "-c", "echo 'hello world' > index.html; busybox httpd -f -p 8000"] - readinessProbe: - tcpSocket: - port: 8000 - periodSeconds: 1 + - name: busybox + image: busybox + ports: + - containerPort: 8000 + command: + [ + "sh", + "-c", + "echo 'hello world' > index.html; busybox httpd -f -p 8000", + ] + readinessProbe: + tcpSocket: + port: 8000 + periodSeconds: 1 --- apiVersion: v1 kind: Service @@ -32,4 +37,4 @@ spec: ports: - protocol: TCP port: 8000 - targetPort: 8000 \ No newline at end of file + targetPort: 8000 diff --git a/tilt_modules/namespace/test/job-default-namespace.yaml b/tilt_modules/namespace/test/job-default-namespace.yaml index 45d587a1..3e2330f9 100644 --- a/tilt_modules/namespace/test/job-default-namespace.yaml +++ b/tilt_modules/namespace/test/job-default-namespace.yaml @@ -7,7 +7,7 @@ spec: template: spec: containers: - - name: namespace-test-verify - image: curlimages/curl - command: ["curl", "-fsSL", "http://namespace-test-busybox:8000/"] - restartPolicy: Never \ No newline at end of file + - name: namespace-test-verify + image: curlimages/curl + command: ["curl", "-fsSL", "http://namespace-test-busybox:8000/"] + restartPolicy: Never diff --git a/tilt_modules/namespace/test/job.yaml b/tilt_modules/namespace/test/job.yaml index 0495814c..2d5ca4a5 100644 --- a/tilt_modules/namespace/test/job.yaml +++ b/tilt_modules/namespace/test/job.yaml @@ -8,7 +8,7 @@ spec: template: spec: containers: - - name: namespace-test-verify - image: curlimages/curl - command: ["curl", "-fsSL", "http://namespace-test-busybox:8000/"] - restartPolicy: Never \ No newline at end of file + - name: namespace-test-verify + image: curlimages/curl + command: ["curl", "-fsSL", "http://namespace-test-busybox:8000/"] + restartPolicy: Never diff --git a/tilt_modules/secret/README.md b/tilt_modules/secret/README.md index 4b88f5db..e5446c1a 100644 --- a/tilt_modules/secret/README.md +++ b/tilt_modules/secret/README.md @@ -14,8 +14,8 @@ secret_yaml_generic(name: str, namespace: str = "", from_file: Union[str, List] Returns YAML for a generic secret. -* `from_file` ( str ) – equivalent to `kubectl create secret --from-file` -* `secret_type` ( str ) - equivalent to `kubectl create secret --type` +- `from_file` ( str ) – equivalent to `kubectl create secret --from-file` +- `secret_type` ( str ) - equivalent to `kubectl create secret --type` ### secret_create_generic diff --git a/tilt_modules/secret/test/.pgpass b/tilt_modules/secret/test/.pgpass index f66b2c47..9378dd4a 100644 --- a/tilt_modules/secret/test/.pgpass +++ b/tilt_modules/secret/test/.pgpass @@ -1 +1 @@ -hostname:5432:database:username:password \ No newline at end of file +hostname:5432:database:username:password diff --git a/tilt_modules/secret/test/job.yaml b/tilt_modules/secret/test/job.yaml index f4989b30..d54232c3 100644 --- a/tilt_modules/secret/test/job.yaml +++ b/tilt_modules/secret/test/job.yaml @@ -7,18 +7,18 @@ spec: template: spec: containers: - - name: secret-verify - image: alpine - command: ["grep", "password", "/var/secrets/pgpass/.pgpass"] - volumeMounts: - - name: pgpass - mountPath: /var/secrets/pgpass - env: - - name: PGPASSFILE - value: /var/secrets/pgpass/.pgpass + - name: secret-verify + image: alpine + command: ["grep", "password", "/var/secrets/pgpass/.pgpass"] + volumeMounts: + - name: pgpass + mountPath: /var/secrets/pgpass + env: + - name: PGPASSFILE + value: /var/secrets/pgpass/.pgpass restartPolicy: Never volumes: - - name: pgpass - secret: - secretName: pgpass - defaultMode: 0600 \ No newline at end of file + - name: pgpass + secret: + secretName: pgpass + defaultMode: 0600