diff --git a/.github/workflows/seq-e2e-tests.yml b/.github/workflows/seq-e2e-tests.yml
new file mode 100644
index 0000000..4d581e6
--- /dev/null
+++ b/.github/workflows/seq-e2e-tests.yml
@@ -0,0 +1,40 @@
+name: SEQ e2e tests
+
+on:
+ push:
+ branches:
+ - '*'
+ pull_request:
+ types: [labeled,synchronize,reopened]
+
+jobs:
+ seq-e2e-tests:
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Git checkout
+ uses: actions/checkout@v3
+ - name: Install killall
+ run: |
+ sudo apt-get update
+ sudo apt-get install psmisc
+ - name: Set up Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: "1.21"
+ check-latest: true
+ cache: true
+ cache-dependency-path: |
+ go.sum
+ - name: Run ETH L1
+ uses: hoverkraft-tech/compose-action@v2.0.1
+ with:
+ compose-file: "./compose.yml"
+ down-flags: |
+ -v
+ services: |
+ l1
+ - name: Run e2e tests
+ run: |
+ chmod +x ./scripts/run.sh
+ MODE="test" ./scripts/run.sh
+ shell: bash
\ No newline at end of file
diff --git a/.github/workflows/seq-load-tests.yml b/.github/workflows/seq-load-tests.yml
deleted file mode 100644
index a190018..0000000
--- a/.github/workflows/seq-load-tests.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-# # Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-# # See the file LICENSE for licensing terms.
-
-# name: SEQ Load Tests
-
-# on:
-# push:
-# branches:
-# - main
-# #pull_request:
-# #types: [labeled,synchronize,reopened]
-
-# jobs:
-# seq-load-tests:
-# #if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'run load') }}
-# strategy:
-# matrix:
-# level: [v1, v2, v3] # v4 is not supported
-# runs-on:
-# labels: ubuntu-20.04
-# timeout-minutes: 10
-# steps:
-# - name: Checkout
-# uses: actions/checkout@v3
-# - name: Set up Go
-# uses: actions/setup-go@v4
-# with:
-# go-version: "1.20"
-# check-latest: true
-# cache: true
-# cache-dependency-path: |
-# go.sum
-# - name: Run load tests
-# shell: bash
-# run: GOAMD64=${{ matrix.level }} scripts/tests.load_msg.sh
-# concurrency:
-# group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
-# cancel-in-progress: true
diff --git a/.github/workflows/seq-release.yml b/.github/workflows/seq-release.yml
index a398086..6be1ee3 100644
--- a/.github/workflows/seq-release.yml
+++ b/.github/workflows/seq-release.yml
@@ -13,32 +13,6 @@ on:
types: [labeled,synchronize,reopened]
jobs:
- # token-wallet-release:
- # runs-on: macos-latest-xl
- # if: ${{ github.ref == 'refs/heads/main' || startsWith(github.event.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run release') }}
- # steps:
- # - name: Checkout
- # uses: actions/checkout@v3
- # - name: Set up Go
- # uses: actions/setup-go@v4
- # with:
- # go-version: "1.20"
- # check-latest: true
- # cache: true
- # cache-dependency-path: |
- # go.sum
- # examples/tokenvm/go.sum
- # - name: Build wallet
- # working-directory: ./cmd/token-wallet
- # shell: bash
- # run: scripts/build.sh
- # env:
- # PUBLISH: false
- # - name: Archive Builds
- # uses: actions/upload-artifact@v3
- # with:
- # name: token-wallet
- # path: ./cmd/token-wallet/token-wallet.zip
seq-release:
# We build with 20.04 to maintain max compatibility: https://github.com/golang/go/issues/57328
diff --git a/.github/workflows/seq-sync-tests.yml b/.github/workflows/seq-sync-tests.yml
deleted file mode 100644
index 26c7980..0000000
--- a/.github/workflows/seq-sync-tests.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-# # Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-# # See the file LICENSE for licensing terms.
-
-# name: SEQ Sync Tests
-
-# on:
-# push:
-# branches:
-# - main
-# #pull_request:
-# # types: [labeled,synchronize,reopened]
-
-# jobs:
-# seq-sync-tests:
-# # if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'run CI') }}
-# runs-on:
-# labels: ubuntu-20.04
-# timeout-minutes: 25
-# steps:
-# - name: Checkout
-# uses: actions/checkout@v3
-# - name: Set up Go
-# uses: actions/setup-go@v4
-# with:
-# go-version: "1.20"
-# check-latest: true
-# cache: true
-# cache-dependency-path: |
-# go.sum
-# - name: Run sync tests
-# shell: bash
-# run: scripts/run.sh
-# env:
-# MODE: "full-test"
-# concurrency:
-# group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
-# cancel-in-progress: true
diff --git a/.gitignore b/.gitignore
index a314473..e86b631 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,7 @@
*.log
*~
.DS_Store
-.token_cli/
+.seq_cli/
awscpu
# Binaries for programs and plugins
@@ -43,6 +43,7 @@ awscpu
*.fls
*.gz
*.pdf
+*.db
.coverage
@@ -57,7 +58,7 @@ genesis.json
dist/
*.pk
tmp-storage-testing
-.token-cli*
+.seq-cli*
deploys/
.morpheus-cli*
*.coverage.html
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 3eb17ad..2b41cc7 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -3,9 +3,9 @@
# ref. https://goreleaser.com/customization/build/
builds:
- - id: token-cli
- main: ./cmd/token-cli
- binary: token-cli
+ - id: seq-cli
+ main: ./cmd/seq-cli
+ binary: seq-cli
flags:
- -v
goos:
@@ -31,65 +31,9 @@ builds:
goamd64: v1
env:
- CC=o64-clang
- - id: tokenvm
- main: ./cmd/tokenvm
- binary: tokenvm
- flags:
- - -v
- goos:
- - linux
- - darwin
- goarch:
- - amd64
- - arm64
- env:
- - CGO_ENABLED=1
- - CGO_CFLAGS=-O -D__BLST_PORTABLE__ # Set the CGO flags to use the portable version of BLST
- overrides:
- - goos: linux
- goarch: arm64
- env:
- - CC=aarch64-linux-gnu-gcc
- - goos: darwin
- goarch: arm64
- env:
- - CC=oa64-clang
- - goos: darwin
- goarch: amd64
- goamd64: v1
- env:
- - CC=o64-clang
- - id: token-faucet
- main: ./cmd/token-faucet
- binary: token-faucet
- flags:
- - -v
- goos:
- - linux
- - darwin
- goarch:
- - amd64
- - arm64
- env:
- - CGO_ENABLED=1
- - CGO_CFLAGS=-O -D__BLST_PORTABLE__ # Set the CGO flags to use the portable version of BLST
- overrides:
- - goos: linux
- goarch: arm64
- env:
- - CC=aarch64-linux-gnu-gcc
- - goos: darwin
- goarch: arm64
- env:
- - CC=oa64-clang
- - goos: darwin
- goarch: amd64
- goamd64: v1
- env:
- - CC=o64-clang
- - id: token-feed
- main: ./cmd/token-feed
- binary: token-feed
+ - id: seqvm
+ main: ./cmd/seqvm
+ binary: seqvm
flags:
- -v
goos:
@@ -117,11 +61,11 @@ builds:
- CC=o64-clang
checksum:
- name_template: "tokenvm_{{ .Version }}_checksums.txt"
+ name_template: "seqvm_{{ .Version }}_checksums.txt"
archives:
- id: default
- name_template: 'tokenvm_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
+ name_template: 'seqvm_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
release:
make_latest: false # Should be done manually
diff --git a/README.md b/README.md
index 3fb4737..f8c62da 100644
--- a/README.md
+++ b/README.md
@@ -9,29 +9,10 @@ audited.
The `SeqVM` is built from the ground up with the shared sequencer built directly into the chain
enabling decentralization from the start. This enable users to easily send messages from rollups like NodeKit chain to the shared sequencer. The contents of `SequencerMSG` is just `ChainId|Data|FromAddress` where the data is the transaction data
from the rollup translated into a byte[].
+### Arcadia
+Rollups using Arcadia, will be able to produce blocks with sub second block times without losing synchronous atomic composability with other rollups using Arcadia, all thanks to Arcadia's ability to preconf rollup block chunks in 250ms and make the block available for rollups to pull instantly after preconfing.
-
-### Arbitrary Token Minting
-The `SeqVM` also has the ability to create, mint, and transfer user-generated
-tokens with ease. When creating an asset, the owner is given "admin control" of
-the asset functions and can later mint more of an asset, update its metadata
-(during a reveal for example), or transfer/revoke ownership (if rotating their
-key or turning over to their community).
-
-Assets are a native feature of the `SeqVM` and the storage engine is
-optimized specifically to support their efficient usage (each balance entry
-requires only 72 bytes of state = `assetID|publicKey=>balance(uint64)`). This
-storage format makes it possible to parallelize the execution of any transfers
-that don't touch the same accounts. This parallelism will take effect as soon
-as it is re-added upstream by the `hypersdk` (no action required in the
-`SeqVM`).
-
-### Avalanche Warp Support
-We plan to take advantage of the Avalanche Warp Messaging (AWM) support provided by the
-`hypersdk` to enable any `SeqVM` to receive messages from our `NodeKit Hub` subnet without
-relying on a trusted relayer or bridge (just the validators of the `SeqVM` and `NodeKit Hub`
-sending the message). This feature is still in-progress and we will be sharing more details in
-the upcoming months.
+> Read more about arcadia [here](./arcadia.md).
## Demos
The first step to running these demos is to launch your own `SeqVM` Subnet. You
@@ -42,7 +23,7 @@ minutes):
```
_By default, this allocates all funds on the network to
-`token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp`. The private
+`seq1qrzvk4zlwj9zsacqgtufx7zvapd3quufqpxk5rsdd4633m4wz2fdjlydh3t`. The private
key for this address is
`0x323b1d8f4eed5f0da9da93071b034f2dce9d2d22692c172f3cb252a64ddfafd01b057de320297c29ad0c1f589ea216869cf1938d88c9fbd70d6748323dbf2fa7`.
For convenience, this key has is also stored at `demo.pk`._
@@ -50,107 +31,62 @@ For convenience, this key has is also stored at `demo.pk`._
_If you don't need 2 Subnets for your testing, you can run `MODE="run-single"
./scripts/run.sh`._
-To make it easy to interact with the `SeqVM`, we implemented the `token-cli`.
+To make it easy to interact with the `SeqVM`, we implemented the `seq-cli`.
Next, you'll need to build this. You can use the following command from this location
to do so:
```bash
./scripts/build.sh
```
-_This command will put the compiled CLI in `./build/token-cli`._
+_This command will put the compiled CLI in `./build/seq-cli`._
Lastly, you'll need to add the chains you created and the default key to the
-`token-cli`. You can use the following commands from this location to do so:
+`seq-cli`. You can use the following commands from this location to do so:
```bash
-./build/token-cli key import demo.pk
-./build/token-cli chain import-anr
+./build/seq-cli key import demo.pk
+./build/seq-cli chain import-anr
```
_`chain import-anr` connects to the Avalanche Network Runner server running in
the background and pulls the URIs of all nodes tracking each chain you
created._
-### Mint and Trade
-#### Step 1: Create Your Asset
-First up, let's create our own asset. You can do so by running the following
-command from this location:
-```bash
-./build/token-cli action create-asset
-```
-
-When you are done, the output should look something like this:
-```
-database: .token-cli
-address: token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp
-chainID: Em2pZtHr7rDCzii43an2bBi1M2mTFyLN33QP1Xfjy7BcWtaH9
-metadata (can be changed later): MarioCoin
-continue (y/n): y
-✅ txID: 27grFs9vE2YP9kwLM5hQJGLDvqEY9ii71zzdoRHNGC4Appavug
-```
-
-_`txID` is the `assetID` of your new asset._
-
-The "loaded address" here is the address of the default private key (`demo.pk`). We
-use this key to authenticate all interactions with the `SeqVM`.
-
-#### Step 2: Mint Your Asset
-After we've created our own asset, we can now mint some of it. You can do so by
-running the following command from this location:
-```bash
-./build/token-cli action mint-asset
-```
-
-When you are done, the output should look something like this (usually easiest
-just to mint to yourself).
-```
-database: .token-cli
-address: token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp
-chainID: Em2pZtHr7rDCzii43an2bBi1M2mTFyLN33QP1Xfjy7BcWtaH9
-assetID: 27grFs9vE2YP9kwLM5hQJGLDvqEY9ii71zzdoRHNGC4Appavug
-metadata: MarioCoin supply: 0
-recipient: token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp
-amount: 10000
-continue (y/n): y
-✅ txID: X1E5CVFgFFgniFyWcj5wweGg66TyzjK2bMWWTzFwJcwFYkF72
-```
-
-#### Step 3: View Your Balance
+## View Your Balance
Now, let's check that the mint worked right by checking our balance. You can do
so by running the following command from this location:
```bash
-./build/token-cli key balance
+./build/seq-cli key balance
```
When you are done, the output should look something like this:
```
-database: .token-cli
-address: token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp
+database: .seq-cli
+address: seq1qrzvk4zlwj9zsacqgtufx7zvapd3quufqpxk5rsdd4633m4wz2fdjlydh3t
chainID: Em2pZtHr7rDCzii43an2bBi1M2mTFyLN33QP1Xfjy7BcWtaH9
-assetID (use TKN for native token): 27grFs9vE2YP9kwLM5hQJGLDvqEY9ii71zzdoRHNGC4Appavug
-metadata: MarioCoin supply: 10000 warp: false
+assetID (use SEQ for native seq): 27grFs9vE2YP9kwLM5hQJGLDvqEY9ii71zzdoRHNGC4Appavug
balance: 10000 27grFs9vE2YP9kwLM5hQJGLDvqEY9ii71zzdoRHNGC4Appavug
```
-#### Bonus: Watch Activity in Real-Time
+## Bonus: Watch Activity in Real-Time
To provide a better sense of what is actually happening on-chain, the
-`token-cli` comes bundled with a simple explorer that logs all blocks/txs that
+`seq-cli` comes bundled with a simple explorer that logs all blocks/txs that
occur on-chain. You can run this utility by running the following command from
this location:
```bash
-./build/token-cli chain watch
+./build/seq-cli chain watch
```
If you run it correctly, you'll see the following input (will run until the
network shuts down or you exit):
```
-database: .token-cli
+database: .seq-cli
available chains: 2 excluded: []
0) chainID: Em2pZtHr7rDCzii43an2bBi1M2mTFyLN33QP1Xfjy7BcWtaH9
1) chainID: cKVefMmNPSKmLoshR15Fzxmx52Y5yUSPqWiJsNFUg1WgNQVMX
select chainID: 0
watching for new blocks on Em2pZtHr7rDCzii43an2bBi1M2mTFyLN33QP1Xfjy7BcWtaH9 👀
height:13 txs:1 units:488 root:2po1n8rqdpNuwpMGndqC2hjt6Xa3cUDsjEpm7D6u9kJRFEPmdL avg TPS:0.026082
-✅ KwHcsy3TXcnDyoMNmpMYC4EUvXPDPCoTK8YaEigG7nWwwdi1n actor: token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp units: 496 summary (*actions.SequencerMsg): [data: ]
+✅ KwHcsy3TXcnDyoMNmpMYC4EUvXPDPCoTK8YaEigG7nWwwdi1n actor: seq1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp units: 496 summary (*actions.SequencerMsg): [data: ]
```
diff --git a/actions/auction.go b/actions/auction.go
new file mode 100644
index 0000000..2a755d0
--- /dev/null
+++ b/actions/auction.go
@@ -0,0 +1,176 @@
+package actions
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/binary"
+ "fmt"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/crypto/bls"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/auth"
+ "github.com/AnomalyFi/nodekit-seq/storage"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+var _ chain.Action = (*Auction)(nil)
+
+type AuctionInfo struct {
+ EpochNumber uint64 `json:"epochNumber"`
+ BidPrice uint64 `json:"bidPrice"`
+ BuilderSEQAddress codec.Address `json:"builderSEQAddress"`
+}
+
+func (info *AuctionInfo) HashAuctionInfo() ([32]byte, error) {
+ msg := binary.BigEndian.AppendUint64(nil, info.EpochNumber)
+ msg = binary.BigEndian.AppendUint64(msg, info.BidPrice)
+ msg = append(msg, info.BuilderSEQAddress[:]...)
+ hash := sha256.Sum256(msg)
+ return hash, nil
+}
+
+func (info *AuctionInfo) Marshal(p *codec.Packer) {
+ p.PackUint64(info.EpochNumber)
+ p.PackUint64(info.BidPrice)
+ p.PackAddress(info.BuilderSEQAddress)
+}
+
+func UnmarshalAuctionInfo(p *codec.Packer) (*AuctionInfo, error) {
+ var auctionInfo AuctionInfo
+ auctionInfo.EpochNumber = p.UnpackUint64(true)
+ auctionInfo.BidPrice = p.UnpackUint64(true)
+ p.UnpackAddress(&auctionInfo.BuilderSEQAddress)
+ if p.Err() != nil {
+ return nil, p.Err()
+ }
+ return &auctionInfo, nil
+}
+
+type Auction struct {
+ AuctionInfo AuctionInfo `json:"auctionInfo"`
+ BuilderPublicKey []byte `json:"builderPublicKey"` // BLS public key of the bidder.
+ BuilderSignature []byte `json:"signature"`
+}
+
+func (*Auction) GetTypeID() uint8 {
+ return AuctionID
+}
+
+func (a *Auction) StateKeys(_ codec.Address, _ ids.ID) state.Keys {
+ return state.Keys{
+ string(storage.BalanceKey(a.AuctionInfo.BuilderSEQAddress)): state.Read | state.Write,
+ string(storage.BalanceKey(ArcadiaFundAddress())): state.All,
+ string(storage.ArcadiaBidKey(a.AuctionInfo.EpochNumber)): state.Write | state.Allocate,
+ }
+}
+
+func (*Auction) StateKeysMaxChunks() []uint16 {
+ return []uint16{storage.BalanceChunks, storage.BalanceChunks, hactions.EpochExitsChunks}
+}
+
+// This is a permissioned action, only authorized address can pass the execution.
+func (a *Auction) Execute(
+ ctx context.Context,
+ rules chain.Rules,
+ mu state.Mutable,
+ _ int64,
+ hght uint64,
+ actor codec.Address,
+ _ ids.ID,
+) ([][]byte, error) {
+ // TODO: this allows any whitelisted address to submit arcadia bid.
+ // change this to only allow the arcadia address to submit the bid.
+ if !isWhiteListed(rules, actor) {
+ return nil, ErrNotWhiteListed
+ }
+
+ // Allow auction bid for next epoch processed only during the current epoch.
+ if a.AuctionInfo.EpochNumber != Epoch(hght, rules.GetEpochLength())+1 {
+ return nil, fmt.Errorf("epoch number is not valid, expected: %d, actual: %d", Epoch(hght, rules.GetEpochLength())+1, a.AuctionInfo.EpochNumber)
+ }
+
+ pubkey, err := bls.PublicKeyFromBytes(a.BuilderPublicKey)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse public key: %w", err)
+ }
+
+ digest, err := a.AuctionInfo.HashAuctionInfo()
+ if err != nil {
+ return nil, fmt.Errorf("unable to hash auction info")
+ }
+
+ sig, err := bls.SignatureFromBytes(a.BuilderSignature)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse signature: %w", err)
+ }
+
+ // Verify the signature.
+ if !bls.Verify(digest[:], pubkey, sig) {
+ return nil, ErrInvalidBidderSignature
+ }
+
+ builderSEQAddress := codec.CreateAddress(auth.BLSID, utils.ToID(a.BuilderPublicKey))
+ if builderSEQAddress != a.AuctionInfo.BuilderSEQAddress {
+ return nil, ErrParsedBuilderSEQAddressMismatch
+ }
+ // deduct the bid amount from bidder.
+ if err := storage.SubBalance(ctx, mu, builderSEQAddress, a.AuctionInfo.BidPrice); err != nil {
+ return nil, err
+ }
+
+ // Bid amount is sent to the Arcadia fund address.
+ if err := storage.AddBalance(ctx, mu, ArcadiaFundAddress(), a.AuctionInfo.BidPrice, true); err != nil {
+ return nil, err
+ }
+
+ // Store bid information.
+ if err := storage.StoreArcadiaBidInfo(ctx, mu, a.AuctionInfo.EpochNumber, a.AuctionInfo.BidPrice, a.BuilderPublicKey, a.BuilderSignature); err != nil {
+ return nil, err
+ }
+
+ return nil, nil
+}
+
+func (*Auction) ComputeUnits(codec.Address, chain.Rules) uint64 {
+ return AuctionComputeUnits
+}
+
+func (*Auction) Size() int {
+ return 2*consts.Uint64Len + bls.PublicKeyLen + bls.SignatureLen + codec.AddressLen
+}
+
+func (a *Auction) Marshal(p *codec.Packer) {
+ a.AuctionInfo.Marshal(p)
+ p.PackBytes(a.BuilderPublicKey)
+ p.PackBytes(a.BuilderSignature)
+}
+
+func UnmarshalAuction(p *codec.Packer) (chain.Action, error) {
+ var auction Auction
+ auctionInfo, err := UnmarshalAuctionInfo(p)
+ if err != nil {
+ return nil, err
+ }
+ auction.AuctionInfo = *auctionInfo
+ p.UnpackBytes(48, true, &auction.BuilderPublicKey)
+ p.UnpackBytes(96, true, &auction.BuilderSignature)
+ return &auction, p.Err()
+}
+
+func (*Auction) ValidRange(chain.Rules) (int64, int64) {
+ // Returning -1, -1 means that the action is always valid.
+ return -1, -1
+}
+
+func (*Auction) NMTNamespace() []byte {
+ return DefaultNMTNamespace
+}
+
+func (*Auction) UseFeeMarket() bool {
+ return false
+}
diff --git a/actions/burn_asset.go b/actions/burn_asset.go
deleted file mode 100644
index 67f1545..0000000
--- a/actions/burn_asset.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "context"
-
- "github.com/ava-labs/avalanchego/ids"
- smath "github.com/ava-labs/avalanchego/utils/math"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
-)
-
-var _ chain.Action = (*BurnAsset)(nil)
-
-type BurnAsset struct {
- // Asset is the [TxID] that created the asset.
- Asset ids.ID `json:"asset"`
-
- // Number of assets to mint to [To].
- Value uint64 `json:"value"`
-}
-
-func (*BurnAsset) GetTypeID() uint8 {
- return burnAssetID
-}
-
-func (b *BurnAsset) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- actor := auth.GetActor(rauth)
- return []string{
- string(storage.AssetKey(b.Asset)),
- string(storage.BalanceKey(actor, b.Asset)),
- }
-}
-
-func (*BurnAsset) StateKeysMaxChunks() []uint16 {
- return []uint16{storage.AssetChunks, storage.BalanceChunks}
-}
-
-func (*BurnAsset) OutputsWarpMessage() bool {
- return false
-}
-
-func (b *BurnAsset) Execute(
- ctx context.Context,
- _ chain.Rules,
- mu state.Mutable,
- _ int64,
- rauth chain.Auth,
- _ ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
- if b.Value == 0 {
- return false, BurnComputeUnits, OutputValueZero, nil, nil
- }
- if err := storage.SubBalance(ctx, mu, actor, b.Asset, b.Value); err != nil {
- return false, BurnComputeUnits, utils.ErrBytes(err), nil, nil
- }
- exists, symbol, decimals, metadata, supply, owner, warp, err := storage.GetAsset(ctx, mu, b.Asset)
- if err != nil {
- return false, BurnComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if !exists {
- return false, BurnComputeUnits, OutputAssetMissing, nil, nil
- }
- newSupply, err := smath.Sub(supply, b.Value)
- if err != nil {
- return false, BurnComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.SetAsset(ctx, mu, b.Asset, symbol, decimals, metadata, newSupply, owner, warp); err != nil {
- return false, BurnComputeUnits, utils.ErrBytes(err), nil, nil
- }
- return true, BurnComputeUnits, nil, nil, nil
-}
-
-func (*BurnAsset) MaxComputeUnits(chain.Rules) uint64 {
- return BurnComputeUnits
-}
-
-func (*BurnAsset) Size() int {
- return consts.IDLen + consts.Uint64Len
-}
-
-func (b *BurnAsset) Marshal(p *codec.Packer) {
- p.PackID(b.Asset)
- p.PackUint64(b.Value)
-}
-
-func UnmarshalBurnAsset(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
- var burn BurnAsset
- p.UnpackID(false, &burn.Asset) // can burn native asset
- burn.Value = p.UnpackUint64(true)
- return &burn, p.Err()
-}
-
-func (*BurnAsset) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*BurnAsset) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/consts.go b/actions/consts.go
index 2959a28..42b867f 100644
--- a/actions/consts.go
+++ b/actions/consts.go
@@ -5,35 +5,18 @@ package actions
// Note: Registry will error during initialization if a duplicate ID is assigned. We explicitly assign IDs to avoid accidental remapping.
const (
- burnAssetID uint8 = 0
- closeOrderID uint8 = 1
- createAssetID uint8 = 2
- exportAssetID uint8 = 3
- importAssetID uint8 = 4
- createOrderID uint8 = 5
- fillOrderID uint8 = 6
- mintAssetID uint8 = 7
- transferID uint8 = 8
- exportBlockID uint8 = 9
- importBlockID uint8 = 10
- msgID uint8 = 11
+ TransferID uint8 = 0
+ MsgID uint8 = 1
+ AuctionID uint8 = 2
)
const (
// TODO: tune this
- BurnComputeUnits = 2
- CloseOrderComputeUnits = 5
- CreateAssetComputeUnits = 10
- ExportAssetComputeUnits = 10
- ImportAssetComputeUnits = 10
- CreateOrderComputeUnits = 5
- NoFillOrderComputeUnits = 5
- FillOrderComputeUnits = 15
- MintAssetComputeUnits = 2
- TransferComputeUnits = 1
- ExportBlockComputeUnits = 15
- ImportBlockComputeUnits = 15
- MsgComputeUnits = 15
+ TransferComputeUnits = 1
+ EpochExitComputeUnits = 10
+ AuctionComputeUnits = 4
+
+ MsgComputeUnits = 15
MaxSymbolSize = 8
MaxMemoSize = 256
diff --git a/actions/create_asset.go b/actions/create_asset.go
deleted file mode 100644
index 12df0f3..0000000
--- a/actions/create_asset.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "context"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-)
-
-var _ chain.Action = (*CreateAsset)(nil)
-
-type CreateAsset struct {
- Symbol []byte `json:"symbol"`
- Decimals uint8 `json:"decimals"`
- Metadata []byte `json:"metadata"`
-}
-
-func (*CreateAsset) GetTypeID() uint8 {
- return createAssetID
-}
-
-func (*CreateAsset) StateKeys(_ chain.Auth, txID ids.ID) []string {
- return []string{
- string(storage.AssetKey(txID)),
- }
-}
-
-func (*CreateAsset) StateKeysMaxChunks() []uint16 {
- return []uint16{storage.AssetChunks}
-}
-
-func (*CreateAsset) OutputsWarpMessage() bool {
- return false
-}
-
-func (c *CreateAsset) Execute(
- ctx context.Context,
- _ chain.Rules,
- mu state.Mutable,
- _ int64,
- rauth chain.Auth,
- txID ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
- if len(c.Symbol) == 0 {
- return false, CreateAssetComputeUnits, OutputSymbolEmpty, nil, nil
- }
- if len(c.Symbol) > MaxSymbolSize {
- return false, CreateAssetComputeUnits, OutputSymbolTooLarge, nil, nil
- }
- if c.Decimals > MaxDecimals {
- return false, CreateAssetComputeUnits, OutputDecimalsTooLarge, nil, nil
- }
- if len(c.Metadata) == 0 {
- return false, CreateAssetComputeUnits, OutputMetadataEmpty, nil, nil
- }
- if len(c.Metadata) > MaxMetadataSize {
- return false, CreateAssetComputeUnits, OutputMetadataTooLarge, nil, nil
- }
- // It should only be possible to overwrite an existing asset if there is
- // a hash collision.
- if err := storage.SetAsset(ctx, mu, txID, c.Symbol, c.Decimals, c.Metadata, 0, actor, false); err != nil {
- return false, CreateAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- return true, CreateAssetComputeUnits, nil, nil, nil
-}
-
-func (*CreateAsset) MaxComputeUnits(chain.Rules) uint64 {
- return CreateAssetComputeUnits
-}
-
-func (c *CreateAsset) Size() int {
- // TODO: add small bytes (smaller int prefix)
- return codec.BytesLen(c.Symbol) + consts.Uint8Len + codec.BytesLen(c.Metadata)
-}
-
-func (c *CreateAsset) Marshal(p *codec.Packer) {
- p.PackBytes(c.Symbol)
- p.PackByte(c.Decimals)
- p.PackBytes(c.Metadata)
-}
-
-func UnmarshalCreateAsset(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
- var create CreateAsset
- p.UnpackBytes(MaxSymbolSize, true, &create.Symbol)
- create.Decimals = p.UnpackByte()
- p.UnpackBytes(MaxMetadataSize, true, &create.Metadata)
- return &create, p.Err()
-}
-
-func (*CreateAsset) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*CreateAsset) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/epoch_exit.go b/actions/epoch_exit.go
new file mode 100644
index 0000000..007eb89
--- /dev/null
+++ b/actions/epoch_exit.go
@@ -0,0 +1,168 @@
+package actions
+
+import (
+ "bytes"
+ "context"
+ "encoding/hex"
+ "fmt"
+ "slices"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/AnomalyFi/nodekit-seq/storage"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+var _ chain.Action = (*EpochExit)(nil)
+
+const (
+ CreateExit = iota
+ DeleteExit
+)
+
+type EpochExit struct {
+ Info hactions.EpochInfo `json:"info"`
+ Epoch uint64 `json:"epoch"`
+ OpCode int `json:"opcode"`
+}
+
+func (*EpochExit) GetTypeID() uint8 {
+ return hactions.EpochExitID
+}
+
+func (e *EpochExit) StateKeys(_ codec.Address, _ ids.ID) state.Keys {
+ return state.Keys{
+ string(hactions.EpochExitsKey(e.Epoch)): state.All,
+ string(storage.RollupInfoKey(e.Info.Namespace)): state.Read,
+ string(storage.RollupRegistryKey()): state.Read,
+ }
+}
+
+func (*EpochExit) StateKeysMaxChunks() []uint16 {
+ return []uint16{hactions.EpochExitsChunks, hactions.RollupInfoChunks, hactions.RollupRegistryChunks}
+}
+
+// TODO: Add check for curr epoch > start epoch of arcadia.
+func (e *EpochExit) Execute(
+ ctx context.Context,
+ _ chain.Rules,
+ mu state.Mutable,
+ _ int64,
+ _ uint64,
+ actor codec.Address,
+ _ ids.ID,
+) ([][]byte, error) {
+ if e.Epoch != e.Info.Epoch {
+ return nil, fmt.Errorf("epoch is not equal to what's in the meta, expected: %d, actual: %d", e.Epoch, e.Info.Epoch)
+ }
+
+ // check if rollup is registered.
+ nss, err := storage.GetRollupRegistry(ctx, mu)
+ if err != nil {
+ return nil, err
+ }
+
+ if !contains(nss, e.Info.Namespace) {
+ return nil, fmt.Errorf("namespace is not registered, namespace: %s", hex.EncodeToString(e.Info.Namespace))
+ }
+
+ rollupInfo, err := storage.GetRollupInfo(ctx, mu, e.Info.Namespace)
+ // rollup info will not be nil, as rollup is registered.
+ if err != nil {
+ return nil, err
+ }
+
+ if rollupInfo.AuthoritySEQAddress != actor {
+ return nil, ErrNotAuthorized
+ }
+
+ epochExits, exists, err := storage.GetEpochExits(ctx, mu, e.Epoch)
+ if err != nil {
+ return nil, err
+ }
+
+ switch e.OpCode {
+ case CreateExit:
+ // Check if rollup exited already for the Epoch.
+ if exists {
+ for _, es := range epochExits.Exits {
+ if bytes.Equal(e.Info.Namespace, es.Namespace) {
+ return nil, fmt.Errorf("exit already exists, namespace: %s, epoch: %d", hex.EncodeToString(e.Info.Namespace), e.Epoch)
+ }
+ }
+ }
+ if !exists {
+ epochExits = new(hactions.EpochExitInfo)
+ epochExits.Exits = make([]*hactions.EpochInfo, 0)
+ }
+ epochExits.Exits = append(epochExits.Exits, &e.Info)
+ if err := storage.SetEpochExits(ctx, mu, e.Epoch, epochExits); err != nil {
+ return nil, err
+ }
+ case DeleteExit:
+ idx := -1
+ // Check if rollup exit exists and get its index in epoch exits.
+ if exists {
+ for i, es := range epochExits.Exits {
+ if bytes.Equal(e.Info.Namespace, es.Namespace) {
+ idx = i
+ break
+ }
+ }
+ }
+ // Rollup did not exit prior.
+ if idx == -1 {
+ return nil, fmt.Errorf("exit not found, namespace: %s, epoch: %d", hex.EncodeToString(e.Info.Namespace), e.Epoch)
+ }
+ epochExits.Exits = slices.Delete(epochExits.Exits, idx, idx+1)
+ if err := storage.SetEpochExits(ctx, mu, e.Epoch, epochExits); err != nil {
+ return nil, err
+ }
+ default:
+ return nil, fmt.Errorf("op code(%d) not supported", e.OpCode)
+ }
+
+ return nil, nil
+}
+
+func (*EpochExit) ComputeUnits(codec.Address, chain.Rules) uint64 {
+ return EpochExitComputeUnits
+}
+
+func (e *EpochExit) Size() int {
+ return e.Info.Size() + consts.Uint64Len + consts.IntLen
+}
+
+func (e *EpochExit) Marshal(p *codec.Packer) {
+ e.Info.Marshal(p)
+ p.PackUint64(e.Epoch)
+ p.PackInt(e.OpCode)
+}
+
+func UnmarshalEpochExit(p *codec.Packer) (chain.Action, error) {
+ var epoch EpochExit
+ info, err := hactions.UnmarshalEpochInfo(p)
+ if err != nil {
+ return nil, err
+ }
+ epoch.Info = *info
+ epoch.Epoch = p.UnpackUint64(true)
+ epoch.OpCode = p.UnpackInt(false)
+ return &epoch, nil
+}
+
+func (*EpochExit) ValidRange(chain.Rules) (int64, int64) {
+ // Returning -1, -1 means that the action is always valid.
+ return -1, -1
+}
+
+func (*EpochExit) NMTNamespace() []byte {
+ return DefaultNMTNamespace // TODO: mark this the same to registering namespace?
+}
+
+func (*EpochExit) UseFeeMarket() bool {
+ return false
+}
diff --git a/actions/errors.go b/actions/errors.go
index b63f0aa..c945115 100644
--- a/actions/errors.go
+++ b/actions/errors.go
@@ -5,4 +5,14 @@ package actions
import "errors"
-var ErrNoSwapToFill = errors.New("no swap to fill")
+var (
+ ErrOutputValueZero = errors.New("value is zero")
+ ErrNotWhiteListed = errors.New("not whitelisted")
+ ErrInvalidBidderSignature = errors.New("invalid bidder signature")
+ ErrParsedBuilderSEQAddressMismatch = errors.New("parsed builder SEQ address mismatch")
+ ErrOutputMemoTooLarge = errors.New("memo is too large")
+ ErrNameSpaceNotRegistered = errors.New("namespace not registered")
+ ErrNotAuthorized = errors.New("not authorized")
+ ErrNameSpaceAlreadyRegistered = errors.New("namespace already registered")
+ ErrExitEpochSmallerThanStartEpoch = errors.New("exit epoch is smaller than start epoch")
+)
diff --git a/actions/export_asset.go b/actions/export_asset.go
deleted file mode 100644
index ed5c20e..0000000
--- a/actions/export_asset.go
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "context"
-
- "github.com/ava-labs/avalanchego/ids"
- smath "github.com/ava-labs/avalanchego/utils/math"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
-)
-
-var _ chain.Action = (*ExportAsset)(nil)
-
-type ExportAsset struct {
- To ed25519.PublicKey `json:"to"`
- Asset ids.ID `json:"asset"`
- Value uint64 `json:"value"`
- Return bool `json:"return"`
- Reward uint64 `json:"reward"`
- SwapIn uint64 `json:"swapIn"`
- AssetOut ids.ID `json:"assetOut"`
- SwapOut uint64 `json:"swapOut"`
- SwapExpiry int64 `json:"swapExpiry"`
- Destination ids.ID `json:"destination"`
-}
-
-func (*ExportAsset) GetTypeID() uint8 {
- return exportAssetID
-}
-
-func (e *ExportAsset) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- actor := auth.GetActor(rauth)
- if e.Return {
- return []string{
- string(storage.AssetKey(e.Asset)),
- string(storage.BalanceKey(actor, e.Asset)),
- }
- }
- return []string{
- string(storage.AssetKey(e.Asset)),
- string(storage.LoanKey(e.Asset, e.Destination)),
- string(storage.BalanceKey(actor, e.Asset)),
- }
-}
-
-func (e *ExportAsset) StateKeysMaxChunks() []uint16 {
- if e.Return {
- return []uint16{storage.AssetChunks, storage.BalanceChunks}
- }
- return []uint16{storage.AssetChunks, storage.LoanChunks, storage.BalanceChunks}
-}
-
-func (*ExportAsset) OutputsWarpMessage() bool {
- return true
-}
-
-func (e *ExportAsset) executeReturn(
- ctx context.Context,
- mu state.Mutable,
- actor ed25519.PublicKey,
- txID ids.ID,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- exists, symbol, decimals, metadata, supply, _, isWarp, err := storage.GetAsset(ctx, mu, e.Asset)
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if !exists {
- return false, ExportAssetComputeUnits, OutputAssetMissing, nil, nil
- }
- if !isWarp {
- return false, ExportAssetComputeUnits, OutputNotWarpAsset, nil, nil
- }
- allowedDestination, err := ids.ToID(metadata[consts.IDLen:])
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if allowedDestination != e.Destination {
- return false, ExportAssetComputeUnits, OutputWrongDestination, nil, nil
- }
- newSupply, err := smath.Sub(supply, e.Value)
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- newSupply, err = smath.Sub(newSupply, e.Reward)
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if newSupply > 0 {
- if err := storage.SetAsset(ctx, mu, e.Asset, symbol, decimals, metadata, newSupply, ed25519.EmptyPublicKey, true); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- } else {
- if err := storage.DeleteAsset(ctx, mu, e.Asset); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- }
- if err := storage.SubBalance(ctx, mu, actor, e.Asset, e.Value); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if e.Reward > 0 {
- if err := storage.SubBalance(ctx, mu, actor, e.Asset, e.Reward); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- }
- originalAsset, err := ids.ToID(metadata[:consts.IDLen])
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- wt := &WarpTransfer{
- To: e.To,
- Symbol: symbol,
- Decimals: decimals,
- Asset: originalAsset,
- Value: e.Value,
- Return: e.Return,
- Reward: e.Reward,
- SwapIn: e.SwapIn,
- AssetOut: e.AssetOut,
- SwapOut: e.SwapOut,
- SwapExpiry: e.SwapExpiry,
- TxID: txID,
- DestinationChainID: e.Destination,
- }
- payload, err := wt.Marshal()
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- wm := &warp.UnsignedMessage{
- // NetworkID + SourceChainID is populated by hypersdk
- Payload: payload,
- }
- return true, ExportAssetComputeUnits, nil, wm, nil
-}
-
-func (e *ExportAsset) executeLoan(
- ctx context.Context,
- mu state.Mutable,
- actor ed25519.PublicKey,
- txID ids.ID,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- exists, symbol, decimals, _, _, _, isWarp, err := storage.GetAsset(ctx, mu, e.Asset)
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if !exists {
- return false, ExportAssetComputeUnits, OutputAssetMissing, nil, nil
- }
- if isWarp {
- // Cannot export an asset if it was warped in and not returning
- return false, ExportAssetComputeUnits, OutputWarpAsset, nil, nil
- }
- if err := storage.AddLoan(ctx, mu, e.Asset, e.Destination, e.Value); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.SubBalance(ctx, mu, actor, e.Asset, e.Value); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if e.Reward > 0 {
- if err := storage.AddLoan(ctx, mu, e.Asset, e.Destination, e.Reward); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.SubBalance(ctx, mu, actor, e.Asset, e.Reward); err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- }
- wt := &WarpTransfer{
- To: e.To,
- Symbol: symbol,
- Decimals: decimals,
- Asset: e.Asset,
- Value: e.Value,
- Return: e.Return,
- Reward: e.Reward,
- SwapIn: e.SwapIn,
- AssetOut: e.AssetOut,
- SwapOut: e.SwapOut,
- SwapExpiry: e.SwapExpiry,
- TxID: txID,
- DestinationChainID: e.Destination,
- }
- payload, err := wt.Marshal()
- if err != nil {
- return false, ExportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- wm := &warp.UnsignedMessage{
- // NetworkID + SourceChainID is populated by hypersdk
- Payload: payload,
- }
- return true, ExportAssetComputeUnits, nil, wm, nil
-}
-
-func (e *ExportAsset) Execute(
- ctx context.Context,
- _ chain.Rules,
- mu state.Mutable,
- _ int64,
- rauth chain.Auth,
- txID ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
- if e.Value == 0 {
- return false, ExportAssetComputeUnits, OutputValueZero, nil, nil
- }
- if e.Destination == ids.Empty {
- // This would result in multiplying balance export by whoever imports the
- // transaction.
- return false, ExportAssetComputeUnits, OutputAnycast, nil, nil
- }
- // TODO: check if destination is ourselves
- if e.Return {
- return e.executeReturn(ctx, mu, actor, txID)
- }
- return e.executeLoan(ctx, mu, actor, txID)
-}
-
-func (*ExportAsset) MaxComputeUnits(chain.Rules) uint64 {
- return ExportAssetComputeUnits
-}
-
-func (*ExportAsset) Size() int {
- return ed25519.PublicKeyLen + consts.IDLen +
- consts.Uint64Len + consts.BoolLen +
- consts.Uint64Len + /* op bits */
- consts.Uint64Len + consts.Uint64Len + consts.IDLen + consts.Uint64Len +
- consts.Int64Len + consts.IDLen
-}
-
-func (e *ExportAsset) Marshal(p *codec.Packer) {
- p.PackPublicKey(e.To)
- p.PackID(e.Asset)
- p.PackUint64(e.Value)
- p.PackBool(e.Return)
- op := codec.NewOptionalWriter(consts.Uint64Len*3 + consts.Int64Len + consts.IDLen)
- op.PackUint64(e.Reward)
- op.PackUint64(e.SwapIn)
- op.PackID(e.AssetOut)
- op.PackUint64(e.SwapOut)
- op.PackInt64(e.SwapExpiry)
- p.PackOptional(op)
- p.PackID(e.Destination)
-}
-
-func UnmarshalExportAsset(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
- var export ExportAsset
- p.UnpackPublicKey(false, &export.To) // can transfer to blackhole
- p.UnpackID(false, &export.Asset) // may export native
- export.Value = p.UnpackUint64(true)
- export.Return = p.UnpackBool()
- op := p.NewOptionalReader()
- export.Reward = op.UnpackUint64() // reward not required
- export.SwapIn = op.UnpackUint64() // optional
- op.UnpackID(&export.AssetOut)
- export.SwapOut = op.UnpackUint64()
- export.SwapExpiry = op.UnpackInt64()
- op.Done()
- p.UnpackID(true, &export.Destination)
- if err := p.Err(); err != nil {
- return nil, err
- }
- // Handle swap checks
- if !ValidSwapParams(
- export.Value,
- export.SwapIn,
- export.AssetOut,
- export.SwapOut,
- export.SwapExpiry,
- ) {
- return nil, chain.ErrInvalidObject
- }
- return &export, nil
-}
-
-func (*ExportAsset) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*ExportAsset) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/export_block_msg.go b/actions/export_block_msg.go
deleted file mode 100644
index a20f68c..0000000
--- a/actions/export_block_msg.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "context"
-
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
-)
-
-var _ chain.Action = (*ExportBlockMsg)(nil)
-
-type ExportBlockMsg struct {
- Prnt ids.ID `json:"parent"`
- Tmstmp int64 `json:"timestamp"`
- Hght uint64 `json:"height"`
- StateRoot ids.ID `json:"stateRoot"`
- Destination ids.ID `json:"destination"`
-}
-
-func (*ExportBlockMsg) GetTypeID() uint8 {
- return exportBlockID
-}
-
-func (e *ExportBlockMsg) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- // TODO may need to be fixed
- return []string{
- string(storage.PrefixBlockKey(e.StateRoot, e.Destination)),
- string(storage.PrefixBlockKey(e.Prnt, e.Destination)),
- }
-}
-
-// TODO probably need to fix
-func (e *ExportBlockMsg) StateKeysMaxChunks() []uint16 {
- return []uint16{storage.AssetChunks, storage.LoanChunks, storage.BalanceChunks}
-}
-
-func (e *ExportBlockMsg) executeLoan(
- ctx context.Context,
- mu state.Mutable,
- actor ed25519.PublicKey,
- txID ids.ID,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- // TODO may need to add a destination chainID to this
- wt := &chain.WarpBlock{
- Prnt: e.Prnt,
- Tmstmp: e.Tmstmp,
- Hght: e.Hght,
- StateRoot: e.StateRoot,
- TxID: txID,
- }
- payload, err := wt.Marshal()
- if err != nil {
- return false, ExportBlockComputeUnits, utils.ErrBytes(err), nil, nil
- }
- wm := &warp.UnsignedMessage{
- // NetworkID + SourceChainID is populated by hypersdk
- Payload: payload,
- }
- return true, ExportBlockComputeUnits, nil, wm, nil
-}
-
-func (e *ExportBlockMsg) Execute(
- ctx context.Context,
- _ chain.Rules,
- mu state.Mutable,
- _ int64,
- rauth chain.Auth,
- txID ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
- // unitsUsed := e.MaxUnits(r) // max units == units
- if e.Destination == ids.Empty {
- // This would result in multiplying balance export by whoever imports the
- // transaction.
- return false, ExportBlockComputeUnits, OutputAnycast, nil, nil
- }
- // TODO: check if destination is ourselves
- // if e.Return {
- // return e.executeReturn(ctx, r, db, actor, txID)
- // }
- return e.executeLoan(ctx, mu, actor, txID)
-}
-
-func (*ExportBlockMsg) MaxUnits(chain.Rules) uint64 {
- // TODO fix this
- return ExportBlockComputeUnits
-}
-
-func (*ExportBlockMsg) Size() int {
- return consts.IDLen + consts.Int64Len + consts.Uint64Len + consts.Int64Len + consts.IDLen
-}
-
-func (*ExportBlockMsg) OutputsWarpMessage() bool {
- return true
-}
-
-func (*ExportBlockMsg) MaxComputeUnits(chain.Rules) uint64 {
- return ExportBlockComputeUnits
-}
-
-func (e *ExportBlockMsg) Marshal(p *codec.Packer) {
- p.PackID(e.Prnt)
- p.PackInt64(e.Tmstmp)
- p.PackUint64(e.Hght)
- p.PackID(e.StateRoot)
- p.PackID(e.Destination)
-}
-
-func UnmarshalExportBlockMsg(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
- var export ExportBlockMsg
- p.UnpackID(true, &export.Prnt)
- export.Tmstmp = p.UnpackInt64(true)
- export.Hght = p.UnpackUint64(true)
- p.UnpackID(true, &export.StateRoot)
- p.UnpackID(true, &export.Destination)
- if err := p.Err(); err != nil {
- return nil, err
- }
- return &export, nil
-}
-
-func (*ExportBlockMsg) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*ExportBlockMsg) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/import_asset.go b/actions/import_asset.go
deleted file mode 100644
index a914ee0..0000000
--- a/actions/import_asset.go
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "bytes"
- "context"
-
- "github.com/ava-labs/avalanchego/ids"
- smath "github.com/ava-labs/avalanchego/utils/math"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
-)
-
-var _ chain.Action = (*ImportAsset)(nil)
-
-type ImportAsset struct {
- // Fill indicates if the actor wishes to fill the order request in the warp
- // message. This must be true if the warp message is in a block with
- // a timestamp < [SwapExpiry].
- Fill bool `json:"fill"`
-
- // warpTransfer is parsed from the inner *warp.Message
- warpTransfer *WarpTransfer
-
- // warpMessage is the full *warp.Message parsed from [chain.Transaction]
- warpMessage *warp.Message
-}
-
-func (*ImportAsset) GetTypeID() uint8 {
- return importAssetID
-}
-
-func (i *ImportAsset) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- var (
- keys []string
- assetID ids.ID
- actor = auth.GetActor(rauth)
- )
- if i.warpTransfer.Return {
- assetID = i.warpTransfer.Asset
- keys = []string{
- string(storage.AssetKey(i.warpTransfer.Asset)),
- string(storage.LoanKey(i.warpTransfer.Asset, i.warpMessage.SourceChainID)),
- string(storage.BalanceKey(i.warpTransfer.To, i.warpTransfer.Asset)),
- }
- } else {
- assetID = ImportedAssetID(i.warpTransfer.Asset, i.warpMessage.SourceChainID)
- keys = []string{
- string(storage.AssetKey(assetID)),
- string(storage.BalanceKey(i.warpTransfer.To, assetID)),
- }
- }
-
- // If the [warpTransfer] specified a reward, we add the state key to make
- // sure it is paid.
- if i.warpTransfer.Reward > 0 {
- keys = append(keys, string(storage.BalanceKey(actor, assetID)))
- }
-
- // If the [warpTransfer] requests a swap, we add the state keys to transfer
- // the required balances.
- if i.Fill && i.warpTransfer.SwapIn > 0 {
- keys = append(keys, string(storage.BalanceKey(actor, i.warpTransfer.AssetOut)))
- keys = append(keys, string(storage.BalanceKey(actor, assetID)))
- keys = append(keys, string(storage.BalanceKey(i.warpTransfer.To, i.warpTransfer.AssetOut)))
- }
- return keys
-}
-
-func (i *ImportAsset) StateKeysMaxChunks() []uint16 {
- // Can't use [warpTransfer] because it may not be populated yet
- chunks := []uint16{}
- chunks = append(chunks, storage.LoanChunks)
- chunks = append(chunks, storage.AssetChunks)
- chunks = append(chunks, storage.BalanceChunks)
-
- // If the [warpTransfer] specified a reward, we add the state key to make
- // sure it is paid.
- chunks = append(chunks, storage.BalanceChunks)
-
- // If the [warpTransfer] requests a swap, we add the state keys to transfer
- // the required balances.
- if i.Fill {
- chunks = append(chunks, storage.BalanceChunks)
- chunks = append(chunks, storage.BalanceChunks)
- chunks = append(chunks, storage.BalanceChunks)
- }
- return chunks
-}
-
-func (*ImportAsset) OutputsWarpMessage() bool {
- return false
-}
-
-func (i *ImportAsset) executeMint(
- ctx context.Context,
- mu state.Mutable,
- actor ed25519.PublicKey,
-) []byte {
- asset := ImportedAssetID(i.warpTransfer.Asset, i.warpMessage.SourceChainID)
- exists, symbol, decimals, metadata, supply, _, warp, err := storage.GetAsset(ctx, mu, asset)
- if err != nil {
- return utils.ErrBytes(err)
- }
- if exists && !warp {
- // Should not be possible
- return OutputConflictingAsset
- }
- if !exists {
- symbol = i.warpTransfer.Symbol
- decimals = i.warpTransfer.Decimals
- metadata = ImportedAssetMetadata(i.warpTransfer.Asset, i.warpMessage.SourceChainID)
- }
- newSupply, err := smath.Add64(supply, i.warpTransfer.Value)
- if err != nil {
- return utils.ErrBytes(err)
- }
- newSupply, err = smath.Add64(newSupply, i.warpTransfer.Reward)
- if err != nil {
- return utils.ErrBytes(err)
- }
- if err := storage.SetAsset(ctx, mu, asset, symbol, decimals, metadata, newSupply, ed25519.EmptyPublicKey, true); err != nil {
- return utils.ErrBytes(err)
- }
- if err := storage.AddBalance(ctx, mu, i.warpTransfer.To, asset, i.warpTransfer.Value, true); err != nil {
- return utils.ErrBytes(err)
- }
- if i.warpTransfer.Reward > 0 {
- if err := storage.AddBalance(ctx, mu, actor, asset, i.warpTransfer.Reward, true); err != nil {
- return utils.ErrBytes(err)
- }
- }
- return nil
-}
-
-func (i *ImportAsset) executeReturn(
- ctx context.Context,
- mu state.Mutable,
- actor ed25519.PublicKey,
-) []byte {
- exists, symbol, decimals, _, _, _, warp, err := storage.GetAsset(ctx, mu, i.warpTransfer.Asset)
- if err != nil {
- return utils.ErrBytes(err)
- }
- if !exists {
- return OutputAssetMissing
- }
- if !bytes.Equal(i.warpTransfer.Symbol, symbol) {
- return OutputSymbolIncorrect
- }
- if i.warpTransfer.Decimals != decimals {
- return OutputDecimalsIncorrect
- }
- if warp {
- return OutputWarpAsset
- }
- if err := storage.SubLoan(
- ctx, mu, i.warpTransfer.Asset,
- i.warpMessage.SourceChainID, i.warpTransfer.Value,
- ); err != nil {
- return utils.ErrBytes(err)
- }
- if err := storage.AddBalance(
- ctx, mu, i.warpTransfer.To,
- i.warpTransfer.Asset, i.warpTransfer.Value,
- true,
- ); err != nil {
- return utils.ErrBytes(err)
- }
- if i.warpTransfer.Reward > 0 {
- if err := storage.SubLoan(
- ctx, mu, i.warpTransfer.Asset,
- i.warpMessage.SourceChainID, i.warpTransfer.Reward,
- ); err != nil {
- return utils.ErrBytes(err)
- }
- if err := storage.AddBalance(
- ctx, mu, actor,
- i.warpTransfer.Asset, i.warpTransfer.Reward,
- true,
- ); err != nil {
- return utils.ErrBytes(err)
- }
- }
- return nil
-}
-
-func (i *ImportAsset) Execute(
- ctx context.Context,
- r chain.Rules,
- mu state.Mutable,
- t int64,
- rauth chain.Auth,
- _ ids.ID,
- warpVerified bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
- if !warpVerified {
- return false, ImportAssetComputeUnits, OutputWarpVerificationFailed, nil, nil
- }
- if i.warpTransfer.DestinationChainID != r.ChainID() {
- return false, ImportAssetComputeUnits, OutputInvalidDestination, nil, nil
- }
- if i.warpTransfer.Value == 0 {
- return false, ImportAssetComputeUnits, OutputValueZero, nil, nil
- }
- var output []byte
- if i.warpTransfer.Return {
- output = i.executeReturn(ctx, mu, actor)
- } else {
- output = i.executeMint(ctx, mu, actor)
- }
- if len(output) > 0 {
- return false, ImportAssetComputeUnits, output, nil, nil
- }
- if i.warpTransfer.SwapIn == 0 {
- // We are ensured that [i.Fill] is false here because of logic in unmarshal
- return true, ImportAssetComputeUnits, nil, nil, nil
- }
- if !i.Fill {
- if i.warpTransfer.SwapExpiry > t {
- return false, ImportAssetComputeUnits, OutputMustFill, nil, nil
- }
- return true, ImportAssetComputeUnits, nil, nil, nil
- }
- // TODO: charge more if swap is performed
- var assetIn ids.ID
- if i.warpTransfer.Return {
- assetIn = i.warpTransfer.Asset
- } else {
- assetIn = ImportedAssetID(i.warpTransfer.Asset, i.warpMessage.SourceChainID)
- }
- if err := storage.SubBalance(ctx, mu, i.warpTransfer.To, assetIn, i.warpTransfer.SwapIn); err != nil {
- return false, ImportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.AddBalance(ctx, mu, actor, assetIn, i.warpTransfer.SwapIn, true); err != nil {
- return false, ImportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.SubBalance(ctx, mu, actor, i.warpTransfer.AssetOut, i.warpTransfer.SwapOut); err != nil {
- return false, ImportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.AddBalance(ctx, mu, i.warpTransfer.To, i.warpTransfer.AssetOut, i.warpTransfer.SwapOut, true); err != nil {
- return false, ImportAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- return true, ImportAssetComputeUnits, nil, nil, nil
-}
-
-func (*ImportAsset) MaxComputeUnits(chain.Rules) uint64 {
- return ImportAssetComputeUnits
-}
-
-func (*ImportAsset) Size() int {
- return consts.BoolLen
-}
-
-// All we encode that is action specific for now is the type byte from the
-// registry.
-func (i *ImportAsset) Marshal(p *codec.Packer) {
- p.PackBool(i.Fill)
-}
-
-func UnmarshalImportAsset(p *codec.Packer, wm *warp.Message) (chain.Action, error) {
- var (
- imp ImportAsset
- err error
- )
- imp.Fill = p.UnpackBool()
- if err := p.Err(); err != nil {
- return nil, err
- }
- imp.warpMessage = wm
- imp.warpTransfer, err = UnmarshalWarpTransfer(imp.warpMessage.Payload)
- if err != nil {
- return nil, err
- }
- // Ensure we can fill the swap if it exists
- if imp.Fill && imp.warpTransfer.SwapIn == 0 {
- return nil, ErrNoSwapToFill
- }
- return &imp, nil
-}
-
-func (*ImportAsset) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*ImportAsset) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/import_block_msg.go b/actions/import_block_msg.go
deleted file mode 100644
index 0927fa1..0000000
--- a/actions/import_block_msg.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "context"
-
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/nodekit-seq/storage"
-)
-
-var _ chain.Action = (*ImportBlockMsg)(nil)
-
-type ImportBlockMsg struct {
- // Fill indicates if the actor wishes to fill the order request in the warp
- // message. This must be true if the warp message is in a block with
- // a timestamp < [SwapExpiry].
- Fill bool `json:"fill"`
- // warpTransfer is parsed from the inner *warp.Message
- warpMsg *chain.WarpBlock
-
- // warpMessage is the full *warp.Message parsed from [chain.Transaction]
- warpMessage *warp.Message
-}
-
-func (e *ImportBlockMsg) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- // TODO needs to be fixed
- return []string{
- string(storage.PrefixBlockKey(e.warpMsg.StateRoot, e.warpMsg.Prnt)),
- }
-}
-
-func (i *ImportBlockMsg) StateKeysMaxChunks() []uint16 {
- // TODO need to fix this
- // Can't use [warpTransfer] because it may not be populated yet
- chunks := []uint16{}
- chunks = append(chunks, storage.LoanChunks)
- chunks = append(chunks, storage.AssetChunks)
- chunks = append(chunks, storage.BalanceChunks)
-
- // If the [warpTransfer] specified a reward, we add the state key to make
- // sure it is paid.
- chunks = append(chunks, storage.BalanceChunks)
-
- // If the [warpTransfer] requests a swap, we add the state keys to transfer
- // the required balances.
- if i.Fill {
- chunks = append(chunks, storage.BalanceChunks)
- chunks = append(chunks, storage.BalanceChunks)
- chunks = append(chunks, storage.BalanceChunks)
- }
- return chunks
-}
-
-func (i *ImportBlockMsg) Execute(
- ctx context.Context,
- r chain.Rules,
- mu state.Mutable,
- t int64,
- rauth chain.Auth,
- _ ids.ID,
- warpVerified bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- if !warpVerified {
- return false, ImportBlockComputeUnits, OutputValueZero, nil, nil
- }
- return true, ImportBlockComputeUnits, nil, nil, nil
-}
-
-func (i *ImportBlockMsg) MaxComputeUnits(chain.Rules) uint64 {
- return ImportBlockComputeUnits
-}
-
-func (*ImportBlockMsg) Size() int {
- return consts.BoolLen
-}
-
-func (*ImportBlockMsg) OutputsWarpMessage() bool {
- return false
-}
-
-func (*ImportBlockMsg) GetTypeID() uint8 {
- return importBlockID
-}
-
-// All we encode that is action specific for now is the type byte from the
-// registry.
-func (i *ImportBlockMsg) Marshal(p *codec.Packer) {
- p.PackBool(i.Fill)
-}
-
-func UnmarshalImportBlockMsg(p *codec.Packer, wm *warp.Message) (chain.Action, error) {
- var (
- imp ImportBlockMsg
- err error
- )
- imp.Fill = p.UnpackBool()
- if err := p.Err(); err != nil {
- return nil, err
- }
- imp.warpMessage = wm
- imp.warpMsg, err = chain.UnmarshalWarpBlock(imp.warpMessage.Payload)
- if err != nil {
- return nil, err
- }
-
- return &imp, nil
-}
-
-func (*ImportBlockMsg) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*ImportBlockMsg) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/mint_asset.go b/actions/mint_asset.go
deleted file mode 100644
index 5edbafd..0000000
--- a/actions/mint_asset.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "context"
-
- "github.com/ava-labs/avalanchego/ids"
- smath "github.com/ava-labs/avalanchego/utils/math"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
-)
-
-var _ chain.Action = (*MintAsset)(nil)
-
-type MintAsset struct {
- // To is the recipient of the [Value].
- To ed25519.PublicKey `json:"to"`
-
- // Asset is the [TxID] that created the asset.
- Asset ids.ID `json:"asset"`
-
- // Number of assets to mint to [To].
- Value uint64 `json:"value"`
-}
-
-func (*MintAsset) GetTypeID() uint8 {
- return mintAssetID
-}
-
-func (m *MintAsset) StateKeys(chain.Auth, ids.ID) []string {
- return []string{
- string(storage.AssetKey(m.Asset)),
- string(storage.BalanceKey(m.To, m.Asset)),
- }
-}
-
-func (*MintAsset) StateKeysMaxChunks() []uint16 {
- return []uint16{storage.AssetChunks, storage.BalanceChunks}
-}
-
-func (*MintAsset) OutputsWarpMessage() bool {
- return false
-}
-
-func (m *MintAsset) Execute(
- ctx context.Context,
- _ chain.Rules,
- mu state.Mutable,
- _ int64,
- rauth chain.Auth,
- _ ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
- if m.Asset == ids.Empty {
- return false, MintAssetComputeUnits, OutputAssetIsNative, nil, nil
- }
- if m.Value == 0 {
- return false, MintAssetComputeUnits, OutputValueZero, nil, nil
- }
- exists, symbol, decimals, metadata, supply, owner, isWarp, err := storage.GetAsset(ctx, mu, m.Asset)
- if err != nil {
- return false, MintAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if !exists {
- return false, MintAssetComputeUnits, OutputAssetMissing, nil, nil
- }
- if isWarp {
- return false, MintAssetComputeUnits, OutputWarpAsset, nil, nil
- }
- if owner != actor {
- return false, MintAssetComputeUnits, OutputWrongOwner, nil, nil
- }
- newSupply, err := smath.Add64(supply, m.Value)
- if err != nil {
- return false, MintAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.SetAsset(ctx, mu, m.Asset, symbol, decimals, metadata, newSupply, actor, isWarp); err != nil {
- return false, MintAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- if err := storage.AddBalance(ctx, mu, m.To, m.Asset, m.Value, true); err != nil {
- return false, MintAssetComputeUnits, utils.ErrBytes(err), nil, nil
- }
- return true, MintAssetComputeUnits, nil, nil, nil
-}
-
-func (*MintAsset) MaxComputeUnits(chain.Rules) uint64 {
- return MintAssetComputeUnits
-}
-
-func (*MintAsset) Size() int {
- return ed25519.PublicKeyLen + consts.IDLen + consts.Uint64Len
-}
-
-func (m *MintAsset) Marshal(p *codec.Packer) {
- p.PackPublicKey(m.To)
- p.PackID(m.Asset)
- p.PackUint64(m.Value)
-}
-
-func UnmarshalMintAsset(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
- var mint MintAsset
- p.UnpackPublicKey(true, &mint.To) // cannot mint to blackhole
- p.UnpackID(true, &mint.Asset) // empty ID is the native asset
- mint.Value = p.UnpackUint64(true)
- return &mint, p.Err()
-}
-
-func (*MintAsset) ValidRange(chain.Rules) (int64, int64) {
- // Returning -1, -1 means that the action is always valid.
- return -1, -1
-}
-
-func (*MintAsset) NMTNamespace() []byte {
- return DefaultNMTNamespace
-}
diff --git a/actions/msg.go b/actions/msg.go
index 84d5209..e525b4b 100644
--- a/actions/msg.go
+++ b/actions/msg.go
@@ -9,85 +9,67 @@ import (
"github.com/AnomalyFi/hypersdk/chain"
"github.com/AnomalyFi/hypersdk/codec"
"github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
"github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/storage"
"github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
)
var _ chain.Action = (*SequencerMsg)(nil)
type SequencerMsg struct {
- ChainId []byte `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"`
- Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
- FromAddress ed25519.PublicKey `json:"from_address"`
- // `protobuf:"bytes,3,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"`
+ ChainID []byte `json:"chain_id"` // little endian encoded uint64
+ Data []byte `json:"data"`
+ FromAddress codec.Address `json:"from_address"`
+ RelayerID int `json:"relayer_id"`
}
func (*SequencerMsg) GetTypeID() uint8 {
- return msgID
+ return MsgID
}
-func (t *SequencerMsg) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- // owner, err := utils.ParseAddress(t.FromAddress)
- // if err != nil {
- // return nil, err
- // }
-
- return []string{
- // We always pay fees with the native asset (which is [ids.Empty])
- string(storage.BalanceKey(auth.GetActor(rauth), ids.Empty)),
- // string(t.ChainId),
- // string(t.Data),
- }
+func (*SequencerMsg) StateKeys(_ codec.Address, _ ids.ID) state.Keys {
+ return state.Keys{}
}
// TODO fix this
func (*SequencerMsg) StateKeysMaxChunks() []uint16 {
- return []uint16{storage.BalanceChunks}
+ return []uint16{}
}
-func (*SequencerMsg) OutputsWarpMessage() bool {
- return false
-}
-
-func (t *SequencerMsg) Execute(
- ctx context.Context,
+func (*SequencerMsg) Execute(
+ _ context.Context,
_ chain.Rules,
- mu state.Mutable,
+ _ state.Mutable,
_ int64,
- rauth chain.Auth,
+ _ uint64,
+ _ codec.Address,
_ ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- return true, MsgComputeUnits, nil, nil, nil
+) ([][]byte, error) {
+ return nil, nil
}
-func (*SequencerMsg) MaxComputeUnits(chain.Rules) uint64 {
+func (*SequencerMsg) ComputeUnits(codec.Address, chain.Rules) uint64 {
return MsgComputeUnits
}
-func (*SequencerMsg) Size() int {
- // TODO this should be larger because it should consider the max byte array length
- // We use size as the price of this transaction but we could just as easily
- // use any other calculation.
- return ed25519.PublicKeyLen + consts.IDLen + consts.Uint64Len
+func (msg *SequencerMsg) Size() int {
+ return codec.BytesLen(msg.ChainID) + codec.BytesLen(msg.Data) + codec.AddressLen + consts.IntLen
}
-func (t *SequencerMsg) Marshal(p *codec.Packer) {
- p.PackPublicKey(t.FromAddress)
- p.PackBytes(t.Data)
- p.PackBytes(t.ChainId)
+func (msg *SequencerMsg) Marshal(p *codec.Packer) {
+ p.PackAddress(msg.FromAddress)
+ p.PackBytes(msg.Data)
+ p.PackBytes(msg.ChainID)
+ p.PackInt(msg.RelayerID)
}
-func UnmarshalSequencerMsg(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
+func UnmarshalSequencerMsg(p *codec.Packer) (chain.Action, error) {
var sequencermsg SequencerMsg
- p.UnpackPublicKey(false, &sequencermsg.FromAddress)
+ p.UnpackAddress(&sequencermsg.FromAddress)
// TODO need to correct this and check byte count
p.UnpackBytes(-1, true, &sequencermsg.Data)
- p.UnpackBytes(-1, true, &sequencermsg.ChainId)
+ p.UnpackBytes(-1, true, &sequencermsg.ChainID)
+ // Note, required has to be false or RelayerID of 0 will report ID not populated
+ sequencermsg.RelayerID = p.UnpackInt(false)
return &sequencermsg, p.Err()
}
@@ -96,6 +78,10 @@ func (*SequencerMsg) ValidRange(chain.Rules) (int64, int64) {
return -1, -1
}
-func (t *SequencerMsg) NMTNamespace() []byte {
- return t.ChainId
+func (msg *SequencerMsg) NMTNamespace() []byte {
+ return msg.ChainID
+}
+
+func (*SequencerMsg) UseFeeMarket() bool {
+ return true
}
diff --git a/actions/outputs.go b/actions/outputs.go
deleted file mode 100644
index 8cfdbe8..0000000
--- a/actions/outputs.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-var (
- OutputValueZero = []byte("value is zero")
- OutputMemoTooLarge = []byte("memo is too large")
- OutputAssetIsNative = []byte("cannot mint native asset")
- OutputAssetAlreadyExists = []byte("asset already exists")
- OutputAssetMissing = []byte("asset missing")
- OutputInTickZero = []byte("in rate is zero")
- OutputOutTickZero = []byte("out rate is zero")
- OutputSupplyZero = []byte("supply is zero")
- OutputSupplyMisaligned = []byte("supply is misaligned")
- OutputOrderMissing = []byte("order is missing")
- OutputUnauthorized = []byte("unauthorized")
- OutputWrongIn = []byte("wrong in asset")
- OutputWrongOut = []byte("wrong out asset")
- OutputWrongOwner = []byte("wrong owner")
- OutputInsufficientInput = []byte("insufficient input")
- OutputInsufficientOutput = []byte("insufficient output")
- OutputValueMisaligned = []byte("value is misaligned")
- OutputSymbolEmpty = []byte("symbol is empty")
- OutputSymbolIncorrect = []byte("symbol is incorrect")
- OutputSymbolTooLarge = []byte("symbol is too large")
- OutputDecimalsIncorrect = []byte("decimal is incorrect")
- OutputDecimalsTooLarge = []byte("decimal is too large")
- OutputMetadataEmpty = []byte("metadata is empty")
- OutputMetadataTooLarge = []byte("metadata is too large")
- OutputSameInOut = []byte("same asset used for in and out")
- OutputConflictingAsset = []byte("warp has same asset as another")
- OutputAnycast = []byte("anycast output")
- OutputNotWarpAsset = []byte("not warp asset")
- OutputWarpAsset = []byte("warp asset")
- OutputWrongDestination = []byte("wrong destination")
- OutputMustFill = []byte("must fill request")
- OutputWarpVerificationFailed = []byte("warp verification failed")
- OutputInvalidDestination = []byte("invalid destination")
-)
-
-// var (
-// OutputValueZero = []byte("value is zero")
-// OutputAssetIsNative = []byte("cannot mint native asset")
-// OutputAssetAlreadyExists = []byte("asset already exists")
-// OutputAssetMissing = []byte("asset missing")
-// OutputInTickZero = []byte("in rate is zero")
-// OutputOutTickZero = []byte("out rate is zero")
-// OutputSupplyZero = []byte("supply is zero")
-// OutputSupplyMisaligned = []byte("supply is misaligned")
-// OutputOrderMissing = []byte("order is missing")
-// OutputUnauthorized = []byte("unauthorized")
-// OutputWrongIn = []byte("wrong in asset")
-// OutputWrongOut = []byte("wrong out asset")
-// OutputWrongOwner = []byte("wrong owner")
-// OutputInsufficientInput = []byte("insufficient input")
-// OutputInsufficientOutput = []byte("insufficient output")
-// OutputValueMisaligned = []byte("value is misaligned")
-// OutputMetadataTooLarge = []byte("metadata is too large")
-// OutputSameInOut = []byte("same asset used for in and out")
-// OutputConflictingAsset = []byte("warp has same asset as another")
-// OutputAnycast = []byte("anycast output")
-// OutputNotWarpAsset = []byte("not warp asset")
-// OutputWarpAsset = []byte("warp asset")
-// OutputWrongDestination = []byte("wrong destination")
-// OutputMustFill = []byte("must fill request")
-// OutputWarpVerificationFailed = []byte("warp verification failed")
-// )
diff --git a/actions/rollup_register.go b/actions/rollup_register.go
new file mode 100644
index 0000000..c92bb38
--- /dev/null
+++ b/actions/rollup_register.go
@@ -0,0 +1,173 @@
+package actions
+
+import (
+ "bytes"
+ "context"
+ "encoding/hex"
+ "fmt"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/AnomalyFi/nodekit-seq/storage"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+var _ chain.Action = (*RollupRegistration)(nil)
+
+const (
+ CreateRollup = iota
+ ExitRollup
+ UpdateRollup
+)
+
+type RollupRegistration struct {
+ Info hactions.RollupInfo `json:"info"`
+ Namespace []byte `json:"namespace"`
+ OpCode int `json:"opcode"`
+}
+
+func (*RollupRegistration) GetTypeID() uint8 {
+ return hactions.RollupRegisterID
+}
+
+func (r *RollupRegistration) StateKeys(_ codec.Address, _ ids.ID) state.Keys {
+ return state.Keys{
+ string(storage.RollupInfoKey(r.Namespace)): state.All,
+ string(storage.RollupRegistryKey()): state.All,
+ }
+}
+
+func (*RollupRegistration) StateKeysMaxChunks() []uint16 {
+ return []uint16{hactions.RollupInfoChunks, hactions.RollupRegistryChunks}
+}
+
+// TODO: this action needs to be managed by DAO to manage deletions since we are not deleting any namespace from storage
+// but only by marking them as regsitered or exited
+func (r *RollupRegistration) Execute(
+ ctx context.Context,
+ rules chain.Rules,
+ mu state.Mutable,
+ _ int64,
+ hght uint64,
+ actor codec.Address,
+ _ ids.ID,
+) ([][]byte, error) {
+ if !bytes.Equal(r.Namespace, r.Info.Namespace) {
+ return nil, fmt.Errorf("namespace is not equal to what's in the meta, expected: %s, actual: %s", hex.EncodeToString(r.Namespace), hex.EncodeToString(r.Info.Namespace))
+ }
+
+ if len(r.Namespace) > consts.MaxNamespaceLen {
+ return nil, fmt.Errorf("namespace length is too long, maximum: %d, actual: %d", consts.MaxNamespaceLen, len(r.Namespace))
+ }
+
+ namespaces, err := storage.GetRollupRegistry(ctx, mu)
+ if err != nil {
+ return nil, fmt.Errorf("unable to get namespaces: %w", err)
+ }
+
+ switch r.OpCode {
+ case CreateRollup:
+ if !contains(namespaces, r.Namespace) {
+ namespaces = append(namespaces, r.Namespace)
+ } else {
+ // only allow modifing informations that are not related to ExitEpoch or StartEpoch
+ if err := authorizationChecks(ctx, actor, namespaces, r.Namespace, mu); err != nil {
+ return nil, fmt.Errorf("authorization failed: %w", err)
+ }
+ }
+ if r.Info.StartEpoch < Epoch(hght, rules.GetEpochLength())+2 || r.Info.ExitEpoch != 0 {
+ return nil, fmt.Errorf("epoch number is not valid, minimum: %d, actual: %d, exit: %d", Epoch(hght, rules.GetEpochLength())+2, r.Info.StartEpoch, r.Info.ExitEpoch)
+ }
+ if r.Info.ExitEpoch != 0 {
+ return nil, fmt.Errorf("exit epoch not 0")
+ }
+
+ if err := storage.SetRollupInfo(ctx, mu, r.Namespace, &r.Info); err != nil {
+ return nil, fmt.Errorf("unable to set rollup info(CREATE): %w", err)
+ }
+ case UpdateRollup:
+ // only allow modifing informations that are not related to ExitEpoch or StartEpoch
+ if err := authorizationChecks(ctx, actor, namespaces, r.Namespace, mu); err != nil {
+ return nil, fmt.Errorf("authorization failed(UPDATE): %w", err)
+ }
+
+ rollupInfoExists, err := storage.GetRollupInfo(ctx, mu, r.Namespace)
+ if err != nil {
+ return nil, fmt.Errorf("unable to get existing rollup info(UPDATE): %w", err)
+ }
+
+ // rewrite epoch info
+ r.Info.ExitEpoch = rollupInfoExists.ExitEpoch
+ r.Info.StartEpoch = rollupInfoExists.StartEpoch
+
+ if err := storage.SetRollupInfo(ctx, mu, r.Namespace, &r.Info); err != nil {
+ return nil, fmt.Errorf("unable to set rollup info(UPDATE): %w", err)
+ }
+ case ExitRollup:
+ if err := authorizationChecks(ctx, actor, namespaces, r.Namespace, mu); err != nil {
+ return nil, fmt.Errorf("unable to set rollup info(EXIT): %w", err)
+ }
+ rollupInfoExists, err := storage.GetRollupInfo(ctx, mu, r.Namespace)
+ if err != nil {
+ return nil, fmt.Errorf("unable to get existing rollup info(UPDATE): %w", err)
+ }
+ if r.Info.ExitEpoch < rollupInfoExists.StartEpoch || r.Info.ExitEpoch < Epoch(hght, rules.GetEpochLength())+2 {
+ return nil, fmt.Errorf("(EXIT)epoch number is not valid, minimum: %d, actual: %d, start: %d", Epoch(hght, rules.GetEpochLength())+2, r.Info.ExitEpoch, rollupInfoExists.StartEpoch)
+ }
+
+ // overwrite StartEpoch
+ r.Info.StartEpoch = rollupInfoExists.StartEpoch
+
+ if err := storage.SetRollupInfo(ctx, mu, r.Namespace, &r.Info); err != nil {
+ return nil, fmt.Errorf("unable to set rollup info(EXIT): %w", err)
+ }
+ default:
+ return nil, fmt.Errorf("op code(%d) not supported", r.OpCode)
+ }
+ if err := storage.SetRollupRegistry(ctx, mu, namespaces); err != nil {
+ return nil, err
+ }
+
+ return nil, nil
+}
+
+func (*RollupRegistration) ComputeUnits(codec.Address, chain.Rules) uint64 {
+ return hactions.RollupRegisterComputeUnits
+}
+
+func (r *RollupRegistration) Size() int {
+ return r.Info.Size() + len(r.Namespace) + consts.Uint64Len + consts.IntLen
+}
+
+func (r *RollupRegistration) Marshal(p *codec.Packer) {
+ r.Info.Marshal(p)
+ p.PackBytes(r.Namespace)
+ p.PackInt(r.OpCode)
+}
+
+func UnmarshalRollupRegister(p *codec.Packer) (chain.Action, error) {
+ var rollupReg RollupRegistration
+ info, err := hactions.UnmarshalRollupInfo(p)
+ if err != nil {
+ return nil, err
+ }
+ rollupReg.Info = *info
+ p.UnpackBytes(-1, false, &rollupReg.Namespace)
+ rollupReg.OpCode = p.UnpackInt(false)
+ return &rollupReg, nil
+}
+
+func (*RollupRegistration) ValidRange(chain.Rules) (int64, int64) {
+ return -1, -1
+}
+
+func (*RollupRegistration) NMTNamespace() []byte {
+ return DefaultNMTNamespace
+}
+
+func (*RollupRegistration) UseFeeMarket() bool {
+ return false
+}
diff --git a/actions/transfer.go b/actions/transfer.go
index 7bdd03e..9c78ba1 100644
--- a/actions/transfer.go
+++ b/actions/transfer.go
@@ -9,23 +9,16 @@ import (
"github.com/AnomalyFi/hypersdk/chain"
"github.com/AnomalyFi/hypersdk/codec"
"github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
"github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
"github.com/AnomalyFi/nodekit-seq/storage"
"github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
)
var _ chain.Action = (*Transfer)(nil)
type Transfer struct {
// To is the recipient of the [Value].
- To ed25519.PublicKey `json:"to"`
-
- // Asset to transfer to [To].
- Asset ids.ID `json:"asset"`
+ To codec.Address `json:"to"`
// Amount are transferred to [To].
Value uint64 `json:"value"`
@@ -35,13 +28,13 @@ type Transfer struct {
}
func (*Transfer) GetTypeID() uint8 {
- return transferID
+ return TransferID
}
-func (t *Transfer) StateKeys(rauth chain.Auth, _ ids.ID) []string {
- return []string{
- string(storage.BalanceKey(auth.GetActor(rauth), t.Asset)),
- string(storage.BalanceKey(t.To, t.Asset)),
+func (t *Transfer) StateKeys(actor codec.Address, _ ids.ID) state.Keys {
+ return state.Keys{
+ string(storage.BalanceKey(actor)): state.Read | state.Write,
+ string(storage.BalanceKey(t.To)): state.All,
}
}
@@ -49,55 +42,48 @@ func (*Transfer) StateKeysMaxChunks() []uint16 {
return []uint16{storage.BalanceChunks, storage.BalanceChunks}
}
-func (*Transfer) OutputsWarpMessage() bool {
- return false
-}
-
func (t *Transfer) Execute(
ctx context.Context,
_ chain.Rules,
mu state.Mutable,
_ int64,
- rauth chain.Auth,
+ _ uint64,
+ actor codec.Address,
_ ids.ID,
- _ bool,
-) (bool, uint64, []byte, *warp.UnsignedMessage, error) {
- actor := auth.GetActor(rauth)
+) ([][]byte, error) {
if t.Value == 0 {
- return false, TransferComputeUnits, OutputValueZero, nil, nil
+ return nil, ErrOutputValueZero
}
if len(t.Memo) > MaxMemoSize {
- return false, CreateAssetComputeUnits, OutputMemoTooLarge, nil, nil
+ return nil, ErrOutputMemoTooLarge
}
- if err := storage.SubBalance(ctx, mu, actor, t.Asset, t.Value); err != nil {
- return false, TransferComputeUnits, utils.ErrBytes(err), nil, nil
+ if err := storage.SubBalance(ctx, mu, actor, t.Value); err != nil {
+ return nil, err
}
// TODO: allow sender to configure whether they will pay to create
- if err := storage.AddBalance(ctx, mu, t.To, t.Asset, t.Value, true); err != nil {
- return false, TransferComputeUnits, utils.ErrBytes(err), nil, nil
+ if err := storage.AddBalance(ctx, mu, t.To, t.Value, true); err != nil {
+ return nil, err
}
- return true, TransferComputeUnits, nil, nil, nil
+ return nil, nil
}
-func (*Transfer) MaxComputeUnits(chain.Rules) uint64 {
+func (*Transfer) ComputeUnits(codec.Address, chain.Rules) uint64 {
return TransferComputeUnits
}
func (t *Transfer) Size() int {
- return ed25519.PublicKeyLen + consts.IDLen + consts.Uint64Len + codec.BytesLen(t.Memo)
+ return codec.AddressLen + consts.Uint64Len + codec.BytesLen(t.Memo)
}
func (t *Transfer) Marshal(p *codec.Packer) {
- p.PackPublicKey(t.To)
- p.PackID(t.Asset)
+ p.PackAddress(t.To)
p.PackUint64(t.Value)
p.PackBytes(t.Memo)
}
-func UnmarshalTransfer(p *codec.Packer, _ *warp.Message) (chain.Action, error) {
+func UnmarshalTransfer(p *codec.Packer) (chain.Action, error) {
var transfer Transfer
- p.UnpackPublicKey(false, &transfer.To) // can transfer to blackhole
- p.UnpackID(false, &transfer.Asset) // empty ID is the native asset
+ p.UnpackAddress(&transfer.To)
transfer.Value = p.UnpackUint64(true)
p.UnpackBytes(MaxMemoSize, false, &transfer.Memo)
return &transfer, p.Err()
@@ -111,3 +97,7 @@ func (*Transfer) ValidRange(chain.Rules) (int64, int64) {
func (*Transfer) NMTNamespace() []byte {
return DefaultNMTNamespace
}
+
+func (*Transfer) UseFeeMarket() bool {
+ return false
+}
diff --git a/actions/utils.go b/actions/utils.go
new file mode 100644
index 0000000..fe6738b
--- /dev/null
+++ b/actions/utils.go
@@ -0,0 +1,71 @@
+package actions
+
+import (
+ "bytes"
+ "context"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/AnomalyFi/nodekit-seq/storage"
+)
+
+// checks if the actor is in the list of whitelisted addresses.
+// whitelisted addresses are allowed to submit auction transactions.
+func isWhiteListed(rules chain.Rules, actor codec.Address) bool {
+ whitelistedAddressesB, _ := rules.FetchCustom("whitelisted.Addresses")
+ whitelistedAddresses := whitelistedAddressesB.([]codec.Address)
+ return containsAddress(whitelistedAddresses, actor)
+}
+
+// checks if a given address is in the list of addresses.
+func containsAddress(addrs []codec.Address, addr codec.Address) bool {
+ for _, a := range addrs {
+ if a == addr {
+ return true
+ }
+ }
+ return false
+}
+
+// checks if a given byte slice is in the list of byte slices.
+func contains(arr [][]byte, ns []byte) bool {
+ for _, v := range arr {
+ if bytes.Equal(v, ns) {
+ return true
+ }
+ }
+ return false
+}
+
+// ArcadiaFundAddress returns the address of Arcadia fund.
+func ArcadiaFundAddress() codec.Address {
+ b := make([]byte, 33)
+ b[32] = 0x1
+ addr, _ := codec.ToAddress(b)
+ return addr
+}
+
+// checks if ns is in the list of registered namespaces.
+// fetches the info of the rollup and checks if the actor is the authority.
+func authorizationChecks(ctx context.Context, actor codec.Address, namespaces [][]byte, ns []byte, im state.Immutable) error {
+ if !contains(namespaces, ns) {
+ return ErrNameSpaceNotRegistered
+ }
+
+ info, err := storage.GetRollupInfo(ctx, im, ns)
+ if err != nil {
+ return err
+ }
+
+ if info.AuthoritySEQAddress != actor {
+ return ErrNotAuthorized
+ }
+
+ return nil
+}
+
+// Epoch returns the epoch number for a given block height.
+func Epoch(blockHeight uint64, epochLength int64) uint64 {
+ return blockHeight / uint64(epochLength)
+}
diff --git a/actions/warp_transfer.go b/actions/warp_transfer.go
deleted file mode 100644
index b7a754c..0000000
--- a/actions/warp_transfer.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package actions
-
-import (
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/ava-labs/avalanchego/ids"
-)
-
-type WarpTransfer struct {
- To ed25519.PublicKey `json:"to"`
- Symbol []byte `json:"symbol"`
- Decimals uint8 `json:"decimals"`
- Asset ids.ID `json:"asset"`
- Value uint64 `json:"value"`
-
- // Return is set to true when a warp message is sending funds back to the
- // chain where they were created.
- Return bool `json:"return"`
-
- // Reward is the amount of [Asset] to send the [Actor] that submits this
- // transaction.
- Reward uint64 `json:"reward"`
-
- // SwapIn is the amount of [Asset] we are willing to swap for [AssetOut].
- SwapIn uint64 `json:"swapIn"`
- // AssetOut is the asset we are seeking to get for [SwapIn].
- AssetOut ids.ID `json:"assetOut"`
- // SwapOut is the amount of [AssetOut] we are seeking.
- SwapOut uint64 `json:"swapOut"`
- // SwapExpiry is the unix timestamp at which the swap becomes invalid (and
- // the message can be processed without a swap.
- SwapExpiry int64 `json:"swapExpiry"`
-
- // TxID is the transaction that created this message. This is used to ensure
- // there is WarpID uniqueness.
- TxID ids.ID `json:"txID"`
-
- // DestinationChainID is the destination of this transfer. We assume this
- // must be populated (not anycast).
- DestinationChainID ids.ID `json:"destinationChainID"`
-}
-
-func (w *WarpTransfer) size() int {
- return ed25519.PublicKeyLen + codec.BytesLen(w.Symbol) + consts.Uint8Len + consts.IDLen +
- consts.Uint64Len + consts.BoolLen +
- consts.Uint64Len + /* op bits */
- consts.Uint64Len + consts.Uint64Len + consts.IDLen + consts.Uint64Len + consts.Int64Len +
- consts.IDLen + consts.IDLen
-}
-
-func (w *WarpTransfer) Marshal() ([]byte, error) {
- p := codec.NewWriter(w.size(), w.size())
- p.PackPublicKey(w.To)
- p.PackBytes(w.Symbol)
- p.PackByte(w.Decimals)
- p.PackID(w.Asset)
- p.PackUint64(w.Value)
- p.PackBool(w.Return)
- op := codec.NewOptionalWriter(consts.Uint64Len*3 + consts.IDLen + consts.Int64Len)
- op.PackUint64(w.Reward)
- op.PackUint64(w.SwapIn)
- op.PackID(w.AssetOut)
- op.PackUint64(w.SwapOut)
- op.PackInt64(w.SwapExpiry)
- p.PackOptional(op)
- p.PackID(w.TxID)
- p.PackID(w.DestinationChainID)
- return p.Bytes(), p.Err()
-}
-
-func ImportedAssetID(assetID ids.ID, sourceChainID ids.ID) ids.ID {
- return utils.ToID(ImportedAssetMetadata(assetID, sourceChainID))
-}
-
-func ImportedAssetMetadata(assetID ids.ID, sourceChainID ids.ID) []byte {
- k := make([]byte, consts.IDLen*2)
- copy(k, assetID[:])
- copy(k[consts.IDLen:], sourceChainID[:])
- return k
-}
-
-func UnmarshalWarpTransfer(b []byte) (*WarpTransfer, error) {
- maxWarpTransferSize := ed25519.PublicKeyLen + codec.BytesLenSize(MaxSymbolSize) + consts.Uint8Len + consts.IDLen +
- consts.Uint64Len + consts.BoolLen +
- consts.Uint64Len + /* op bits */
- consts.Uint64Len + consts.Uint64Len + consts.IDLen + consts.Uint64Len + consts.Int64Len +
- consts.IDLen + consts.IDLen
-
- var transfer WarpTransfer
- p := codec.NewReader(b, maxWarpTransferSize)
- p.UnpackPublicKey(false, &transfer.To)
- p.UnpackBytes(MaxSymbolSize, true, &transfer.Symbol)
- transfer.Decimals = p.UnpackByte()
- p.UnpackID(false, &transfer.Asset)
- transfer.Value = p.UnpackUint64(true)
- transfer.Return = p.UnpackBool()
- op := p.NewOptionalReader()
- transfer.Reward = op.UnpackUint64() // reward not required
- transfer.SwapIn = op.UnpackUint64() // optional
- op.UnpackID(&transfer.AssetOut)
- transfer.SwapOut = op.UnpackUint64()
- transfer.SwapExpiry = op.UnpackInt64()
- op.Done()
- p.UnpackID(true, &transfer.TxID)
- p.UnpackID(true, &transfer.DestinationChainID)
- if err := p.Err(); err != nil {
- return nil, err
- }
- if !p.Empty() {
- return nil, chain.ErrInvalidObject
- }
- // Handle swap checks
- if !ValidSwapParams(
- transfer.Value,
- transfer.SwapIn,
- transfer.AssetOut,
- transfer.SwapOut,
- transfer.SwapExpiry,
- ) {
- return nil, chain.ErrInvalidObject
- }
- return &transfer, nil
-}
-
-func ValidSwapParams(
- value uint64,
- swapIn uint64,
- assetOut ids.ID,
- swapOut uint64,
- swapExpiry int64,
-) bool {
- if swapExpiry < 0 {
- return false
- }
- if swapIn > value {
- return false
- }
- if swapIn > 0 {
- return swapOut != 0
- }
- if assetOut != ids.Empty {
- return false
- }
- if swapOut != 0 {
- return false
- }
- if swapExpiry != 0 {
- return false
- }
- return true
-}
diff --git a/arcadia.md b/arcadia.md
new file mode 100644
index 0000000..f84b2da
--- /dev/null
+++ b/arcadia.md
@@ -0,0 +1,49 @@
+# Arcadia
+
+Arcadia facilitates the Shared Block Production on The Composable Network for participating Rollups. Block Production on Arcadia is divided into 12s(6 SEQ blocks) epochs with a single block builder building blocks for all the participating rollups in that epoch. The winning block builder is selected through an Ahead Of Time Auction on Arcadia. Rollup blocks are built as chunks and preconfed by validators. All txs in preconfed chunks will be included in SEQ blocks later.
+
+## Rollups:
+- Rollups opt for shared block production by Arcadia ahead of time from a given epoch and are added to the list of participating rollups for the shared auction.
+- Rollups get synchronous atomic composability for the blocks built during the participating epoch.
+- Once opt-in for shared block production, rollups continue in the list of participating rollups for future epochs until they entirely opt out or opt out for a specific epoch.
+- Rollups opt-in and out entirely through the `RegisterRollup` action tx.
+- Rollups opt-out for an epoch through `epochExit` action tx.
+
+## Ahead Of Time Auction:
+- Auction for rights to build blocks for participating rollups in epoch K starts one epoch earlier and ends with the production of the 4th block of SEQ in epoch K-1.
+- Rollups can Opt In or Out for epoch K before the end of epoch K-2. The list of participating rollups for epoch K finalises with the end of epoch K-2, and builders bid for rights to build blocks for all participating rollups based on the perceived value accrual for epoch K and private order flow deals.
+- With the 4th block of SEQ in epoch k-1 produced, the winning bid is sent to be included in the next SEQ block as an `Auction` action tx to deduct the bid amount from the builder.
+- All participating entities are notified about the bid winner once the `Auction` action tx is made through a SEQ block.
+
+## Chunks:
+- In Arcadia, txs are preconfed as chunks rather than blocks.
+- There are two defined chunk types: i. Top Of Block(ToB) ii. Rest Of Block(RoB). A chunk consists of a set of txs or tx bundles, depending on whether it is a ToB or RoB.
+- SEQ supports a single rollup tx or cross-chain bundle in a single tx as multi-action tx is supported.
+- A ToB contains cross-rollup bundles only. However, a ToB does not necessarily need to contain txs for all participating rollups, but it can contain any subset of the list. A RoB contains txs for a single rollup.
+- Chunks get preconfed by validators and made available for rollups to pull.
+- A Rollup block can have multiple ToB chunks but only one RoB chunk.
+
+## Block Builders:
+- Block builders participate in the auction after confirming their ability to build blocks for participating rollups.
+- They build ToB chunks for different subsets of participating rollups and RoB chunks for each rollup. They continuously send them with rollup block numbers and chunk nonce to Arcadia to get them preconfed by SEQ validators.
+- Every rollup block, ideally, contains many ToBs and one RoB. ToBs are ordered by the chunk nonce included, along with the chunk followed by RoB.
+
+ToB chunks contain different subsets of rollups:
+
+
+
+
+A rollup block built by the builder:
+
+
+
+
+## SEQ Validators:
+- SEQ validators register with Arcadia to receive chunks for preconfing.
+- Validators make a few assertions on chunks and issues chunk certificate if all assertions are satisfied.
+- Validators store the signature verified txs in an emap to prevent duplicate txs and ease signature verification while accepting the block.
+- SEQ blocks are produced every 2 seconds. Validators fetch the `SequencerMsg` txs payload from Arcadia to get included in the SEQ block and fill the rest of the block with `non SequencerMsg` txs.
+
+## E2E Flow:
+![E2E flow](./assets/e2e.png)
+
diff --git a/archiver/orm_archiver.go b/archiver/orm_archiver.go
new file mode 100644
index 0000000..4e2890f
--- /dev/null
+++ b/archiver/orm_archiver.go
@@ -0,0 +1,430 @@
+package archiver
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "math/big"
+ "strings"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/nodekit-seq/types"
+ "github.com/ava-labs/avalanchego/ids"
+ "gorm.io/driver/postgres"
+ "gorm.io/driver/sqlite"
+ "gorm.io/gorm"
+)
+
+type ORMArchiverConfig struct {
+ Enabled bool `json:"enabled"`
+ ArchiverType string `json:"archiverType"`
+ DSN string `json:"dsn"`
+}
+
+type ORMArchiver struct {
+ db *gorm.DB
+}
+
+type DBBlock struct {
+ gorm.Model
+ BlockID string `gorm:"index;unique"`
+ Parent string
+ Timestamp int64
+ Height uint64 `gorm:"index;unique"`
+ L1Head int64
+
+ Bytes []byte
+}
+
+func NewORMArchiver(db *gorm.DB) *ORMArchiver {
+ err := db.AutoMigrate(&DBBlock{})
+ if err != nil {
+ // TODO: what could be the graceful way to handle the error?
+ log.Fatalf("failed to migrate db: %s", err)
+ }
+ return &ORMArchiver{
+ db: db,
+ }
+}
+
+func NewORMArchiverFromConfigBytes(configBytes []byte) (*ORMArchiver, error) {
+ var conf ORMArchiverConfig
+ err := json.Unmarshal(configBytes, &conf)
+ if err != nil {
+ return nil, err
+ }
+
+ log.Printf("using %s as archiver\n", conf.ArchiverType)
+ switch strings.ToLower(conf.ArchiverType) {
+ case "postgresql":
+ db, err := gorm.Open(postgres.New(postgres.Config{
+ DSN: conf.DSN,
+ PreferSimpleProtocol: true,
+ }))
+ if err != nil {
+ return nil, err
+ }
+ return NewORMArchiver(db), nil
+ case "sqlite":
+ db, err := gorm.Open(sqlite.Open(conf.DSN), &gorm.Config{})
+ if err != nil {
+ return nil, err
+ }
+ return NewORMArchiver(db), nil
+ default:
+ db, err := gorm.Open(sqlite.Open("default.db"), &gorm.Config{})
+ if err != nil {
+ return nil, err
+ }
+ return NewORMArchiver(db), nil
+ }
+}
+
+func NewORMArchiverFromConfig(conf *ORMArchiverConfig) (*ORMArchiver, error) {
+ switch strings.ToLower(conf.ArchiverType) {
+ case "postgresql":
+ db, err := gorm.Open(postgres.New(postgres.Config{
+ DSN: conf.DSN,
+ PreferSimpleProtocol: true,
+ }))
+ log.Println("using postgresql as archiver")
+ if err != nil {
+ return nil, err
+ }
+ return NewORMArchiver(db), nil
+ case "sqlite":
+ db, err := gorm.Open(sqlite.Open(conf.DSN), &gorm.Config{})
+ if err != nil {
+ return nil, err
+ }
+ return NewORMArchiver(db), nil
+ default:
+ db, err := gorm.Open(sqlite.Open("default.db"), &gorm.Config{})
+ if err != nil {
+ return nil, err
+ }
+ return NewORMArchiver(db), nil
+ }
+}
+
+func (oa *ORMArchiver) InsertBlock(block *chain.StatelessBlock) error {
+ blkID := block.ID()
+ blkBytes, err := block.Marshal()
+ if err != nil {
+ return err
+ }
+ log.Printf("inserting block(%d): %s\n", block.Hght, blkID.String())
+
+ // TODO need to add L1Head and real Id
+ newBlock := DBBlock{
+ BlockID: blkID.String(),
+ Parent: block.Prnt.String(),
+ Timestamp: block.Tmstmp,
+ Height: block.Hght,
+ L1Head: block.L1Head,
+ Bytes: blkBytes,
+ }
+
+ tx := oa.db.Begin()
+ if err := tx.Create(&newBlock).Error; err != nil {
+ tx.Rollback()
+ return err
+ }
+
+ if err := tx.Commit().Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (oa *ORMArchiver) GetBlock(dbBlock *DBBlock, blockParser chain.Parser) (*chain.StatefulBlock, *ids.ID, error) {
+ tx := oa.db.First(dbBlock)
+ if tx.Error != nil {
+ return nil, nil, tx.Error
+ }
+
+ blk, err := chain.UnmarshalBlock(dbBlock.Bytes, blockParser)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ id, err := ids.FromString(dbBlock.BlockID)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return blk, &id, nil
+}
+
+func (oa *ORMArchiver) GetBlockByID(id string, parser chain.Parser) (*chain.StatefulBlock, error) {
+ var dbBlock DBBlock
+ tx := oa.db.Where("block_id = ?", id).Find(&dbBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+ log.Printf("block height id: %s, wanted: %s\n", dbBlock.BlockID, id)
+
+ blk, err := chain.UnmarshalBlock(dbBlock.Bytes, parser)
+ if err != nil {
+ return nil, err
+ }
+ return blk, nil
+}
+
+func (oa *ORMArchiver) GetBlockByHeight(height uint64, parser chain.Parser) (*chain.StatefulBlock, error) {
+ var dbBlock DBBlock
+ tx := oa.db.Where("height = ?", height).Find(&dbBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+
+ blk, err := chain.UnmarshalBlock(dbBlock.Bytes, parser)
+ if err != nil {
+ return nil, err
+ }
+ return blk, nil
+}
+
+func (oa *ORMArchiver) DeleteBlock(dbBlock *DBBlock) (bool, error) {
+ tx := oa.db.Begin()
+ if err := tx.Delete(&dbBlock).Error; err != nil {
+ return false, err
+ }
+ if err := tx.Commit().Error; err != nil {
+ return false, err
+ }
+
+ return true, nil
+}
+
+func (oa *ORMArchiver) GetBlockHeadersByHeight(args *types.GetBlockHeadersByHeightArgs) (*types.BlockHeadersResponse, error) {
+ ret := new(types.BlockHeadersResponse)
+
+ if args.Height > 1 {
+ var dbBlock DBBlock
+ tx := oa.db.Where("height = ?", args.Height-1).Find(&dbBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+
+ ret.Prev = types.BlockInfo{
+ BlockID: dbBlock.BlockID,
+ Timestamp: dbBlock.Timestamp,
+ L1Head: uint64(dbBlock.L1Head),
+ Height: dbBlock.Height,
+ }
+ }
+
+ var blocks []DBBlock
+ res := oa.db.Where("height >= ? AND timestamp < ?", args.Height, args.EndTimeStamp).Order("height").Find(&blocks)
+ if res.Error != nil {
+ return nil, res.Error
+ }
+
+ ret.Blocks = make([]types.BlockInfo, 0, len(blocks))
+ for _, block := range blocks {
+ blkInfo := types.BlockInfo{
+ BlockID: block.BlockID,
+ Timestamp: block.Timestamp,
+ L1Head: uint64(block.L1Head),
+ Height: block.Height,
+ }
+ if len(ret.Blocks) > 0 && blkInfo.Height-1 != ret.Blocks[len(ret.Blocks)-1].Height {
+ return nil, fmt.Errorf("queried blocks aren't consecutive, prev: %d, current: %d", blkInfo.Height, ret.Blocks[len(ret.Blocks)-1].Height)
+ }
+ ret.Blocks = append(ret.Blocks, blkInfo)
+ }
+ var next DBBlock
+ res = oa.db.Where("timestamp >= ?", args.EndTimeStamp).Order("height").First(&next)
+ if res.Error == nil {
+ ret.Next = types.BlockInfo{
+ BlockID: next.BlockID,
+ Timestamp: next.Timestamp,
+ L1Head: uint64(next.L1Head),
+ Height: next.Height,
+ }
+ } else {
+ ret.Next = types.BlockInfo{}
+ }
+
+ return ret, nil
+}
+
+func (oa *ORMArchiver) GetBlockHeadersByID(args *types.GetBlockHeadersIDArgs) (*types.BlockHeadersResponse, error) {
+ ret := new(types.BlockHeadersResponse)
+ if args.ID == "" {
+ return nil, fmt.Errorf("ID in args is not specified")
+ }
+
+ var firstBlock DBBlock
+ tx := oa.db.Where("block_id", args.ID).Find(&firstBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+
+ firstBlockHeight := firstBlock.Height
+
+ ret.Prev = types.BlockInfo{}
+ if firstBlockHeight > 1 {
+ var prevBlock DBBlock
+ tx := oa.db.Where("height = ?", firstBlockHeight-1).Find(&prevBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+
+ ret.Prev = types.BlockInfo{
+ BlockID: prevBlock.BlockID,
+ Timestamp: prevBlock.Timestamp,
+ L1Head: uint64(prevBlock.L1Head),
+ Height: prevBlock.Height,
+ }
+ }
+
+ var blocks []DBBlock
+ res := oa.db.Where("height >= ? AND timestamp < ?", firstBlockHeight, args.EndTimeStamp).Order("height").Find(&blocks)
+ if res.Error != nil {
+ return nil, res.Error
+ }
+
+ ret.Blocks = make([]types.BlockInfo, 0, len(blocks))
+ for _, block := range blocks {
+ blkInfo := types.BlockInfo{
+ BlockID: block.BlockID,
+ Timestamp: block.Timestamp,
+ L1Head: uint64(block.L1Head),
+ Height: block.Height,
+ }
+ if len(ret.Blocks) > 0 && blkInfo.Height-1 != ret.Blocks[len(ret.Blocks)-1].Height {
+ return nil, fmt.Errorf("queried blocks aren't consecutive")
+ }
+ ret.Blocks = append(ret.Blocks, blkInfo)
+ }
+ var next DBBlock
+ res = oa.db.Where("timestamp >= ?", args.EndTimeStamp).Order("height").First(&next)
+ if res.Error == nil {
+ ret.Next = types.BlockInfo{
+ BlockID: next.BlockID,
+ Timestamp: next.Timestamp,
+ L1Head: uint64(next.L1Head),
+ Height: next.Height,
+ }
+ } else {
+ ret.Next = types.BlockInfo{}
+ }
+
+ return ret, nil
+}
+
+func (oa *ORMArchiver) GetBlockHeadersAfterTimestamp(args *types.GetBlockHeadersByStartTimeStampArgs) (*types.BlockHeadersResponse, error) {
+ ret := new(types.BlockHeadersResponse)
+
+ var startBlock DBBlock
+ tx := oa.db.Where("timestamp >= ?", args.StartTimeStamp).Order("timestamp").First(&startBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+
+ firstBlockHeight := startBlock.Height
+
+ ret.Prev = types.BlockInfo{}
+ if firstBlockHeight > 1 {
+ var prevBlock DBBlock
+ tx := oa.db.Where("height = ?", firstBlockHeight-1).Find(&prevBlock)
+ if tx.Error != nil {
+ return nil, tx.Error
+ }
+
+ ret.Prev = types.BlockInfo{
+ BlockID: prevBlock.BlockID,
+ Timestamp: prevBlock.Timestamp,
+ L1Head: uint64(prevBlock.L1Head),
+ Height: prevBlock.Height,
+ }
+ }
+
+ var blocks []DBBlock
+ res := oa.db.Where("height >= ? AND timestamp < ?", firstBlockHeight, args.EndTimeStamp).Order("height").Find(&blocks)
+ if res.Error != nil {
+ return nil, res.Error
+ }
+
+ ret.Blocks = make([]types.BlockInfo, 0, len(blocks))
+ for _, block := range blocks {
+ blkInfo := types.BlockInfo{
+ BlockID: block.BlockID,
+ Timestamp: block.Timestamp,
+ L1Head: uint64(block.L1Head),
+ Height: block.Height,
+ }
+ if len(ret.Blocks) > 0 && blkInfo.Height-1 != ret.Blocks[len(ret.Blocks)-1].Height {
+ return nil, fmt.Errorf("queried blocks aren't consecutive")
+ }
+ ret.Blocks = append(ret.Blocks, blkInfo)
+ }
+ var next DBBlock
+ res = oa.db.Where("timestamp >= ?", args.EndTimeStamp).Order("height").First(&next)
+ if res.Error == nil {
+ ret.Next = types.BlockInfo{
+ BlockID: next.BlockID,
+ Timestamp: next.Timestamp,
+ L1Head: uint64(next.L1Head),
+ Height: next.Height,
+ }
+ } else {
+ ret.Next = types.BlockInfo{}
+ }
+
+ return ret, nil
+}
+
+func (oa *ORMArchiver) GetCommitmentBlocks(args *types.GetBlockCommitmentArgs, parser chain.Parser) (*types.SequencerWarpBlockResponse, error) {
+ ret := new(types.SequencerWarpBlockResponse)
+
+ if args.First < 1 {
+ return nil, fmt.Errorf("the first block height is smaller than 1")
+ }
+
+ var blocks []DBBlock
+ res := oa.db.Where("height >= ? AND height <= ?", args.First, args.CurrentHeight).Order("height").Limit(args.MaxBlocks).Find(&blocks)
+ if res.Error != nil {
+ return nil, res.Error
+ }
+
+ ret.Blocks = make([]types.SequencerWarpBlock, 0)
+ for _, dbBlock := range blocks {
+ blk, err := chain.UnmarshalBlock(dbBlock.Bytes, parser)
+ if err != nil {
+ return nil, err
+ }
+ blkID, err := blk.ID()
+ if err != nil {
+ return nil, err
+ }
+
+ header := &types.Header{
+ Height: dbBlock.Height,
+ Timestamp: uint64(dbBlock.Timestamp),
+ L1Head: uint64(dbBlock.L1Head),
+ TransactionsRoot: types.NmtRoot{
+ Root: blkID[:],
+ },
+ }
+
+ comm := header.Commit()
+
+ parentRoot := types.NewU256().SetBytes(blk.Prnt)
+ bigParentRoot := parentRoot.Int
+
+ ret.Blocks = append(ret.Blocks, types.SequencerWarpBlock{
+ BlockID: dbBlock.BlockID,
+ Timestamp: dbBlock.Timestamp,
+ L1Head: uint64(dbBlock.L1Head),
+ Height: big.NewInt(int64(dbBlock.Height)),
+ BlockRoot: &comm.Uint256().Int,
+ ParentRoot: &bigParentRoot,
+ })
+ }
+
+ return ret, nil
+}
diff --git a/assets/e2e.png b/assets/e2e.png
new file mode 100644
index 0000000..0966097
Binary files /dev/null and b/assets/e2e.png differ
diff --git a/assets/rollup_block.png b/assets/rollup_block.png
new file mode 100644
index 0000000..97ed3ab
Binary files /dev/null and b/assets/rollup_block.png differ
diff --git a/assets/tob.png b/assets/tob.png
new file mode 100644
index 0000000..5d67e6f
Binary files /dev/null and b/assets/tob.png differ
diff --git a/auth/bls.go b/auth/bls.go
new file mode 100644
index 0000000..bbc4c4e
--- /dev/null
+++ b/auth/bls.go
@@ -0,0 +1,120 @@
+// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+
+package auth
+
+import (
+ "context"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/crypto"
+ "github.com/AnomalyFi/hypersdk/crypto/bls"
+ "github.com/AnomalyFi/hypersdk/utils"
+)
+
+var _ chain.Auth = (*BLS)(nil)
+
+const (
+ BLSComputeUnits = 10
+ BLSSize = bls.PublicKeyLen + bls.SignatureLen
+)
+
+type BLS struct {
+ Signer *bls.PublicKey `json:"signer,omitempty"`
+ Signature *bls.Signature `json:"signature,omitempty"`
+
+ addr codec.Address
+}
+
+func (b *BLS) address() codec.Address {
+ if b.addr == codec.EmptyAddress {
+ b.addr = NewBLSAddress(b.Signer)
+ }
+ return b.addr
+}
+
+func (*BLS) GetTypeID() uint8 {
+ return BLSID
+}
+
+func (*BLS) ComputeUnits(chain.Rules) uint64 {
+ return BLSComputeUnits
+}
+
+func (*BLS) ValidRange(chain.Rules) (int64, int64) {
+ return -1, -1
+}
+
+func (b *BLS) Verify(_ context.Context, msg []byte) error {
+ if !bls.Verify(msg, b.Signer, b.Signature) {
+ return crypto.ErrInvalidSignature
+ }
+ return nil
+}
+
+func (b *BLS) Actor() codec.Address {
+ return b.address()
+}
+
+func (b *BLS) Sponsor() codec.Address {
+ return b.address()
+}
+
+func (*BLS) Size() int {
+ return BLSSize
+}
+
+func (b *BLS) Marshal(p *codec.Packer) {
+ p.PackFixedBytes(bls.PublicKeyToBytes(b.Signer))
+ p.PackFixedBytes(bls.SignatureToBytes(b.Signature))
+}
+
+func UnmarshalBLS(p *codec.Packer) (chain.Auth, error) {
+ var b BLS
+
+ signer := make([]byte, bls.PublicKeyLen)
+ p.UnpackFixedBytes(bls.PublicKeyLen, &signer)
+ signature := make([]byte, bls.SignatureLen)
+ p.UnpackFixedBytes(bls.SignatureLen, &signature)
+
+ pk, err := bls.PublicKeyFromBytes(signer)
+ if err != nil {
+ return nil, err
+ }
+ b.Signer = pk
+
+ sig, err := bls.SignatureFromBytes(signature)
+ if err != nil {
+ return nil, err
+ }
+
+ b.Signature = sig
+ return &b, p.Err()
+}
+
+var _ chain.AuthFactory = (*BLSFactory)(nil)
+
+type BLSFactory struct {
+ priv *bls.PrivateKey
+}
+
+func NewBLSFactory(priv *bls.PrivateKey) *BLSFactory {
+ return &BLSFactory{priv}
+}
+
+func (b *BLSFactory) Sign(msg []byte) (chain.Auth, error) {
+ return &BLS{Signer: bls.PublicFromPrivateKey(b.priv), Signature: bls.Sign(msg, b.priv)}, nil
+}
+
+func (*BLSFactory) MaxUnits() (uint64, uint64) {
+ return BLSSize, BLSComputeUnits
+}
+
+func (b *BLSFactory) Address() codec.Address {
+ return NewBLSAddress(bls.PublicFromPrivateKey(b.priv))
+}
+
+func NewBLSAddress(pk *bls.PublicKey) codec.Address {
+ return codec.CreateAddress(BLSID, utils.ToID(bls.PublicKeyToBytes(pk)))
+}
diff --git a/auth/consts.go b/auth/consts.go
index cc033b6..368877e 100644
--- a/auth/consts.go
+++ b/auth/consts.go
@@ -7,11 +7,12 @@ import "github.com/AnomalyFi/hypersdk/vm"
// Note: Registry will error during initialization if a duplicate ID is assigned. We explicitly assign IDs to avoid accidental remapping.
const (
- ed25519ID uint8 = 0
+ Ed25519ID uint8 = 0
+ BLSID uint8 = 1
)
func Engines() map[uint8]vm.AuthEngine {
return map[uint8]vm.AuthEngine{
- ed25519ID: &ED25519AuthEngine{},
+ Ed25519ID: &ED25519AuthEngine{},
}
}
diff --git a/auth/ed25519.go b/auth/ed25519.go
index d9b72eb..5920dbe 100644
--- a/auth/ed25519.go
+++ b/auth/ed25519.go
@@ -8,12 +8,9 @@ import (
"github.com/AnomalyFi/hypersdk/chain"
"github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/crypto"
"github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/AnomalyFi/nodekit-seq/storage"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/utils/math"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
+ "github.com/AnomalyFi/hypersdk/utils"
)
var _ chain.Auth = (*ED25519)(nil)
@@ -26,13 +23,22 @@ const (
type ED25519 struct {
Signer ed25519.PublicKey `json:"signer"`
Signature ed25519.Signature `json:"signature"`
+
+ addr codec.Address
+}
+
+func (d *ED25519) address() codec.Address {
+ if d.addr == codec.EmptyAddress {
+ d.addr = NewED25519Address(d.Signer)
+ }
+ return d.addr
}
func (*ED25519) GetTypeID() uint8 {
- return ed25519ID
+ return Ed25519ID
}
-func (*ED25519) MaxComputeUnits(chain.Rules) uint64 {
+func (*ED25519) ComputeUnits(chain.Rules) uint64 {
return ED25519ComputeUnits
}
@@ -40,33 +46,19 @@ func (*ED25519) ValidRange(chain.Rules) (int64, int64) {
return -1, -1
}
-func (d *ED25519) StateKeys() []string {
- return []string{
- // We always pay fees with the native asset (which is [ids.Empty])
- string(storage.BalanceKey(d.Signer, ids.Empty)),
- }
-}
-
-func (d *ED25519) AsyncVerify(msg []byte) error {
+func (d *ED25519) Verify(_ context.Context, msg []byte) error {
if !ed25519.Verify(msg, d.Signer, d.Signature) {
- return ed25519.ErrInvalidSignature
+ return crypto.ErrInvalidSignature
}
return nil
}
-func (d *ED25519) Verify(
- _ context.Context,
- r chain.Rules,
- _ state.Immutable,
- _ chain.Action,
-) (uint64, error) {
- // We don't do anything during verify (there is no additional state to check
- // to authorize the signer other than verifying the signature)
- return d.MaxComputeUnits(r), nil
+func (d *ED25519) Actor() codec.Address {
+ return d.address()
}
-func (d *ED25519) Payer() []byte {
- return d.Signer[:]
+func (d *ED25519) Sponsor() codec.Address {
+ return d.address()
}
func (*ED25519) Size() int {
@@ -74,49 +66,19 @@ func (*ED25519) Size() int {
}
func (d *ED25519) Marshal(p *codec.Packer) {
- p.PackPublicKey(d.Signer)
- p.PackSignature(d.Signature)
+ p.PackFixedBytes(d.Signer[:])
+ p.PackFixedBytes(d.Signature[:])
}
-func UnmarshalED25519(p *codec.Packer, _ *warp.Message) (chain.Auth, error) {
+func UnmarshalED25519(p *codec.Packer) (chain.Auth, error) {
var d ED25519
- p.UnpackPublicKey(true, &d.Signer)
- p.UnpackSignature(&d.Signature)
+ signer := d.Signer[:] // avoid allocating additional memory
+ p.UnpackFixedBytes(ed25519.PublicKeyLen, &signer)
+ signature := d.Signature[:] // avoid allocating additional memory
+ p.UnpackFixedBytes(ed25519.SignatureLen, &signature)
return &d, p.Err()
}
-func (d *ED25519) CanDeduct(
- ctx context.Context,
- im state.Immutable,
- amount uint64,
-) error {
- bal, err := storage.GetBalance(ctx, im, d.Signer, ids.Empty)
- if err != nil {
- return err
- }
- if bal < amount {
- return storage.ErrInvalidBalance
- }
- return nil
-}
-
-func (d *ED25519) Deduct(
- ctx context.Context,
- mu state.Mutable,
- amount uint64,
-) error {
- return storage.SubBalance(ctx, mu, d.Signer, ids.Empty, amount)
-}
-
-func (d *ED25519) Refund(
- ctx context.Context,
- mu state.Mutable,
- amount uint64,
-) error {
- // Don't create account if it doesn't exist (may have sent all funds).
- return storage.AddBalance(ctx, mu, d.Signer, ids.Empty, amount, false)
-}
-
var _ chain.AuthFactory = (*ED25519Factory)(nil)
func NewED25519Factory(priv ed25519.PrivateKey) *ED25519Factory {
@@ -127,28 +89,31 @@ type ED25519Factory struct {
priv ed25519.PrivateKey
}
-func (d *ED25519Factory) Sign(msg []byte, _ chain.Action) (chain.Auth, error) {
- sig := ed25519.Sign(msg, d.priv)
- return &ED25519{d.priv.PublicKey(), sig}, nil
+func (e *ED25519Factory) Sign(msg []byte) (chain.Auth, error) {
+ sig := ed25519.Sign(msg, e.priv)
+ return &ED25519{Signer: e.priv.PublicKey(), Signature: sig}, nil
+}
+
+func (*ED25519Factory) MaxUnits() (uint64, uint64) {
+ return ED25519Size, ED25519ComputeUnits
}
-func (*ED25519Factory) MaxUnits() (uint64, uint64, []uint16) {
- return ED25519Size, ED25519ComputeUnits, []uint16{storage.BalanceChunks}
+func (e *ED25519Factory) Address() codec.Address {
+ return NewED25519Address(e.priv.PublicKey())
}
type ED25519AuthEngine struct{}
func (*ED25519AuthEngine) GetBatchVerifier(cores int, count int) chain.AuthBatchVerifier {
- batchSize := math.Max(count/cores, ed25519.MinBatchSize)
+ batchSize := max(count/cores, ed25519.MinBatchSize)
return &ED25519Batch{
batchSize: batchSize,
total: count,
}
}
-func (*ED25519AuthEngine) Cache(auth chain.Auth) {
- pk := GetSigner(auth)
- ed25519.CachePublicKey(pk)
+func (*ED25519AuthEngine) Cache(chain.Auth) {
+ // TODO: add support for caching expanded public key to make batch verification faster
}
type ED25519Batch struct {
@@ -186,3 +151,7 @@ func (b *ED25519Batch) Done() []func() error {
}
return []func() error{b.batch.VerifyAsync()}
}
+
+func NewED25519Address(pk ed25519.PublicKey) codec.Address {
+ return codec.CreateAddress(Ed25519ID, utils.ToID(pk[:]))
+}
diff --git a/auth/helpers.go b/auth/helpers.go
deleted file mode 100644
index 733b252..0000000
--- a/auth/helpers.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package auth
-
-import (
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
-)
-
-func GetActor(auth chain.Auth) ed25519.PublicKey {
- switch a := auth.(type) {
- case *ED25519:
- return a.Signer
- default:
- return ed25519.EmptyPublicKey
- }
-}
-
-func GetSigner(auth chain.Auth) ed25519.PublicKey {
- switch a := auth.(type) {
- case *ED25519:
- return a.Signer
- default:
- return ed25519.EmptyPublicKey
- }
-}
diff --git a/challenge/challenge.go b/challenge/challenge.go
deleted file mode 100644
index 7d837af..0000000
--- a/challenge/challenge.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package challenge
-
-import (
- "crypto/rand"
- "crypto/sha512"
- "math/big"
- "math/bits"
- "sync"
- "sync/atomic"
-)
-
-const (
- bitsPerByte = 8
- saltLength = 32
- maxSolutionSize = 128
-)
-
-var big1 = big.NewInt(1)
-
-func New() ([]byte, error) {
- b := make([]byte, saltLength)
- _, err := rand.Read(b)
- return b, err
-}
-
-func Verify(salt []byte, solution []byte, difficulty uint16) bool {
- lSalt := len(salt)
- if lSalt != saltLength {
- return false
- }
- lSolution := len(solution)
- if lSolution > maxSolutionSize {
- return false
- }
- // TODO: add more sophisticated algo/make configurable
- h := sha512.New()
- if _, err := h.Write(salt); err != nil {
- return false
- }
- if _, err := h.Write(solution); err != nil {
- return false
- }
- checksum := h.Sum(nil)
- leadingZeros := 0
- for i := 0; i < len(checksum); i++ {
- leading := bits.LeadingZeros8(checksum[i])
- leadingZeros += leading
- if leading < bitsPerByte {
- break
- }
- }
- return leadingZeros >= int(difficulty)
-}
-
-func Search(salt []byte, difficulty uint16, cores int) ([]byte, uint64) {
- var (
- solution []byte
- wg sync.WaitGroup
-
- attempted uint64
- )
- for i := 0; i < cores; i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
-
- var (
- start = make([]byte, maxSolutionSize/2) // give space to increment without surpassing max solution size
- _, _ = rand.Read(start)
- work = new(big.Int).SetBytes(start)
- attempts = uint64(0)
- )
- for len(solution) == 0 {
- attempts++
-
- workBytes := work.Bytes()
- if Verify(salt, workBytes, difficulty) {
- solution = workBytes
- atomic.AddUint64(&attempted, attempts)
- return
- }
- work.Add(work, big1)
- }
- atomic.AddUint64(&attempted, attempts)
- }()
- }
- wg.Wait()
- return solution, attempted
-}
diff --git a/challenge/challenge_test.go b/challenge/challenge_test.go
deleted file mode 100644
index 6453f60..0000000
--- a/challenge/challenge_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package challenge
-
-import (
- "fmt"
- "testing"
-)
-
-// Bench: go test -bench=. -benchtime=20x -benchmem
-//
-// goos: darwin
-// goarch: arm64
-// pkg: github.com/AnomalyFi/hypersdk/examples/tokenvm/challenge
-// BenchmarkSearch/difficulty=22_cores=1-12 10 1856272250 ns/op 1099921195 B/op 17186238 allocs/op
-// BenchmarkSearch/difficulty=22_cores=2-12 10 530316125 ns/op 540141624 B/op 8439696 allocs/op
-// BenchmarkSearch/difficulty=22_cores=4-12 10 255920258 ns/op 504088876 B/op 7876351 allocs/op
-// BenchmarkSearch/difficulty=22_cores=8-12 10 201556788 ns/op 558042440 B/op 8719356 allocs/op
-// BenchmarkSearch/difficulty=24_cores=1-12 10 2141673050 ns/op 1294475182 B/op 20226149 allocs/op
-// BenchmarkSearch/difficulty=24_cores=2-12 10 1759634617 ns/op 2028179908 B/op 31690253 allocs/op
-// BenchmarkSearch/difficulty=24_cores=4-12 10 981203300 ns/op 1917939096 B/op 29967719 allocs/op
-// BenchmarkSearch/difficulty=24_cores=8-12 10 1029257296 ns/op 2799724116 B/op 43745459 allocs/op
-// BenchmarkSearch/difficulty=26_cores=1-12 10 25587392621 ns/op 15294127182 B/op 238970344 allocs/op
-// BenchmarkSearch/difficulty=26_cores=2-12 10 9736256296 ns/op 11060180190 B/op 172814962 allocs/op
-// BenchmarkSearch/difficulty=26_cores=4-12 10 7760700688 ns/op 14721375220 B/op 230020906 allocs/op
-// BenchmarkSearch/difficulty=26_cores=8-12 10 2061354667 ns/op 5178224786 B/op 80909309 allocs/op
-// BenchmarkSearch/difficulty=28_cores=1-12 10 72567312888 ns/op 43706653524 B/op 682915321 allocs/op
-// BenchmarkSearch/difficulty=28_cores=2-12 10 16132176175 ns/op 18316828398 B/op 286199839 allocs/op
-// BenchmarkSearch/difficulty=28_cores=4-12 10 16948325900 ns/op 32005616084 B/op 500086387 allocs/op
-
-func BenchmarkSearch(b *testing.B) {
- salt, err := New()
- if err != nil {
- b.Fatal(err)
- }
- for _, difficulty := range []uint16{22, 24, 26, 28} {
- for _, cores := range []int{1, 2, 4, 8} {
- b.Run(fmt.Sprintf("difficulty=%d cores=%d", difficulty, cores), func(b *testing.B) {
- for i := 0; i < b.N; i++ {
- Search(salt, difficulty, cores)
- }
- })
- }
- }
-}
diff --git a/cmd/seq-cli/cmd/action.go b/cmd/seq-cli/cmd/action.go
new file mode 100644
index 0000000..1c3b6f0
--- /dev/null
+++ b/cmd/seq-cli/cmd/action.go
@@ -0,0 +1,221 @@
+// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+
+//nolint:lll
+package cmd
+
+import (
+ "context"
+ "encoding/binary"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/chain"
+ hconsts "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/crypto/bls"
+ hrpc "github.com/AnomalyFi/hypersdk/rpc"
+ hutils "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/actions"
+ "github.com/AnomalyFi/nodekit-seq/auth"
+ "github.com/AnomalyFi/nodekit-seq/consts"
+
+ "github.com/spf13/cobra"
+)
+
+var priorityFee uint64 = 0
+
+var actionCmd = &cobra.Command{
+ Use: "action",
+ RunE: func(*cobra.Command, []string) error {
+ return ErrMissingSubcommand
+ },
+}
+
+var transferCmd = &cobra.Command{
+ Use: "transfer",
+ RunE: func(*cobra.Command, []string) error {
+ ctx := context.Background()
+ _, priv, factory, cli, scli, tcli, err := handler.DefaultActor()
+ if err != nil {
+ return err
+ }
+
+ // Get balance info
+ balance, err := handler.GetBalance(ctx, tcli, priv.Address)
+ if balance == 0 || err != nil {
+ return err
+ }
+
+ // Select recipient
+ recipient, err := handler.Root().PromptAddress("recipient")
+ if err != nil {
+ return err
+ }
+
+ // Select amount
+ amount, err := handler.Root().PromptAmount("amount", consts.Decimals, balance, nil)
+ if err != nil {
+ return err
+ }
+
+ // Confirm action
+ cont, err := handler.Root().PromptContinue()
+ if !cont || err != nil {
+ return err
+ }
+
+ // Generate transaction
+ _, err = sendAndWait(ctx, []chain.Action{&actions.Transfer{
+ To: recipient,
+ Value: amount,
+ }}, cli, scli, tcli, factory, priorityFee, true)
+ return err
+ },
+}
+
+var sequencerMsgCmd = &cobra.Command{
+ Use: "sequencer-msg",
+ RunE: func(*cobra.Command, []string) error {
+ ctx := context.Background()
+ _, _, factory, cli, scli, tcli, err := handler.DefaultActor()
+ if err != nil {
+ return err
+ }
+
+ recipient, err := handler.Root().PromptAddress("recipient")
+ if err != nil {
+ return err
+ }
+ // Confirm action
+ cont, err := handler.Root().PromptContinue()
+ if !cont || err != nil {
+ return err
+ }
+
+ // Generate transaction
+ txID, err := sendAndWait(ctx, []chain.Action{&actions.SequencerMsg{
+ Data: []byte{0x00, 0x01, 0x02},
+ ChainID: []byte("nkit"),
+ FromAddress: recipient,
+ }}, cli, scli, tcli, factory, priorityFee, true)
+
+ hutils.Outf("{{green}}txId:{{/}} %s\n", txID)
+
+ return err
+ },
+}
+
+var rollupCmd = &cobra.Command{
+ Use: "rollup-register",
+ RunE: func(*cobra.Command, []string) error {
+ ctx := context.Background()
+ _, _, factory, cli, scli, tcli, err := handler.DefaultActor()
+ if err != nil {
+ return err
+ }
+
+ namespaceStr, err := handler.Root().PromptString("namespace", 0, 8)
+ if err != nil {
+ return err
+ }
+ namespace := []byte(namespaceStr)
+ feeRecipient, err := handler.Root().PromptAddress("feeRecipient")
+ if err != nil {
+ return err
+ }
+
+ op, err := handler.Root().PromptChoice("(0)create (1)exit (2)update", 3)
+ if err != nil {
+ return err
+ }
+
+ e, _ := cli.GetCurrentEpoch()
+ info := hactions.RollupInfo{
+ FeeRecipient: feeRecipient,
+ Namespace: namespace,
+ AuthoritySEQAddress: feeRecipient,
+ SequencerPublicKey: feeRecipient[:],
+ StartEpoch: e + 10,
+ ExitEpoch: 0,
+ }
+ // Generate transaction
+ _, err = sendAndWait(ctx, []chain.Action{&actions.RollupRegistration{
+ Namespace: namespace,
+ Info: info,
+ OpCode: op,
+ }}, cli, scli, tcli, factory, 0, true)
+ return err
+ },
+}
+
+var auctionCmd = &cobra.Command{
+ Use: "auction",
+ RunE: func(*cobra.Command, []string) error {
+ ctx := context.Background()
+ _, _, factory, cli, scli, tcli, err := handler.DefaultActor()
+ if err != nil {
+ return err
+ }
+
+ bidPrice, err := handler.Root().PromptAmount("bid price", consts.Decimals, 0, nil)
+ if err != nil {
+ return err
+ }
+ _, hght, _, err := cli.Accepted(ctx)
+ if err != nil {
+ return err
+ }
+
+ epochNumber := hght/12*hconsts.MillisecondsPerSecond + 1
+
+ p, err := bls.GeneratePrivateKey()
+ if err != nil {
+ return err
+ }
+ builderSEQAddress := auth.NewBLSAddress(bls.PublicFromPrivateKey(p))
+ pubKeyBytes := bls.PublicKeyToBytes(bls.PublicFromPrivateKey(p))
+
+ builderMsg := make([]byte, 16)
+ binary.BigEndian.PutUint64(builderMsg[:8], epochNumber)
+ binary.BigEndian.PutUint64(builderMsg[8:], bidPrice)
+ builderMsg = append(builderMsg, pubKeyBytes...)
+
+ sig := bls.Sign(builderMsg, p)
+
+ // Generate transaction
+ action := []chain.Action{
+ &actions.Transfer{
+ To: builderSEQAddress,
+ Value: bidPrice * 2,
+ },
+ &actions.Auction{
+ AuctionInfo: actions.AuctionInfo{
+ EpochNumber: epochNumber,
+ BidPrice: bidPrice,
+ BuilderSEQAddress: builderSEQAddress,
+ },
+ BuilderPublicKey: pubKeyBytes,
+ BuilderSignature: bls.SignatureToBytes(sig),
+ },
+ }
+
+ _, err = sendAndWait(ctx, action, cli, scli, tcli, factory, 0, true)
+ return err
+ },
+}
+
+var updateArcadiaURL = &cobra.Command{
+ Use: "updateArcadiaURL",
+ RunE: func(*cobra.Command, []string) error {
+ // ctx := context.Background()
+ str, err := handler.Root().PromptString("val rpc url", 1, 100)
+ if err != nil {
+ return err
+ }
+ valCLI := hrpc.NewJSONRPCValClient(str)
+ str, err = handler.Root().PromptString("new arcadia url", 1, 150)
+ if err != nil {
+ return err
+ }
+ return valCLI.UpdateArcadiaURL(str)
+ },
+}
diff --git a/cmd/token-cli/cmd/chain.go b/cmd/seq-cli/cmd/chain.go
similarity index 82%
rename from cmd/token-cli/cmd/chain.go
rename to cmd/seq-cli/cmd/chain.go
index a562738..ee2e262 100644
--- a/cmd/token-cli/cmd/chain.go
+++ b/cmd/seq-cli/cmd/chain.go
@@ -37,7 +37,7 @@ var importANRChainCmd = &cobra.Command{
}
var importAvalancheOpsChainCmd = &cobra.Command{
- Use: "import-ops [chainID] [path]",
+ Use: "import-ops [path]",
PreRunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return ErrInvalidArgs
@@ -97,9 +97,6 @@ var watchChainCmd = &cobra.Command{
var cli *trpc.JSONRPCClient
return handler.Root().WatchChain(hideTxs, pastBlocks, startBlock, func(uri string, networkID uint32, chainID ids.ID) (chain.Parser, error) {
- fmt.Println("Here is network Id: %d", networkID)
- fmt.Println("Here is uri: %s", uri)
-
cli = trpc.NewJSONRPCClient(uri, networkID, chainID)
return cli.Parser(context.TODO())
}, func(tx *chain.Transaction, result *chain.Result) {
@@ -107,7 +104,7 @@ var watchChainCmd = &cobra.Command{
// Should never happen
return
}
- handleTx(cli, tx, result)
+ handleTx(tx, result)
})
},
}
@@ -121,32 +118,14 @@ var testHeaderCmd = &cobra.Command{
return err
}
- // start, err := handler.Root().PromptTime("start")
- // if err != nil {
- // return err
- // }
-
- // //1698200132261
- // end, err := handler.Root().PromptTime("end")
- // if err != nil {
- // return err
- // }
-
- // // start_time := time.Unix(start, 0)
- // // end_time := time.Unix(end, 0)
-
- // start := time.Now().Unix()
-
- // end := time.Now().Unix() - 120
-
start := int64(1702502928)
end := int64(1702502930)
- start_time := start * 1000
+ startTime := start * 1000
- end_time := end * 1000
+ endTime := end * 1000
- res, err := tcli.GetBlockHeadersByStart(ctx, start_time, end_time)
+ res, err := tcli.GetBlockHeadersByStartTimeStamp(ctx, startTime, endTime)
if err != nil {
return err
}
@@ -158,3 +137,21 @@ var testHeaderCmd = &cobra.Command{
return nil
},
}
+
+var rollupsCmd = &cobra.Command{
+ Use: "rollups",
+ RunE: func(_ *cobra.Command, args []string) error {
+ ctx := context.Background()
+ _, _, _, _, _, tcli, err := handler.DefaultActor()
+ if err != nil {
+ return err
+ }
+ namespaces, err := tcli.RollupRegistry(ctx)
+ if err != nil {
+ return err
+ }
+ fmt.Printf("num of rollups registered: %d\n", len(namespaces))
+
+ return nil
+ },
+}
diff --git a/cmd/token-cli/cmd/errors.go b/cmd/seq-cli/cmd/errors.go
similarity index 100%
rename from cmd/token-cli/cmd/errors.go
rename to cmd/seq-cli/cmd/errors.go
diff --git a/cmd/token-cli/cmd/genesis.go b/cmd/seq-cli/cmd/genesis.go
similarity index 82%
rename from cmd/token-cli/cmd/genesis.go
rename to cmd/seq-cli/cmd/genesis.go
index 7a713be..9f37a48 100644
--- a/cmd/token-cli/cmd/genesis.go
+++ b/cmd/seq-cli/cmd/genesis.go
@@ -10,7 +10,8 @@ import (
"github.com/fatih/color"
"github.com/spf13/cobra"
- "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/fees"
+
"github.com/AnomalyFi/nodekit-seq/genesis"
)
@@ -33,21 +34,21 @@ var genGenesisCmd = &cobra.Command{
RunE: func(_ *cobra.Command, args []string) error {
g := genesis.Default()
if len(minUnitPrice) > 0 {
- d, err := chain.ParseDimensions(minUnitPrice)
+ d, err := fees.ParseDimensions(minUnitPrice)
if err != nil {
return err
}
g.MinUnitPrice = d
}
if len(maxBlockUnits) > 0 {
- d, err := chain.ParseDimensions(maxBlockUnits)
+ d, err := fees.ParseDimensions(maxBlockUnits)
if err != nil {
return err
}
g.MaxBlockUnits = d
}
if len(windowTargetUnits) > 0 {
- d, err := chain.ParseDimensions(windowTargetUnits)
+ d, err := fees.ParseDimensions(windowTargetUnits)
if err != nil {
return err
}
@@ -56,7 +57,12 @@ var genGenesisCmd = &cobra.Command{
if minBlockGap >= 0 {
g.MinBlockGap = minBlockGap
}
-
+ if minEmptyBlockGap >= 0 {
+ g.MinEmptyBlockGap = minEmptyBlockGap
+ }
+ if epochLength > 0 {
+ g.EpochLength = epochLength
+ }
a, err := os.ReadFile(args[0])
if err != nil {
return err
diff --git a/cmd/seq-cli/cmd/handler.go b/cmd/seq-cli/cmd/handler.go
new file mode 100644
index 0000000..9758378
--- /dev/null
+++ b/cmd/seq-cli/cmd/handler.go
@@ -0,0 +1,125 @@
+// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+
+package cmd
+
+import (
+ "context"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/cli"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/crypto/ed25519"
+ "github.com/AnomalyFi/hypersdk/pubsub"
+ "github.com/AnomalyFi/hypersdk/rpc"
+ "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/auth"
+ "github.com/AnomalyFi/nodekit-seq/consts"
+ trpc "github.com/AnomalyFi/nodekit-seq/rpc"
+
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+var _ cli.Controller = (*Controller)(nil)
+
+type Handler struct {
+ h *cli.Handler
+}
+
+func NewHandler(h *cli.Handler) *Handler {
+ return &Handler{h}
+}
+
+func (h *Handler) Root() *cli.Handler {
+ return h.h
+}
+
+func (h *Handler) DefaultActor() (
+ ids.ID, *cli.PrivateKey, chain.AuthFactory,
+ *rpc.JSONRPCClient, *rpc.WebSocketClient, *trpc.JSONRPCClient, error,
+) {
+ addr, priv, err := h.h.GetDefaultKey(true)
+ if err != nil {
+ return ids.Empty, nil, nil, nil, nil, nil, err
+ }
+ chainID, uris, err := h.h.GetDefaultChain(true)
+ if err != nil {
+ return ids.Empty, nil, nil, nil, nil, nil, err
+ }
+ // For [defaultActor], we always send requests to the first returned URI.
+ jcli := rpc.NewJSONRPCClient(uris[0])
+ networkID, _, _, err := jcli.Network(context.TODO())
+ if err != nil {
+ return ids.Empty, nil, nil, nil, nil, nil, err
+ }
+ scli, err := rpc.NewWebSocketClient(
+ uris[0],
+ rpc.DefaultHandshakeTimeout,
+ pubsub.MaxPendingMessages,
+ pubsub.MaxReadMessageSize,
+ )
+ if err != nil {
+ return ids.Empty, nil, nil, nil, nil, nil, err
+ }
+ return chainID, &cli.PrivateKey{Address: addr, Bytes: priv}, auth.NewED25519Factory(ed25519.PrivateKey(priv)), jcli, scli,
+ trpc.NewJSONRPCClient(
+ uris[0],
+ networkID,
+ chainID,
+ ), nil
+}
+
+func (*Handler) GetBalance(
+ ctx context.Context,
+ cli *trpc.JSONRPCClient,
+ addr codec.Address,
+) (uint64, error) {
+ saddr, err := codec.AddressBech32(consts.HRP, addr)
+ if err != nil {
+ return 0, err
+ }
+ balance, err := cli.Balance(ctx, saddr)
+ if err != nil {
+ return 0, err
+ }
+ if balance == 0 {
+ utils.Outf("{{red}}balance:{{/}} 0 %s\n", consts.Symbol)
+ utils.Outf("{{red}}please send funds to %s{{/}}\n", saddr)
+ utils.Outf("{{red}}exiting...{{/}}\n")
+ return 0, nil
+ }
+ utils.Outf(
+ "{{yellow}}balance:{{/}} %s %s\n",
+ utils.FormatBalance(balance, consts.Decimals),
+ consts.Symbol,
+ )
+ return balance, nil
+}
+
+type Controller struct {
+ databasePath string
+}
+
+func NewController(databasePath string) *Controller {
+ return &Controller{databasePath}
+}
+
+func (c *Controller) DatabasePath() string {
+ return c.databasePath
+}
+
+func (*Controller) Symbol() string {
+ return consts.Symbol
+}
+
+func (*Controller) Decimals() uint8 {
+ return consts.Decimals
+}
+
+func (*Controller) Address(addr codec.Address) string {
+ return codec.MustAddressBech32(consts.HRP, addr)
+}
+
+func (*Controller) ParseAddress(address string) (codec.Address, error) {
+ return codec.ParseAddressBech32(consts.HRP, address)
+}
diff --git a/cmd/token-cli/cmd/key.go b/cmd/seq-cli/cmd/key.go
similarity index 53%
rename from cmd/token-cli/cmd/key.go
rename to cmd/seq-cli/cmd/key.go
index b0e2d3a..2ffcc5c 100644
--- a/cmd/token-cli/cmd/key.go
+++ b/cmd/seq-cli/cmd/key.go
@@ -5,19 +5,18 @@ package cmd
import (
"context"
- "time"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/utils"
"github.com/ava-labs/avalanchego/ids"
"github.com/spf13/cobra"
- "github.com/AnomalyFi/nodekit-seq/challenge"
- frpc "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/rpc"
+ "github.com/AnomalyFi/hypersdk/cli"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/crypto/ed25519"
+ "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/auth"
+
tconsts "github.com/AnomalyFi/nodekit-seq/consts"
trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- tutils "github.com/AnomalyFi/nodekit-seq/utils"
)
var keyCmd = &cobra.Command{
@@ -30,7 +29,25 @@ var keyCmd = &cobra.Command{
var genKeyCmd = &cobra.Command{
Use: "generate",
RunE: func(*cobra.Command, []string) error {
- return handler.Root().GenerateKey()
+ p, err := ed25519.GeneratePrivateKey()
+ if err != nil {
+ return err
+ }
+ priv := &cli.PrivateKey{
+ Address: auth.NewED25519Address(p.PublicKey()),
+ Bytes: p[:],
+ }
+ if err := handler.h.StoreKey(priv); err != nil {
+ return err
+ }
+ if err := handler.h.StoreDefaultKey(priv.Address); err != nil {
+ return err
+ }
+ utils.Outf(
+ "{{green}}created address:{{/}} %s",
+ codec.MustAddressBech32(tconsts.HRP, priv.Address),
+ )
+ return nil
},
}
@@ -43,14 +60,33 @@ var importKeyCmd = &cobra.Command{
return nil
},
RunE: func(_ *cobra.Command, args []string) error {
- return handler.Root().ImportKey(args[0])
+ p, err := utils.LoadBytes(args[0], ed25519.PrivateKeyLen)
+ if err != nil {
+ return err
+ }
+ pk := ed25519.PrivateKey(p)
+ priv := &cli.PrivateKey{
+ Address: auth.NewED25519Address(pk.PublicKey()),
+ Bytes: p,
+ }
+ if err := handler.h.StoreKey(priv); err != nil {
+ return err
+ }
+ if err := handler.h.StoreDefaultKey(priv.Address); err != nil {
+ return err
+ }
+ utils.Outf(
+ "{{green}}imported address:{{/}} %s",
+ codec.MustAddressBech32(tconsts.HRP, priv.Address),
+ )
+ return nil
},
}
func lookupSetKeyBalance(choice int, address string, uri string, networkID uint32, chainID ids.ID) error {
// TODO: just load once
cli := trpc.NewJSONRPCClient(uri, networkID, chainID)
- balance, err := cli.Balance(context.TODO(), address, ids.Empty)
+ balance, err := cli.Balance(context.TODO(), address)
if err != nil {
return err
}
@@ -71,10 +107,10 @@ var setKeyCmd = &cobra.Command{
},
}
-func lookupKeyBalance(pk ed25519.PublicKey, uri string, networkID uint32, chainID ids.ID, assetID ids.ID) error {
- _, _, _, _, err := handler.GetAssetInfo(
+func lookupKeyBalance(addr codec.Address, uri string, networkID uint32, chainID ids.ID, _ ids.ID) error {
+ _, err := handler.GetBalance(
context.TODO(), trpc.NewJSONRPCClient(uri, networkID, chainID),
- pk, assetID, true)
+ addr)
return err
}
@@ -84,43 +120,3 @@ var balanceKeyCmd = &cobra.Command{
return handler.Root().Balance(checkAllChains, true, lookupKeyBalance)
},
}
-
-var faucetKeyCmd = &cobra.Command{
- Use: "faucet",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
-
- // Get private key
- _, priv, _, _, _, _, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Get faucet
- faucetURI, err := handler.Root().PromptString("faucet URI", 0, consts.MaxInt)
- if err != nil {
- return err
- }
- fcli := frpc.NewJSONRPCClient(faucetURI)
- faucet, err := fcli.FaucetAddress(ctx)
- if err != nil {
- return err
- }
-
- // Search for funds
- salt, difficulty, err := fcli.Challenge(ctx)
- if err != nil {
- return err
- }
- utils.Outf("{{yellow}}searching for faucet solutions (difficulty=%d, faucet=%s):{{/}} %x\n", difficulty, faucet, salt)
- start := time.Now()
- solution, attempts := challenge.Search(salt, difficulty, numCores)
- utils.Outf("{{cyan}}found solution (attempts=%d, t=%s):{{/}} %x\n", attempts, time.Since(start), solution)
- txID, amount, err := fcli.SolveChallenge(ctx, tutils.Address(priv.PublicKey()), salt, solution)
- if err != nil {
- return err
- }
- utils.Outf("{{green}}faucet funds incoming (%s %s):{{/}} %s\n", utils.FormatBalance(amount, tconsts.Decimals), tconsts.Symbol, txID)
- return nil
- },
-}
diff --git a/cmd/token-cli/cmd/prometheus.go b/cmd/seq-cli/cmd/prometheus.go
similarity index 99%
rename from cmd/token-cli/cmd/prometheus.go
rename to cmd/seq-cli/cmd/prometheus.go
index a066188..e38dec2 100644
--- a/cmd/token-cli/cmd/prometheus.go
+++ b/cmd/seq-cli/cmd/prometheus.go
@@ -98,7 +98,7 @@ var generatePrometheusCmd = &cobra.Command{
utils.Outf("{{yellow}}memory (avalanchego) usage:{{/}} %s\n", panels[len(panels)-1])
panels = append(panels, fmt.Sprintf("avalanche_%s_vm_go_memstats_alloc_bytes", chainID))
- utils.Outf("{{yellow}}memory (tokenvm) usage:{{/}} %s\n", panels[len(panels)-1])
+ utils.Outf("{{yellow}}memory (seqvm) usage:{{/}} %s\n", panels[len(panels)-1])
panels = append(panels, fmt.Sprintf("increase(avalanche_%s_handler_chits_sum[5s])/1000000/5 + increase(avalanche_%s_handler_notify_sum[5s])/1000000/5 + increase(avalanche_%s_handler_get_sum[5s])/1000000/5 + increase(avalanche_%s_handler_push_query_sum[5s])/1000000/5 + increase(avalanche_%s_handler_put_sum[5s])/1000000/5 + increase(avalanche_%s_handler_pull_query_sum[5s])/1000000/5 + increase(avalanche_%s_handler_query_failed_sum[5s])/1000000/5", chainID, chainID, chainID, chainID, chainID, chainID, chainID))
utils.Outf("{{yellow}}consensus engine processing (ms/s):{{/}} %s\n", panels[len(panels)-1])
diff --git a/cmd/seq-cli/cmd/resolutions.go b/cmd/seq-cli/cmd/resolutions.go
new file mode 100644
index 0000000..895acec
--- /dev/null
+++ b/cmd/seq-cli/cmd/resolutions.go
@@ -0,0 +1,104 @@
+// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+
+package cmd
+
+import (
+ "context"
+ "fmt"
+ "reflect"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/cli"
+ "github.com/AnomalyFi/hypersdk/codec"
+
+ "github.com/AnomalyFi/hypersdk/rpc"
+ "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/actions"
+
+ tconsts "github.com/AnomalyFi/nodekit-seq/consts"
+ trpc "github.com/AnomalyFi/nodekit-seq/rpc"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+// sendAndWait may not be used concurrently
+func sendAndWait(
+ ctx context.Context, action []chain.Action, cli *rpc.JSONRPCClient,
+ scli *rpc.WebSocketClient, tcli *trpc.JSONRPCClient, factory chain.AuthFactory, priorityFee uint64, printStatus bool,
+) (ids.ID, error) {
+ parser, err := tcli.Parser(ctx)
+ if err != nil {
+ return ids.Empty, err
+ }
+ _, tx, _, err := cli.GenerateTransaction(ctx, parser, action, factory, priorityFee)
+ if err != nil {
+ return ids.Empty, err
+ }
+
+ if err := scli.RegisterTx(tx); err != nil {
+ return ids.Empty, err
+ }
+ var res *chain.Result
+ for {
+ txID, dErr, result, err := scli.ListenTx(ctx)
+ if dErr != nil {
+ return ids.Empty, dErr
+ }
+ if err != nil {
+ return ids.Empty, err
+ }
+ if txID == tx.ID() {
+ res = result
+ break
+ }
+ // TODO: don't drop these results (may be needed by a different connection)
+ utils.Outf("{{yellow}}skipping unexpected transaction:{{/}} %s\n", tx.ID())
+ }
+ if printStatus {
+ handler.Root().PrintStatus(tx.ID(), res.Success)
+ }
+ return tx.ID(), nil
+}
+
+func handleTx(tx *chain.Transaction, result *chain.Result) {
+ actor := tx.Auth.Actor()
+ if !result.Success {
+ utils.Outf(
+ "%s {{yellow}}%s{{/}} {{yellow}}actor:{{/}} %s {{yellow}}error:{{/}} [%s] {{yellow}}fee (max %.2f%%):{{/}} %s %s {{yellow}}consumed:{{/}} [%s]\n",
+ "❌",
+ tx.ID(),
+ codec.MustAddressBech32(tconsts.HRP, actor),
+ result.Error,
+ float64(result.Fee)/float64(tx.Base.MaxFee)*100,
+ utils.FormatBalance(result.Fee, tconsts.Decimals),
+ tconsts.Symbol,
+ cli.ParseDimensions(result.Units),
+ )
+ return
+ }
+
+ for _, act := range tx.Actions {
+ var summaryStr string
+ switch action := act.(type) {
+ case *actions.Transfer:
+ amountStr := utils.FormatBalance(action.Value, tconsts.Decimals)
+ summaryStr = fmt.Sprintf("%s %s -> %s", amountStr, tconsts.Symbol, codec.MustAddressBech32(tconsts.HRP, action.To))
+ if len(action.Memo) > 0 {
+ summaryStr += fmt.Sprintf(" (memo: %s)", action.Memo)
+ }
+ default:
+ }
+ utils.Outf(
+ "%s {{yellow}}%s{{/}} {{yellow}}actor:{{/}} %s {{yellow}}summary (%s):{{/}} [%s] {{yellow}}fee (max %.2f%%):{{/}} %s %s {{yellow}}consumed:{{/}} [%s]\n",
+ "✅",
+ tx.ID(),
+ codec.MustAddressBech32(tconsts.HRP, actor),
+ reflect.TypeOf(act),
+ summaryStr,
+ float64(result.Fee)/float64(tx.Base.MaxFee)*100,
+ utils.FormatBalance(result.Fee, tconsts.Decimals),
+ tconsts.Symbol,
+ cli.ParseDimensions(result.Units),
+ )
+ }
+}
diff --git a/cmd/token-cli/cmd/root.go b/cmd/seq-cli/cmd/root.go
similarity index 89%
rename from cmd/token-cli/cmd/root.go
rename to cmd/seq-cli/cmd/root.go
index 20163bb..bbe81f7 100644
--- a/cmd/token-cli/cmd/root.go
+++ b/cmd/seq-cli/cmd/root.go
@@ -14,7 +14,7 @@ import (
const (
fsModeWrite = 0o600
- defaultDatabase = ".token-cli"
+ defaultDatabase = ".seq-cli"
defaultGenesis = "genesis.json"
)
@@ -24,6 +24,8 @@ var (
dbPath string
genesisFile string
minBlockGap int64
+ minEmptyBlockGap int64
+ epochLength int64
minUnitPrice []string
maxBlockUnits []string
windowTargetUnits []string
@@ -37,12 +39,11 @@ var (
prometheusData string
startPrometheus bool
maxFee int64
- numCores int
rootCmd = &cobra.Command{
- Use: "token-cli",
- Short: "TokenVM CLI",
- SuggestFor: []string{"token-cli", "tokencli"},
+ Use: "seq-cli",
+ Short: "SEQVM CLI",
+ SuggestFor: []string{"seq-cli", "seq-cli"},
}
)
@@ -108,6 +109,18 @@ func init() {
-1,
"minimum block gap (ms)",
)
+ genGenesisCmd.PersistentFlags().Int64Var(
+ &minEmptyBlockGap,
+ "min-empty-block-gap",
+ -1,
+ "minimum empty block gap (ms)",
+ )
+ genGenesisCmd.PersistentFlags().Int64Var(
+ &epochLength,
+ "epoch-length",
+ 6,
+ "epoch length (# of SEQ blocks)",
+ )
genesisCmd.AddCommand(
genGenesisCmd,
)
@@ -119,18 +132,11 @@ func init() {
false,
"check all chains",
)
- balanceKeyCmd.PersistentFlags().IntVar(
- &numCores,
- "num-cores",
- 4,
- "number of cores to use when searching for faucet solutions",
- )
keyCmd.AddCommand(
genKeyCmd,
importKeyCmd,
setKeyCmd,
balanceKeyCmd,
- faucetKeyCmd,
)
// chain
@@ -148,24 +154,16 @@ func init() {
chainInfoCmd,
watchChainCmd,
testHeaderCmd,
+ rollupsCmd,
)
// actions
actionCmd.AddCommand(
- fundFaucetCmd,
-
transferCmd,
-
- createAssetCmd,
- mintAssetCmd,
- // burnAssetCmd,
-
- importAssetCmd,
- exportAssetCmd,
-
sequencerMsgCmd,
-
- // exportBlockCmd,
+ rollupCmd,
+ auctionCmd,
+ updateArcadiaURL,
)
// spam
@@ -189,7 +187,6 @@ func init() {
)
spamCmd.AddCommand(
runSpamCmd,
- runSpamSequencerMsgCmd,
)
// prometheus
diff --git a/cmd/seq-cli/cmd/spam.go b/cmd/seq-cli/cmd/spam.go
new file mode 100644
index 0000000..660cd8e
--- /dev/null
+++ b/cmd/seq-cli/cmd/spam.go
@@ -0,0 +1,100 @@
+// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
+// See the file LICENSE for licensing terms.
+
+package cmd
+
+import (
+ "context"
+
+ "github.com/ava-labs/avalanchego/ids"
+ "github.com/spf13/cobra"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/cli"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/crypto/ed25519"
+ "github.com/AnomalyFi/hypersdk/pubsub"
+ "github.com/AnomalyFi/hypersdk/rpc"
+ "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/actions"
+ "github.com/AnomalyFi/nodekit-seq/auth"
+ "github.com/AnomalyFi/nodekit-seq/consts"
+
+ trpc "github.com/AnomalyFi/nodekit-seq/rpc"
+)
+
+var spamCmd = &cobra.Command{
+ Use: "spam",
+ RunE: func(*cobra.Command, []string) error {
+ return ErrMissingSubcommand
+ },
+}
+
+var runSpamCmd = &cobra.Command{
+ Use: "run",
+ RunE: func(*cobra.Command, []string) error {
+ var sclient *rpc.WebSocketClient
+ var tclient *trpc.JSONRPCClient
+ var maxFeeParsed *uint64
+ if maxFee >= 0 {
+ v := uint64(maxFee)
+ maxFeeParsed = &v
+ }
+ return handler.Root().Spam(maxTxBacklog, maxFeeParsed, randomRecipient,
+ func(uri string, networkID uint32, chainID ids.ID) error { // createClient
+ tclient = trpc.NewJSONRPCClient(uri, networkID, chainID)
+ sc, err := rpc.NewWebSocketClient(uri, rpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize)
+ if err != nil {
+ return err
+ }
+ sclient = sc
+ return nil
+ },
+ func(priv *cli.PrivateKey) (chain.AuthFactory, error) { // getFactory
+ return auth.NewED25519Factory(ed25519.PrivateKey(priv.Bytes)), nil
+ },
+ func() (*cli.PrivateKey, error) { // createAccount
+ p, err := ed25519.GeneratePrivateKey()
+ if err != nil {
+ return nil, err
+ }
+ return &cli.PrivateKey{
+ Address: auth.NewED25519Address(p.PublicKey()),
+ Bytes: p[:],
+ }, nil
+ },
+ func(choice int, address string) (uint64, error) { // lookupBalance
+ balance, err := tclient.Balance(context.TODO(), address)
+ if err != nil {
+ return 0, err
+ }
+ utils.Outf(
+ "%d) {{cyan}}address:{{/}} %s {{cyan}}balance:{{/}} %s %s\n",
+ choice,
+ address,
+ utils.FormatBalance(balance, consts.Decimals),
+ consts.Symbol,
+ )
+ return balance, err
+ },
+ func(ctx context.Context, chainID ids.ID) (chain.Parser, error) { // getParser
+ return tclient.Parser(ctx)
+ },
+ func(addr codec.Address, amount uint64) []chain.Action { // getTransfer
+ return []chain.Action{&actions.Transfer{
+ To: addr,
+ Value: amount,
+ }}
+ },
+ func(cli *rpc.JSONRPCClient, priv *cli.PrivateKey) func(context.Context, uint64) error { // submitDummy
+ return func(ictx context.Context, count uint64) error {
+ _, err := sendAndWait(ictx, []chain.Action{&actions.Transfer{
+ To: priv.Address,
+ Value: count, // prevent duplicate txs
+ }}, cli, sclient, tclient, auth.NewED25519Factory(ed25519.PrivateKey(priv.Bytes)), priorityFee, false)
+ return err
+ }
+ },
+ )
+ },
+}
diff --git a/cmd/token-cli/main.go b/cmd/seq-cli/main.go
similarity index 58%
rename from cmd/token-cli/main.go
rename to cmd/seq-cli/main.go
index da2413a..a5da0ba 100644
--- a/cmd/token-cli/main.go
+++ b/cmd/seq-cli/main.go
@@ -1,19 +1,19 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
-// "token-cli" implements tokenvm client operation interface.
+// "seq-cli" implements seqvm client operation interface.
package main
import (
"os"
"github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-cli/cmd"
+ "github.com/AnomalyFi/nodekit-seq/cmd/seq-cli/cmd"
)
func main() {
if err := cmd.Execute(); err != nil {
- utils.Outf("{{red}}token-cli exited with error:{{/}} %+v\n", err)
+ utils.Outf("{{red}}seq-cli exited with error:{{/}} %+v\n", err)
os.Exit(1)
}
os.Exit(0)
diff --git a/cmd/tokenvm/main.go b/cmd/seqvm/main.go
similarity index 81%
rename from cmd/tokenvm/main.go
rename to cmd/seqvm/main.go
index 78ea3df..8f8268f 100644
--- a/cmd/tokenvm/main.go
+++ b/cmd/seqvm/main.go
@@ -8,7 +8,7 @@ import (
"fmt"
"os"
- "github.com/AnomalyFi/nodekit-seq/cmd/tokenvm/version"
+ "github.com/AnomalyFi/nodekit-seq/cmd/seqvm/version"
"github.com/AnomalyFi/nodekit-seq/controller"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/ulimit"
@@ -17,9 +17,9 @@ import (
)
var rootCmd = &cobra.Command{
- Use: "tokenvm",
- Short: "TokenVM agent",
- SuggestFor: []string{"tokenvm"},
+ Use: "seqvm",
+ Short: "SeqVM agent",
+ SuggestFor: []string{"seqvm"},
RunE: runFunc,
}
@@ -35,7 +35,7 @@ func init() {
func main() {
if err := rootCmd.Execute(); err != nil {
- fmt.Fprintf(os.Stderr, "tokenvm failed %v\n", err)
+ fmt.Fprintf(os.Stderr, "seqvm failed %v\n", err)
os.Exit(1)
}
os.Exit(0)
diff --git a/cmd/tokenvm/version/version.go b/cmd/seqvm/version/version.go
similarity index 91%
rename from cmd/tokenvm/version/version.go
rename to cmd/seqvm/version/version.go
index 2d1b336..3bd6172 100644
--- a/cmd/tokenvm/version/version.go
+++ b/cmd/seqvm/version/version.go
@@ -16,7 +16,7 @@ func init() {
cobra.EnablePrefixMatching = true
}
-// NewCommand implements "tokenvm version" command.
+// NewCommand implements "seqvm version" command.
func NewCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "version",
diff --git a/cmd/token-cli/cmd/action.go b/cmd/token-cli/cmd/action.go
deleted file mode 100644
index 1238e3b..0000000
--- a/cmd/token-cli/cmd/action.go
+++ /dev/null
@@ -1,878 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-//nolint:lll
-package cmd
-
-import (
- "context"
- "errors"
- "time"
-
- // "math/rand"
- // "encoding/hex"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/pubsub"
- "github.com/AnomalyFi/hypersdk/rpc"
- hutils "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/actions"
- frpc "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/rpc"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
-
- "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/utils/set"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
- "github.com/spf13/cobra"
-)
-
-const (
- dummyBlockAgeThreshold = 25
- dummyHeightThreshold = 3
-)
-
-var actionCmd = &cobra.Command{
- Use: "action",
- RunE: func(*cobra.Command, []string) error {
- return ErrMissingSubcommand
- },
-}
-
-var fundFaucetCmd = &cobra.Command{
- Use: "fund-faucet",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
-
- // Get faucet
- faucetURI, err := handler.Root().PromptString("faucet URI", 0, consts.MaxInt)
- if err != nil {
- return err
- }
- fcli := frpc.NewJSONRPCClient(faucetURI)
- faucetAddress, err := fcli.FaucetAddress(ctx)
- if err != nil {
- return err
- }
-
- // Get clients
- _, priv, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Get balance
- _, decimals, balance, _, err := handler.GetAssetInfo(ctx, tcli, priv.PublicKey(), ids.Empty, true)
- if balance == 0 || err != nil {
- return err
- }
-
- // Select amount
- amount, err := handler.Root().PromptAmount("amount", decimals, balance, nil)
- if err != nil {
- return err
- }
-
- // Confirm action
- cont, err := handler.Root().PromptContinue()
- if !cont || err != nil {
- return err
- }
-
- // Generate transaction
- pk, err := utils.ParseAddress(faucetAddress)
- if err != nil {
- return err
- }
- if _, _, err = sendAndWait(ctx, nil, &actions.Transfer{
- To: pk,
- Asset: ids.Empty,
- Value: amount,
- }, cli, scli, tcli, factory, true); err != nil {
- return err
- }
- hutils.Outf("{{green}}funded faucet:{{/}} %s\n", faucetAddress)
- return nil
- },
-}
-
-var transferCmd = &cobra.Command{
- Use: "transfer",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
- _, priv, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Select token to send
- assetID, err := handler.Root().PromptAsset("assetID", true)
- if err != nil {
- return err
- }
- _, decimals, balance, _, err := handler.GetAssetInfo(ctx, tcli, priv.PublicKey(), assetID, true)
- if balance == 0 || err != nil {
- return err
- }
-
- // Select recipient
- recipient, err := handler.Root().PromptAddress("recipient")
- if err != nil {
- return err
- }
-
- // Select amount
- amount, err := handler.Root().PromptAmount("amount", decimals, balance, nil)
- if err != nil {
- return err
- }
-
- // Confirm action
- cont, err := handler.Root().PromptContinue()
- if !cont || err != nil {
- return err
- }
-
- // Generate transaction
- _, _, err = sendAndWait(ctx, nil, &actions.Transfer{
- To: recipient,
- Asset: assetID,
- Value: amount,
- }, cli, scli, tcli, factory, true)
- return err
- },
-}
-
-var createAssetCmd = &cobra.Command{
- Use: "create-asset",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
- _, _, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Add symbol to token
- symbol, err := handler.Root().PromptString("symbol", 1, actions.MaxSymbolSize)
- if err != nil {
- return err
- }
-
- // Add decimal to token
- decimals, err := handler.Root().PromptInt("decimals", actions.MaxDecimals)
- if err != nil {
- return err
- }
-
- // Add metadata to token
- metadata, err := handler.Root().PromptString("metadata", 1, actions.MaxMetadataSize)
- if err != nil {
- return err
- }
-
- // Confirm action
- cont, err := handler.Root().PromptContinue()
- if !cont || err != nil {
- return err
- }
-
- // Generate transaction
- _, _, err = sendAndWait(ctx, nil, &actions.CreateAsset{
- Symbol: []byte(symbol),
- Decimals: uint8(decimals), // already constrain above to prevent overflow
- Metadata: []byte(metadata),
- }, cli, scli, tcli, factory, true)
- return err
- },
-}
-
-var sequencerMsgCmd = &cobra.Command{
- Use: "sequencer-msg",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
- _, _, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // // Add metadata to token
- // promptText := promptui.Prompt{
- // Label: "metadata (can be changed later)",
- // Validate: func(input string) error {
- // if len(input) > actions.MaxMetadataSize {
- // return errors.New("input too large")
- // }
- // return nil
- // },
- // }
- // metadata, err := promptText.Run()
- // if err != nil {
- // return err
- // }
-
- recipient, err := handler.Root().PromptAddress("recipient")
- if err != nil {
- return err
- }
- // Confirm action
- cont, err := handler.Root().PromptContinue()
- if !cont || err != nil {
- return err
- }
-
- // Generate transaction
- _, _, err = sendAndWait(ctx, nil, &actions.SequencerMsg{
- Data: []byte{0x00, 0x01, 0x02},
- ChainId: []byte("nkit"),
- FromAddress: recipient,
- }, cli, scli, tcli, factory, true)
-
- return err
- },
-}
-
-var mintAssetCmd = &cobra.Command{
- Use: "mint-asset",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
- _, priv, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Select token to mint
- assetID, err := handler.Root().PromptAsset("assetID", false)
- if err != nil {
- return err
- }
- exists, symbol, decimals, metadata, supply, owner, warp, err := tcli.Asset(ctx, assetID, false)
- if err != nil {
- return err
- }
- if !exists {
- hutils.Outf("{{red}}%s does not exist{{/}}\n", assetID)
- hutils.Outf("{{red}}exiting...{{/}}\n")
- return nil
- }
- if warp {
- hutils.Outf("{{red}}cannot mint a warped asset{{/}}\n", assetID)
- hutils.Outf("{{red}}exiting...{{/}}\n")
- return nil
- }
- if owner != utils.Address(priv.PublicKey()) {
- hutils.Outf("{{red}}%s is the owner of %s, you are not{{/}}\n", owner, assetID)
- hutils.Outf("{{red}}exiting...{{/}}\n")
- return nil
- }
- hutils.Outf(
- "{{yellow}}symbol:{{/}} %s {{yellow}}decimals:{{/}} %s {{yellow}}metadata:{{/}} %s {{yellow}}supply:{{/}} %d\n",
- string(symbol),
- decimals,
- string(metadata),
- supply,
- )
-
- // Select recipient
- recipient, err := handler.Root().PromptAddress("recipient")
- if err != nil {
- return err
- }
-
- // Select amount
- amount, err := handler.Root().PromptAmount("amount", decimals, consts.MaxUint64-supply, nil)
- if err != nil {
- return err
- }
-
- // Confirm action
- cont, err := handler.Root().PromptContinue()
- if !cont || err != nil {
- return err
- }
-
- // Generate transaction
- _, _, err = sendAndWait(ctx, nil, &actions.MintAsset{
- Asset: assetID,
- To: recipient,
- Value: amount,
- }, cli, scli, tcli, factory, true)
- return err
- },
-}
-
-func performImport(
- ctx context.Context,
- scli *rpc.JSONRPCClient,
- dcli *rpc.JSONRPCClient,
- dscli *rpc.WebSocketClient,
- dtcli *trpc.JSONRPCClient,
- exportTxID ids.ID,
- factory chain.AuthFactory,
-) error {
- // Select TxID (if not provided)
- var err error
- if exportTxID == ids.Empty {
- exportTxID, err = handler.Root().PromptID("export txID")
- if err != nil {
- return err
- }
- }
-
- // Generate warp signature (as long as >= 80% stake)
- var (
- msg *warp.Message
- subnetWeight, sigWeight uint64
- )
- for ctx.Err() == nil {
- msg, subnetWeight, sigWeight, err = scli.GenerateAggregateWarpSignature(ctx, exportTxID)
- if sigWeight >= (subnetWeight*4)/5 && err == nil {
- break
- }
- if err == nil {
- hutils.Outf(
- "{{yellow}}waiting for signature weight:{{/}} %d {{yellow}}observed:{{/}} %d\n",
- subnetWeight,
- sigWeight,
- )
- } else {
- hutils.Outf("{{red}}encountered error:{{/}} %v\n", err)
- }
- cont, err := handler.Root().PromptBool("try again")
- if err != nil {
- return err
- }
- if !cont {
- hutils.Outf("{{red}}exiting...{{/}}\n")
- return nil
- }
- }
- if ctx.Err() != nil {
- return ctx.Err()
- }
- wt, err := actions.UnmarshalWarpTransfer(msg.UnsignedMessage.Payload)
- if err != nil {
- return err
- }
- outputAssetID := wt.Asset
- if !wt.Return {
- outputAssetID = actions.ImportedAssetID(wt.Asset, msg.SourceChainID)
- }
- hutils.Outf(
- "%s {{yellow}}to:{{/}} %s {{yellow}}source assetID:{{/}} %s {{yellow}}source symbol:{{/}} %s {{yellow}}output assetID:{{/}} %s {{yellow}}value:{{/}} %s {{yellow}}reward:{{/}} %s {{yellow}}return:{{/}} %t\n",
- hutils.ToID(
- msg.UnsignedMessage.Payload,
- ),
- utils.Address(wt.To),
- wt.Asset,
- wt.Symbol,
- outputAssetID,
- hutils.FormatBalance(wt.Value, wt.Decimals),
- hutils.FormatBalance(wt.Reward, wt.Decimals),
- wt.Return,
- )
- if wt.SwapIn > 0 {
- _, outSymbol, outDecimals, _, _, _, _, err := dtcli.Asset(ctx, wt.AssetOut, false)
- if err != nil {
- return err
- }
- hutils.Outf(
- "{{yellow}}asset in:{{/}} %s {{yellow}}swap in:{{/}} %s {{yellow}}asset out:{{/}} %s {{yellow}}symbol out:{{/}} %s {{yellow}}swap out:{{/}} %s {{yellow}}swap expiry:{{/}} %d\n",
- outputAssetID,
- hutils.FormatBalance(wt.SwapIn, wt.Decimals),
- wt.AssetOut,
- outSymbol,
- hutils.FormatBalance(wt.SwapOut, outDecimals),
- wt.SwapExpiry,
- )
- }
- hutils.Outf(
- "{{yellow}}signature weight:{{/}} %d {{yellow}}total weight:{{/}} %d\n",
- sigWeight,
- subnetWeight,
- )
-
- // Select fill
- var fill bool
- if wt.SwapIn > 0 {
- fill, err = handler.Root().PromptBool("fill")
- if err != nil {
- return err
- }
- }
- if !fill && wt.SwapExpiry > time.Now().UnixMilli() {
- return ErrMustFill
- }
-
- // Generate transaction
- _, _, err = sendAndWait(ctx, msg, &actions.ImportAsset{
- Fill: fill,
- }, dcli, dscli, dtcli, factory, true)
- return err
-}
-
-// TODO need to update this
-// func performImportMsg(
-// ctx context.Context,
-// scli *rpc.JSONRPCClient,
-// dcli *rpc.JSONRPCClient,
-// dtcli *trpc.JSONRPCClient,
-// exportTxID ids.ID,
-// priv ed25519.PrivateKey,
-// factory chain.AuthFactory,
-// ) error {
-// // Select TxID (if not provided)
-// var err error
-// if exportTxID == ids.Empty {
-// exportTxID, err = promptID("export txID")
-// if err != nil {
-// return err
-// }
-// }
-
-// // Generate warp signature (as long as >= 80% stake)
-// var (
-// msg *warp.Message
-// subnetWeight, sigWeight uint64
-// )
-// for ctx.Err() == nil {
-// msg, subnetWeight, sigWeight, err = scli.GenerateAggregateWarpSignature(ctx, exportTxID)
-// if sigWeight >= (subnetWeight*4)/5 && err == nil {
-// break
-// }
-// if err == nil {
-// hutils.Outf(
-// "{{yellow}}waiting for signature weight:{{/}} %d {{yellow}}observed:{{/}} %d\n",
-// subnetWeight,
-// sigWeight,
-// )
-// } else {
-// hutils.Outf("{{red}}encountered error:{{/}} %v\n", err)
-// }
-// cont, err := promptBool("try again")
-// if err != nil {
-// return err
-// }
-// if !cont {
-// hutils.Outf("{{red}}exiting...{{/}}\n")
-// return nil
-// }
-// }
-// if ctx.Err() != nil {
-// return ctx.Err()
-// }
-// wt, err := chain.UnmarshalWarpBlock(msg.UnsignedMessage.Payload)
-// if err != nil {
-// return err
-// }
-// hutils.Outf(
-// "{{yellow}}Timestamp:{{/}} %d {{yellow}}Height:{{/}} %d\n",
-// wt.Tmstmp,
-// wt.Hght,
-// )
-
-// // hutils.Outf(
-// // "%s {{yellow}}to:{{/}} %s {{yellow}}source \n",
-// // hutils.ToID(
-// // msg.UnsignedMessage.Payload,
-// // ),
-// // )
-// hutils.Outf(
-// "{{yellow}}signature weight:{{/}} %d {{yellow}}total weight:{{/}} %d\n",
-// sigWeight,
-// subnetWeight,
-// )
-
-// // Attempt to send dummy transaction if needed
-// if err := submitDummy(ctx, dcli, dtcli, priv.PublicKey(), factory); err != nil {
-// fmt.Println("Error in submit of dummy TX: %w", err)
-// return err
-// }
-// fmt.Println("MAKE IT PAST DUMMY")
-
-// // Generate transaction
-// parser, err := dtcli.Parser(ctx)
-// if err != nil {
-// fmt.Println("Error in parser of dummy TX: %w", err)
-// return err
-// }
-
-// fmt.Println("MAKE IT PAST Parser")
-
-// //TODO this is what tests our block validation
-// submit, tx, _, err := dcli.GenerateTransaction(ctx, parser, msg, &actions.ImportBlockMsg{
-// Fill: true,
-// }, factory, true)
-// if err != nil {
-// fmt.Println("Error in generation of verification TX: %w", err)
-// return err
-// }
-
-// fmt.Println("MAKE IT PAST generate")
-
-// if err := submit(ctx); err != nil {
-// fmt.Println("Error in submission of verification TX: %w", err)
-// return err
-// }
-
-// fmt.Println("MAKE IT PAST submit")
-
-// success, err := dtcli.WaitForTransaction(ctx, tx.ID())
-// if err != nil {
-// return err
-// }
-// printStatus(tx.ID(), success)
-// return nil
-// }
-
-// func submitDummy(
-// ctx context.Context,
-// cli *rpc.JSONRPCClient,
-// tcli *trpc.JSONRPCClient,
-// dest ed25519.PublicKey,
-// factory chain.AuthFactory,
-// ) error {
-// var (
-// logEmitted bool
-// txsSent uint64
-// )
-// for ctx.Err() == nil {
-// _, h, t, err := cli.Accepted(ctx)
-// if err != nil {
-// return err
-// }
-// underHeight := h < dummyHeightThreshold
-// if underHeight || time.Now().Unix()-t > dummyBlockAgeThreshold {
-// if underHeight && !logEmitted {
-// hutils.Outf(
-// "{{yellow}}waiting for snowman++ activation (needed for AWM)...{{/}}\n",
-// )
-// logEmitted = true
-// }
-// parser, err := tcli.Parser(ctx)
-// if err != nil {
-// return err
-// }
-// submit, tx, _, err := cli.GenerateTransaction(ctx, parser, nil, &actions.Transfer{
-// To: dest,
-// Value: txsSent + 1, // prevent duplicate txs
-// }, factory, false)
-// if err != nil {
-// return err
-// }
-// if err := submit(ctx); err != nil {
-// return err
-// }
-// if _, err := tcli.WaitForTransaction(ctx, tx.ID()); err != nil {
-// return err
-// }
-// txsSent++
-// time.Sleep(750 * time.Millisecond)
-// continue
-// }
-// if logEmitted {
-// hutils.Outf("{{yellow}}snowman++ activated{{/}}\n")
-// }
-// return nil
-// }
-// return ctx.Err()
-// }
-
-var importAssetCmd = &cobra.Command{
- Use: "import-asset",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
- currentChainID, _, factory, dcli, dscli, dtcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Select source
- _, uris, err := handler.Root().PromptChain("sourceChainID", set.Of(currentChainID))
- if err != nil {
- return err
- }
- scli := rpc.NewJSONRPCClient(uris[0])
-
- // Perform import
- return performImport(ctx, scli, dcli, dscli, dtcli, ids.Empty, factory)
- },
-}
-
-var exportAssetCmd = &cobra.Command{
- Use: "export-asset",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
- currentChainID, priv, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- // Select token to send
- assetID, err := handler.Root().PromptAsset("assetID", true)
- if err != nil {
- return err
- }
- _, decimals, balance, sourceChainID, err := handler.GetAssetInfo(ctx, tcli, priv.PublicKey(), assetID, true)
- if balance == 0 || err != nil {
- return err
- }
-
- // Select recipient
- recipient, err := handler.Root().PromptAddress("recipient")
- if err != nil {
- return err
- }
-
- // Select amount
- amount, err := handler.Root().PromptAmount("amount", decimals, balance, nil)
- if err != nil {
- return err
- }
-
- // Determine return
- var ret bool
- if sourceChainID != ids.Empty {
- ret = true
- }
-
- // Select reward
- reward, err := handler.Root().PromptAmount("reward", decimals, balance-amount, nil)
- if err != nil {
- return err
- }
-
- // Determine destination
- destination := sourceChainID
- if !ret {
- destination, _, err = handler.Root().PromptChain("destination", set.Of(currentChainID))
- if err != nil {
- return err
- }
- }
-
- // Determine if swap in
- swap, err := handler.Root().PromptBool("swap on import")
- if err != nil {
- return err
- }
- var (
- swapIn uint64
- assetOut ids.ID
- swapOut uint64
- swapExpiry int64
- )
- if swap {
- swapIn, err = handler.Root().PromptAmount("swap in", decimals, amount, nil)
- if err != nil {
- return err
- }
- assetOut, err = handler.Root().PromptAsset("asset out (on destination)", true)
- if err != nil {
- return err
- }
- uris, err := handler.Root().GetChain(destination)
- if err != nil {
- return err
- }
- networkID, _, _, err := cli.Network(ctx)
- if err != nil {
- return err
- }
- dcli := trpc.NewJSONRPCClient(uris[0], networkID, destination)
- _, decimals, _, _, err := handler.GetAssetInfo(ctx, dcli, priv.PublicKey(), assetOut, false)
- if err != nil {
- return err
- }
- swapOut, err = handler.Root().PromptAmount(
- "swap out (on destination, no decimals)",
- decimals,
- consts.MaxUint64,
- nil,
- )
- if err != nil {
- return err
- }
- swapExpiry, err = handler.Root().PromptTime("swap expiry")
- if err != nil {
- return err
- }
- }
-
- // Confirm action
- cont, err := handler.Root().PromptContinue()
- if !cont || err != nil {
- return err
- }
-
- // Generate transaction
- success, txID, err := sendAndWait(ctx, nil, &actions.ExportAsset{
- To: recipient,
- Asset: assetID,
- Value: amount,
- Return: ret,
- Reward: reward,
- SwapIn: swapIn,
- AssetOut: assetOut,
- SwapOut: swapOut,
- SwapExpiry: swapExpiry,
- Destination: destination,
- }, cli, scli, tcli, factory, true)
- if err != nil {
- return err
- }
- if !success {
- return errors.New("not successful")
- }
-
- // Perform import
- imp, err := handler.Root().PromptBool("perform import on destination")
- if err != nil {
- return err
- }
- if imp {
- uris, err := handler.Root().GetChain(destination)
- if err != nil {
- return err
- }
- networkID, _, _, err := cli.Network(ctx)
- if err != nil {
- return err
- }
- dscli, err := rpc.NewWebSocketClient(uris[0], rpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize)
- if err != nil {
- return err
- }
- if err := performImport(ctx, cli, rpc.NewJSONRPCClient(uris[0]), dscli, trpc.NewJSONRPCClient(uris[0], networkID, destination), txID, factory); err != nil {
- return err
- }
- }
-
- // Ask if user would like to switch to destination chain
- sw, err := handler.Root().PromptBool("switch default chain to destination")
- if err != nil {
- return err
- }
- if !sw {
- return nil
- }
- return handler.Root().StoreDefaultChain(destination)
- },
-}
-
-// var exportBlockCmd = &cobra.Command{
-// Use: "export-block",
-// RunE: func(*cobra.Command, []string) error {
-// ctx := context.Background()
-// _, priv, factory, cli, tcli, err := defaultActor()
-// if err != nil {
-// return err
-// }
-
-// //, set.Set[ids.ID]{currentChainID: {}}
-// sourceChainID, _, err := promptChainNoExclude("sourceChainID")
-
-// if err != nil {
-// return err
-// }
-
-// blockRoot, err := promptID("stateRoot")
-
-// if err != nil {
-// return err
-// }
-
-// parentRoot, err := promptID("parentRoot")
-
-// if err != nil {
-// return err
-// }
-
-// height, err := promptUint("Height")
-
-// if err != nil {
-// return err
-// }
-
-// tmstmp, err := promptTime("Timestamp")
-
-// if err != nil {
-// return err
-// }
-
-// // Determine destination
-// destination := sourceChainID
-// // if !ret {
-// // destination, _, err = promptChain("destination", set.Set[ids.ID]{currentChainID: {}})
-// // if err != nil {
-// // return err
-// // }
-// // }
-
-// // Determine if swap in
-
-// // Confirm action
-// cont, err := promptContinue()
-// if !cont || err != nil {
-// return err
-// }
-
-// // Attempt to send dummy transaction if needed
-// if err := submitDummy(ctx, cli, tcli, priv.PublicKey(), factory); err != nil {
-// return err
-// }
-
-// fmt.Println("GOT TO HERE")
-
-// // Generate transaction
-// parser, err := tcli.Parser(ctx)
-// if err != nil {
-// return err
-// }
-// submit, tx, _, err := cli.GenerateTransaction(ctx, parser, nil, &actions.ExportBlockMsg{
-// Prnt: parentRoot,
-// Tmstmp: tmstmp,
-// Hght: height,
-// StateRoot: blockRoot,
-// Destination: destination,
-// }, factory, false)
-// if err != nil {
-// fmt.Errorf("Error in generation of TX: %w", err)
-// return err
-// }
-// if err := submit(ctx); err != nil {
-// fmt.Errorf("Error in submit of TX: %w", err)
-// return err
-// }
-// success, err := tcli.WaitForTransaction(ctx, tx.ID())
-// if err != nil {
-// return err
-// }
-// printStatus(tx.ID(), success)
-
-// // Perform import
-// imp, err := promptBool("perform import on destination for block")
-// if err != nil {
-// return err
-// }
-// if imp {
-// uris, err := GetChain(destination)
-// if err != nil {
-// return err
-// }
-// if err := performImportMsg(ctx, cli, rpc.NewJSONRPCClient(uris[0]), trpc.NewJSONRPCClient(uris[0], destination), tx.ID(), priv, factory); err != nil {
-// return err
-// }
-// }
-
-// // Ask if user would like to switch to destination chain
-// sw, err := promptBool("switch default chain to destination")
-// if err != nil {
-// return err
-// }
-// if !sw {
-// return nil
-// }
-// return StoreDefault(defaultChainKey, destination[:])
-// },
-// }
diff --git a/cmd/token-cli/cmd/handler.go b/cmd/token-cli/cmd/handler.go
deleted file mode 100644
index c22c6ab..0000000
--- a/cmd/token-cli/cmd/handler.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package cmd
-
-import (
- "context"
-
- "github.com/AnomalyFi/hypersdk/cli"
- hconsts "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/pubsub"
- "github.com/AnomalyFi/hypersdk/rpc"
- hutils "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/consts"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/ids"
-)
-
-var _ cli.Controller = (*Controller)(nil)
-
-type Handler struct {
- h *cli.Handler
-}
-
-func NewHandler(h *cli.Handler) *Handler {
- return &Handler{h}
-}
-
-func (h *Handler) Root() *cli.Handler {
- return h.h
-}
-
-func (*Handler) GetAssetInfo(
- ctx context.Context,
- cli *trpc.JSONRPCClient,
- publicKey ed25519.PublicKey,
- assetID ids.ID,
- checkBalance bool,
-) ([]byte, uint8, uint64, ids.ID, error) {
- var sourceChainID ids.ID
- exists, symbol, decimals, metadata, supply, _, warp, err := cli.Asset(ctx, assetID, false)
- if err != nil {
- return nil, 0, 0, ids.Empty, err
- }
- if assetID != ids.Empty {
- if !exists {
- hutils.Outf("{{red}}%s does not exist{{/}}\n", assetID)
- hutils.Outf("{{red}}exiting...{{/}}\n")
- return nil, 0, 0, ids.Empty, nil
- }
- if warp {
- sourceChainID = ids.ID(metadata[hconsts.IDLen:])
- sourceAssetID := ids.ID(metadata[:hconsts.IDLen])
- hutils.Outf(
- "{{yellow}}sourceChainID:{{/}} %s {{yellow}}sourceAssetID:{{/}} %s {{yellow}}supply:{{/}} %d\n",
- sourceChainID,
- sourceAssetID,
- supply,
- )
- } else {
- hutils.Outf(
- "{{yellow}}symbol:{{/}} %s {{yellow}}decimals:{{/}} %d {{yellow}}metadata:{{/}} %s {{yellow}}supply:{{/}} %d {{yellow}}warp:{{/}} %t\n",
- symbol,
- decimals,
- metadata,
- supply,
- warp,
- )
- }
- }
- if !checkBalance {
- return symbol, decimals, 0, sourceChainID, nil
- }
- addr := utils.Address(publicKey)
- balance, err := cli.Balance(ctx, addr, assetID)
- if err != nil {
- return nil, 0, 0, ids.Empty, err
- }
- if balance == 0 {
- hutils.Outf("{{red}}balance:{{/}} 0 %s\n", assetID)
- hutils.Outf("{{red}}please send funds to %s{{/}}\n", addr)
- hutils.Outf("{{red}}exiting...{{/}}\n")
- } else {
- hutils.Outf(
- "{{yellow}}balance:{{/}} %s %s\n",
- hutils.FormatBalance(balance, decimals),
- symbol,
- )
- }
- return symbol, decimals, balance, sourceChainID, nil
-}
-
-func (h *Handler) DefaultActor() (
- ids.ID, ed25519.PrivateKey, *auth.ED25519Factory,
- *rpc.JSONRPCClient, *rpc.WebSocketClient, *trpc.JSONRPCClient, error,
-) {
- priv, err := h.h.GetDefaultKey(true)
- if err != nil {
- return ids.Empty, ed25519.EmptyPrivateKey, nil, nil, nil, nil, err
- }
- chainID, uris, err := h.h.GetDefaultChain(true)
- if err != nil {
- return ids.Empty, ed25519.EmptyPrivateKey, nil, nil, nil, nil, err
- }
- // For [defaultActor], we always send requests to the first returned URI.
- cli := rpc.NewJSONRPCClient(uris[0])
- networkID, _, _, err := cli.Network(context.TODO())
- if err != nil {
- return ids.Empty, ed25519.EmptyPrivateKey, nil, nil, nil, nil, err
- }
- scli, err := rpc.NewWebSocketClient(
- uris[0],
- rpc.DefaultHandshakeTimeout,
- pubsub.MaxPendingMessages,
- pubsub.MaxReadMessageSize,
- )
- if err != nil {
- return ids.Empty, ed25519.EmptyPrivateKey, nil, nil, nil, nil, err
- }
- return chainID, priv, auth.NewED25519Factory(priv), cli, scli,
- trpc.NewJSONRPCClient(
- uris[0],
- networkID,
- chainID,
- ), nil
-}
-
-type Controller struct {
- databasePath string
-}
-
-func NewController(databasePath string) *Controller {
- return &Controller{databasePath}
-}
-
-func (c *Controller) DatabasePath() string {
- return c.databasePath
-}
-
-func (*Controller) Symbol() string {
- return consts.Symbol
-}
-
-func (*Controller) Decimals() uint8 {
- return consts.Decimals
-}
-
-func (*Controller) Address(pk ed25519.PublicKey) string {
- return utils.Address(pk)
-}
-
-func (*Controller) ParseAddress(address string) (ed25519.PublicKey, error) {
- return utils.ParseAddress(address)
-}
diff --git a/cmd/token-cli/cmd/resolutions.go b/cmd/token-cli/cmd/resolutions.go
deleted file mode 100644
index 0a3e284..0000000
--- a/cmd/token-cli/cmd/resolutions.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package cmd
-
-import (
- "context"
- "fmt"
- "reflect"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/cli"
- "github.com/AnomalyFi/hypersdk/rpc"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/actions"
- "github.com/AnomalyFi/nodekit-seq/auth"
- tconsts "github.com/AnomalyFi/nodekit-seq/consts"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- tutils "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
-)
-
-// sendAndWait may not be used concurrently
-func sendAndWait(
- ctx context.Context, warpMsg *warp.Message, action chain.Action, cli *rpc.JSONRPCClient,
- scli *rpc.WebSocketClient, tcli *trpc.JSONRPCClient, factory chain.AuthFactory, printStatus bool,
-) (bool, ids.ID, error) {
- parser, err := tcli.Parser(ctx)
- if err != nil {
- return false, ids.Empty, err
- }
- _, tx, _, err := cli.GenerateTransaction(ctx, parser, warpMsg, action, factory)
- if err != nil {
- return false, ids.Empty, err
- }
-
- if err := scli.RegisterTx(tx); err != nil {
- return false, ids.Empty, err
- }
- var res *chain.Result
- for {
- txID, dErr, result, err := scli.ListenTx(ctx)
- if dErr != nil {
- return false, ids.Empty, dErr
- }
- if err != nil {
- return false, ids.Empty, err
- }
- if txID != tx.ID() {
- continue
- }
- res = result
- break
- }
- if printStatus {
- handler.Root().PrintStatus(tx.ID(), res.Success)
- }
- return res.Success, tx.ID(), nil
-}
-
-func handleTx(c *trpc.JSONRPCClient, tx *chain.Transaction, result *chain.Result) {
- summaryStr := string(result.Output)
- actor := auth.GetActor(tx.Auth)
- status := "⚠️"
- if result.Success {
- status = "✅"
- switch action := tx.Action.(type) {
- case *actions.CreateAsset:
- summaryStr = fmt.Sprintf("assetID: %s symbol: %s decimals: %d metadata: %s", tx.ID(), action.Symbol, action.Decimals, action.Metadata)
- case *actions.MintAsset:
- _, symbol, decimals, _, _, _, _, err := c.Asset(context.TODO(), action.Asset, true)
- if err != nil {
- utils.Outf("{{red}}could not fetch asset info:{{/}} %v", err)
- return
- }
- amountStr := utils.FormatBalance(action.Value, decimals)
- summaryStr = fmt.Sprintf("%s %s -> %s", amountStr, symbol, tutils.Address(action.To))
- case *actions.BurnAsset:
- summaryStr = fmt.Sprintf("%d %s -> 🔥", action.Value, action.Asset)
-
- case *actions.Transfer:
- _, symbol, decimals, _, _, _, _, err := c.Asset(context.TODO(), action.Asset, true)
- if err != nil {
- utils.Outf("{{red}}could not fetch asset info:{{/}} %v", err)
- return
- }
- amountStr := utils.FormatBalance(action.Value, decimals)
- summaryStr = fmt.Sprintf("%s %s -> %s", amountStr, symbol, tutils.Address(action.To))
- if len(action.Memo) > 0 {
- summaryStr += fmt.Sprintf(" (memo: %s)", action.Memo)
- }
- case *actions.ImportAsset:
- wm := tx.WarpMessage
- signers, _ := wm.Signature.NumSigners()
- wt, _ := actions.UnmarshalWarpTransfer(wm.Payload)
- summaryStr = fmt.Sprintf("source: %s signers: %d | ", wm.SourceChainID, signers)
- if wt.Return {
- summaryStr += fmt.Sprintf("%s %s -> %s (return: %t)", utils.FormatBalance(wt.Value, wt.Decimals), wt.Symbol, tutils.Address(wt.To), wt.Return)
- } else {
- summaryStr += fmt.Sprintf("%s %s (new: %s, original: %s) -> %s (return: %t)", utils.FormatBalance(wt.Value, wt.Decimals), wt.Symbol, actions.ImportedAssetID(wt.Asset, wm.SourceChainID), wt.Asset, tutils.Address(wt.To), wt.Return)
- }
- if wt.Reward > 0 {
- summaryStr += fmt.Sprintf(" | reward: %s", utils.FormatBalance(wt.Reward, wt.Decimals))
- }
- if wt.SwapIn > 0 {
- _, outSymbol, outDecimals, _, _, _, _, err := c.Asset(context.TODO(), wt.AssetOut, true)
- if err != nil {
- utils.Outf("{{red}}could not fetch asset info:{{/}} %v", err)
- return
- }
- summaryStr += fmt.Sprintf(" | swap in: %s %s swap out: %s %s expiry: %d fill: %t", utils.FormatBalance(wt.SwapIn, wt.Decimals), wt.Symbol, utils.FormatBalance(wt.SwapOut, outDecimals), outSymbol, wt.SwapExpiry, action.Fill)
- }
- case *actions.ExportAsset:
- wt, _ := actions.UnmarshalWarpTransfer(result.WarpMessage.Payload)
- summaryStr = fmt.Sprintf("destination: %s | ", action.Destination)
- var outputAssetID ids.ID
- if !action.Return {
- outputAssetID = actions.ImportedAssetID(action.Asset, result.WarpMessage.SourceChainID)
- summaryStr += fmt.Sprintf("%s %s (%s) -> %s (return: %t)", utils.FormatBalance(action.Value, wt.Decimals), wt.Symbol, action.Asset, tutils.Address(action.To), action.Return)
- } else {
- outputAssetID = wt.Asset
- summaryStr += fmt.Sprintf("%s %s (current: %s, original: %s) -> %s (return: %t)", utils.FormatBalance(action.Value, wt.Decimals), wt.Symbol, action.Asset, wt.Asset, tutils.Address(action.To), action.Return)
- }
- if wt.Reward > 0 {
- summaryStr += fmt.Sprintf(" | reward: %s", utils.FormatBalance(wt.Reward, wt.Decimals))
- }
- if wt.SwapIn > 0 {
- _, outSymbol, outDecimals, _, _, _, _, err := c.Asset(context.TODO(), wt.AssetOut, true)
- if err != nil {
- utils.Outf("{{red}}could not fetch asset info:{{/}} %v", err)
- return
- }
- summaryStr += fmt.Sprintf(" | swap in: %s %s (%s) swap out: %s %s expiry: %d", utils.FormatBalance(wt.SwapIn, wt.Decimals), wt.Symbol, outputAssetID, utils.FormatBalance(wt.SwapOut, outDecimals), outSymbol, wt.SwapExpiry)
- }
- }
- }
- utils.Outf(
- "%s {{yellow}}%s{{/}} {{yellow}}actor:{{/}} %s {{yellow}}summary (%s):{{/}} [%s] {{yellow}}fee (max %.2f%%):{{/}} %s %s {{yellow}}consumed:{{/}} [%s]\n",
- status,
- tx.ID(),
- tutils.Address(actor),
- reflect.TypeOf(tx.Action),
- summaryStr,
- float64(result.Fee)/float64(tx.Base.MaxFee)*100,
- utils.FormatBalance(result.Fee, tconsts.Decimals),
- tconsts.Symbol,
- cli.ParseDimensions(result.Consumed),
- )
-}
diff --git a/cmd/token-cli/cmd/spam.go b/cmd/token-cli/cmd/spam.go
deleted file mode 100644
index 502a2a4..0000000
--- a/cmd/token-cli/cmd/spam.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package cmd
-
-import (
- "context"
- crand "crypto/rand"
- "fmt"
- "math/rand"
-
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/pubsub"
- "github.com/AnomalyFi/hypersdk/rpc"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/actions"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/consts"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/spf13/cobra"
-)
-
-var spamCmd = &cobra.Command{
- Use: "spam",
- RunE: func(*cobra.Command, []string) error {
- return ErrMissingSubcommand
- },
-}
-
-var runSpamCmd = &cobra.Command{
- Use: "run",
- RunE: func(*cobra.Command, []string) error {
- var sclient *rpc.WebSocketClient
- var tclient *trpc.JSONRPCClient
- var maxFeeParsed *uint64
- if maxFee >= 0 {
- v := uint64(maxFee)
- maxFeeParsed = &v
- }
- return handler.Root().Spam(maxTxBacklog, maxFeeParsed, randomRecipient,
- func(uri string, networkID uint32, chainID ids.ID) {
- tclient = trpc.NewJSONRPCClient(uri, networkID, chainID)
- sc, err := rpc.NewWebSocketClient(uri, rpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize)
- if err != nil {
- panic(err)
- }
- sclient = sc
- },
- func(pk ed25519.PrivateKey) chain.AuthFactory {
- return auth.NewED25519Factory(pk)
- },
- func(choice int, address string) (uint64, error) {
- balance, err := tclient.Balance(context.TODO(), address, ids.Empty)
- if err != nil {
- return 0, err
- }
- utils.Outf(
- "%d) {{cyan}}address:{{/}} %s {{cyan}}balance:{{/}} %s %s\n",
- choice,
- address,
- utils.FormatBalance(balance, consts.Decimals),
- consts.Symbol,
- )
- return balance, err
- },
- func(ctx context.Context, chainID ids.ID) (chain.Parser, error) {
- return tclient.Parser(ctx)
- },
- func(pk ed25519.PublicKey, amount uint64) chain.Action {
- return &actions.Transfer{
- To: pk,
- Asset: ids.Empty,
- Value: amount,
- }
- },
- func(cli *rpc.JSONRPCClient, pk ed25519.PrivateKey) func(context.Context, uint64) error {
- return func(ictx context.Context, count uint64) error {
- _, _, err := sendAndWait(ictx, nil, &actions.Transfer{
- To: pk.PublicKey(),
- Value: count, // prevent duplicate txs
- }, cli, sclient, tclient, auth.NewED25519Factory(pk), false)
- return err
- }
- },
- )
- },
-}
-
-var runSpamSequencerMsgCmd = &cobra.Command{
- Use: "smsg",
- RunE: func(*cobra.Command, []string) error {
- ctx := context.Background()
-
- _, _, factory, cli, scli, tcli, err := handler.DefaultActor()
- if err != nil {
- return err
- }
-
- numAddress, err := handler.Root().PromptInt("how many addresses to generate?", 500)
- if err != nil {
- return err
- }
-
- numMsgs, err := handler.Root().PromptInt("how many msgs to send?", 10000)
- if err != nil {
- return err
- }
-
- for i := 0; i < numAddress; i++ {
- handler.Root().GenerateKey()
- }
-
- keys, err := handler.Root().GetKeys()
- if err != nil {
- return err
- }
-
- for _, k := range keys {
- for i := 0; i < numMsgs; i++ {
- data, err := randomBytes()
- fmt.Printf("data size(byte): %d\n", len(data))
- if err != nil {
- fmt.Println("error genrateing bytes, skipping")
- continue
- }
- _, _, err = sendAndWait(ctx, nil, &actions.SequencerMsg{
- Data: data,
- ChainId: []byte("nkit"),
- FromAddress: k.PublicKey(),
- }, cli, scli, tcli, factory, true)
- if err != nil {
- fmt.Println("error submitting tx, skipping")
- }
- }
- }
-
- return err
- },
-}
-
-func randomBytes() ([]byte, error) {
- // 256 kb
- numBytes := rand.Intn(256 * 1024)
-
- b := make([]byte, numBytes)
-
- _, err := crand.Read(b)
- if err != nil {
- return nil, err
- }
-
- return b, nil
-}
diff --git a/cmd/token-faucet/config/config.go b/cmd/token-faucet/config/config.go
deleted file mode 100644
index 8c43491..0000000
--- a/cmd/token-faucet/config/config.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package config
-
-import "github.com/AnomalyFi/hypersdk/crypto/ed25519"
-
-type Config struct {
- HTTPHost string `json:"host"`
- HTTPPort int `json:"port"`
-
- PrivateKeyBytes []byte `json:"privateKeyBytes"`
-
- TokenRPC string `json:"tokenRPC"`
- Amount uint64 `json:"amount"`
- StartDifficulty uint16 `json:"startDifficulty"`
- SolutionsPerSalt int `json:"solutionsPerSalt"`
- TargetDurationPerSalt int64 `json:"targetDurationPerSalt"` // seconds
-}
-
-func (c *Config) PrivateKey() ed25519.PrivateKey {
- return ed25519.PrivateKey(c.PrivateKeyBytes)
-}
diff --git a/cmd/token-faucet/demo.json b/cmd/token-faucet/demo.json
deleted file mode 100644
index 00df0ef..0000000
--- a/cmd/token-faucet/demo.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "host": "",
- "port": 9091,
- "privateKeyBytes": "933IN5CnG5Qls9+BtdOsfwWrSTSeKB3ephZ6EAWeLWwg/d/FFTpFKk8qrIvMghyxug45iZL76WowpCCOIVgNpw==",
- "tokenRPC": "http://127.0.0.1:62451/ext/bc/2mzRiBeC83RzGcanb5B35BXNSDMc59RxGoxF4g5REGAB5m5sPP",
- "amount": 100000000,
- "startDifficulty": 25,
- "solutionsPerSalt": 10,
- "targetDurationPerSalt": 300
-}
diff --git a/cmd/token-faucet/main.go b/cmd/token-faucet/main.go
deleted file mode 100644
index ac9408e..0000000
--- a/cmd/token-faucet/main.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package main
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "net"
- "os"
- "os/signal"
- "sync"
- "syscall"
- "time"
-
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/server"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/config"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/manager"
- frpc "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/rpc"
- tutils "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/snow/engine/common"
- "github.com/ava-labs/avalanchego/utils/logging"
- "go.uber.org/zap"
-)
-
-var (
- allowedOrigins = []string{"*"}
- allowedHosts = []string{"*"}
- shutdownTimeout = 30 * time.Second
- httpConfig = server.HTTPConfig{
- ReadTimeout: 30 * time.Second,
- ReadHeaderTimeout: 30 * time.Second,
- WriteTimeout: 30 * time.Second,
- IdleTimeout: 120 * time.Second,
- }
-)
-
-func fatal(l logging.Logger, msg string, fields ...zap.Field) {
- l.Fatal(msg, fields...)
- os.Exit(1)
-}
-
-func main() {
- logFactory := logging.NewFactory(logging.Config{
- DisplayLevel: logging.Info,
- })
- l, err := logFactory.Make("main")
- if err != nil {
- utils.Outf("{{red}}unable to initialize logger{{/}}: %v\n", err)
- os.Exit(1)
- }
- log := l
-
- // Load config
- if len(os.Args) != 2 {
- fatal(log, "no config file specified")
- }
- configPath := os.Args[1]
- rawConfig, err := os.ReadFile(configPath)
- if err != nil {
- fatal(log, "cannot open config file", zap.String("path", configPath), zap.Error(err))
- }
- var c config.Config
- if err := json.Unmarshal(rawConfig, &c); err != nil {
- fatal(log, "cannot read config file", zap.Error(err))
- }
-
- // Create private key
- if len(c.PrivateKeyBytes) == 0 {
- priv, err := ed25519.GeneratePrivateKey()
- if err != nil {
- fatal(log, "cannot generate private key", zap.Error(err))
- }
- c.PrivateKeyBytes = priv[:]
- b, err := json.MarshalIndent(&c, "", " ")
- if err != nil {
- fatal(log, "cannot marshal new config", zap.Error(err))
- }
- fi, err := os.Lstat(configPath)
- if err != nil {
- fatal(log, "cannot get file stats for config", zap.Error(err))
- }
- if err := os.WriteFile(configPath, b, fi.Mode().Perm()); err != nil {
- fatal(log, "cannot write new config", zap.Error(err))
- }
- log.Info("created new faucet address", zap.String("address", tutils.Address(priv.PublicKey())))
- } else {
- log.Info("loaded faucet address", zap.String("address", tutils.Address(c.PrivateKey().PublicKey())))
- }
-
- // Create server
- listenAddress := net.JoinHostPort(c.HTTPHost, fmt.Sprintf("%d", c.HTTPPort))
- listener, err := net.Listen("tcp", listenAddress)
- if err != nil {
- fatal(log, "cannot create listener", zap.Error(err))
- }
- srv, err := server.New("", log, listener, httpConfig, allowedOrigins, allowedHosts, shutdownTimeout)
- if err != nil {
- fatal(log, "cannot create server", zap.Error(err))
- }
-
- // Start manager
- manager, err := manager.New(log, &c)
- if err != nil {
- fatal(log, "cannot create manager", zap.Error(err))
- }
- go func() {
- if err := manager.Run(context.Background()); err != nil {
- log.Error("manager error", zap.Error(err))
- }
- }()
-
- // Add faucet handler
- faucetServer := frpc.NewJSONRPCServer(manager)
- handler, err := server.NewHandler(faucetServer, "faucet")
- if err != nil {
- fatal(log, "cannot create handler", zap.Error(err))
- }
- if err := srv.AddRoute(&common.HTTPHandler{
- LockOptions: common.NoLock,
- Handler: handler,
- }, &sync.RWMutex{}, "faucet", ""); err != nil {
- fatal(log, "cannot add facuet route", zap.Error(err))
- }
-
- // Start server
- sigs := make(chan os.Signal, 1)
- signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
- go func() {
- sig := <-sigs
- log.Info("triggering server shutdown", zap.Any("signal", sig))
- _ = srv.Shutdown()
- }()
- log.Info("server exited", zap.Error(srv.Dispatch()))
-}
diff --git a/cmd/token-faucet/manager/manager.go b/cmd/token-faucet/manager/manager.go
deleted file mode 100644
index f58c7ce..0000000
--- a/cmd/token-faucet/manager/manager.go
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package manager
-
-import (
- "bytes"
- "context"
- "errors"
- "sync"
- "time"
-
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/rpc"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/actions"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/challenge"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/config"
- "github.com/AnomalyFi/nodekit-seq/consts"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- tutils "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/utils/logging"
- "github.com/ava-labs/avalanchego/utils/set"
- "github.com/ava-labs/avalanchego/utils/timer"
- "go.uber.org/zap"
-)
-
-type Manager struct {
- log logging.Logger
- config *config.Config
-
- cli *rpc.JSONRPCClient
- tcli *trpc.JSONRPCClient
-
- factory *auth.ED25519Factory
-
- l sync.RWMutex
- t *timer.Timer
- lastRotation int64
- salt []byte
- difficulty uint16
- solutions set.Set[ids.ID]
-}
-
-func New(logger logging.Logger, config *config.Config) (*Manager, error) {
- ctx := context.TODO()
- cli := rpc.NewJSONRPCClient(config.TokenRPC)
- networkID, _, chainID, err := cli.Network(ctx)
- if err != nil {
- return nil, err
- }
- tcli := trpc.NewJSONRPCClient(config.TokenRPC, networkID, chainID)
- m := &Manager{log: logger, config: config, cli: cli, tcli: tcli, factory: auth.NewED25519Factory(config.PrivateKey())}
- m.lastRotation = time.Now().Unix()
- m.difficulty = m.config.StartDifficulty
- m.solutions = set.NewSet[ids.ID](m.config.SolutionsPerSalt)
- m.salt, err = challenge.New()
- if err != nil {
- return nil, err
- }
- addr := tutils.Address(m.config.PrivateKey().PublicKey())
- bal, err := tcli.Balance(ctx, addr, ids.Empty)
- if err != nil {
- return nil, err
- }
- m.log.Info("faucet initialized",
- zap.String("address", addr),
- zap.Uint16("difficulty", m.difficulty),
- zap.String("balance", utils.FormatBalance(bal, consts.Decimals)),
- )
- m.t = timer.NewTimer(m.updateDifficulty)
- return m, nil
-}
-
-func (m *Manager) Run(ctx context.Context) error {
- m.t.SetTimeoutIn(time.Duration(m.config.TargetDurationPerSalt) * time.Second)
- go m.t.Dispatch()
- <-ctx.Done()
- m.t.Stop()
- return ctx.Err()
-}
-
-func (m *Manager) updateDifficulty() {
- m.l.Lock()
- defer m.l.Unlock()
-
- // If time since [lastRotation] is within half of the target duration,
- // we attempted to update difficulty when we just reset during block processing.
- now := time.Now().Unix()
- if now-m.lastRotation < m.config.TargetDurationPerSalt/2 {
- return
- }
-
- // Decrease difficulty if there are no solutions in this period
- if m.difficulty > m.config.StartDifficulty && m.solutions.Len() == 0 {
- m.difficulty--
- m.log.Info("decreasing faucet difficulty", zap.Uint16("new difficulty", m.difficulty))
- }
- m.lastRotation = time.Now().Unix()
- salt, err := challenge.New()
- if err != nil {
- panic(err)
- }
- m.salt = salt
- m.solutions.Clear()
- m.t.SetTimeoutIn(time.Duration(m.config.TargetDurationPerSalt) * time.Second)
-}
-
-func (m *Manager) GetFaucetAddress(_ context.Context) (ed25519.PublicKey, error) {
- return m.config.PrivateKey().PublicKey(), nil
-}
-
-func (m *Manager) GetChallenge(_ context.Context) ([]byte, uint16, error) {
- m.l.RLock()
- defer m.l.RUnlock()
-
- return m.salt, m.difficulty, nil
-}
-
-func (m *Manager) sendFunds(ctx context.Context, destination ed25519.PublicKey, amount uint64) (ids.ID, uint64, error) {
- parser, err := m.tcli.Parser(ctx)
- if err != nil {
- return ids.Empty, 0, err
- }
- submit, tx, maxFee, err := m.cli.GenerateTransaction(ctx, parser, nil, &actions.Transfer{
- To: destination,
- Asset: ids.Empty,
- Value: amount,
- }, m.factory)
- if err != nil {
- return ids.Empty, 0, err
- }
- if amount < maxFee {
- m.log.Warn("abandoning airdrop because network fee is greater than amount", zap.String("maxFee", utils.FormatBalance(maxFee, consts.Decimals)))
- return ids.Empty, 0, errors.New("network fee too high")
- }
- addr := tutils.Address(m.config.PrivateKey().PublicKey())
- bal, err := m.tcli.Balance(ctx, addr, ids.Empty)
- if err != nil {
- return ids.Empty, 0, err
- }
- if bal < maxFee+amount {
- // This is a "best guess" heuristic for balance as there may be txs in-flight.
- m.log.Warn("faucet has insufficient funds", zap.String("balance", utils.FormatBalance(bal, consts.Decimals)))
- return ids.Empty, 0, errors.New("insufficient balance")
- }
- return tx.ID(), maxFee, submit(ctx)
-}
-
-func (m *Manager) SolveChallenge(ctx context.Context, solver ed25519.PublicKey, salt []byte, solution []byte) (ids.ID, uint64, error) {
- m.l.Lock()
- defer m.l.Unlock()
-
- // Ensure solution is valid
- if !bytes.Equal(m.salt, salt) {
- return ids.Empty, 0, errors.New("salt expired")
- }
- if !challenge.Verify(salt, solution, m.difficulty) {
- return ids.Empty, 0, errors.New("invalid solution")
- }
- solutionID := utils.ToID(solution)
- if m.solutions.Contains(solutionID) {
- return ids.Empty, 0, errors.New("duplicate solution")
- }
-
- // Issue transaction
- txID, maxFee, err := m.sendFunds(ctx, solver, m.config.Amount)
- if err != nil {
- return ids.Empty, 0, err
- }
- m.log.Info("fauceted funds",
- zap.Stringer("txID", txID),
- zap.String("max fee", utils.FormatBalance(maxFee, consts.Decimals)),
- zap.String("destination", tutils.Address(solver)),
- zap.String("amount", utils.FormatBalance(m.config.Amount, consts.Decimals)),
- )
- m.solutions.Add(solutionID)
-
- // Roll salt if hit expected solutions
- if m.solutions.Len() >= m.config.SolutionsPerSalt {
- m.difficulty++
- m.log.Info("increasing faucet difficulty", zap.Uint16("new difficulty", m.difficulty))
- m.lastRotation = time.Now().Unix()
- m.salt, err = challenge.New()
- if err != nil {
- // Should never happen
- return ids.Empty, 0, err
- }
- m.solutions.Clear()
- m.t.Cancel()
- m.t.SetTimeoutIn(time.Duration(m.config.TargetDurationPerSalt) * time.Second)
- }
- return txID, m.config.Amount, nil
-}
diff --git a/cmd/token-faucet/rpc/dependencies.go b/cmd/token-faucet/rpc/dependencies.go
deleted file mode 100644
index 0d4127f..0000000
--- a/cmd/token-faucet/rpc/dependencies.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package rpc
-
-import (
- "context"
-
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/ava-labs/avalanchego/ids"
-)
-
-type Manager interface {
- GetFaucetAddress(context.Context) (ed25519.PublicKey, error)
- GetChallenge(context.Context) ([]byte, uint16, error)
- SolveChallenge(context.Context, ed25519.PublicKey, []byte, []byte) (ids.ID, uint64, error)
-}
diff --git a/cmd/token-faucet/rpc/jsonrpc_client.go b/cmd/token-faucet/rpc/jsonrpc_client.go
deleted file mode 100644
index 38b215c..0000000
--- a/cmd/token-faucet/rpc/jsonrpc_client.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package rpc
-
-import (
- "context"
- "strings"
-
- "github.com/ava-labs/avalanchego/ids"
-
- "github.com/AnomalyFi/hypersdk/requester"
-)
-
-const (
- JSONRPCEndpoint = "/faucet"
-)
-
-type JSONRPCClient struct {
- requester *requester.EndpointRequester
-}
-
-// New creates a new client object.
-func NewJSONRPCClient(uri string) *JSONRPCClient {
- uri = strings.TrimSuffix(uri, "/")
- uri += JSONRPCEndpoint
- req := requester.New(uri, "faucet")
- return &JSONRPCClient{
- requester: req,
- }
-}
-
-func (cli *JSONRPCClient) FaucetAddress(ctx context.Context) (string, error) {
- resp := new(FaucetAddressReply)
- err := cli.requester.SendRequest(
- ctx,
- "faucetAddress",
- nil,
- resp,
- )
- return resp.Address, err
-}
-
-func (cli *JSONRPCClient) Challenge(ctx context.Context) ([]byte, uint16, error) {
- resp := new(ChallengeReply)
- err := cli.requester.SendRequest(
- ctx,
- "challenge",
- nil,
- resp,
- )
- return resp.Salt, resp.Difficulty, err
-}
-
-func (cli *JSONRPCClient) SolveChallenge(ctx context.Context, addr string, salt []byte, solution []byte) (ids.ID, uint64, error) {
- resp := new(SolveChallengeReply)
- err := cli.requester.SendRequest(
- ctx,
- "solveChallenge",
- &SolveChallengeArgs{
- Address: addr,
- Salt: salt,
- Solution: solution,
- },
- resp,
- )
- return resp.TxID, resp.Amount, err
-}
diff --git a/cmd/token-faucet/rpc/jsonrpc_server.go b/cmd/token-faucet/rpc/jsonrpc_server.go
deleted file mode 100644
index f379474..0000000
--- a/cmd/token-faucet/rpc/jsonrpc_server.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package rpc
-
-import (
- "net/http"
-
- "github.com/ava-labs/avalanchego/ids"
-
- "github.com/AnomalyFi/nodekit-seq/utils"
-)
-
-type JSONRPCServer struct {
- m Manager
-}
-
-func NewJSONRPCServer(m Manager) *JSONRPCServer {
- return &JSONRPCServer{m}
-}
-
-type FaucetAddressReply struct {
- Address string `json:"address"`
-}
-
-func (j *JSONRPCServer) FaucetAddress(req *http.Request, _ *struct{}, reply *FaucetAddressReply) (err error) {
- addr, err := j.m.GetFaucetAddress(req.Context())
- if err != nil {
- return err
- }
- reply.Address = utils.Address(addr)
- return nil
-}
-
-type ChallengeReply struct {
- Salt []byte `json:"salt"`
- Difficulty uint16 `json:"difficulty"`
-}
-
-func (j *JSONRPCServer) Challenge(req *http.Request, _ *struct{}, reply *ChallengeReply) (err error) {
- salt, difficulty, err := j.m.GetChallenge(req.Context())
- if err != nil {
- return err
- }
- reply.Salt = salt
- reply.Difficulty = difficulty
- return nil
-}
-
-type SolveChallengeArgs struct {
- Address string `json:"address"`
- Salt []byte `json:"salt"`
- Solution []byte `json:"solution"`
-}
-
-type SolveChallengeReply struct {
- TxID ids.ID `json:"txID"`
- Amount uint64 `json:"amount"`
-}
-
-func (j *JSONRPCServer) SolveChallenge(req *http.Request, args *SolveChallengeArgs, reply *SolveChallengeReply) error {
- addr, err := utils.ParseAddress(args.Address)
- if err != nil {
- return err
- }
- txID, amount, err := j.m.SolveChallenge(req.Context(), addr, args.Salt, args.Solution)
- if err != nil {
- return err
- }
- reply.TxID = txID
- reply.Amount = amount
- return nil
-}
diff --git a/cmd/token-feed/config/config.go b/cmd/token-feed/config/config.go
deleted file mode 100644
index 409e784..0000000
--- a/cmd/token-feed/config/config.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package config
-
-import (
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/nodekit-seq/utils"
-)
-
-type Config struct {
- HTTPHost string `json:"host"`
- HTTPPort int `json:"port"`
-
- TokenRPC string `json:"tokenRPC"`
-
- Recipient string `json:"recipient"`
- recipientPublicKey ed25519.PublicKey
-
- FeedSize int `json:"feedSize"`
- MinFee uint64 `json:"minFee"`
- FeeDelta uint64 `json:"feeDelta"`
- MessagesPerEpoch int `json:"messagesPerEpoch"`
- TargetDurationPerEpoch int64 `json:"targetDurationPerEpoch"` // seconds
-}
-
-func (c *Config) RecipientPublicKey() (ed25519.PublicKey, error) {
- if c.recipientPublicKey != ed25519.EmptyPublicKey {
- return c.recipientPublicKey, nil
- }
- pk, err := utils.ParseAddress(c.Recipient)
- if err == nil {
- c.recipientPublicKey = pk
- }
- return pk, err
-}
diff --git a/cmd/token-feed/demo.json b/cmd/token-feed/demo.json
deleted file mode 100644
index c3bc988..0000000
--- a/cmd/token-feed/demo.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "host": "",
- "port": 9092,
- "tokenRPC": "http://127.0.0.1:62451/ext/bc/2mzRiBeC83RzGcanb5B35BXNSDMc59RxGoxF4g5REGAB5m5sPP",
- "recipient": "token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp",
- "feedSize": 100,
- "minFee": 10000000,
- "feeDelta": 10000000,
- "messagesPerEpoch": 10,
- "targetDurationPerEpoch": 300
-}
diff --git a/cmd/token-feed/main.go b/cmd/token-feed/main.go
deleted file mode 100644
index 2aba59a..0000000
--- a/cmd/token-feed/main.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package main
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "net"
- "os"
- "os/signal"
- "sync"
- "syscall"
- "time"
-
- "github.com/AnomalyFi/hypersdk/server"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/config"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/manager"
- frpc "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/rpc"
- "github.com/ava-labs/avalanchego/snow/engine/common"
- "github.com/ava-labs/avalanchego/utils/logging"
- "go.uber.org/zap"
-)
-
-var (
- allowedOrigins = []string{"*"}
- allowedHosts = []string{"*"}
- shutdownTimeout = 30 * time.Second
- httpConfig = server.HTTPConfig{
- ReadTimeout: 30 * time.Second,
- ReadHeaderTimeout: 30 * time.Second,
- WriteTimeout: 30 * time.Second,
- IdleTimeout: 120 * time.Second,
- }
-)
-
-func fatal(l logging.Logger, msg string, fields ...zap.Field) {
- l.Fatal(msg, fields...)
- os.Exit(1)
-}
-
-func main() {
- logFactory := logging.NewFactory(logging.Config{
- DisplayLevel: logging.Info,
- })
- l, err := logFactory.Make("main")
- if err != nil {
- utils.Outf("{{red}}unable to initialize logger{{/}}: %v\n", err)
- os.Exit(1)
- }
- log := l
-
- // Load config
- if len(os.Args) != 2 {
- fatal(log, "no config file specified")
- }
- configPath := os.Args[1]
- rawConfig, err := os.ReadFile(configPath)
- if err != nil {
- fatal(log, "cannot open config file", zap.String("path", configPath), zap.Error(err))
- }
- var c config.Config
- if err := json.Unmarshal(rawConfig, &c); err != nil {
- fatal(log, "cannot read config file", zap.Error(err))
- }
-
- // Load recipient
- if _, err := c.RecipientPublicKey(); err != nil {
- fatal(log, "cannot parse recipient address", zap.Error(err))
- }
- log.Info("loaded feed recipient", zap.String("address", c.Recipient))
-
- // Create server
- listenAddress := net.JoinHostPort(c.HTTPHost, fmt.Sprintf("%d", c.HTTPPort))
- listener, err := net.Listen("tcp", listenAddress)
- if err != nil {
- fatal(log, "cannot create listener", zap.Error(err))
- }
- srv, err := server.New("", log, listener, httpConfig, allowedOrigins, allowedHosts, shutdownTimeout)
- if err != nil {
- fatal(log, "cannot create server", zap.Error(err))
- }
-
- // Start manager
- manager, err := manager.New(log, &c)
- if err != nil {
- fatal(log, "cannot create manager", zap.Error(err))
- }
- go func() {
- if err := manager.Run(context.Background()); err != nil {
- log.Error("manager error", zap.Error(err))
- }
- }()
-
- // Add feed handler
- feedServer := frpc.NewJSONRPCServer(manager)
- handler, err := server.NewHandler(feedServer, "feed")
- if err != nil {
- fatal(log, "cannot create handler", zap.Error(err))
- }
- if err := srv.AddRoute(&common.HTTPHandler{
- LockOptions: common.NoLock,
- Handler: handler,
- }, &sync.RWMutex{}, "feed", ""); err != nil {
- fatal(log, "cannot add facuet route", zap.Error(err))
- }
-
- // Start server
- sigs := make(chan os.Signal, 1)
- signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
- go func() {
- sig := <-sigs
- log.Info("triggering server shutdown", zap.Any("signal", sig))
- _ = srv.Shutdown()
- }()
- log.Info("server exited", zap.Error(srv.Dispatch()))
-}
diff --git a/cmd/token-feed/manager/manager.go b/cmd/token-feed/manager/manager.go
deleted file mode 100644
index f4541cd..0000000
--- a/cmd/token-feed/manager/manager.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package manager
-
-import (
- "context"
- "encoding/json"
- "sync"
- "time"
-
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/pubsub"
- "github.com/AnomalyFi/hypersdk/rpc"
- "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/actions"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/config"
- "github.com/AnomalyFi/nodekit-seq/consts"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- tutils "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/utils/logging"
- "github.com/ava-labs/avalanchego/utils/timer"
- "go.uber.org/zap"
- "golang.org/x/exp/slices"
-)
-
-type FeedContent struct {
- Message string `json:"message"`
- URL string `json:"url"`
-}
-
-type FeedObject struct {
- Address string `json:"address"`
- TxID ids.ID `json:"txID"`
- Timestamp int64 `json:"timestamp"`
- Fee uint64 `json:"fee"`
-
- Content *FeedContent `json:"content"`
-}
-
-type Manager struct {
- log logging.Logger
- config *config.Config
-
- tcli *trpc.JSONRPCClient
-
- l sync.RWMutex
- t *timer.Timer
- epochStart int64
- epochMessages int
- feeAmount uint64
-
- f sync.RWMutex
- // TODO: persist this
- feed []*FeedObject
-}
-
-func New(logger logging.Logger, config *config.Config) (*Manager, error) {
- ctx := context.TODO()
- cli := rpc.NewJSONRPCClient(config.TokenRPC)
- networkID, _, chainID, err := cli.Network(ctx)
- if err != nil {
- return nil, err
- }
- tcli := trpc.NewJSONRPCClient(config.TokenRPC, networkID, chainID)
- m := &Manager{log: logger, config: config, tcli: tcli, feed: []*FeedObject{}}
- m.epochStart = time.Now().Unix()
- m.feeAmount = m.config.MinFee
- m.log.Info("feed initialized",
- zap.String("address", m.config.Recipient),
- zap.String("fee", utils.FormatBalance(m.feeAmount, consts.Decimals)),
- )
- m.t = timer.NewTimer(m.updateFee)
- return m, nil
-}
-
-func (m *Manager) updateFee() {
- m.l.Lock()
- defer m.l.Unlock()
-
- // If time since [epochStart] is within half of the target duration,
- // we attempted to update fee when we just reset during block processing.
- now := time.Now().Unix()
- if now-m.epochStart < m.config.TargetDurationPerEpoch/2 {
- return
- }
-
- // Decrease fee if there are no messages in this epoch
- if m.feeAmount > m.config.MinFee && m.epochMessages == 0 {
- m.feeAmount -= m.config.FeeDelta
- m.log.Info("decreasing message fee", zap.Uint64("fee", m.feeAmount))
- }
- m.epochMessages = 0
- m.epochStart = time.Now().Unix()
- m.t.SetTimeoutIn(time.Duration(m.config.TargetDurationPerEpoch) * time.Second)
-}
-
-func (m *Manager) Run(ctx context.Context) error {
- // Start update timer
- m.t.SetTimeoutIn(time.Duration(m.config.TargetDurationPerEpoch) * time.Second)
- go m.t.Dispatch()
- defer m.t.Stop()
-
- parser, err := m.tcli.Parser(ctx)
- if err != nil {
- return err
- }
- recipientPubKey, err := m.config.RecipientPublicKey()
- if err != nil {
- return err
- }
- for ctx.Err() == nil { // handle WS client failure
- scli, err := rpc.NewWebSocketClient(m.config.TokenRPC, rpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize)
- if err != nil {
- m.log.Warn("unable to connect to RPC", zap.String("uri", m.config.TokenRPC), zap.Error(err))
- time.Sleep(10 * time.Second)
- continue
- }
- if err := scli.RegisterBlocks(); err != nil {
- m.log.Warn("unable to connect to register for blocks", zap.String("uri", m.config.TokenRPC), zap.Error(err))
- time.Sleep(10 * time.Second)
- continue
- }
- for ctx.Err() == nil {
- // Listen for blocks
- blk, results, _, _, err := scli.ListenBlock(ctx, parser)
- if err != nil {
- m.log.Warn("unable to listen for blocks", zap.Error(err))
- break
- }
-
- // Look for transactions to recipient
- for i, tx := range blk.Txs {
- action, ok := tx.Action.(*actions.Transfer)
- if !ok {
- continue
- }
- if action.To != recipientPubKey {
- continue
- }
- if len(action.Memo) == 0 {
- continue
- }
- result := results[i]
- from := auth.GetActor(tx.Auth)
- if !result.Success {
- m.log.Info("incoming message failed on-chain", zap.String("from", tutils.Address(from)), zap.String("memo", string(action.Memo)), zap.Uint64("payment", action.Value), zap.Uint64("required", m.feeAmount))
- continue
- }
- if action.Value < m.feeAmount {
- m.log.Info("incoming message did not pay enough", zap.String("from", tutils.Address(from)), zap.String("memo", string(action.Memo)), zap.Uint64("payment", action.Value), zap.Uint64("required", m.feeAmount))
- continue
- }
-
- var c FeedContent
- if err := json.Unmarshal(action.Memo, &c); err != nil {
- m.log.Info("incoming message could not be parsed", zap.String("from", tutils.Address(from)), zap.String("memo", string(action.Memo)), zap.Uint64("payment", action.Value), zap.Error(err))
- continue
- }
- if len(c.Message) == 0 {
- m.log.Info("incoming message was empty", zap.String("from", tutils.Address(from)), zap.String("memo", string(action.Memo)), zap.Uint64("payment", action.Value))
- continue
- }
- // TODO: pre-verify URLs
- addr := tutils.Address(from)
- m.l.Lock()
- m.f.Lock()
- m.feed = append([]*FeedObject{{
- Address: addr,
- TxID: tx.ID(),
- Timestamp: blk.Tmstmp,
- Fee: action.Value,
- Content: &c,
- }}, m.feed...)
- if len(m.feed) > m.config.FeedSize {
- // TODO: do this more efficiently using a rolling window
- m.feed[m.config.FeedSize] = nil // prevent memory leak
- m.feed = m.feed[:m.config.FeedSize]
- }
- m.epochMessages++
- if m.epochMessages >= m.config.MessagesPerEpoch {
- m.feeAmount += m.config.FeeDelta
- m.log.Info("increasing message fee", zap.Uint64("fee", m.feeAmount))
- m.epochMessages = 0
- m.epochStart = time.Now().Unix()
- m.t.Cancel()
- m.t.SetTimeoutIn(time.Duration(m.config.TargetDurationPerEpoch) * time.Second)
- }
- m.log.Info("received incoming message", zap.String("from", tutils.Address(from)), zap.String("memo", string(action.Memo)), zap.Uint64("payment", action.Value), zap.Uint64("new required", m.feeAmount))
- m.f.Unlock()
- m.l.Unlock()
- }
- }
- if ctx.Err() != nil {
- return ctx.Err()
- }
-
- // Sleep before trying again
- time.Sleep(10 * time.Second)
- }
- return ctx.Err()
-}
-
-func (m *Manager) GetFeedInfo(_ context.Context) (ed25519.PublicKey, uint64, error) {
- m.l.RLock()
- defer m.l.RUnlock()
-
- pk, err := m.config.RecipientPublicKey()
- return pk, m.feeAmount, err
-}
-
-// TODO: allow for multiple feeds
-func (m *Manager) GetFeed(context.Context) ([]*FeedObject, error) {
- m.f.RLock()
- defer m.f.RUnlock()
-
- return slices.Clone(m.feed), nil
-}
diff --git a/cmd/token-feed/rpc/dependencies.go b/cmd/token-feed/rpc/dependencies.go
deleted file mode 100644
index 3dfefa2..0000000
--- a/cmd/token-feed/rpc/dependencies.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package rpc
-
-import (
- "context"
-
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/manager"
-)
-
-type Manager interface {
- GetFeedInfo(context.Context) (ed25519.PublicKey, uint64, error)
- GetFeed(context.Context) ([]*manager.FeedObject, error)
-}
diff --git a/cmd/token-feed/rpc/jsonrpc_client.go b/cmd/token-feed/rpc/jsonrpc_client.go
deleted file mode 100644
index 06aa00a..0000000
--- a/cmd/token-feed/rpc/jsonrpc_client.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package rpc
-
-import (
- "context"
- "strings"
-
- "github.com/AnomalyFi/hypersdk/requester"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/manager"
-)
-
-const (
- JSONRPCEndpoint = "/feed"
-)
-
-type JSONRPCClient struct {
- requester *requester.EndpointRequester
-}
-
-// New creates a new client object.
-func NewJSONRPCClient(uri string) *JSONRPCClient {
- uri = strings.TrimSuffix(uri, "/")
- uri += JSONRPCEndpoint
- req := requester.New(uri, "feed")
- return &JSONRPCClient{
- requester: req,
- }
-}
-
-func (cli *JSONRPCClient) FeedInfo(ctx context.Context) (string, uint64, error) {
- resp := new(FeedInfoReply)
- err := cli.requester.SendRequest(
- ctx,
- "feedInfo",
- nil,
- resp,
- )
- return resp.Address, resp.Fee, err
-}
-
-func (cli *JSONRPCClient) Feed(ctx context.Context) ([]*manager.FeedObject, error) {
- resp := new(FeedReply)
- err := cli.requester.SendRequest(
- ctx,
- "feed",
- nil,
- resp,
- )
- return resp.Feed, err
-}
diff --git a/cmd/token-feed/rpc/jsonrpc_server.go b/cmd/token-feed/rpc/jsonrpc_server.go
deleted file mode 100644
index 509bd0b..0000000
--- a/cmd/token-feed/rpc/jsonrpc_server.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package rpc
-
-import (
- "net/http"
-
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/manager"
- "github.com/AnomalyFi/nodekit-seq/utils"
-)
-
-type JSONRPCServer struct {
- m Manager
-}
-
-func NewJSONRPCServer(m Manager) *JSONRPCServer {
- return &JSONRPCServer{m}
-}
-
-type FeedInfoReply struct {
- Address string `json:"address"`
- Fee uint64 `json:"fee"`
-}
-
-func (j *JSONRPCServer) FeedInfo(req *http.Request, _ *struct{}, reply *FeedInfoReply) (err error) {
- addr, fee, err := j.m.GetFeedInfo(req.Context())
- if err != nil {
- return err
- }
- reply.Address = utils.Address(addr)
- reply.Fee = fee
- return nil
-}
-
-type FeedReply struct {
- Feed []*manager.FeedObject `json:"feed"`
-}
-
-func (j *JSONRPCServer) Feed(req *http.Request, _ *struct{}, reply *FeedReply) (err error) {
- feed, err := j.m.GetFeed(req.Context())
- if err != nil {
- return err
- }
- reply.Feed = feed
- return nil
-}
diff --git a/cmd/token-wallet/.gitignore b/cmd/token-wallet/.gitignore
deleted file mode 100644
index aef31e7..0000000
--- a/cmd/token-wallet/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-build/bin
-node_modules
-frontend/dist
-.token-wallet
-token-wallet.zip
diff --git a/cmd/token-wallet/README.md b/cmd/token-wallet/README.md
deleted file mode 100644
index cb5b5fc..0000000
--- a/cmd/token-wallet/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Token Wallet
-
-## Configuration
-If you want to override the default configuration, place a `config.json` file at `~/.token-wallet/config.json`.
-
-## Live Development
-To run in live development mode, run `./scripts/dev.sh` in the project directory. This will run a Vite development
-server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser
-and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect
-to this in your browser, and you can call your Go code from devtools.
-
-## Release
-To build a distributable package for MacOS, run `./scripts/build.sh`.
diff --git a/cmd/token-wallet/app.go b/cmd/token-wallet/app.go
deleted file mode 100644
index 03973a1..0000000
--- a/cmd/token-wallet/app.go
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package main
-
-import (
- "context"
- "runtime/debug"
-
- "github.com/AnomalyFi/nodekit-seq/cmd/token-wallet/backend"
-
- "github.com/wailsapp/wails/v2/pkg/logger"
- "github.com/wailsapp/wails/v2/pkg/runtime"
-)
-
-type App struct {
- ctx context.Context
- log logger.Logger
- b *backend.Backend
-}
-
-// NewApp creates a new App application struct
-func NewApp() *App {
- return &App{
- log: logger.NewDefaultLogger(),
- }
-}
-
-// startup is called when the app starts. The context is saved
-// so we can call the runtime methods
-func (a *App) startup(ctx context.Context) {
- a.ctx = ctx
- a.b = backend.New(func(err error) {
- a.log.Error(err.Error())
- runtime.Quit(ctx)
- })
- if err := a.b.Start(ctx); err != nil {
- a.log.Error(err.Error())
- runtime.Quit(ctx)
- }
-}
-
-// shutdown is called after the frontend is destroyed.
-func (a *App) shutdown(ctx context.Context) {
- if err := a.b.Shutdown(ctx); err != nil {
- a.log.Error(err.Error())
- }
-}
-
-func (a *App) GetLatestBlocks() []*backend.BlockInfo {
- return a.b.GetLatestBlocks()
-}
-
-func (a *App) GetTransactionStats() []*backend.GenericInfo {
- return a.b.GetTransactionStats()
-}
-
-func (a *App) GetAccountStats() []*backend.GenericInfo {
- return a.b.GetAccountStats()
-}
-
-func (a *App) GetUnitPrices() []*backend.GenericInfo {
- return a.b.GetUnitPrices()
-}
-
-func (a *App) GetChainID() string {
- return a.b.GetChainID()
-}
-
-func (a *App) GetMyAssets() []*backend.AssetInfo {
- return a.b.GetMyAssets()
-}
-
-func (a *App) GetBalance() ([]*backend.BalanceInfo, error) {
- return a.b.GetBalance()
-}
-
-func (a *App) CreateAsset(symbol string, decimals string, metadata string) error {
- return a.b.CreateAsset(symbol, decimals, metadata)
-}
-
-func (a *App) MintAsset(asset string, address string, amount string) error {
- return a.b.MintAsset(asset, address, amount)
-}
-
-func (a *App) Transfer(asset string, address string, amount string, memo string) error {
- return a.b.Transfer(asset, address, amount, memo)
-}
-
-func (a *App) GetAddress() string {
- return a.b.GetAddress()
-}
-
-func (a *App) GetTransactions() *backend.Transactions {
- return a.b.GetTransactions()
-}
-
-func (a *App) StartFaucetSearch() (*backend.FaucetSearchInfo, error) {
- return a.b.StartFaucetSearch()
-}
-
-func (a *App) GetFaucetSolutions() *backend.FaucetSolutions {
- return a.b.GetFaucetSolutions()
-}
-
-func (a *App) GetAddressBook() []*backend.AddressInfo {
- return a.b.GetAddressBook()
-}
-
-func (a *App) AddAddressBook(name string, address string) error {
- return a.b.AddAddressBook(name, address)
-}
-
-func (a *App) GetAllAssets() []*backend.AssetInfo {
- return a.b.GetAllAssets()
-}
-
-func (a *App) AddAsset(asset string) error {
- return a.b.AddAsset(asset)
-}
-
-// func (a *App) GetMyOrders() ([]*backend.Order, error) {
-// return a.b.GetMyOrders()
-// }
-
-// func (a *App) GetOrders(pair string) ([]*backend.Order, error) {
-// return a.b.GetOrders(pair)
-// }
-
-// func (a *App) CreateOrder(assetIn string, inTick string, assetOut string, outTick string, supply string) error {
-// return a.b.CreateOrder(assetIn, inTick, assetOut, outTick, supply)
-// }
-
-// func (a *App) FillOrder(orderID string, orderOwner string, assetIn string, inTick string, assetOut string, amount string) error {
-// return a.b.FillOrder(orderID, orderOwner, assetIn, inTick, assetOut, amount)
-// }
-
-// func (a *App) CloseOrder(orderID string, assetOut string) error {
-// return a.b.CloseOrder(orderID, assetOut)
-// }
-
-func (a *App) GetFeedInfo() (*backend.FeedInfo, error) {
- return a.b.GetFeedInfo()
-}
-
-func (a *App) GetFeed() ([]*backend.FeedObject, error) {
- return a.b.GetFeed()
-}
-
-func (a *App) Message(message string, url string) error {
- return a.b.Message(message, url)
-}
-
-func (a *App) OpenLink(url string) {
- runtime.BrowserOpenURL(a.ctx, url)
-}
-
-func (a *App) GetCommitHash() string {
- if info, ok := debug.ReadBuildInfo(); ok {
- for _, setting := range info.Settings {
- if setting.Key == "vcs.revision" {
- return setting.Value
- }
- }
- }
- return ""
-}
diff --git a/cmd/token-wallet/backend/backend.go b/cmd/token-wallet/backend/backend.go
deleted file mode 100644
index 40d95ec..0000000
--- a/cmd/token-wallet/backend/backend.go
+++ /dev/null
@@ -1,1006 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package backend
-
-import (
- "context"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "math"
- "net"
- "net/http"
- "net/url"
- "os"
- "path"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "github.com/AnomalyFi/hypersdk/chain"
- hcli "github.com/AnomalyFi/hypersdk/cli"
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/pubsub"
- "github.com/AnomalyFi/hypersdk/rpc"
- hutils "github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/hypersdk/window"
- "github.com/AnomalyFi/nodekit-seq/actions"
- "github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/challenge"
- frpc "github.com/AnomalyFi/nodekit-seq/cmd/token-faucet/rpc"
- "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/manager"
- ferpc "github.com/AnomalyFi/nodekit-seq/cmd/token-feed/rpc"
- tconsts "github.com/AnomalyFi/nodekit-seq/consts"
- trpc "github.com/AnomalyFi/nodekit-seq/rpc"
- "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/cache"
- "github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/utils/set"
- "github.com/ava-labs/avalanchego/utils/units"
-)
-
-const (
- databaseFolder = ".token-wallet/db"
- configFile = ".token-wallet/config.json"
-)
-
-type Backend struct {
- ctx context.Context
- fatal func(error)
-
- s *Storage
- c *Config
-
- priv ed25519.PrivateKey
- factory *auth.ED25519Factory
- pk ed25519.PublicKey
- addr string
-
- cli *rpc.JSONRPCClient
- chainID ids.ID
- scli *rpc.WebSocketClient
- tcli *trpc.JSONRPCClient
- parser chain.Parser
- fcli *frpc.JSONRPCClient
- fecli *ferpc.JSONRPCClient
-
- blockLock sync.Mutex
- blocks []*BlockInfo
- stats []*TimeStat
- currentStat *TimeStat
-
- txAlertLock sync.Mutex
- transactionAlerts []*Alert
-
- searchLock sync.Mutex
- search *FaucetSearchInfo
- searchAlerts []*Alert
-
- htmlCache *cache.LRU[string, *HTMLMeta]
- urlQueue chan string
-}
-
-// NewApp creates a new App application struct
-func New(fatal func(error)) *Backend {
- return &Backend{
- fatal: fatal,
-
- blocks: []*BlockInfo{},
- stats: []*TimeStat{},
- transactionAlerts: []*Alert{},
- searchAlerts: []*Alert{},
- htmlCache: &cache.LRU[string, *HTMLMeta]{Size: 128},
- urlQueue: make(chan string, 128),
- }
-}
-
-func (b *Backend) Start(ctx context.Context) error {
- b.ctx = ctx
- homeDir, err := os.UserHomeDir()
- if err != nil {
- return err
- }
-
- // Open storage
- databasePath := path.Join(homeDir, databaseFolder)
- s, err := OpenStorage(databasePath)
- if err != nil {
- return err
- }
- b.s = s
-
- // Generate key
- key, err := s.GetKey()
- if err != nil {
- return err
- }
- if key == ed25519.EmptyPrivateKey {
- // TODO: encrypt key
- priv, err := ed25519.GeneratePrivateKey()
- if err != nil {
- return err
- }
- if err := s.StoreKey(priv); err != nil {
- return err
- }
- key = priv
- }
- b.priv = key
- b.factory = auth.NewED25519Factory(b.priv)
- b.pk = b.priv.PublicKey()
- b.addr = utils.Address(b.pk)
- if err := b.AddAddressBook("Me", b.addr); err != nil {
- return err
- }
- if err := b.s.StoreAsset(ids.Empty, false); err != nil {
- return err
- }
-
- // Open config
- configPath := path.Join(homeDir, configFile)
- rawConifg, err := os.ReadFile(configPath)
- if err != nil {
- // TODO: replace with DEVNET
- b.c = &Config{
- TokenRPC: "http://54.190.240.186:9090",
- FaucetRPC: "http://54.190.240.186:9091",
- SearchCores: 4,
- FeedRPC: "http://54.190.240.186:9092",
- }
- } else {
- var config Config
- if err := json.Unmarshal(rawConifg, &config); err != nil {
- return err
- }
- b.c = &config
- }
-
- // Create clients
- b.cli = rpc.NewJSONRPCClient(b.c.TokenRPC)
- networkID, _, chainID, err := b.cli.Network(b.ctx)
- if err != nil {
- return err
- }
- b.chainID = chainID
- scli, err := rpc.NewWebSocketClient(b.c.TokenRPC, rpc.DefaultHandshakeTimeout, pubsub.MaxPendingMessages, pubsub.MaxReadMessageSize)
- if err != nil {
- return err
- }
- b.scli = scli
- b.tcli = trpc.NewJSONRPCClient(b.c.TokenRPC, networkID, chainID)
- parser, err := b.tcli.Parser(b.ctx)
- if err != nil {
- return err
- }
- b.parser = parser
- b.fcli = frpc.NewJSONRPCClient(b.c.FaucetRPC)
- b.fecli = ferpc.NewJSONRPCClient(b.c.FeedRPC)
-
- // Start fetching blocks
- go b.collectBlocks()
- go b.parseURLs()
- return nil
-}
-
-func (b *Backend) collectBlocks() {
- if err := b.scli.RegisterBlocks(); err != nil {
- b.fatal(err)
- return
- }
-
- var (
- start time.Time
- lastBlock int64
- tpsWindow = window.Window{}
- )
- for b.ctx.Err() == nil {
- blk, results, prices, _, err := b.scli.ListenBlock(b.ctx, b.parser)
- if err != nil {
- b.fatal(err)
- return
- }
- consumed := chain.Dimensions{}
- failTxs := 0
- for i, result := range results {
- nconsumed, err := chain.Add(consumed, result.Consumed)
- if err != nil {
- b.fatal(err)
- return
- }
- consumed = nconsumed
-
- tx := blk.Txs[i]
- actor := auth.GetActor(tx.Auth)
- if !result.Success {
- failTxs++
- }
-
- // We should exit action parsing as soon as possible
- switch action := tx.Action.(type) {
- case *actions.Transfer:
- if actor != b.pk && action.To != b.pk {
- continue
- }
-
- _, symbol, decimals, _, _, owner, _, err := b.tcli.Asset(b.ctx, action.Asset, true)
- if err != nil {
- b.fatal(err)
- return
- }
- txInfo := &TransactionInfo{
- ID: tx.ID().String(),
- Size: fmt.Sprintf("%.2fKB", float64(tx.Size())/units.KiB),
- Success: result.Success,
- Timestamp: blk.Tmstmp,
- Actor: utils.Address(actor),
- Type: "Transfer",
- Units: hcli.ParseDimensions(result.Consumed),
- Fee: fmt.Sprintf("%s %s", hutils.FormatBalance(result.Fee, tconsts.Decimals), tconsts.Symbol),
- }
- if result.Success {
- txInfo.Summary = fmt.Sprintf("%s %s -> %s", hutils.FormatBalance(action.Value, decimals), symbol, utils.Address(action.To))
- if len(action.Memo) > 0 {
- txInfo.Summary += fmt.Sprintf(" (memo: %s)", action.Memo)
- }
- } else {
- txInfo.Summary = string(result.Output)
- }
- if action.To == b.pk {
- if actor != b.pk && result.Success {
- b.txAlertLock.Lock()
- b.transactionAlerts = append(b.transactionAlerts, &Alert{"info", fmt.Sprintf("Received %s %s from Transfer", hutils.FormatBalance(action.Value, decimals), symbol)})
- b.txAlertLock.Unlock()
- }
- hasAsset, err := b.s.HasAsset(action.Asset)
- if err != nil {
- b.fatal(err)
- return
- }
- if !hasAsset {
- if err := b.s.StoreAsset(action.Asset, b.addr == owner); err != nil {
- b.fatal(err)
- return
- }
- }
- if err := b.s.StoreTransaction(txInfo); err != nil {
- b.fatal(err)
- return
- }
- } else if actor == b.pk {
- if err := b.s.StoreTransaction(txInfo); err != nil {
- b.fatal(err)
- return
- }
- }
- case *actions.CreateAsset:
- if actor != b.pk {
- continue
- }
-
- if err := b.s.StoreAsset(tx.ID(), true); err != nil {
- b.fatal(err)
- return
- }
- txInfo := &TransactionInfo{
- ID: tx.ID().String(),
- Size: fmt.Sprintf("%.2fKB", float64(tx.Size())/units.KiB),
- Success: result.Success,
- Timestamp: blk.Tmstmp,
- Actor: utils.Address(actor),
- Type: "CreateAsset",
- Units: hcli.ParseDimensions(result.Consumed),
- Fee: fmt.Sprintf("%s %s", hutils.FormatBalance(result.Fee, tconsts.Decimals), tconsts.Symbol),
- }
- if result.Success {
- txInfo.Summary = fmt.Sprintf("assetID: %s symbol: %s decimals: %d metadata: %s", tx.ID(), action.Symbol, action.Decimals, action.Metadata)
- } else {
- txInfo.Summary = string(result.Output)
- }
- if err := b.s.StoreTransaction(txInfo); err != nil {
- b.fatal(err)
- return
- }
- case *actions.MintAsset:
- if actor != b.pk && action.To != b.pk {
- continue
- }
-
- _, symbol, decimals, _, _, owner, _, err := b.tcli.Asset(b.ctx, action.Asset, true)
- if err != nil {
- b.fatal(err)
- return
- }
- txInfo := &TransactionInfo{
- ID: tx.ID().String(),
- Timestamp: blk.Tmstmp,
- Size: fmt.Sprintf("%.2fKB", float64(tx.Size())/units.KiB),
- Success: result.Success,
- Actor: utils.Address(actor),
- Type: "Mint",
- Units: hcli.ParseDimensions(result.Consumed),
- Fee: fmt.Sprintf("%s %s", hutils.FormatBalance(result.Fee, tconsts.Decimals), tconsts.Symbol),
- }
- if result.Success {
- txInfo.Summary = fmt.Sprintf("%s %s -> %s", hutils.FormatBalance(action.Value, decimals), symbol, utils.Address(action.To))
- } else {
- txInfo.Summary = string(result.Output)
- }
- if action.To == b.pk {
- if actor != b.pk && result.Success {
- b.txAlertLock.Lock()
- b.transactionAlerts = append(b.transactionAlerts, &Alert{"info", fmt.Sprintf("Received %s %s from Mint", hutils.FormatBalance(action.Value, decimals), symbol)})
- b.txAlertLock.Unlock()
- }
- hasAsset, err := b.s.HasAsset(action.Asset)
- if err != nil {
- b.fatal(err)
- return
- }
- if !hasAsset {
- if err := b.s.StoreAsset(action.Asset, b.addr == owner); err != nil {
- b.fatal(err)
- return
- }
- }
- if err := b.s.StoreTransaction(txInfo); err != nil {
- b.fatal(err)
- return
- }
- } else if actor == b.pk {
- if err := b.s.StoreTransaction(txInfo); err != nil {
- b.fatal(err)
- return
- }
- }
- }
- }
- now := time.Now()
- if start.IsZero() {
- start = now
- }
- bi := &BlockInfo{}
- if lastBlock != 0 {
- since := now.Unix() - lastBlock
- newWindow, err := window.Roll(tpsWindow, int(since))
- if err != nil {
- b.fatal(err)
- return
- }
- tpsWindow = newWindow
- window.Update(&tpsWindow, window.WindowSliceSize-consts.Uint64Len, uint64(len(blk.Txs)))
- runningDuration := time.Since(start)
- tpsDivisor := math.Min(window.WindowSize, runningDuration.Seconds())
- bi.TPS = fmt.Sprintf("%.2f", float64(window.Sum(tpsWindow))/tpsDivisor)
- bi.Latency = time.Now().UnixMilli() - blk.Tmstmp
- } else {
- window.Update(&tpsWindow, window.WindowSliceSize-consts.Uint64Len, uint64(len(blk.Txs)))
- bi.TPS = "0.0"
- }
- blkID, err := blk.ID()
- if err != nil {
- b.fatal(err)
- return
- }
- bi.Timestamp = blk.Tmstmp
- bi.ID = blkID.String()
- bi.Height = blk.Hght
- bi.Size = fmt.Sprintf("%.2fKB", float64(blk.Size())/units.KiB)
- bi.Consumed = hcli.ParseDimensions(consumed)
- bi.Prices = hcli.ParseDimensions(prices)
- bi.StateRoot = blk.StateRoot.String()
- bi.FailTxs = failTxs
- bi.Txs = len(blk.Txs)
-
- // TODO: find a more efficient way to support this
- b.blockLock.Lock()
- b.blocks = append([]*BlockInfo{bi}, b.blocks...)
- if len(b.blocks) > 100 {
- b.blocks = b.blocks[:100]
- }
- sTime := blk.Tmstmp / consts.MillisecondsPerSecond
- if b.currentStat != nil && b.currentStat.Timestamp != sTime {
- b.stats = append(b.stats, b.currentStat)
- b.currentStat = nil
- }
- if b.currentStat == nil {
- b.currentStat = &TimeStat{Timestamp: sTime, Accounts: set.Set[string]{}}
- }
- b.currentStat.Transactions += bi.Txs
- for _, tx := range blk.Txs {
- b.currentStat.Accounts.Add(string(tx.Auth.Payer()))
- }
- b.currentStat.Prices = prices
- snow := time.Now().Unix()
- newStart := 0
- for i, item := range b.stats {
- newStart = i
- if snow-item.Timestamp < 120 {
- break
- }
- }
- b.stats = b.stats[newStart:]
- b.blockLock.Unlock()
-
- lastBlock = now.Unix()
- }
-}
-
-func (b *Backend) Shutdown(context.Context) error {
- _ = b.scli.Close()
- return b.s.Close()
-}
-
-func (b *Backend) GetLatestBlocks() []*BlockInfo {
- b.blockLock.Lock()
- defer b.blockLock.Unlock()
-
- return b.blocks
-}
-
-func (b *Backend) GetTransactionStats() []*GenericInfo {
- b.blockLock.Lock()
- defer b.blockLock.Unlock()
-
- info := make([]*GenericInfo, len(b.stats))
- for i := 0; i < len(b.stats); i++ {
- info[i] = &GenericInfo{b.stats[i].Timestamp, uint64(b.stats[i].Transactions), ""}
- }
- return info
-}
-
-func (b *Backend) GetAccountStats() []*GenericInfo {
- b.blockLock.Lock()
- defer b.blockLock.Unlock()
-
- info := make([]*GenericInfo, len(b.stats))
- for i := 0; i < len(b.stats); i++ {
- info[i] = &GenericInfo{b.stats[i].Timestamp, uint64(b.stats[i].Accounts.Len()), ""}
- }
- return info
-}
-
-func (b *Backend) GetUnitPrices() []*GenericInfo {
- b.blockLock.Lock()
- defer b.blockLock.Unlock()
-
- info := make([]*GenericInfo, 0, len(b.stats)*chain.FeeDimensions)
- for i := 0; i < len(b.stats); i++ {
- info = append(info, &GenericInfo{b.stats[i].Timestamp, b.stats[i].Prices[0], "Bandwidth"})
- info = append(info, &GenericInfo{b.stats[i].Timestamp, b.stats[i].Prices[1], "Compute"})
- info = append(info, &GenericInfo{b.stats[i].Timestamp, b.stats[i].Prices[2], "Storage [Read]"})
- info = append(info, &GenericInfo{b.stats[i].Timestamp, b.stats[i].Prices[3], "Storage [Create]"})
- info = append(info, &GenericInfo{b.stats[i].Timestamp, b.stats[i].Prices[4], "Storage [Modify]"})
- }
- return info
-}
-
-func (b *Backend) GetChainID() string {
- return b.chainID.String()
-}
-
-func (b *Backend) GetMyAssets() []*AssetInfo {
- assets := []*AssetInfo{}
- assetIDs, owned, err := b.s.GetAssets()
- if err != nil {
- b.fatal(err)
- return nil
- }
- for i, asset := range assetIDs {
- if !owned[i] {
- continue
- }
- _, symbol, decimals, metadata, supply, owner, _, err := b.tcli.Asset(b.ctx, asset, false)
- if err != nil {
- b.fatal(err)
- return nil
- }
- strAsset := asset.String()
- assets = append(assets, &AssetInfo{
- ID: asset.String(),
- Symbol: string(symbol),
- Decimals: int(decimals),
- Metadata: string(metadata),
- Supply: hutils.FormatBalance(supply, decimals),
- Creator: owner,
- StrSymbol: fmt.Sprintf("%s [%s..%s]", symbol, strAsset[:3], strAsset[len(strAsset)-3:]),
- })
- }
- return assets
-}
-
-func (b *Backend) CreateAsset(symbol string, decimals string, metadata string) error {
- // Ensure have sufficient balance
- bal, err := b.tcli.Balance(b.ctx, b.addr, ids.Empty)
- if err != nil {
- return err
- }
-
- // Generate transaction
- udecimals, err := strconv.ParseUint(decimals, 10, 8)
- if err != nil {
- return err
- }
- _, tx, maxFee, err := b.cli.GenerateTransaction(b.ctx, b.parser, nil, &actions.CreateAsset{
- Symbol: []byte(symbol),
- Decimals: uint8(udecimals),
- Metadata: []byte(metadata),
- }, b.factory)
- if err != nil {
- return fmt.Errorf("%w: unable to generate transaction", err)
- }
- if maxFee > bal {
- return fmt.Errorf("insufficient balance (have: %s %s, want: %s %s)", hutils.FormatBalance(bal, tconsts.Decimals), tconsts.Symbol, hutils.FormatBalance(maxFee, tconsts.Decimals), tconsts.Symbol)
- }
- if err := b.scli.RegisterTx(tx); err != nil {
- return err
- }
-
- // Wait for transaction
- _, dErr, result, err := b.scli.ListenTx(b.ctx)
- if err != nil {
- return err
- }
- if dErr != nil {
- return err
- }
- if !result.Success {
- return fmt.Errorf("transaction failed on-chain: %s", result.Output)
- }
- return nil
-}
-
-func (b *Backend) MintAsset(asset string, address string, amount string) error {
- // Input validation
- assetID, err := ids.FromString(asset)
- if err != nil {
- return err
- }
- _, _, decimals, _, _, _, _, err := b.tcli.Asset(b.ctx, assetID, true)
- if err != nil {
- return err
- }
- value, err := hutils.ParseBalance(amount, decimals)
- if err != nil {
- return err
- }
- to, err := utils.ParseAddress(address)
- if err != nil {
- return err
- }
-
- // Ensure have sufficient balance
- bal, err := b.tcli.Balance(b.ctx, b.addr, ids.Empty)
- if err != nil {
- return err
- }
-
- // Generate transaction
- _, tx, maxFee, err := b.cli.GenerateTransaction(b.ctx, b.parser, nil, &actions.MintAsset{
- To: to,
- Asset: assetID,
- Value: value,
- }, b.factory)
- if err != nil {
- return fmt.Errorf("%w: unable to generate transaction", err)
- }
- if maxFee > bal {
- return fmt.Errorf("insufficient balance (have: %s %s, want: %s %s)", hutils.FormatBalance(bal, tconsts.Decimals), tconsts.Symbol, hutils.FormatBalance(maxFee, tconsts.Decimals), tconsts.Symbol)
- }
- if err := b.scli.RegisterTx(tx); err != nil {
- return err
- }
-
- // Wait for transaction
- _, dErr, result, err := b.scli.ListenTx(b.ctx)
- if err != nil {
- return err
- }
- if dErr != nil {
- return err
- }
- if !result.Success {
- return fmt.Errorf("transaction failed on-chain: %s", result.Output)
- }
- return nil
-}
-
-func (b *Backend) Transfer(asset string, address string, amount string, memo string) error {
- // Input validation
- assetID, err := ids.FromString(asset)
- if err != nil {
- return err
- }
- _, symbol, decimals, _, _, _, _, err := b.tcli.Asset(b.ctx, assetID, true)
- if err != nil {
- return err
- }
- value, err := hutils.ParseBalance(amount, decimals)
- if err != nil {
- return err
- }
- to, err := utils.ParseAddress(address)
- if err != nil {
- return err
- }
-
- // Ensure have sufficient balance for transfer
- sendBal, err := b.tcli.Balance(b.ctx, b.addr, assetID)
- if err != nil {
- return err
- }
- if value > sendBal {
- return fmt.Errorf("insufficient balance (have: %s %s, want: %s %s)", hutils.FormatBalance(sendBal, decimals), symbol, hutils.FormatBalance(value, decimals), symbol)
- }
-
- // Ensure have sufficient balance for fees
- bal, err := b.tcli.Balance(b.ctx, b.addr, ids.Empty)
- if err != nil {
- return err
- }
-
- // Generate transaction
- _, tx, maxFee, err := b.cli.GenerateTransaction(b.ctx, b.parser, nil, &actions.Transfer{
- To: to,
- Asset: assetID,
- Value: value,
- Memo: []byte(memo),
- }, b.factory)
- if err != nil {
- return fmt.Errorf("%w: unable to generate transaction", err)
- }
- if assetID != ids.Empty {
- if maxFee > bal {
- return fmt.Errorf("insufficient balance (have: %s %s, want: %s %s)", hutils.FormatBalance(bal, tconsts.Decimals), tconsts.Symbol, hutils.FormatBalance(maxFee, tconsts.Decimals), tconsts.Symbol)
- }
- } else {
- if maxFee+value > bal {
- return fmt.Errorf("insufficient balance (have: %s %s, want: %s %s)", hutils.FormatBalance(bal, tconsts.Decimals), tconsts.Symbol, hutils.FormatBalance(maxFee+value, tconsts.Decimals), tconsts.Symbol)
- }
- }
- if err := b.scli.RegisterTx(tx); err != nil {
- return err
- }
-
- // Wait for transaction
- _, dErr, result, err := b.scli.ListenTx(b.ctx)
- if err != nil {
- return err
- }
- if dErr != nil {
- return err
- }
- if !result.Success {
- return fmt.Errorf("transaction failed on-chain: %s", result.Output)
- }
- return nil
-}
-
-func (b *Backend) GetAddress() string {
- return b.addr
-}
-
-func (b *Backend) GetBalance() ([]*BalanceInfo, error) {
- assets, _, err := b.s.GetAssets()
- if err != nil {
- return nil, err
- }
- balances := []*BalanceInfo{}
- for _, asset := range assets {
- _, symbol, decimals, _, _, _, _, err := b.tcli.Asset(b.ctx, asset, true)
- if err != nil {
- return nil, err
- }
- bal, err := b.tcli.Balance(b.ctx, b.addr, asset)
- if err != nil {
- return nil, err
- }
- strAsset := asset.String()
- if asset == ids.Empty {
- balances = append(balances, &BalanceInfo{ID: asset.String(), Str: fmt.Sprintf("%s %s", hutils.FormatBalance(bal, decimals), symbol), Bal: fmt.Sprintf("%s (Balance: %s)", symbol, hutils.FormatBalance(bal, decimals)), Has: bal > 0})
- } else {
- balances = append(balances, &BalanceInfo{ID: asset.String(), Str: fmt.Sprintf("%s %s [%s]", hutils.FormatBalance(bal, decimals), symbol, asset), Bal: fmt.Sprintf("%s [%s..%s] (Balance: %s)", symbol, strAsset[:3], strAsset[len(strAsset)-3:], hutils.FormatBalance(bal, decimals)), Has: bal > 0})
- }
- }
- return balances, nil
-}
-
-func (b *Backend) GetTransactions() *Transactions {
- b.txAlertLock.Lock()
- defer b.txAlertLock.Unlock()
-
- var alerts []*Alert
- if len(b.transactionAlerts) > 0 {
- alerts = b.transactionAlerts
- b.transactionAlerts = []*Alert{}
- }
- txs, err := b.s.GetTransactions()
- if err != nil {
- b.fatal(err)
- return nil
- }
- return &Transactions{alerts, txs}
-}
-
-func (b *Backend) StartFaucetSearch() (*FaucetSearchInfo, error) {
- b.searchLock.Lock()
- if b.search != nil {
- b.searchLock.Unlock()
- return nil, errors.New("already searching")
- }
- b.search = &FaucetSearchInfo{}
- b.searchLock.Unlock()
-
- address, err := b.fcli.FaucetAddress(b.ctx)
- if err != nil {
- b.searchLock.Lock()
- b.search = nil
- b.searchLock.Unlock()
- return nil, err
- }
- salt, difficulty, err := b.fcli.Challenge(b.ctx)
- if err != nil {
- b.searchLock.Lock()
- b.search = nil
- b.searchLock.Unlock()
- return nil, err
- }
- b.search.FaucetAddress = address
- b.search.Salt = hex.EncodeToString(salt)
- b.search.Difficulty = difficulty
-
- // Search in the background
- go func() {
- start := time.Now()
- solution, attempts := challenge.Search(salt, difficulty, b.c.SearchCores)
- txID, amount, err := b.fcli.SolveChallenge(b.ctx, b.addr, salt, solution)
- b.searchLock.Lock()
- b.search.Solution = hex.EncodeToString(solution)
- b.search.Attempts = attempts
- b.search.Elapsed = time.Since(start).String()
- if err == nil {
- b.search.TxID = txID.String()
- b.search.Amount = fmt.Sprintf("%s %s", hutils.FormatBalance(amount, tconsts.Decimals), tconsts.Symbol)
- b.searchAlerts = append(b.searchAlerts, &Alert{"success", fmt.Sprintf("Search Successful [Attempts: %d, Elapsed: %s]", attempts, b.search.Elapsed)})
- } else {
- b.search.Err = err.Error()
- b.searchAlerts = append(b.searchAlerts, &Alert{"error", fmt.Sprintf("Search Failed: %v", err)})
- }
- search := b.search
- b.search = nil
- b.searchLock.Unlock()
- if err := b.s.StoreSolution(search); err != nil {
- b.fatal(err)
- }
- }()
- return b.search, nil
-}
-
-func (b *Backend) GetFaucetSolutions() *FaucetSolutions {
- solutions, err := b.s.GetSolutions()
- if err != nil {
- b.fatal(err)
- return nil
- }
-
- b.searchLock.Lock()
- defer b.searchLock.Unlock()
-
- var alerts []*Alert
- if len(b.searchAlerts) > 0 {
- alerts = b.searchAlerts
- b.searchAlerts = []*Alert{}
- }
-
- return &FaucetSolutions{alerts, b.search, solutions}
-}
-
-func (b *Backend) GetAddressBook() []*AddressInfo {
- addresses, err := b.s.GetAddresses()
- if err != nil {
- b.fatal(err)
- return nil
- }
- return addresses
-}
-
-// Any existing address will be overwritten with a new name
-func (b *Backend) AddAddressBook(name string, address string) error {
- name = strings.TrimSpace(name)
- address = strings.TrimSpace(address)
- return b.s.StoreAddress(address, name)
-}
-
-func (b *Backend) GetAllAssets() []*AssetInfo {
- arr, _, err := b.s.GetAssets()
- if err != nil {
- b.fatal(err)
- return nil
- }
- assets := []*AssetInfo{}
- for _, asset := range arr {
- _, symbol, decimals, metadata, supply, owner, _, err := b.tcli.Asset(b.ctx, asset, false)
- if err != nil {
- b.fatal(err)
- return nil
- }
- strAsset := asset.String()
- assets = append(assets, &AssetInfo{
- ID: asset.String(),
- Symbol: string(symbol),
- Decimals: int(decimals),
- Metadata: string(metadata),
- Supply: hutils.FormatBalance(supply, decimals),
- Creator: owner,
- StrSymbol: fmt.Sprintf("%s [%s..%s]", symbol, strAsset[:3], strAsset[len(strAsset)-3:]),
- })
- }
- return assets
-}
-
-func (b *Backend) AddAsset(asset string) error {
- assetID, err := ids.FromString(asset)
- if err != nil {
- return err
- }
- hasAsset, err := b.s.HasAsset(assetID)
- if err != nil {
- return err
- }
- if hasAsset {
- return nil
- }
- exists, _, _, _, _, owner, _, err := b.tcli.Asset(b.ctx, assetID, true)
- if err != nil {
- return err
- }
- if !exists {
- return ErrAssetMissing
- }
- return b.s.StoreAsset(assetID, owner == b.addr)
-}
-
-func (b *Backend) GetFeedInfo() (*FeedInfo, error) {
- addr, fee, err := b.fecli.FeedInfo(context.TODO())
- if err != nil {
- return nil, err
- }
- return &FeedInfo{
- addr,
- fmt.Sprintf("%s %s", hutils.FormatBalance(fee, tconsts.Decimals), tconsts.Symbol),
- }, nil
-}
-
-func (b *Backend) parseURLs() {
- client := http.DefaultClient
- for {
- select {
- case u := <-b.urlQueue:
- // Protect against maliciously crafted URLs
- parsedURL, err := url.Parse(u)
- if err != nil {
- continue
- }
- if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
- continue
- }
- ip := net.ParseIP(parsedURL.Host)
- if ip != nil {
- if ip.IsPrivate() || ip.IsLoopback() {
- continue
- }
- }
-
- // Attempt to fetch URL contents
- ctx, cancel := context.WithTimeout(b.ctx, 30*time.Second)
- req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
- if err != nil {
- cancel()
- continue
- }
- resp, err := client.Do(req)
- if err != nil {
- fmt.Println("unable to fetch URL", err)
- // We already put the URL in as nil in
- // our cache, so we won't refetch it.
- cancel()
- continue
- }
- b.htmlCache.Put(u, ParseHTML(u, parsedURL.Host, resp.Body))
- _ = resp.Body.Close()
- cancel()
- case <-b.ctx.Done():
- return
- }
- }
-}
-
-func (b *Backend) GetFeed() ([]*FeedObject, error) {
- feed, err := b.fecli.Feed(context.TODO())
- if err != nil {
- return nil, err
- }
- nfeed := make([]*FeedObject, 0, len(feed))
- for _, fo := range feed {
- tfo := &FeedObject{
- Address: fo.Address,
- ID: fo.TxID.String(),
- Timestamp: fo.Timestamp,
- Fee: fmt.Sprintf("%s %s", hutils.FormatBalance(fo.Fee, tconsts.Decimals), tconsts.Symbol),
-
- Message: fo.Content.Message,
- URL: fo.Content.URL,
- }
- if len(fo.Content.URL) > 0 {
- if m, ok := b.htmlCache.Get(fo.Content.URL); ok {
- tfo.URLMeta = m
- } else {
- b.htmlCache.Put(fo.Content.URL, nil) // ensure we don't refetch
- b.urlQueue <- fo.Content.URL
- }
- }
- nfeed = append(nfeed, tfo)
- }
- return nfeed, nil
-}
-
-func (b *Backend) Message(message string, url string) error {
- // Get latest feed info
- recipient, fee, err := b.fecli.FeedInfo(context.TODO())
- if err != nil {
- return err
- }
- recipientAddr, err := utils.ParseAddress(recipient)
- if err != nil {
- return err
- }
-
- // Encode data
- fc := &manager.FeedContent{
- Message: message,
- URL: url,
- }
- data, err := json.Marshal(fc)
- if err != nil {
- return err
- }
-
- // Ensure have sufficient balance
- bal, err := b.tcli.Balance(b.ctx, b.addr, ids.Empty)
- if err != nil {
- return err
- }
-
- // Generate transaction
- _, tx, maxFee, err := b.cli.GenerateTransaction(b.ctx, b.parser, nil, &actions.Transfer{
- To: recipientAddr,
- Asset: ids.Empty,
- Value: fee,
- Memo: data,
- }, b.factory)
- if err != nil {
- return fmt.Errorf("%w: unable to generate transaction", err)
- }
- if maxFee+fee > bal {
- return fmt.Errorf("insufficient balance (have: %s %s, want: %s %s)", hutils.FormatBalance(bal, tconsts.Decimals), tconsts.Symbol, hutils.FormatBalance(maxFee+fee, tconsts.Decimals), tconsts.Symbol)
- }
- if err := b.scli.RegisterTx(tx); err != nil {
- return err
- }
-
- // Wait for transaction
- _, dErr, result, err := b.scli.ListenTx(b.ctx)
- if err != nil {
- return err
- }
- if dErr != nil {
- return err
- }
- if !result.Success {
- return fmt.Errorf("transaction failed on-chain: %s", result.Output)
- }
- return nil
-}
diff --git a/cmd/token-wallet/backend/config.go b/cmd/token-wallet/backend/config.go
deleted file mode 100644
index f132ca6..0000000
--- a/cmd/token-wallet/backend/config.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package backend
-
-type Config struct {
- TokenRPC string `json:"tokenRPC"`
- FaucetRPC string `json:"faucetRPC"`
- SearchCores int `json:"searchCores"`
- FeedRPC string `json:"feedRPC"`
-}
diff --git a/cmd/token-wallet/backend/errors.go b/cmd/token-wallet/backend/errors.go
deleted file mode 100644
index c6b68c8..0000000
--- a/cmd/token-wallet/backend/errors.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package backend
-
-import "errors"
-
-var (
- ErrDuplicate = errors.New("duplicate")
- ErrAssetMissing = errors.New("asset missing")
-)
diff --git a/cmd/token-wallet/backend/html.go b/cmd/token-wallet/backend/html.go
deleted file mode 100644
index fa19857..0000000
--- a/cmd/token-wallet/backend/html.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package backend
-
-import (
- "io"
-
- "golang.org/x/net/html"
-)
-
-// Inspiration: https://gist.github.com/inotnako/c4a82f6723f6ccea5d83c5d3689373dd
-type HTMLMeta struct {
- URL string
- Host string
-
- SiteName string
- Title string
- Description string
- Image string
-}
-
-func ParseHTML(url string, host string, resp io.Reader) *HTMLMeta {
- z := html.NewTokenizer(resp)
-
- titleFound := false
-
- hm := new(HTMLMeta)
- hm.URL = url
- hm.Host = host
-
- for {
- tt := z.Next()
- switch tt {
- case html.ErrorToken:
- return hm
- case html.StartTagToken, html.SelfClosingTagToken:
- // TODO: to handle reddit, we need to wait for page to load before parsing
- // TODO: to handle twitter, need to fix many redirect issue
- t := z.Token()
- if t.Data == `body` {
- return hm
- }
- if t.Data == "title" {
- titleFound = true
- }
- if t.Data == "meta" {
- desc, ok := extractMetaProperty(t, "description")
- if ok {
- hm.Description = desc
- }
-
- ogTitle, ok := extractMetaProperty(t, "og:title")
- if ok {
- hm.Title = ogTitle
- }
-
- ogDesc, ok := extractMetaProperty(t, "og:description")
- if ok {
- hm.Description = ogDesc
- }
-
- ogImage, ok := extractMetaProperty(t, "og:image")
- if ok {
- hm.Image = ogImage
- }
-
- ogSiteName, ok := extractMetaProperty(t, "og:site_name")
- if ok {
- hm.SiteName = ogSiteName
- }
- }
- case html.TextToken:
- t := z.Token()
- if titleFound {
- if len(hm.Title) == 0 {
- hm.Title = t.Data
- }
- titleFound = false
- }
- }
- }
-}
-
-func extractMetaProperty(t html.Token, prop string) (content string, ok bool) {
- for _, attr := range t.Attr {
- if attr.Key == "property" && attr.Val == prop {
- ok = true
- }
-
- if attr.Key == "content" {
- content = attr.Val
- }
- }
-
- return
-}
diff --git a/cmd/token-wallet/backend/models.go b/cmd/token-wallet/backend/models.go
deleted file mode 100644
index 13758dc..0000000
--- a/cmd/token-wallet/backend/models.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package backend
-
-import (
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/ava-labs/avalanchego/utils/set"
-)
-
-type Alert struct {
- Type string
- Content string
-}
-
-type AddressInfo struct {
- Name string
- Address string
- AddrStr string
-}
-
-type TransactionInfo struct {
- ID string
- Size string
- Timestamp int64
- Actor string
-
- Success bool
- Type string
- Units string
- Fee string
- Summary string
-}
-
-type TimeStat struct {
- Timestamp int64
- Transactions int
- Accounts set.Set[string]
- Prices chain.Dimensions
-}
-
-type BlockInfo struct {
- Timestamp int64
- ID string
- Height uint64
- Size string
- TPS string
- Consumed string
- Prices string
- StateRoot string
-
- Txs int
- FailTxs int
-
- Latency int64
-}
-
-type GenericInfo struct {
- Timestamp int64
- Count uint64
- Category string
-}
-
-type AssetInfo struct {
- ID string
-
- Symbol string
- Decimals int
- Metadata string
- Supply string
- Creator string
- StrSymbol string
-}
-
-type BalanceInfo struct {
- ID string
-
- Str string
- Bal string
- Has bool
-}
-
-type Transactions struct {
- Alerts []*Alert
- TxInfos []*TransactionInfo
-}
-
-type FaucetSearchInfo struct {
- FaucetAddress string
- Salt string
- Difficulty uint16
-
- Solution string
- Attempts uint64
- Elapsed string
-
- Amount string
- TxID string
-
- Err string
-}
-
-type FaucetSolutions struct {
- Alerts []*Alert
- CurrentSearch *FaucetSearchInfo
- PastSearches []*FaucetSearchInfo
-}
-
-// type Order struct {
-// ID string
-// InID string
-// InSymbol string
-// OutID string
-// OutSymbol string
-
-// // Set step value
-// Price string
-// InTick string
-// OutTick string
-// Rate float64
-
-// Remaining string
-// Owner string
-
-// MaxInput string
-// InputStep string
-// }
-
-type FeedInfo struct {
- Address string
- Fee string
-}
-
-type FeedObject struct {
- Address string
- ID string
- Timestamp int64
- Fee string
-
- Message string
- URL string
-
- URLMeta *HTMLMeta
-}
diff --git a/cmd/token-wallet/backend/storage.go b/cmd/token-wallet/backend/storage.go
deleted file mode 100644
index f079606..0000000
--- a/cmd/token-wallet/backend/storage.go
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package backend
-
-import (
- "encoding/binary"
- "encoding/json"
- "errors"
- "fmt"
- "time"
-
- "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/pebble"
- hutils "github.com/AnomalyFi/hypersdk/utils"
- tconsts "github.com/AnomalyFi/nodekit-seq/consts"
- "github.com/AnomalyFi/nodekit-seq/utils"
- "github.com/ava-labs/avalanchego/database"
- "github.com/ava-labs/avalanchego/ids"
-)
-
-const (
- keyPrefix = 0x0
- assetsPrefix = 0x1
- transactionPrefix = 0x2
- searchPrefix = 0x3
- addressPrefix = 0x4
- orderPrefix = 0x5
-)
-
-type Storage struct {
- db database.Database
-}
-
-func OpenStorage(databasePath string) (*Storage, error) {
- db, _, err := pebble.New(databasePath, pebble.NewDefaultConfig())
- if err != nil {
- return nil, err
- }
- return &Storage{db}, nil
-}
-
-func (s *Storage) StoreKey(privateKey ed25519.PrivateKey) error {
- has, err := s.db.Has([]byte{keyPrefix})
- if err != nil {
- return err
- }
- if has {
- return ErrDuplicate
- }
- return s.db.Put([]byte{keyPrefix}, privateKey[:])
-}
-
-func (s *Storage) GetKey() (ed25519.PrivateKey, error) {
- v, err := s.db.Get([]byte{keyPrefix})
- if errors.Is(err, database.ErrNotFound) {
- return ed25519.EmptyPrivateKey, nil
- }
- if err != nil {
- return ed25519.EmptyPrivateKey, err
- }
- return ed25519.PrivateKey(v), nil
-}
-
-func (s *Storage) StoreAsset(assetID ids.ID, owned bool) error {
- k := make([]byte, 1+ids.IDLen)
- k[0] = assetsPrefix
- copy(k[1:], assetID[:])
- v := []byte{0x0}
- if owned {
- v = []byte{0x1}
- }
- return s.db.Put(k, v)
-}
-
-func (s *Storage) HasAsset(assetID ids.ID) (bool, error) {
- k := make([]byte, 1+ids.IDLen)
- k[0] = assetsPrefix
- copy(k[1:], assetID[:])
- return s.db.Has(k)
-}
-
-func (s *Storage) GetAssets() ([]ids.ID, []bool, error) {
- iter := s.db.NewIteratorWithPrefix([]byte{assetsPrefix})
- defer iter.Release()
-
- assets := []ids.ID{}
- owned := []bool{}
- for iter.Next() {
- assets = append(assets, ids.ID(iter.Key()[1:]))
- owned = append(owned, iter.Value()[0] == 0x1)
- }
- return assets, owned, iter.Error()
-}
-
-func (s *Storage) StoreTransaction(tx *TransactionInfo) error {
- txID, err := ids.FromString(tx.ID)
- if err != nil {
- return err
- }
- inverseTime := consts.MaxUint64 - uint64(time.Now().UnixMilli())
- k := make([]byte, 1+consts.Uint64Len+ids.IDLen)
- k[0] = transactionPrefix
- binary.BigEndian.PutUint64(k[1:], inverseTime)
- copy(k[1+consts.Uint64Len:], txID[:])
- b, err := json.Marshal(tx)
- if err != nil {
- return err
- }
- return s.db.Put(k, b)
-}
-
-func (s *Storage) GetTransactions() ([]*TransactionInfo, error) {
- iter := s.db.NewIteratorWithPrefix([]byte{transactionPrefix})
- defer iter.Release()
-
- txs := []*TransactionInfo{}
- for iter.Next() {
- var tx TransactionInfo
- if err := json.Unmarshal(iter.Value(), &tx); err != nil {
- return nil, err
- }
- txs = append(txs, &tx)
- }
- return txs, iter.Error()
-}
-
-func (s *Storage) StoreAddress(address string, nickname string) error {
- pk, err := utils.ParseAddress(address)
- if err != nil {
- return err
- }
- k := make([]byte, 1+ed25519.PublicKeyLen)
- k[0] = addressPrefix
- copy(k[1:], pk[:])
- return s.db.Put(k, []byte(nickname))
-}
-
-func (s *Storage) GetAddresses() ([]*AddressInfo, error) {
- iter := s.db.NewIteratorWithPrefix([]byte{addressPrefix})
- defer iter.Release()
-
- addresses := []*AddressInfo{}
- for iter.Next() {
- pk := ed25519.PublicKey(iter.Key()[1:])
- address := utils.Address(pk)
- nickname := string(iter.Value())
- addresses = append(addresses, &AddressInfo{nickname, address, fmt.Sprintf("%s [%s..%s]", nickname, address[:len(tconsts.HRP)+3], address[len(address)-3:])})
- }
- return addresses, iter.Error()
-}
-
-func (s *Storage) StoreSolution(solution *FaucetSearchInfo) error {
- solutionID := hutils.ToID([]byte(solution.Solution))
- inverseTime := consts.MaxUint64 - uint64(time.Now().UnixMilli())
- k := make([]byte, 1+consts.Uint64Len+ids.IDLen)
- k[0] = searchPrefix
- binary.BigEndian.PutUint64(k[1:], inverseTime)
- copy(k[1+consts.Uint64Len:], solutionID[:])
- b, err := json.Marshal(solution)
- if err != nil {
- return err
- }
- return s.db.Put(k, b)
-}
-
-func (s *Storage) GetSolutions() ([]*FaucetSearchInfo, error) {
- iter := s.db.NewIteratorWithPrefix([]byte{searchPrefix})
- defer iter.Release()
-
- fs := []*FaucetSearchInfo{}
- for iter.Next() {
- var f FaucetSearchInfo
- if err := json.Unmarshal(iter.Value(), &f); err != nil {
- return nil, err
- }
- fs = append(fs, &f)
- }
- return fs, iter.Error()
-}
-
-// func (s *Storage) StoreOrder(orderID ids.ID) error {
-// inverseTime := consts.MaxUint64 - uint64(time.Now().UnixMilli())
-// k := make([]byte, 1+consts.Uint64Len+ids.IDLen)
-// k[0] = orderPrefix
-// binary.BigEndian.PutUint64(k[1:], inverseTime)
-// copy(k[1+consts.Uint64Len:], orderID[:])
-// return s.db.Put(k, nil)
-// }
-
-// func (s *Storage) GetOrders() ([]ids.ID, [][]byte, error) {
-// iter := s.db.NewIteratorWithPrefix([]byte{orderPrefix})
-// defer iter.Release()
-
-// orders := []ids.ID{}
-// keys := [][]byte{}
-// for iter.Next() {
-// k := iter.Key()
-// orders = append(orders, ids.ID(k[1+consts.Uint64Len:]))
-// keys = append(keys, k)
-// }
-// return orders, keys, iter.Error()
-// }
-
-func (s *Storage) DeleteDBKey(k []byte) error {
- return s.db.Delete(k)
-}
-
-func (s *Storage) Close() error {
- if err := s.db.Close(); err != nil {
- return fmt.Errorf("unable to close database: %w", err)
- }
- return nil
-}
diff --git a/cmd/token-wallet/build/appicon.png b/cmd/token-wallet/build/appicon.png
deleted file mode 100644
index 2b45c47..0000000
Binary files a/cmd/token-wallet/build/appicon.png and /dev/null differ
diff --git a/cmd/token-wallet/build/darwin/Info.dev.plist b/cmd/token-wallet/build/darwin/Info.dev.plist
deleted file mode 100644
index 1efd53f..0000000
--- a/cmd/token-wallet/build/darwin/Info.dev.plist
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
- CFBundlePackageType
- APPL
- CFBundleName
- Token Wallet
- CFBundleExecutable
- Token Wallet
- CFBundleIdentifier
- com.ava-labs.token-wallet
- CFBundleVersion
- 0.0.0
- CFBundleShortVersionString
- 0.0.0
- CFBundleIconFile
- iconfile
- LSMinimumSystemVersion
- 10.13.0
- NSHighResolutionCapable
- true
- NSHumanReadableCopyright
- Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
- NSAppTransportSecurity
-
- NSAllowsLocalNetworking
-
-
-
-
diff --git a/cmd/token-wallet/build/darwin/Info.plist b/cmd/token-wallet/build/darwin/Info.plist
deleted file mode 100644
index 1efd53f..0000000
--- a/cmd/token-wallet/build/darwin/Info.plist
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
- CFBundlePackageType
- APPL
- CFBundleName
- Token Wallet
- CFBundleExecutable
- Token Wallet
- CFBundleIdentifier
- com.ava-labs.token-wallet
- CFBundleVersion
- 0.0.0
- CFBundleShortVersionString
- 0.0.0
- CFBundleIconFile
- iconfile
- LSMinimumSystemVersion
- 10.13.0
- NSHighResolutionCapable
- true
- NSHumanReadableCopyright
- Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
- NSAppTransportSecurity
-
- NSAllowsLocalNetworking
-
-
-
-
diff --git a/cmd/token-wallet/config.json b/cmd/token-wallet/config.json
deleted file mode 100644
index 37e70e7..0000000
--- a/cmd/token-wallet/config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "tokenRPC": "http://127.0.0.1:62451/ext/bc/2mzRiBeC83RzGcanb5B35BXNSDMc59RxGoxF4g5REGAB5m5sPP",
- "faucetRPC": "http://127.0.0.1:9091",
- "searchCores": 4,
- "feedRPC": "http://127.0.0.1:9092"
-}
diff --git a/cmd/token-wallet/frontend/index.html b/cmd/token-wallet/frontend/index.html
deleted file mode 100644
index 67f2fde..0000000
--- a/cmd/token-wallet/frontend/index.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
- Token Wallet
-
-
-
-
-
-
diff --git a/cmd/token-wallet/frontend/package-lock.json b/cmd/token-wallet/frontend/package-lock.json
deleted file mode 100644
index 6fb9681..0000000
--- a/cmd/token-wallet/frontend/package-lock.json
+++ /dev/null
@@ -1,4082 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "frontend",
- "version": "0.0.0",
- "dependencies": {
- "@ant-design/icons": "^5.2.5",
- "@ant-design/plots": "^1.2.5",
- "antd": "^5.8.4",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-router-dom": "^6.15.0"
- },
- "devDependencies": {
- "@types/react": "^18.0.17",
- "@types/react-dom": "^18.0.6",
- "@vitejs/plugin-react": "^2.0.1",
- "vite": "^3.0.7"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
- "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.0",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@ant-design/colors": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.0.tgz",
- "integrity": "sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==",
- "dependencies": {
- "@ctrl/tinycolor": "^3.4.0"
- }
- },
- "node_modules/@ant-design/cssinjs": {
- "version": "1.16.2",
- "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.16.2.tgz",
- "integrity": "sha512-W+LT6Xm5sEYZn7ocMAIP9LvX99woxGg1aYu15o608/uUAaJDR7LrxBu/5cnMLa6AQK1829zdoKmRnRFOxAgzEg==",
- "dependencies": {
- "@babel/runtime": "^7.11.1",
- "@emotion/hash": "^0.8.0",
- "@emotion/unitless": "^0.7.5",
- "classnames": "^2.3.1",
- "csstype": "^3.0.10",
- "rc-util": "^5.35.0",
- "stylis": "^4.0.13"
- },
- "peerDependencies": {
- "react": ">=16.0.0",
- "react-dom": ">=16.0.0"
- }
- },
- "node_modules/@ant-design/icons": {
- "version": "5.2.5",
- "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.2.5.tgz",
- "integrity": "sha512-9Jc59v5fl5dzmxqLWtRev3dJwU7Ya9ZheoI6XmZjZiQ7PRtk77rC+Rbt7GJzAPPg43RQ4YO53RE1u8n+Et97vQ==",
- "dependencies": {
- "@ant-design/colors": "^7.0.0",
- "@ant-design/icons-svg": "^4.3.0",
- "@babel/runtime": "^7.11.2",
- "classnames": "^2.2.6",
- "lodash.camelcase": "^4.3.0",
- "rc-util": "^5.31.1"
- },
- "engines": {
- "node": ">=8"
- },
- "peerDependencies": {
- "react": ">=16.0.0",
- "react-dom": ">=16.0.0"
- }
- },
- "node_modules/@ant-design/icons-svg": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz",
- "integrity": "sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g=="
- },
- "node_modules/@ant-design/plots": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@ant-design/plots/-/plots-1.2.5.tgz",
- "integrity": "sha512-8Jvu2xC5y5/B38/9Qr6CBiXCZopsGEA3IR4pjLFlkLoT4OHIKr4y8oIvhahM9mh9ZATyjkrZLWJBI8yETrReGg==",
- "dependencies": {
- "@antv/g2plot": "^2.2.11",
- "@antv/util": "^2.0.9",
- "react-content-loader": "^5.0.4"
- },
- "peerDependencies": {
- "react": ">=16.8.4",
- "react-dom": ">=16.8.4"
- }
- },
- "node_modules/@ant-design/react-slick": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.0.2.tgz",
- "integrity": "sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==",
- "dependencies": {
- "@babel/runtime": "^7.10.4",
- "classnames": "^2.2.5",
- "json2mq": "^0.2.0",
- "resize-observer-polyfill": "^1.5.1",
- "throttle-debounce": "^5.0.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0"
- }
- },
- "node_modules/@antv/adjust": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.2.5.tgz",
- "integrity": "sha512-MfWZOkD9CqXRES6MBGRNe27Q577a72EIwyMnE29wIlPliFvJfWwsrONddpGU7lilMpVKecS3WAzOoip3RfPTRQ==",
- "dependencies": {
- "@antv/util": "~2.0.0",
- "tslib": "^1.10.0"
- }
- },
- "node_modules/@antv/adjust/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@antv/attr": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.3.5.tgz",
- "integrity": "sha512-wuj2gUo6C8Q2ASSMrVBuTcb5LcV+Tc0Egiy6bC42D0vxcQ+ta13CLxgMmHz8mjD0FxTPJDXSciyszRSC5TdLsg==",
- "dependencies": {
- "@antv/color-util": "^2.0.1",
- "@antv/scale": "^0.3.0",
- "@antv/util": "~2.0.0",
- "tslib": "^2.3.1"
- }
- },
- "node_modules/@antv/color-util": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.6.tgz",
- "integrity": "sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==",
- "dependencies": {
- "@antv/util": "^2.0.9",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/component": {
- "version": "0.8.35",
- "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.35.tgz",
- "integrity": "sha512-VnRa5X77nBPI952o2xePEEMSNZ6g2mcUDrQY8mVL2kino/8TFhqDq5fTRmDXZyWyIYd4ulJTz5zgeSwAnX/INQ==",
- "dependencies": {
- "@antv/color-util": "^2.0.3",
- "@antv/dom-util": "~2.0.1",
- "@antv/g-base": "^0.5.9",
- "@antv/matrix-util": "^3.1.0-beta.1",
- "@antv/path-util": "~2.0.7",
- "@antv/scale": "~0.3.1",
- "@antv/util": "~2.0.0",
- "fecha": "~4.2.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/component/node_modules/@antv/path-util": {
- "version": "2.0.15",
- "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.15.tgz",
- "integrity": "sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==",
- "dependencies": {
- "@antv/matrix-util": "^3.0.4",
- "@antv/util": "^2.0.9",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/component/node_modules/@antv/path-util/node_modules/@antv/matrix-util": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.0.4.tgz",
- "integrity": "sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==",
- "dependencies": {
- "@antv/util": "^2.0.9",
- "gl-matrix": "^3.3.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/coord": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.1.tgz",
- "integrity": "sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==",
- "dependencies": {
- "@antv/matrix-util": "^3.1.0-beta.2",
- "@antv/util": "~2.0.12",
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@antv/dom-util": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.4.tgz",
- "integrity": "sha512-2shXUl504fKwt82T3GkuT4Uoc6p9qjCKnJ8gXGLSW4T1W37dqf9AV28aCfoVPHp2BUXpSsB+PAJX2rG/jLHsLQ==",
- "dependencies": {
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/event-emitter": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@antv/event-emitter/-/event-emitter-0.1.3.tgz",
- "integrity": "sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg=="
- },
- "node_modules/@antv/g-base": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.15.tgz",
- "integrity": "sha512-QOtq50QpnKez9J75/Z8j2yZ7QDQdk8R8mVQJiHtaEO5eI7DM4ZbrsWff/Ew26JYmPWdq7nbRuARMAD4PX9uuLA==",
- "dependencies": {
- "@antv/event-emitter": "^0.1.1",
- "@antv/g-math": "^0.1.9",
- "@antv/matrix-util": "^3.1.0-beta.1",
- "@antv/path-util": "~2.0.5",
- "@antv/util": "~2.0.13",
- "@types/d3-timer": "^2.0.0",
- "d3-ease": "^1.0.5",
- "d3-interpolate": "^3.0.1",
- "d3-timer": "^1.0.9",
- "detect-browser": "^5.1.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g-base/node_modules/@antv/path-util": {
- "version": "2.0.15",
- "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.15.tgz",
- "integrity": "sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==",
- "dependencies": {
- "@antv/matrix-util": "^3.0.4",
- "@antv/util": "^2.0.9",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g-base/node_modules/@antv/path-util/node_modules/@antv/matrix-util": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.0.4.tgz",
- "integrity": "sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==",
- "dependencies": {
- "@antv/util": "^2.0.9",
- "gl-matrix": "^3.3.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g-canvas": {
- "version": "0.5.14",
- "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.14.tgz",
- "integrity": "sha512-IUGLEMIMAUYgaBMT8h3FTmYQYz7sjQkKWwh6Psqx+UPK86fySa+G8fMRrh1EqAL07jVB+GRnn6Ym+3FoFUgeFg==",
- "dependencies": {
- "@antv/g-base": "^0.5.12",
- "@antv/g-math": "^0.1.9",
- "@antv/matrix-util": "^3.1.0-beta.1",
- "@antv/path-util": "~2.0.5",
- "@antv/util": "~2.0.0",
- "gl-matrix": "^3.0.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g-canvas/node_modules/@antv/path-util": {
- "version": "2.0.15",
- "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.15.tgz",
- "integrity": "sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==",
- "dependencies": {
- "@antv/matrix-util": "^3.0.4",
- "@antv/util": "^2.0.9",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g-canvas/node_modules/@antv/path-util/node_modules/@antv/matrix-util": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.0.4.tgz",
- "integrity": "sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==",
- "dependencies": {
- "@antv/util": "^2.0.9",
- "gl-matrix": "^3.3.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g-math": {
- "version": "0.1.9",
- "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.9.tgz",
- "integrity": "sha512-KHMSfPfZ5XHM1PZnG42Q2gxXfOitYveNTA7L61lR6mhZ8Y/aExsYmHqaKBsSarU0z+6WLrl9C07PQJZaw0uljQ==",
- "dependencies": {
- "@antv/util": "~2.0.0",
- "gl-matrix": "^3.0.0"
- }
- },
- "node_modules/@antv/g-svg": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.7.tgz",
- "integrity": "sha512-jUbWoPgr4YNsOat2Y/rGAouNQYGpw4R0cvlN0YafwOyacFFYy2zC8RslNd6KkPhhR3XHNSqJOuCYZj/YmLUwYw==",
- "dependencies": {
- "@antv/g-base": "^0.5.12",
- "@antv/g-math": "^0.1.9",
- "@antv/util": "~2.0.0",
- "detect-browser": "^5.0.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g2": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.2.10.tgz",
- "integrity": "sha512-/ZlJ/DFJBCvtEQgE6roxdd6sBml0fZ8ZVfzG+HdjGpA7/ceURb8XkxUcqa0E8NV+e4sFijnaAhBCdUm2whiuyA==",
- "dependencies": {
- "@antv/adjust": "^0.2.1",
- "@antv/attr": "^0.3.1",
- "@antv/color-util": "^2.0.2",
- "@antv/component": "^0.8.27",
- "@antv/coord": "^0.3.0",
- "@antv/dom-util": "^2.0.2",
- "@antv/event-emitter": "~0.1.0",
- "@antv/g-base": "~0.5.6",
- "@antv/g-canvas": "~0.5.10",
- "@antv/g-svg": "~0.5.6",
- "@antv/matrix-util": "^3.1.0-beta.3",
- "@antv/path-util": "^2.0.15",
- "@antv/scale": "^0.3.14",
- "@antv/util": "~2.0.5",
- "tslib": "^2.0.0"
- }
- },
- "node_modules/@antv/g2/node_modules/@antv/path-util": {
- "version": "2.0.15",
- "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.15.tgz",
- "integrity": "sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==",
- "dependencies": {
- "@antv/matrix-util": "^3.0.4",
- "@antv/util": "^2.0.9",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g2/node_modules/@antv/path-util/node_modules/@antv/matrix-util": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.0.4.tgz",
- "integrity": "sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==",
- "dependencies": {
- "@antv/util": "^2.0.9",
- "gl-matrix": "^3.3.0",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/g2plot": {
- "version": "2.4.31",
- "resolved": "https://registry.npmjs.org/@antv/g2plot/-/g2plot-2.4.31.tgz",
- "integrity": "sha512-SlWHYVsJgRN7E1Oe5Qk6yWBrSWmctmloknFmklaqe9vEeK+YB9ZLUffZvtAHT10mA2NZ+VjGUhlnMNgR9M1PQg==",
- "dependencies": {
- "@antv/color-util": "^2.0.6",
- "@antv/event-emitter": "^0.1.2",
- "@antv/g-base": "^0.5.11",
- "@antv/g2": "^4.1.26",
- "@antv/matrix-util": "^3.1.0-beta.2",
- "@antv/path-util": "^3.0.1",
- "@antv/scale": "^0.3.18",
- "@antv/util": "^2.0.17",
- "d3-hierarchy": "^2.0.0",
- "d3-regression": "^1.3.5",
- "fmin": "^0.0.2",
- "pdfast": "^0.2.0",
- "size-sensor": "^1.0.1",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/matrix-util": {
- "version": "3.1.0-beta.3",
- "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.1.0-beta.3.tgz",
- "integrity": "sha512-W2R6Za3A6CmG51Y/4jZUM/tFgYSq7vTqJL1VD9dKrvwxS4sE0ZcXINtkp55CdyBwJ6Cwm8pfoRpnD4FnHahN0A==",
- "dependencies": {
- "@antv/util": "^2.0.9",
- "gl-matrix": "^3.4.3",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/path-util": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-3.0.1.tgz",
- "integrity": "sha512-tpvAzMpF9Qm6ik2YSMqICNU5tco5POOW7S4XoxZAI/B0L26adU+Md/SmO0BBo2SpuywKvzPH3hPT3xmoyhr04Q==",
- "dependencies": {
- "gl-matrix": "^3.1.0",
- "lodash-es": "^4.17.21",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@antv/scale": {
- "version": "0.3.18",
- "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.18.tgz",
- "integrity": "sha512-GHwE6Lo7S/Q5fgaLPaCsW+CH+3zl4aXpnN1skOiEY0Ue9/u+s2EySv6aDXYkAqs//i0uilMDD/0/4n8caX9U9w==",
- "dependencies": {
- "@antv/util": "~2.0.3",
- "fecha": "~4.2.0",
- "tslib": "^2.0.0"
- }
- },
- "node_modules/@antv/util": {
- "version": "2.0.17",
- "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.17.tgz",
- "integrity": "sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==",
- "dependencies": {
- "csstype": "^3.0.8",
- "tslib": "^2.0.3"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz",
- "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==",
- "dev": true,
- "dependencies": {
- "@babel/highlight": "^7.22.10",
- "chalk": "^2.4.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
- "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz",
- "integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==",
- "dev": true,
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.22.10",
- "@babel/generator": "^7.22.10",
- "@babel/helper-compilation-targets": "^7.22.10",
- "@babel/helper-module-transforms": "^7.22.9",
- "@babel/helpers": "^7.22.11",
- "@babel/parser": "^7.22.11",
- "@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.11",
- "@babel/types": "^7.22.11",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
- "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.10",
- "@jridgewell/gen-mapping": "^0.3.2",
- "@jridgewell/trace-mapping": "^0.3.17",
- "jsesc": "^2.5.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
- "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.5",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
- "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
- "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.22.5",
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-hoist-variables": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
- "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
- "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
- "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.5",
- "@babel/helper-simple-access": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-simple-access": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
- "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
- "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
- "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
- "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz",
- "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.11",
- "@babel/types": "^7.22.11"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz",
- "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.22.5",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz",
- "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g==",
- "dev": true,
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
- "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz",
- "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-jsx": "^7.22.5",
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-development": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz",
- "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==",
- "dev": true,
- "dependencies": {
- "@babel/plugin-transform-react-jsx": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-self": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz",
- "integrity": "sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-source": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.22.5.tgz",
- "integrity": "sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
- "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
- "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.22.5",
- "@babel/parser": "^7.22.5",
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
- "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.22.10",
- "@babel/generator": "^7.22.10",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-hoist-variables": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.22.11",
- "@babel/types": "^7.22.11",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.22.11",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
- "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.5",
- "to-fast-properties": "^2.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@ctrl/tinycolor": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
- "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@emotion/hash": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
- "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
- },
- "node_modules/@emotion/unitless": {
- "version": "0.7.5",
- "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
- "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
- "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
- "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.19",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@rc-component/color-picker": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz",
- "integrity": "sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@ctrl/tinycolor": "^3.6.0",
- "classnames": "^2.2.6",
- "rc-util": "^5.30.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/@rc-component/context": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz",
- "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "rc-util": "^5.27.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/@rc-component/mini-decimal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz",
- "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==",
- "dependencies": {
- "@babel/runtime": "^7.18.0"
- },
- "engines": {
- "node": ">=8.x"
- }
- },
- "node_modules/@rc-component/mutate-observer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz",
- "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==",
- "dependencies": {
- "@babel/runtime": "^7.18.0",
- "classnames": "^2.3.2",
- "rc-util": "^5.24.4"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/@rc-component/portal": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz",
- "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==",
- "dependencies": {
- "@babel/runtime": "^7.18.0",
- "classnames": "^2.3.2",
- "rc-util": "^5.24.4"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/@rc-component/tour": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.8.1.tgz",
- "integrity": "sha512-CsrQnfKgNArxx2j1RNHVLZgVA+rLrEj06lIsl4KSynMqADsqz8eKvVkr0F3p9PA10948M6WEEZt5a/FGAbGR2A==",
- "dependencies": {
- "@babel/runtime": "^7.18.0",
- "@rc-component/portal": "^1.0.0-9",
- "@rc-component/trigger": "^1.3.6",
- "classnames": "^2.3.2",
- "rc-util": "^5.24.4"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/@rc-component/trigger": {
- "version": "1.15.6",
- "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.15.6.tgz",
- "integrity": "sha512-Tl19KaGsShf4yzqxumsXVT4c7j0l20Dxe5hgP5S0HmxyhCg3oKen28ntGavRCIPW7cl7wgsGotntqcIokgDHzg==",
- "dependencies": {
- "@babel/runtime": "^7.18.3",
- "@rc-component/portal": "^1.1.0",
- "classnames": "^2.3.2",
- "rc-align": "^4.0.0",
- "rc-motion": "^2.0.0",
- "rc-resize-observer": "^1.3.1",
- "rc-util": "^5.33.0"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/@remix-run/router": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.8.0.tgz",
- "integrity": "sha512-mrfKqIHnSZRyIzBcanNJmVQELTnX+qagEDlcKO90RgRBVOZGSGvZKeDihTRfWcqoDn5N/NkUcwWTccnpN18Tfg==",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@types/d3-timer": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.1.tgz",
- "integrity": "sha512-TF8aoF5cHcLO7W7403blM7L1T+6NF3XMyN3fxyUolq2uOcFeicG/khQg/dGxiCJWoAcmYulYN7LYSRKO54IXaA=="
- },
- "node_modules/@types/prop-types": {
- "version": "15.7.5",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
- "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==",
- "dev": true
- },
- "node_modules/@types/react": {
- "version": "18.2.21",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz",
- "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==",
- "dev": true,
- "dependencies": {
- "@types/prop-types": "*",
- "@types/scheduler": "*",
- "csstype": "^3.0.2"
- }
- },
- "node_modules/@types/react-dom": {
- "version": "18.2.7",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
- "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
- "dev": true,
- "dependencies": {
- "@types/react": "*"
- }
- },
- "node_modules/@types/scheduler": {
- "version": "0.16.3",
- "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
- "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==",
- "dev": true
- },
- "node_modules/@vitejs/plugin-react": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-2.2.0.tgz",
- "integrity": "sha512-FFpefhvExd1toVRlokZgxgy2JtnBOdp4ZDsq7ldCWaqGSGn9UhWMAVm/1lxPL14JfNS5yGz+s9yFrQY6shoStA==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.19.6",
- "@babel/plugin-transform-react-jsx": "^7.19.0",
- "@babel/plugin-transform-react-jsx-development": "^7.18.6",
- "@babel/plugin-transform-react-jsx-self": "^7.18.6",
- "@babel/plugin-transform-react-jsx-source": "^7.19.6",
- "magic-string": "^0.26.7",
- "react-refresh": "^0.14.0"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "peerDependencies": {
- "vite": "^3.0.0"
- }
- },
- "node_modules/align-text": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
- "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==",
- "dependencies": {
- "kind-of": "^3.0.2",
- "longest": "^1.0.1",
- "repeat-string": "^1.5.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/amdefine": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
- "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
- "engines": {
- "node": ">=0.4.2"
- }
- },
- "node_modules/ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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/antd": {
- "version": "5.8.4",
- "resolved": "https://registry.npmjs.org/antd/-/antd-5.8.4.tgz",
- "integrity": "sha512-DbQUmRWf9GAllZsc9NxL9gnrup75F7iZ0OlFY+mXh31JdSYQLLP07CAOK7z/sdQLQdYnAHWyuWvkb2mrRKxnYA==",
- "dependencies": {
- "@ant-design/colors": "^7.0.0",
- "@ant-design/cssinjs": "^1.16.0",
- "@ant-design/icons": "^5.2.2",
- "@ant-design/react-slick": "~1.0.0",
- "@babel/runtime": "^7.18.3",
- "@ctrl/tinycolor": "^3.6.0",
- "@rc-component/color-picker": "~1.4.0",
- "@rc-component/mutate-observer": "^1.0.0",
- "@rc-component/tour": "~1.8.1",
- "@rc-component/trigger": "^1.15.0",
- "classnames": "^2.2.6",
- "copy-to-clipboard": "^3.2.0",
- "dayjs": "^1.11.1",
- "qrcode.react": "^3.1.0",
- "rc-cascader": "~3.14.0",
- "rc-checkbox": "~3.1.0",
- "rc-collapse": "~3.7.0",
- "rc-dialog": "~9.1.0",
- "rc-drawer": "~6.2.0",
- "rc-dropdown": "~4.1.0",
- "rc-field-form": "~1.36.0",
- "rc-image": "~7.1.0",
- "rc-input": "~1.1.0",
- "rc-input-number": "~8.0.2",
- "rc-mentions": "~2.5.0",
- "rc-menu": "~9.10.0",
- "rc-motion": "^2.7.3",
- "rc-notification": "~5.0.4",
- "rc-pagination": "~3.6.0",
- "rc-picker": "~3.13.0",
- "rc-progress": "~3.4.1",
- "rc-rate": "~2.12.0",
- "rc-resize-observer": "^1.2.0",
- "rc-segmented": "~2.2.0",
- "rc-select": "~14.7.1",
- "rc-slider": "~10.1.0",
- "rc-steps": "~6.0.1",
- "rc-switch": "~4.1.0",
- "rc-table": "~7.32.1",
- "rc-tabs": "~12.9.0",
- "rc-textarea": "~1.3.3",
- "rc-tooltip": "~6.0.0",
- "rc-tree": "~5.7.6",
- "rc-tree-select": "~5.11.0",
- "rc-upload": "~4.3.0",
- "rc-util": "^5.32.0",
- "scroll-into-view-if-needed": "^3.0.3",
- "throttle-debounce": "^5.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/ant-design"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array-tree-filter": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
- "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
- },
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
- "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "is-array-buffer": "^3.0.2",
- "is-shared-array-buffer": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/async-validator": {
- "version": "4.2.5",
- "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
- "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/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/browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/camelcase": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
- "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001522",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz",
- "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ]
- },
- "node_modules/center-align": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
- "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==",
- "dependencies": {
- "align-text": "^0.1.3",
- "lazy-cache": "^1.0.3"
- },
- "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/classnames": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
- "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
- },
- "node_modules/cliui": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
- "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==",
- "dependencies": {
- "center-align": "^0.1.1",
- "right-align": "^0.1.1",
- "wordwrap": "0.0.2"
- }
- },
- "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": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/compute-scroll-into-view": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz",
- "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A=="
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
- },
- "node_modules/contour_plot": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/contour_plot/-/contour_plot-0.0.1.tgz",
- "integrity": "sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw=="
- },
- "node_modules/convert-source-map": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
- "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
- "dev": true
- },
- "node_modules/copy-to-clipboard": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
- "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
- "dependencies": {
- "toggle-selection": "^1.0.6"
- }
- },
- "node_modules/csstype": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
- "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-ease": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
- "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
- },
- "node_modules/d3-hierarchy": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz",
- "integrity": "sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw=="
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-regression": {
- "version": "1.3.10",
- "resolved": "https://registry.npmjs.org/d3-regression/-/d3-regression-1.3.10.tgz",
- "integrity": "sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw=="
- },
- "node_modules/d3-timer": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
- "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
- },
- "node_modules/dayjs": {
- "version": "1.11.9",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
- "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
- },
- "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,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/deep-equal": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
- "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dependencies": {
- "is-arguments": "^1.0.4",
- "is-date-object": "^1.0.1",
- "is-regex": "^1.0.4",
- "object-is": "^1.0.1",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.2.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
- "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
- "dependencies": {
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/defined": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz",
- "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/detect-browser": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz",
- "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w=="
- },
- "node_modules/dom-align": {
- "version": "1.12.4",
- "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz",
- "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw=="
- },
- "node_modules/dotignore": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz",
- "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==",
- "dependencies": {
- "minimatch": "^3.0.4"
- },
- "bin": {
- "ignored": "bin/ignored"
- }
- },
- "node_modules/electron-to-chromium": {
- "version": "1.4.500",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.500.tgz",
- "integrity": "sha512-P38NO8eOuWOKY1sQk5yE0crNtrjgjJj6r3NrbIKtG18KzCHmHE2Bt+aQA7/y0w3uYsHWxDa6icOohzjLJ4vJ4A==",
- "dev": true
- },
- "node_modules/es-abstract": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz",
- "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "arraybuffer.prototype.slice": "^1.0.1",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function.prototype.name": "^1.1.5",
- "get-intrinsic": "^1.2.1",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
- "is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.10",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.12.3",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.0",
- "safe-array-concat": "^1.0.0",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trim": "^1.2.7",
- "string.prototype.trimend": "^1.0.6",
- "string.prototype.trimstart": "^1.0.6",
- "typed-array-buffer": "^1.0.0",
- "typed-array-byte-length": "^1.0.0",
- "typed-array-byte-offset": "^1.0.0",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
- "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
- "dependencies": {
- "get-intrinsic": "^1.1.3",
- "has": "^1.0.3",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dependencies": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/esbuild": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
- "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.15.18",
- "@esbuild/linux-loong64": "0.15.18",
- "esbuild-android-64": "0.15.18",
- "esbuild-android-arm64": "0.15.18",
- "esbuild-darwin-64": "0.15.18",
- "esbuild-darwin-arm64": "0.15.18",
- "esbuild-freebsd-64": "0.15.18",
- "esbuild-freebsd-arm64": "0.15.18",
- "esbuild-linux-32": "0.15.18",
- "esbuild-linux-64": "0.15.18",
- "esbuild-linux-arm": "0.15.18",
- "esbuild-linux-arm64": "0.15.18",
- "esbuild-linux-mips64le": "0.15.18",
- "esbuild-linux-ppc64le": "0.15.18",
- "esbuild-linux-riscv64": "0.15.18",
- "esbuild-linux-s390x": "0.15.18",
- "esbuild-netbsd-64": "0.15.18",
- "esbuild-openbsd-64": "0.15.18",
- "esbuild-sunos-64": "0.15.18",
- "esbuild-windows-32": "0.15.18",
- "esbuild-windows-64": "0.15.18",
- "esbuild-windows-arm64": "0.15.18"
- }
- },
- "node_modules/esbuild-android-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
- "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-android-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
- "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-darwin-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
- "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-darwin-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
- "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-freebsd-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
- "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-freebsd-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
- "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-32": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
- "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
- "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-arm": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
- "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
- "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-mips64le": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
- "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-ppc64le": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
- "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-riscv64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
- "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-s390x": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
- "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-netbsd-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
- "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-openbsd-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
- "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-sunos-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
- "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-32": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
- "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
- "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
- "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "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": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/fecha": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
- "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
- },
- "node_modules/fmin": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/fmin/-/fmin-0.0.2.tgz",
- "integrity": "sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==",
- "dependencies": {
- "contour_plot": "^0.0.1",
- "json2module": "^0.0.3",
- "rollup": "^0.25.8",
- "tape": "^4.5.1",
- "uglify-js": "^2.6.2"
- }
- },
- "node_modules/fmin/node_modules/ansi-styles": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
- "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fmin/node_modules/chalk": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
- "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
- "dependencies": {
- "ansi-styles": "^2.2.1",
- "escape-string-regexp": "^1.0.2",
- "has-ansi": "^2.0.0",
- "strip-ansi": "^3.0.0",
- "supports-color": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fmin/node_modules/rollup": {
- "version": "0.25.8",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.25.8.tgz",
- "integrity": "sha512-a2S4Bh3bgrdO4BhKr2E4nZkjTvrJ2m2bWjMTzVYtoqSCn0HnuxosXnaJUHrMEziOWr3CzL9GjilQQKcyCQpJoA==",
- "dependencies": {
- "chalk": "^1.1.1",
- "minimist": "^1.2.0",
- "source-map-support": "^0.3.2"
- },
- "bin": {
- "rollup": "bin/rollup"
- }
- },
- "node_modules/fmin/node_modules/supports-color": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
- "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dependencies": {
- "is-callable": "^1.1.3"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
- },
- "node_modules/function.prototype.name": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
- "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "functions-have-names": "^1.2.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
- "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
- "dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gl-matrix": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
- "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
- "dependencies": {
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dependencies": {
- "get-intrinsic": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/has-ansi": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
- "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/has-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dependencies": {
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "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/internal-slot": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
- "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
- "dependencies": {
- "get-intrinsic": "^1.2.0",
- "has": "^1.0.3",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-arguments": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
- "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dependencies": {
- "has-bigints": "^1.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
- "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
- "dependencies": {
- "has": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
- "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
- "dependencies": {
- "which-typed-array": "^1.1.11"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
- },
- "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=="
- },
- "node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
- "dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/json2module": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/json2module/-/json2module-0.0.3.tgz",
- "integrity": "sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==",
- "dependencies": {
- "rw": "^1.3.2"
- },
- "bin": {
- "json2module": "bin/json2module"
- }
- },
- "node_modules/json2mq": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
- "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==",
- "dependencies": {
- "string-convert": "^0.2.0"
- }
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/lazy-cache": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
- "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/lodash-es": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
- "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
- },
- "node_modules/lodash.camelcase": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
- "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
- },
- "node_modules/longest": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
- "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/magic-string": {
- "version": "0.26.7",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz",
- "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==",
- "dev": true,
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "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.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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
- },
- "node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
- "dev": true
- },
- "node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-is": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
- "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "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": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "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=="
- },
- "node_modules/pdfast": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/pdfast/-/pdfast-0.2.0.tgz",
- "integrity": "sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA=="
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/postcss": {
- "version": "8.4.28",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
- "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/qrcode.react": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz",
- "integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==",
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
- }
- },
- "node_modules/rc-align": {
- "version": "4.0.15",
- "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz",
- "integrity": "sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "2.x",
- "dom-align": "^1.7.0",
- "rc-util": "^5.26.0",
- "resize-observer-polyfill": "^1.5.1"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-cascader": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.14.1.tgz",
- "integrity": "sha512-fCsgjLIQqYZMhFj9UT+x2ZW4uobx7OP5yivcn6Xto5fuxHaldphsryzCeUVmreQOHEo0RP+032Ip9RDzrKVKJA==",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "array-tree-filter": "^2.1.0",
- "classnames": "^2.3.1",
- "rc-select": "~14.7.0",
- "rc-tree": "~5.7.0",
- "rc-util": "^5.35.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-checkbox": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.1.0.tgz",
- "integrity": "sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "^2.3.2",
- "rc-util": "^5.25.2"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-collapse": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.1.tgz",
- "integrity": "sha512-N/7ejyiTf3XElNJBBpxqnZBUuMsQWEOPjB2QkfNvZ/Ca54eAvJXuOD1EGbCWCk2m7v/MSxku7mRpdeaLOCd4Gg==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "2.x",
- "rc-motion": "^2.3.4",
- "rc-util": "^5.27.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-dialog": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.1.0.tgz",
- "integrity": "sha512-5ry+JABAWEbaKyYsmITtrJbZbJys8CtMyzV8Xn4LYuXMeUx5XVHNyJRoqLFE4AzBuXXzOWeaC49cg+XkxK6kHA==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/portal": "^1.0.0-8",
- "classnames": "^2.2.6",
- "rc-motion": "^2.3.0",
- "rc-util": "^5.21.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-drawer": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-6.2.0.tgz",
- "integrity": "sha512-spPkZ3WvP0U0vy5dyzSwlUJ/+vLFtjP/cTwSwejhQRoDBaexSZHsBhELoCZcEggI7LQ7typmtG30lAue2HEhvA==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/portal": "^1.1.1",
- "classnames": "^2.2.6",
- "rc-motion": "^2.6.1",
- "rc-util": "^5.21.2"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-dropdown": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.1.0.tgz",
- "integrity": "sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw==",
- "dependencies": {
- "@babel/runtime": "^7.18.3",
- "@rc-component/trigger": "^1.7.0",
- "classnames": "^2.2.6",
- "rc-util": "^5.17.0"
- },
- "peerDependencies": {
- "react": ">=16.11.0",
- "react-dom": ">=16.11.0"
- }
- },
- "node_modules/rc-field-form": {
- "version": "1.36.2",
- "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.36.2.tgz",
- "integrity": "sha512-tCF/JjUsnxW80Gk4E4ZH74ONsaQMxVTRtui6XhQB8DJc4FHWLLa5pP8zwhxtPKC5NaO0QZ0Cv79JggDubn6n2g==",
- "dependencies": {
- "@babel/runtime": "^7.18.0",
- "async-validator": "^4.1.0",
- "rc-util": "^5.32.2"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-image": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.1.3.tgz",
- "integrity": "sha512-foMl1rcit1F0+vgxE5kf0c8TygQcHhILsOohQUL+JMUbzOo3OBFRcehJudYbqbCTArzCecS8nA1irUU9vvgQbg==",
- "dependencies": {
- "@babel/runtime": "^7.11.2",
- "@rc-component/portal": "^1.0.2",
- "classnames": "^2.2.6",
- "rc-dialog": "~9.1.0",
- "rc-motion": "^2.6.2",
- "rc-util": "^5.34.1"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-input": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.1.1.tgz",
- "integrity": "sha512-NTR1Z4em681L8/ewb2KR80RykSmN8I2mzqzJDCoUmTrV1BB9Hk5d7ha4TnfgdEPPL148N+603sW2LExSXk1IbA==",
- "dependencies": {
- "@babel/runtime": "^7.11.1",
- "classnames": "^2.2.1",
- "rc-util": "^5.18.1"
- },
- "peerDependencies": {
- "react": ">=16.0.0",
- "react-dom": ">=16.0.0"
- }
- },
- "node_modules/rc-input-number": {
- "version": "8.0.4",
- "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.0.4.tgz",
- "integrity": "sha512-TP+G5b7mZtbwXJ/YEZXF/OgbEZ6iqD4+RSuxZJ8VGKGXDcdt0FKIvpFoNQr/knspdFC4OxA0OfsWfFWfN4XSyA==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/mini-decimal": "^1.0.1",
- "classnames": "^2.2.5",
- "rc-input": "~1.1.0",
- "rc-util": "^5.28.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-mentions": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.5.0.tgz",
- "integrity": "sha512-rERXsbUTNVrb5T/iDC0ki/SRGWJnOVraDy6O25Us3FSpuUZ3uq2TPZB4fRk0Hss5kyiEPzz2sprhkI4b+F4jUw==",
- "dependencies": {
- "@babel/runtime": "^7.22.5",
- "@rc-component/trigger": "^1.5.0",
- "classnames": "^2.2.6",
- "rc-input": "~1.1.0",
- "rc-menu": "~9.10.0",
- "rc-textarea": "~1.3.0",
- "rc-util": "^5.22.5"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-menu": {
- "version": "9.10.0",
- "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.10.0.tgz",
- "integrity": "sha512-g27kpXaAoJh/fkPZF65/d4V+w4DhDeqomBdPcGnkFAcJnEM4o21TnVccrBUoDedLKzC7wJRw1Q7VTqEsfEufmw==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/trigger": "^1.6.2",
- "classnames": "2.x",
- "rc-motion": "^2.4.3",
- "rc-overflow": "^1.3.1",
- "rc-util": "^5.27.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-motion": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.7.3.tgz",
- "integrity": "sha512-2xUvo8yGHdOHeQbdI8BtBsCIrWKchEmFEIskf0nmHtJsou+meLd/JE+vnvSX2JxcBrJtXY2LuBpxAOxrbY/wMQ==",
- "dependencies": {
- "@babel/runtime": "^7.11.1",
- "classnames": "^2.2.1",
- "rc-util": "^5.21.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-notification": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.0.5.tgz",
- "integrity": "sha512-uEz2jggourwv/rR0obe7RHEa63UchqX4k+e+Qt2c3LaY7U9Tc+L6ANhzgCKYSA/afm0ebjmNZHoB5Cv47xEOcA==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "2.x",
- "rc-motion": "^2.6.0",
- "rc-util": "^5.20.1"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-overflow": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.1.tgz",
- "integrity": "sha512-RY0nVBlfP9CkxrpgaLlGzkSoh9JhjJLu6Icqs9E7CW6Ewh9s0peF9OHIex4OhfoPsR92LR0fN6BlCY9Z4VoUtA==",
- "dependencies": {
- "@babel/runtime": "^7.11.1",
- "classnames": "^2.2.1",
- "rc-resize-observer": "^1.0.0",
- "rc-util": "^5.19.2"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-pagination": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.6.1.tgz",
- "integrity": "sha512-R/sUnKKXx1Nm4kZfUKS3YKa7yEPF1ZkVB/AynQaHt+nMER7h9wPTfliDJFdYo+RM/nk2JD4Yc5QpUq8fIQHeug==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "^2.2.1",
- "rc-util": "^5.32.2"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-picker": {
- "version": "3.13.1",
- "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-3.13.1.tgz",
- "integrity": "sha512-211SrinX5IXZ9FMMDUMyPLuGOdfftUtd8zj4lqudpFxlMdtgV5+hXUJMBKb26xmDsleOm5iySK6KIHgiaI+U4w==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/trigger": "^1.5.0",
- "classnames": "^2.2.1",
- "rc-util": "^5.30.0"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "date-fns": ">= 2.x",
- "dayjs": ">= 1.x",
- "luxon": ">= 3.x",
- "moment": ">= 2.x",
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- },
- "peerDependenciesMeta": {
- "date-fns": {
- "optional": true
- },
- "dayjs": {
- "optional": true
- },
- "luxon": {
- "optional": true
- },
- "moment": {
- "optional": true
- }
- }
- },
- "node_modules/rc-progress": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.4.2.tgz",
- "integrity": "sha512-iAGhwWU+tsayP+Jkl9T4+6rHeQTG9kDz8JAHZk4XtQOcYN5fj9H34NXNEdRdZx94VUDHMqCb1yOIvi8eJRh67w==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "^2.2.6",
- "rc-util": "^5.16.1"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-rate": {
- "version": "2.12.0",
- "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.12.0.tgz",
- "integrity": "sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "^2.2.5",
- "rc-util": "^5.0.1"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-resize-observer": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz",
- "integrity": "sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg==",
- "dependencies": {
- "@babel/runtime": "^7.20.7",
- "classnames": "^2.2.1",
- "rc-util": "^5.27.0",
- "resize-observer-polyfill": "^1.5.1"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-segmented": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.2.2.tgz",
- "integrity": "sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA==",
- "dependencies": {
- "@babel/runtime": "^7.11.1",
- "classnames": "^2.2.1",
- "rc-motion": "^2.4.4",
- "rc-util": "^5.17.0"
- },
- "peerDependencies": {
- "react": ">=16.0.0",
- "react-dom": ">=16.0.0"
- }
- },
- "node_modules/rc-select": {
- "version": "14.7.4",
- "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.7.4.tgz",
- "integrity": "sha512-qRUpvMVXFy6rdHe+qzHXAqyQAfhErC/oY8dcRtoRjoz0lz2Nx3J+lLL5AnEbjnwlS+/kQTJUZ/65WyCwWwcLwQ==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/trigger": "^1.5.0",
- "classnames": "2.x",
- "rc-motion": "^2.0.1",
- "rc-overflow": "^1.3.1",
- "rc-util": "^5.16.1",
- "rc-virtual-list": "^3.5.2"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": "*",
- "react-dom": "*"
- }
- },
- "node_modules/rc-slider": {
- "version": "10.1.1",
- "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.1.1.tgz",
- "integrity": "sha512-gn8oXazZISEhnmRinI89Z/JD/joAaM35jp+gDtIVSTD/JJMCCBqThqLk1SVJmvtfeiEF/kKaFY0+qt4SDHFUDw==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "^2.2.5",
- "rc-util": "^5.27.0"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-steps": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz",
- "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==",
- "dependencies": {
- "@babel/runtime": "^7.16.7",
- "classnames": "^2.2.3",
- "rc-util": "^5.16.1"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-switch": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz",
- "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==",
- "dependencies": {
- "@babel/runtime": "^7.21.0",
- "classnames": "^2.2.1",
- "rc-util": "^5.30.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-table": {
- "version": "7.32.3",
- "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.32.3.tgz",
- "integrity": "sha512-MqjrI/ibuGg7NEyFsux0dM5GK+3er1gTiZofAkifr2bHf/Sa1nUqXXFmSrYXSOjwpx0xyBnJ3GrHFCIqC/eOzw==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "@rc-component/context": "^1.3.0",
- "classnames": "^2.2.5",
- "rc-resize-observer": "^1.1.0",
- "rc-util": "^5.27.1"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-tabs": {
- "version": "12.9.0",
- "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.9.0.tgz",
- "integrity": "sha512-2HnVowgMVrq0DfQtyu4mCd9E6pXlWNdM6VaDvOOHMsLYqPmpY+7zBqUC6YrrQ9xYXHciTS0e7TtjOHIvpVCHLQ==",
- "dependencies": {
- "@babel/runtime": "^7.11.2",
- "classnames": "2.x",
- "rc-dropdown": "~4.1.0",
- "rc-menu": "~9.10.0",
- "rc-motion": "^2.6.2",
- "rc-resize-observer": "^1.0.0",
- "rc-util": "^5.16.0"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-textarea": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.3.4.tgz",
- "integrity": "sha512-wn0YjTpvcVolcfXa0HtzL+jgV2QcwtfB29RwNAKj8hMgZOju1V24M3TfEDjABeQEAQbUGbjMbISREOX/YSVKhg==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "^2.2.1",
- "rc-input": "~1.1.0",
- "rc-resize-observer": "^1.0.0",
- "rc-util": "^5.27.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-tooltip": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.0.1.tgz",
- "integrity": "sha512-MdvPlsD1fDSxKp9+HjXrc/CxLmA/s11QYIh1R7aExxfodKP7CZA++DG1AjrW80F8IUdHYcR43HAm0Y2BYPelHA==",
- "dependencies": {
- "@babel/runtime": "^7.11.2",
- "@rc-component/trigger": "^1.0.4",
- "classnames": "^2.3.1"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-tree": {
- "version": "5.7.9",
- "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.9.tgz",
- "integrity": "sha512-1hKkToz/EVjJlMVwmZnpXeLXt/1iQMsaAq9m+GNkUbK746gkc7QpJXSN/TzjhTI5Hi+LOSlrMaXLMT0bHPqILQ==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "2.x",
- "rc-motion": "^2.0.1",
- "rc-util": "^5.16.1",
- "rc-virtual-list": "^3.5.1"
- },
- "engines": {
- "node": ">=10.x"
- },
- "peerDependencies": {
- "react": "*",
- "react-dom": "*"
- }
- },
- "node_modules/rc-tree-select": {
- "version": "5.11.2",
- "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.11.2.tgz",
- "integrity": "sha512-ujRFO3pcjSg8R4ndXX2oiNcCu+RgO9ZPcd23CZy18Khm+nRsfWWS3Su7qB0iuoJgzAJ5LK7b6Dio0t7IQDGs9g==",
- "dependencies": {
- "@babel/runtime": "^7.10.1",
- "classnames": "2.x",
- "rc-select": "~14.7.0",
- "rc-tree": "~5.7.0",
- "rc-util": "^5.16.1"
- },
- "peerDependencies": {
- "react": "*",
- "react-dom": "*"
- }
- },
- "node_modules/rc-upload": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.4.tgz",
- "integrity": "sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==",
- "dependencies": {
- "@babel/runtime": "^7.18.3",
- "classnames": "^2.2.5",
- "rc-util": "^5.2.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-util": {
- "version": "5.37.0",
- "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.37.0.tgz",
- "integrity": "sha512-cPMV8DzaHI1KDaS7XPRXAf4J7mtBqjvjikLpQieaeOO7+cEbqY2j7Kso/T0R0OiEZTNcLS/8Zl9YrlXiO9UbjQ==",
- "dependencies": {
- "@babel/runtime": "^7.18.3",
- "react-is": "^16.12.0"
- },
- "peerDependencies": {
- "react": ">=16.9.0",
- "react-dom": ">=16.9.0"
- }
- },
- "node_modules/rc-virtual-list": {
- "version": "3.10.5",
- "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.10.5.tgz",
- "integrity": "sha512-Vc89TL3JHfRlLVQXVj5Hmv0dIflgwmHDcbjt9lrZjOG3wNUDkTF5zci8kFDU/CzdmmqgKu+CUktEpT10VUKYSQ==",
- "dependencies": {
- "@babel/runtime": "^7.20.0",
- "classnames": "^2.2.6",
- "rc-resize-observer": "^1.0.0",
- "rc-util": "^5.36.0"
- },
- "engines": {
- "node": ">=8.x"
- },
- "peerDependencies": {
- "react": "*",
- "react-dom": "*"
- }
- },
- "node_modules/react": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
- "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
- "dependencies": {
- "loose-envify": "^1.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-content-loader": {
- "version": "5.1.4",
- "resolved": "https://registry.npmjs.org/react-content-loader/-/react-content-loader-5.1.4.tgz",
- "integrity": "sha512-hTq7pZi2GKCK6a9d3u6XStozm0QGCEjw8cSqQReiWnh2up6IwCha5R5TF0o6SY5qUDpByloEZEZtnFxpJyENFw==",
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "react": ">=16.0.0"
- }
- },
- "node_modules/react-dom": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
- "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
- "dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.0"
- },
- "peerDependencies": {
- "react": "^18.2.0"
- }
- },
- "node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
- },
- "node_modules/react-refresh": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
- "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-router": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.15.0.tgz",
- "integrity": "sha512-NIytlzvzLwJkCQj2HLefmeakxxWHWAP+02EGqWEZy+DgfHHKQMUoBBjUQLOtFInBMhWtb3hiUy6MfFgwLjXhqg==",
- "dependencies": {
- "@remix-run/router": "1.8.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "react": ">=16.8"
- }
- },
- "node_modules/react-router-dom": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.15.0.tgz",
- "integrity": "sha512-aR42t0fs7brintwBGAv2+mGlCtgtFQeOzK0BM1/OiqEzRejOZtpMZepvgkscpMUnKb8YO84G7s3LsHnnDNonbQ==",
- "dependencies": {
- "@remix-run/router": "1.8.0",
- "react-router": "6.15.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "react": ">=16.8",
- "react-dom": ">=16.8"
- }
- },
- "node_modules/regenerator-runtime": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
- "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
- "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "functions-have-names": "^1.2.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/resize-observer-polyfill": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
- "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
- },
- "node_modules/resolve": {
- "version": "1.22.4",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
- "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==",
- "dependencies": {
- "is-core-module": "^2.13.0",
- "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/resumer": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
- "integrity": "sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w==",
- "dependencies": {
- "through": "~2.3.4"
- }
- },
- "node_modules/right-align": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
- "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==",
- "dependencies": {
- "align-text": "^0.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/rollup": {
- "version": "2.79.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
- "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=10.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/rw": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
- "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
- },
- "node_modules/safe-array-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
- "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">=0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-regex-test": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
- "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-regex": "^1.1.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/scheduler": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
- "dependencies": {
- "loose-envify": "^1.1.0"
- }
- },
- "node_modules/scroll-into-view-if-needed": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz",
- "integrity": "sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg==",
- "dependencies": {
- "compute-scroll-into-view": "^3.0.2"
- }
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/size-sensor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/size-sensor/-/size-sensor-1.0.2.tgz",
- "integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw=="
- },
- "node_modules/source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.3.3.tgz",
- "integrity": "sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==",
- "dependencies": {
- "source-map": "0.1.32"
- }
- },
- "node_modules/source-map-support/node_modules/source-map": {
- "version": "0.1.32",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz",
- "integrity": "sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==",
- "dependencies": {
- "amdefine": ">=0.0.4"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/sourcemap-codec": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
- "deprecated": "Please use @jridgewell/sourcemap-codec instead",
- "dev": true
- },
- "node_modules/string-convert": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz",
- "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="
- },
- "node_modules/string.prototype.trim": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
- "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
- "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
- "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/stylis": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz",
- "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ=="
- },
- "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==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tape": {
- "version": "4.16.2",
- "resolved": "https://registry.npmjs.org/tape/-/tape-4.16.2.tgz",
- "integrity": "sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg==",
- "dependencies": {
- "call-bind": "~1.0.2",
- "deep-equal": "~1.1.1",
- "defined": "~1.0.1",
- "dotignore": "~0.1.2",
- "for-each": "~0.3.3",
- "glob": "~7.2.3",
- "has": "~1.0.3",
- "inherits": "~2.0.4",
- "is-regex": "~1.1.4",
- "minimist": "~1.2.7",
- "object-inspect": "~1.12.3",
- "resolve": "~1.22.1",
- "resumer": "~0.0.0",
- "string.prototype.trim": "~1.2.7",
- "through": "~2.3.8"
- },
- "bin": {
- "tape": "bin/tape"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/throttle-debounce": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
- "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==",
- "engines": {
- "node": ">=12.22"
- }
- },
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
- },
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/toggle-selection": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
- "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
- },
- "node_modules/tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
- },
- "node_modules/typed-array-buffer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
- "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
- "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-byte-offset": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
- "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/uglify-js": {
- "version": "2.8.29",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
- "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==",
- "dependencies": {
- "source-map": "~0.5.1",
- "yargs": "~3.10.0"
- },
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- },
- "optionalDependencies": {
- "uglify-to-browserify": "~1.0.0"
- }
- },
- "node_modules/uglify-to-browserify": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
- "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==",
- "optional": true
- },
- "node_modules/unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
- "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/vite": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz",
- "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.15.9",
- "postcss": "^8.4.18",
- "resolve": "^1.22.1",
- "rollup": "^2.79.1"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@types/node": ">= 14",
- "less": "*",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
- "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/window-size": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
- "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/wordwrap": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
- "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
- "node_modules/yargs": {
- "version": "3.10.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
- "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==",
- "dependencies": {
- "camelcase": "^1.0.2",
- "cliui": "^2.1.0",
- "decamelize": "^1.0.0",
- "window-size": "0.1.0"
- }
- }
- }
-}
diff --git a/cmd/token-wallet/frontend/package.json b/cmd/token-wallet/frontend/package.json
deleted file mode 100644
index 00b4327..0000000
--- a/cmd/token-wallet/frontend/package.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "frontend",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "preview": "vite preview"
- },
- "dependencies": {
- "@ant-design/icons": "^5.2.5",
- "@ant-design/plots": "^1.2.5",
- "antd": "^5.8.4",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-router-dom": "^6.15.0"
- },
- "devDependencies": {
- "@types/react": "^18.0.17",
- "@types/react-dom": "^18.0.6",
- "@vitejs/plugin-react": "^2.0.1",
- "vite": "^3.0.7"
- }
-}
diff --git a/cmd/token-wallet/frontend/package.json.md5 b/cmd/token-wallet/frontend/package.json.md5
deleted file mode 100755
index e2d26f0..0000000
--- a/cmd/token-wallet/frontend/package.json.md5
+++ /dev/null
@@ -1 +0,0 @@
-a20b9b1db483d12bcdf41beb1f25c356
\ No newline at end of file
diff --git a/cmd/token-wallet/frontend/src/App.css b/cmd/token-wallet/frontend/src/App.css
deleted file mode 100644
index 000d801..0000000
--- a/cmd/token-wallet/frontend/src/App.css
+++ /dev/null
@@ -1,59 +0,0 @@
-#app {
- height: 100vh;
- text-align: center;
-}
-
-#logo {
- display: block;
- width: 50%;
- height: 50%;
- margin: auto;
- padding: 10% 0 0;
- background-position: center;
- background-repeat: no-repeat;
- background-size: 100% 100%;
- background-origin: content-box;
-}
-
-.result {
- height: 20px;
- line-height: 20px;
- margin: 1.5rem auto;
-}
-
-.input-box .btn {
- width: 60px;
- height: 30px;
- line-height: 30px;
- border-radius: 3px;
- border: none;
- margin: 0 0 0 20px;
- padding: 0 8px;
- cursor: pointer;
-}
-
-.input-box .btn:hover {
- background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
- color: #333333;
-}
-
-.input-box .input {
- border: none;
- border-radius: 3px;
- outline: none;
- height: 30px;
- line-height: 30px;
- padding: 0 10px;
- background-color: rgba(240, 240, 240, 1);
- -webkit-font-smoothing: antialiased;
-}
-
-.input-box .input:hover {
- border: none;
- background-color: rgba(255, 255, 255, 1);
-}
-
-.input-box .input:focus {
- border: none;
- background-color: rgba(255, 255, 255, 1);
-}
diff --git a/cmd/token-wallet/frontend/src/App.jsx b/cmd/token-wallet/frontend/src/App.jsx
deleted file mode 100644
index 46ed276..0000000
--- a/cmd/token-wallet/frontend/src/App.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import NavBar from "./components/NavBar";
-import { GetCommitHash, OpenLink } from "../wailsjs/go/main/App";
-import { App as AApp, FloatButton, Layout, Row, Typography } from "antd";
-import { useEffect, useState } from "react";
-import { Outlet } from "react-router-dom";
-import logo from "./assets/images/hypersdk.png";
-
-const { Text } = Typography;
-const { Content } = Layout;
-
-const App = () => {
- const [commit, setCommit] = useState("");
- useEffect(() => {
- const getCommit = async () => {
- const c = await GetCommitHash();
- setCommit(c);
- };
- getCommit();
- }, []);
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- {OpenLink("https://github.com/ava-labs/hypersdk")}}>
-
-
-
-
- Commit: {commit}
-
-
-
- );
-};
-
-export default App;
diff --git a/cmd/token-wallet/frontend/src/assets/images/hypersdk.png b/cmd/token-wallet/frontend/src/assets/images/hypersdk.png
deleted file mode 100644
index 68bc317..0000000
Binary files a/cmd/token-wallet/frontend/src/assets/images/hypersdk.png and /dev/null differ
diff --git a/cmd/token-wallet/frontend/src/assets/images/logo-universal.png b/cmd/token-wallet/frontend/src/assets/images/logo-universal.png
deleted file mode 100644
index 2b45c47..0000000
Binary files a/cmd/token-wallet/frontend/src/assets/images/logo-universal.png and /dev/null differ
diff --git a/cmd/token-wallet/frontend/src/components/Explorer.jsx b/cmd/token-wallet/frontend/src/components/Explorer.jsx
deleted file mode 100644
index 6487828..0000000
--- a/cmd/token-wallet/frontend/src/components/Explorer.jsx
+++ /dev/null
@@ -1,235 +0,0 @@
-import { useEffect, useState } from "react";
-import {
- GetLatestBlocks,
- GetTransactionStats,
- GetAccountStats,
- GetUnitPrices,
- GetChainID,
-} from "../../wailsjs/go/main/App";
-import { App, Typography, Divider, List, Card, Col, Row, Popover } from "antd";
-import { InfoCircleOutlined } from "@ant-design/icons";
-import { Area, Line } from "@ant-design/plots";
-const { Title, Text } = Typography;
-
-const Explorer = () => {
- const { message } = App.useApp();
- const [blocks, setBlocks] = useState([]);
- const [transactionStats, setTransactionStats] = useState([]);
- const [accountStats, setAccountStats] = useState([]);
- const [unitPrices, setUnitPrices] = useState([]);
- const [chainID, setChainID] = useState("");
-
- useEffect(() => {
- const getLatestBlocks = async () => {
- GetLatestBlocks()
- .then((blocks) => {
- setBlocks(blocks);
- })
- .catch((error) => {
- message.open({
- type: "error",
- content: error,
- });
- });
- };
-
- const getChainID = async () => {
- GetChainID()
- .then((chainID) => {
- setChainID(chainID);
- })
- .catch((error) => {
- message.open({
- type: "error",
- content: error,
- });
- });
- };
- getChainID();
-
- const getTransactionStats = async () => {
- GetTransactionStats()
- .then((stats) => {
- setTransactionStats(stats);
- })
- .catch((error) => {
- message.open({
- type: "error",
- content: error,
- });
- });
- };
-
- const getAccountStats = async () => {
- GetAccountStats()
- .then((stats) => {
- setAccountStats(stats);
- })
- .catch((error) => {
- message.open({
- type: "error",
- content: error,
- });
- });
- };
-
- const getUnitPrices = async () => {
- GetUnitPrices()
- .then((prices) => {
- setUnitPrices(prices);
- })
- .catch((error) => {
- message.open({
- type: "error",
- content: error,
- });
- });
- };
-
- getLatestBlocks();
- getTransactionStats();
- getAccountStats();
- getUnitPrices();
- const interval = setInterval(() => {
- getLatestBlocks();
- getTransactionStats();
- getAccountStats();
- getUnitPrices();
- }, 500);
-
- return () => clearInterval(interval);
- }, []);
-
- return (
- <>
-
-
-
- Collection of TokenNet Telemetry Over the Last 2 Minutes
-
-
-
- Transactions Per Second: # of transactions
- accepted per second
-
- Active Accounts: # of accounts issusing
- transactions
-
- Unit Prices: Price of each HyperSDK fee
- dimension (Bandwidth, Compute, Storage[Read], Storage[Create],
- Storage[Modify])
-
- }>
- Metrics
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Recent activity for TokenNet (ChainID: {chainID})
-
-
-
- Timestamp: Time that block was created
-
- Transactions: # of successful transactions in
- block
-
- Units Consumed: # of HyperSDK fee units
- consumed
-
- State Root: Merkle root of State at start of
- block execution
-
- Block Size: Size of block in bytes
-
- Accept Latency: Difference between block
- creation and block acceptance
-
- }>
- Blocks
-
-
- (
-
-
-
- {item.Height}
- {" "}
- {item.ID}
-
- Timestamp: {item.Timestamp}
-
- Transactions: {item.Txs}
- {item.Txs > 0 && (
-
- {" "}
- (failed: {item.FailTxs})
-
- )}
-
- Units Consumed: {item.Consumed}
-
- State Root: {item.StateRoot}
-
- Block Size: {item.Size}
-
- Accept Latency: {item.Latency}ms
-
- )}
- />
- >
- );
-};
-
-export default Explorer;
diff --git a/cmd/token-wallet/frontend/src/components/Faucet.jsx b/cmd/token-wallet/frontend/src/components/Faucet.jsx
deleted file mode 100644
index 18e3da7..0000000
--- a/cmd/token-wallet/frontend/src/components/Faucet.jsx
+++ /dev/null
@@ -1,168 +0,0 @@
-import { useEffect, useState } from "react";
-import {
- App,
- Divider,
- List,
- Card,
- Typography,
- Button,
- Spin,
-} from "antd";
-import {
- CheckCircleTwoTone,
- CloseCircleTwoTone,
- LoadingOutlined,
-} from "@ant-design/icons";
-import {
- StartFaucetSearch,
- GetFaucetSolutions,
-} from "../../wailsjs/go/main/App";
-const { Text } = Typography;
-
-const antIcon = ;
-
-const Faucet = () => {
- const { message } = App.useApp();
- const [loaded, setLoaded] = useState(false);
- const [search, setSearch] = useState(null);
- const [solutions, setSolutions] = useState([]);
-
- const startSearch = async () => {
- const newSearch = await StartFaucetSearch();
- setSearch(newSearch);
- };
-
- useEffect(() => {
- const getFaucetSolutions = async () => {
- const faucetSolutions = await GetFaucetSolutions();
- if (faucetSolutions.Alerts !== null) {
- for (var Alert of faucetSolutions.Alerts) {
- message.open({
- type: Alert.Type,
- content: Alert.Content,
- });
- }
- }
- setSearch(faucetSolutions.CurrentSearch);
- setSolutions(faucetSolutions.PastSearches);
- setLoaded(true);
- };
-
- getFaucetSolutions();
- const interval = setInterval(() => {
- getFaucetSolutions();
- }, 500);
-
- return () => clearInterval(interval);
- }, []);
-
- return (
- <>
-
-
- {loaded && search === null && (
-
-
- To protect against bots, TokenNet requires anyone requesting
- funds to solve a Proof-of-Work puzzle. This takes most modern
- computers 30-60 seconds.
-
-
-
-
- While your computer is working on this puzzle, you can browse
- other parts of Token Wallet. You will receive a notifcation when
- your computer solved a puzzle and received funds.
-
-
-
- Request
-
-
- )}
- {loaded && search !== null && (
-
-
-
-
-
- Search Running...
-
-
- (You can leave this page and come back!)
-
-
-
-
-
Faucet Address:
- {search.FaucetAddress}
-
-
Salt:
- {search.Salt}
-
-
Difficulty:
- {search.Difficulty}
-
- )}
-
-
-
Previous Requests
-
(
-
- {item.Err.length > 0 && (
-
-
- {item.Solution}
-
-
-
Salt: {item.Salt}
-
-
Difficulty: {item.Difficulty}
-
-
Attempts: {item.Attempts}
-
-
Elapsed: {item.Elapsed}
-
-
Error: {item.Err}
-
- )}
- {item.Err.length == 0 && (
-
-
- {item.Solution}
-
-
-
Salt: {item.Salt}
-
-
Difficulty: {item.Difficulty}
-
-
Attempts: {item.Attempts}
-
-
Elapsed: {item.Elapsed}
-
-
Amount: {item.Amount}
-
-
TxID: {item.TxID}
-
- )}
-
- )}
- />
-
- >
- );
-};
-export default Faucet;
diff --git a/cmd/token-wallet/frontend/src/components/Feed.jsx b/cmd/token-wallet/frontend/src/components/Feed.jsx
deleted file mode 100644
index fbd4d3a..0000000
--- a/cmd/token-wallet/frontend/src/components/Feed.jsx
+++ /dev/null
@@ -1,413 +0,0 @@
-import { useEffect, useState } from "react";
-import {
- GetFeedInfo,
- GetFeed,
- Message,
- OpenLink,
- GetBalance,
- Transfer as Send,
-} from "../../wailsjs/go/main/App";
-import FundsCheck from "./FundsCheck";
-import { LinkOutlined, InfoCircleOutlined } from "@ant-design/icons";
-import {
- App,
- Input,
- Typography,
- Divider,
- List,
- Button,
- Drawer,
- Form,
- Popover,
- Select,
- InputNumber,
-} from "antd";
-const { Title, Text } = Typography;
-
-const Feed = () => {
- const { message } = App.useApp();
- const [feed, setFeed] = useState([]);
- const [feedInfo, setFeedInfo] = useState({});
- const [openCreate, setOpenCreate] = useState(false);
- const [createForm] = Form.useForm();
- const [openTip, setOpenTip] = useState(false);
- const [tipFocus, setTipFocus] = useState({});
- const [tipForm] = Form.useForm();
- const key = "updatable";
-
- {
- /* Create Handlers */
- }
- const showCreateDrawer = () => {
- setOpenCreate(true);
- };
-
- const onCloseCreate = () => {
- createForm.resetFields();
- setOpenCreate(false);
- };
-
- const onFinishCreate = (values) => {
- console.log("Success:", values);
- createForm.resetFields();
- setOpenCreate(false);
-
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- await Message(values.Message, values.URL);
- const finish = new Date().getTime();
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishCreateFailed = (errorInfo) => {
- console.log("Failed:", errorInfo);
- };
-
- {
- /* Tip Handlers */
- }
- const [balance, setBalance] = useState([]);
- const getBalance = async () => {
- const bals = await GetBalance();
- const parsedBalances = [];
- for (let i = 0; i < bals.length; i++) {
- parsedBalances.push({ value: bals[i].ID, label: bals[i].Bal });
- }
- setBalance(parsedBalances);
- };
- const showTipDrawer = (item) => {
- setTipFocus(item);
- setOpenTip(true);
- };
-
- const onCloseTip = () => {
- tipForm.resetFields();
- setOpenTip(false);
- };
-
- const onFinishTip = (values) => {
- console.log("Success:", values);
- tipForm.resetFields();
- setOpenTip(false);
-
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- await Send(
- values.Asset,
- tipFocus.Address,
- values.Amount,
- `[${tipFocus.ID}]: ${values.Memo}`
- );
- const finish = new Date().getTime();
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- getBalance();
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishTipFailed = (errorInfo) => {
- console.log("Failed:", errorInfo);
- };
-
- const openLink = (url) => {
- OpenLink(url);
- };
-
- useEffect(() => {
- getBalance();
-
- const getFeed = async () => {
- const feed = await GetFeed();
- console.log(feed);
- setFeed(feed);
- };
- const getFeedInfo = async () => {
- const feedInfo = await GetFeedInfo();
- setFeedInfo(feedInfo);
- };
-
- getFeed();
- getFeedInfo();
- const interval = setInterval(() => {
- getFeed();
- getFeedInfo();
- }, 500);
-
- return () => clearInterval(interval);
- }, []);
-
- return (
- <>
-
-
-
- Posts
-
- Because the fees are slow on TokenNet, it is great for
- micropayments.
-
-
- This example allows anyone to pay the feed operator to post
- content for everyone else to see.
-
-
- If the amount of posts goes above the target/5 minutes, the fee
- to post will increase.
-
-
- You can tip posters with any token you own!
-
- }>
- {" "}
-
-
-
-
-
- Create Post
-
-
- (
-
- {item.URL.length == 0 && (
-
-
- {item.Message}
-
-
-
- )}
- {item.URL.length > 0 && (
-
- {item.URLMeta != null && (
-
- {item.URLMeta.Image.length > 0 && (
-
- )}
-
- {item.URLMeta.Title}
- {" "}
-
{
- openLink(item.URLMeta.URL);
- }}
- style={{ margin: "0" }}>
- {item.URLMeta.Host}
-
-
- {item.URLMeta.Description.length > 0 && (
-
- {item.URLMeta.Description}
-
-
-
- )}
-
URL: {item.URL}
-
-
Message: {item.Message}
-
-
- )}
- {item.URLMeta == null && (
-
-
- {item.Message}
-
-
- URL: {item.URL} (
- not reachable )
-
-
- )}
-
- )}
- TxID: {item.ID}
-
- Timestamp: {item.Timestamp}
-
- Fee: {item.Fee}
-
- Actor: {item.Address}
-
- showTipDrawer(item)}>
- Tip
-
-
- )}
- />
-
-
- Create Post
-
- Posts can include both a "message" and a "URL".
-
-
- When posting content, you must pay the "feed fee" to the
- operator that hosts the feed (will be a HyperSDK Program in
- the future).
-
-
- The Token Wallet will attempt to preview posted URLs on the
- feed.
-
-
- The Token Wallet is not able to parse X or Reddit links yet.
- If you'd like to implement that, please reach out!
-
- }>
- {" "}
-
-
- >
- }
- placement={"right"}
- onClose={onCloseCreate}
- open={openCreate}>
- Feed Fee: ~{feedInfo.Fee}
-
-
-
-
-
-
-
-
- Create
-
-
-
-
-
- Send Tip
-
- {" "}
-
-
- >
- }
- placement={"right"}
- onClose={onCloseTip}
- open={openTip}>
-
-
-
-
-
-
-
-
-
-
-
- Tip
-
-
-
-
- >
- );
-};
-
-export default Feed;
diff --git a/cmd/token-wallet/frontend/src/components/FillOrder.jsx b/cmd/token-wallet/frontend/src/components/FillOrder.jsx
deleted file mode 100644
index 54477a7..0000000
--- a/cmd/token-wallet/frontend/src/components/FillOrder.jsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { useRef } from "react";
-import { App, InputNumber, Button } from "antd";
-import { FillOrder as FOrder } from "../../wailsjs/go/main/App";
-
-const FillOrder = ({ order }) => {
- const { message } = App.useApp();
- const amount = useRef("");
- const key = "updatable";
-
- const valueUpdate = (event) => {
- amount.current = event;
- };
-
- const fillOrder = () => {
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- console.log(order, amount.current);
- await FOrder(
- order.ID,
- order.Owner,
- order.InID,
- order.InputStep,
- order.OutID,
- amount.current
- );
- const finish = new Date().getTime();
- amount.current = "";
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- return (
- <>
-
-
- Fill
-
- >
- );
-};
-export default FillOrder;
diff --git a/cmd/token-wallet/frontend/src/components/FundsCheck.jsx b/cmd/token-wallet/frontend/src/components/FundsCheck.jsx
deleted file mode 100644
index 52768d8..0000000
--- a/cmd/token-wallet/frontend/src/components/FundsCheck.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Alert } from "antd";
-import { Link } from "react-router-dom";
-
-const FundsCheck = () => {
- return (
- <>
- {!window.HasBalance && (
-
-
- To interact with TokenNet, you need some funds in your account.
- You can request funds from the Faucet.
-
- }
- type="warning"
- />
-
- )}
- >
- );
-};
-
-export default FundsCheck;
diff --git a/cmd/token-wallet/frontend/src/components/Mint.jsx b/cmd/token-wallet/frontend/src/components/Mint.jsx
deleted file mode 100644
index 25ea592..0000000
--- a/cmd/token-wallet/frontend/src/components/Mint.jsx
+++ /dev/null
@@ -1,410 +0,0 @@
-import { useEffect, useState } from "react";
-import {
- GetMyAssets,
- CreateAsset,
- MintAsset,
- GetAddressBook,
- AddAddressBook,
-} from "../../wailsjs/go/main/App";
-import FundsCheck from "./FundsCheck";
-import { PlusOutlined, InfoCircleOutlined } from "@ant-design/icons";
-import {
- App,
- Select,
- Input,
- InputNumber,
- Space,
- Typography,
- Divider,
- List,
- Button,
- Drawer,
- Form,
- Popover,
-} from "antd";
-const { Title, Text } = Typography;
-
-const Mint = () => {
- const { message } = App.useApp();
- const [assets, setAssets] = useState([]);
- const [openCreate, setOpenCreate] = useState(false);
- const [openMint, setOpenMint] = useState(false);
- const [mintFocus, setMintFocus] = useState({});
- const [createForm] = Form.useForm();
- const [mintForm] = Form.useForm();
- const key = "updatable";
-
- {
- /* Create Handlers */
- }
- const showCreateDrawer = () => {
- setOpenCreate(true);
- };
-
- const onCloseCreate = () => {
- createForm.resetFields();
- setOpenCreate(false);
- };
-
- const onFinishCreate = (values) => {
- console.log("Success:", values);
- createForm.resetFields();
- setOpenCreate(false);
-
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- await CreateAsset(values.Symbol, values.Decimals, values.Metadata);
- const finish = new Date().getTime();
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishCreateFailed = (errorInfo) => {
- console.log("Failed:", errorInfo);
- };
-
- {
- /* Address Book */
- }
- const [addresses, setAddresses] = useState([]);
- const [newNickname, setNewNickname] = useState("");
- const [newAddress, setNewAddress] = useState("");
- const [addAllowed, setAddAllowed] = useState(false);
-
- const onNicknameChange = (event) => {
- setNewNickname(event.target.value);
- if (event.target.value.length > 0 && newAddress.length > 10) {
- setAddAllowed(true);
- } else {
- setAddAllowed(false);
- }
- };
- const onAddressChange = (event) => {
- setNewAddress(event.target.value);
- if (newNickname.length > 0 && event.target.value.length > 10) {
- setAddAllowed(true);
- } else {
- setAddAllowed(false);
- }
- };
-
- const getAddresses = async () => {
- const caddresses = await GetAddressBook();
- setAddresses(caddresses);
- };
-
- const addAddress = (e) => {
- e.preventDefault();
- (async () => {
- try {
- await AddAddressBook(newNickname, newAddress);
- setNewNickname("");
- setNewAddress("");
- await getAddresses();
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- {
- /* Mint Handlers */
- }
- const showMintDrawer = (item) => {
- setMintFocus(item);
- setOpenMint(true);
- };
-
- const onCloseMint = () => {
- mintForm.resetFields();
- setOpenMint(false);
- };
-
- const onFinishMint = (values) => {
- console.log("Success:", values);
- mintForm.resetFields();
- setOpenMint(false);
-
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- await MintAsset(mintFocus.ID, values.Address, values.Amount);
- const finish = new Date().getTime();
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishMintFailed = (errorInfo) => {
- console.log("Failed:", errorInfo);
- };
-
- useEffect(() => {
- const getMyAssets = async () => {
- const assets = await GetMyAssets();
- setAssets(assets);
- };
-
- getAddresses();
- getMyAssets();
- const interval = setInterval(() => {
- getMyAssets();
- }, 500);
-
- return () => clearInterval(interval);
- }, []);
-
- return (
- <>
-
-
-
- Tokens
-
- On TokenNet, anyone can mint their own token.
-
-
- Once you create your own token, it will show up below!
-
- }>
- {" "}
-
-
-
-
-
- Create Token
-
-
- (
-
-
-
- {item.Symbol}
- {" "}
- {item.ID}
-
- Decimals: {item.Decimals}{" "}
- Metadata: {item.Metadata}
-
- Supply: {item.Supply}
-
- showMintDrawer(item)}>
- Mint
-
-
- )}
- />
-
-
- Create Token
-
- When creating your own token, you get to set the symbol,
- decimals, and metadata.
-
-
- Once your token is created, you can mint it to anyone you want
- (including yourself).
-
-
- Be careful! Once you set these values, they cannot be changed.
-
- }>
- {" "}
-
-
- >
- }
- placement={"right"}
- onClose={onCloseCreate}
- open={openCreate}>
-
-
-
-
-
-
-
-
-
-
-
- Create
-
-
-
-
-
- Mint ${mintFocus.Symbol}
-
- You can mint ${mintFocus.Symbol} to anyone on the TokenNet and
- it will show up in their account.
-
-
- You can send parts of a ${mintFocus.Symbol} by using decimals
- in the "Amount" field below.
-
- }>
- {" "}
-
-
- >
- }
- placement={"right"}
- onClose={onCloseMint}
- open={openMint}>
-
- (
- <>
- {menu}
-
-
-
-
- }
- onClick={addAddress}
- disabled={!addAllowed}>
-
- >
- )}
- options={addresses.map((item) => ({
- label: item.AddrStr,
- value: item.Address,
- }))}
- />
-
-
-
-
-
-
- Mint
-
-
-
-
- >
- );
-};
-
-export default Mint;
diff --git a/cmd/token-wallet/frontend/src/components/NavBar.jsx b/cmd/token-wallet/frontend/src/components/NavBar.jsx
deleted file mode 100644
index 18ccc91..0000000
--- a/cmd/token-wallet/frontend/src/components/NavBar.jsx
+++ /dev/null
@@ -1,198 +0,0 @@
-import { useEffect, useState } from "react";
-import {
- GetBalance,
- GetTransactions,
- GetAddress,
-} from "../../wailsjs/go/main/App";
-import {
- WalletTwoTone,
- DashboardOutlined,
- BankOutlined,
- SendOutlined,
- SwapOutlined,
- GoldOutlined,
- CheckCircleTwoTone,
- CloseCircleTwoTone,
- ContainerOutlined,
-} from "@ant-design/icons";
-import { App, Layout, Menu, Typography, Drawer, List, Divider } from "antd";
-const { Text, Link } = Typography;
-import { useLocation, Link as RLink } from "react-router-dom";
-import logo from "../assets/images/logo-universal.png";
-
-const NavBar = () => {
- const location = useLocation();
- const { message } = App.useApp();
- const [balance, setBalance] = useState([]);
- const [nativeBalance, setNativeBalance] = useState({});
- const [transactions, setTransactions] = useState([]);
- const [address, setAddress] = useState("");
- const [open, setOpen] = useState(false);
-
- const items = [
- {
- label: Explorer ,
- key: "explorer",
- icon: ,
- },
- {
- label: Faucet ,
- key: "faucet",
- icon: ,
- },
- {
- label: Mint ,
- key: "mint",
- icon: ,
- },
- {
- label: Transfer ,
- key: "transfer",
- icon: ,
- },
- {
- label: Trade ,
- key: "trade",
- icon: ,
- },
- {
- label: Feed ,
- key: "feed",
- icon: ,
- },
- ];
-
- const showDrawer = () => {
- setOpen(true);
- };
-
- const onClose = () => {
- setOpen(false);
- };
-
- useEffect(() => {
- const getAddress = async () => {
- const address = await GetAddress();
- setAddress(address);
- };
- getAddress();
-
- const getBalance = async () => {
- const newBalance = await GetBalance();
- for (var bal of newBalance) {
- if (bal.ID == "11111111111111111111111111111111LpoYY") {
- setNativeBalance(bal);
- {
- /* TODO: switch to using context */
- }
- window.HasBalance = bal.Has;
- break;
- }
- }
- setBalance(newBalance);
- };
-
- const getTransactions = async () => {
- const txs = await GetTransactions();
- if (txs.Alerts !== null) {
- for (var Alert of txs.Alerts) {
- message.open({
- icon: ,
- type: Alert.Type,
- content: Alert.Content,
- });
- }
- }
- setTransactions(txs.TxInfos);
- };
-
- getBalance();
- getTransactions();
- const interval = setInterval(() => {
- getBalance();
- getTransactions();
- }, 500);
-
- return () => clearInterval(interval);
- }, []);
-
- return (
- <>
-
-
-
-
- {balance.length > 0 && (
-
-
- {nativeBalance.Str}
-
-
- )}
- 1
- ? [location.pathname.slice(1)]
- : ["explorer"]
- }
- />
- {address}}
- size={"large"}
- placement="right"
- onClose={onClose}
- open={open}>
- {/* use a real data source */}
- Tokens
- (
-
- {item.Str}
-
- )}
- />
- Transactions
- (
-
-
- {item.ID}
- {!item.Success && (
-
- )}
- {item.Success && (
-
- )}
-
- Type: {item.Type}
-
- Timestamp: {item.Timestamp}
-
- Units: {item.Units}
-
- Size: {item.Size}
-
- Summary: {item.Summary}
-
- Fee: {item.Fee}
-
- Actor: {item.Actor}
-
- )}
- />
-
-
- >
- );
-};
-
-export default NavBar;
diff --git a/cmd/token-wallet/frontend/src/components/Trade.jsx b/cmd/token-wallet/frontend/src/components/Trade.jsx
deleted file mode 100644
index f51800b..0000000
--- a/cmd/token-wallet/frontend/src/components/Trade.jsx
+++ /dev/null
@@ -1,530 +0,0 @@
-import { useEffect, useState, useRef } from "react";
-import {
- Space,
- App,
- Drawer,
- Divider,
- List,
- Typography,
- Form,
- Input,
- InputNumber,
- Button,
- Select,
- Popover,
-} from "antd";
-import {
- PlusOutlined,
- DoubleRightOutlined,
- InfoCircleOutlined,
-} from "@ant-design/icons";
-import {
- GetBalance,
- GetAllAssets,
- AddAsset,
- GetMyOrders,
- GetOrders,
- CreateOrder,
- CloseOrder,
-} from "../../wailsjs/go/main/App";
-import FundsCheck from "./FundsCheck";
-const { Text } = Typography;
-import FillOrder from "./FillOrder";
-
-const Trade = () => {
- const { message } = App.useApp();
- const key = "updatable";
-
- {
- /* Create Handlers */
- }
- const [openCreate, setOpenCreate] = useState(false);
- const [createForm] = Form.useForm();
- const showCreateDrawer = () => {
- setOpenCreate(true);
- };
-
- const onCloseCreate = () => {
- createForm.resetFields();
- setOpenCreate(false);
- };
-
- const onFinishCreate = (values) => {
- console.log("Success:", values);
- createForm.resetFields();
- setOpenCreate(false);
-
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- await CreateOrder(
- values.InSymbol,
- values.InTick,
- values.OutSymbol,
- values.OutTick,
- values.Supply
- );
- const finish = new Date().getTime();
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishCreateFailed = (errorInfo) => {
- console.log("Failed:", errorInfo);
- };
-
- const [balance, setBalance] = useState([]);
- const getBalance = async () => {
- const bals = await GetBalance();
- console.log(bals);
- const parsedBalances = [];
- for (let i = 0; i < bals.length; i++) {
- parsedBalances.push({ value: bals[i].ID, label: bals[i].Bal });
- }
- setBalance(parsedBalances);
- };
-
- {
- /* Symbol Add (only on out) */
- }
- const [assets, setAssets] = useState([]);
- const [outAssets, setOutAssets] = useState([]);
- const [newAsset, setNewAsset] = useState("");
- const [addAllowed, setAddAllowed] = useState(false);
- const [outAllowed, setOutAllowed] = useState(false);
-
- {
- /* Must use references because we want latest value after construction */
- }
- const inAsset = useRef("");
- const outAsset = useRef("");
-
- const inSelected = (event) => {
- inAsset.current = event;
- if (event.length > 0) {
- outAsset.current = "";
- const limitedAssets = [];
- for (var asset of assets) {
- if (asset.ID == event) {
- continue;
- }
- limitedAssets.push(asset);
- }
- setOutAssets(limitedAssets);
- setOutAllowed(true);
- } else {
- setOutAllowed(false);
- outAsset.current = "";
- setOrders([]);
- }
- };
- const outSelected = (event) => {
- outAsset.current = event;
- getOrders();
- };
-
- const onAssetChange = (event) => {
- setNewAsset(event.target.value);
- if (event.target.value.length > 0) {
- setAddAllowed(true);
- } else {
- setAddAllowed(false);
- }
- };
-
- const getAllAssets = async () => {
- const allAssets = await GetAllAssets();
- setAssets(allAssets);
- };
-
- const addAsset = (e) => {
- e.preventDefault();
- (async () => {
- try {
- await AddAsset(newAsset);
- setNewAsset("");
- const allAssets = await GetAllAssets();
- setAssets(allAssets);
- const limitedAssets = [];
- for (var asset of allAssets) {
- if (asset.ID == inAsset.current) {
- continue;
- }
- limitedAssets.push(asset);
- }
- setOutAssets(limitedAssets);
- message.open({
- type: "success",
- content: `${newAsset} added`,
- });
- } catch (e) {
- message.open({
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const [myOrders, setMyOrders] = useState([]);
- // const getMyOrders = async () => {
- // const newMyOrders = await GetMyOrders();
- // setMyOrders(newMyOrders);
- // };
-
- // const [orders, setOrders] = useState([]);
- // const getOrders = async () => {
- // if (inAsset.current.length == 0 || outAsset.current.length == 0) {
- // console.log(inAsset.current, outAsset.current);
- // setOrders([]);
- // return;
- // }
- // const newOrders = await GetOrders(`${inAsset.current}-${outAsset.current}`);
- // console.log(newOrders);
- // setOrders(newOrders);
- // };
-
- // const closeOrder = (values) => {
- // console.log("Success:", values);
-
- // message.open({
- // key,
- // type: "loading",
- // content: "Processing Transaction...",
- // duration: 0,
- // });
- // (async () => {
- // try {
- // const start = new Date().getTime();
- // await CloseOrder(values.ID, values.OutID);
- // const finish = new Date().getTime();
- // await getMyOrders();
- // message.open({
- // key,
- // type: "success",
- // content: `Transaction Finalized (${finish - start} ms)`,
- // });
- // } catch (e) {
- // message.open({
- // key,
- // type: "error",
- // content: e.toString(),
- // });
- // }
- // })();
- // };
-
- useEffect(() => {
- //getMyOrders();
- // getOrders();
- getBalance();
- getAllAssets();
- // const interval = setInterval(() => {
- // getMyOrders();
- // getOrders();
- // }, 500);
-
- return () => clearInterval(interval);
- }, []);
-
- return (
- <>
-
-
-
- Open Orders
-
- On TokenNet, anyone can trade the tokens they own.
-
-
- Once you create an order (i.e. offer to buy/sell some token), it
- will show up below!
-
-
- When closing an order, all unsold funds will return to you.
-
- }>
- {" "}
-
-
-
-
-
- Create Order
-
-
- (
-
-
- {item.InTick}
- {" "}
- /{" "}
-
- {item.OutTick}
- {" "}
- [Rate: {item.Rate}]
-
- Remaining: {item.Remaining} (Max Trade:{" "}
- {item.MaxInput})
-
- ID: {item.ID}
-
- closeOrder(item)}
- disabled={!window.HasBalance}
- style={{ margin: "8px 0 0 0" }}>
- Close
-
-
- )}
- />
-
- Order Book
-
- The "Order Book" contains all orders for a given pair of tokens
- sorted by rate (best to worst).
-
-
- You can fill an order for any pair where you hold the "in"
- token.
-
-
- Orders on TokenNet are executed as a batch. For each "tick" of
- the input amount, you receive a "tick" of the output amount.
-
-
-
- Example: If you created an order of "2 TKN / 5 YOU" (where
- "YOU" is your token), anyone could pay "2 TKN" to get "5 YOU".
-
-
- }>
- {" "}
-
-
-
-
-
-
-
(
- <>
- {menu}
-
-
-
- }
- onClick={addAsset}
- disabled={!addAllowed}>
-
- >
- )}
- options={outAssets.map((item) => ({
- label: item.StrSymbol,
- value: item.ID,
- }))}
- />
-
- (
-
-
- {item.InTick}
- {" "}
- /{" "}
-
- {item.OutTick}
- {" "}
- [Rate: {item.Rate}]
-
- Remaining: {item.Remaining} (Max Trade:{" "}
- {item.MaxInput})
-
- ID: {item.ID}
-
- Owner: {item.Owner}
-
-
- )}
- />
-
-
- Create Order
-
- Orders on TokenNet are executed as a batch. For each "tick" of
- the input amount, you receive a "tick" of the output amount.
-
-
- When creating an order, the "supply" of tokens you will trade
- for the "token you buy" is locked.
-
-
- When the order is filled, you will receive the "token you buy"
- and the counterparty will receive "the token you sell" (what
- you have).
-
-
-
- Example: If you created an order of "2 TKN / 5 YOU" (where
- "YOU" is your token), anyone could pay "2 TKN" to get "5
- YOU".
-
-
- }>
- {" "}
-
-
- >
- }
- placement={"right"}
- onClose={onCloseCreate}
- open={openCreate}>
-
- (
- <>
- {menu}
-
-
-
- }
- onClick={addAsset}
- disabled={!addAllowed}>
-
- >
- )}
- options={assets.map((item) => ({
- label: item.StrSymbol,
- value: item.ID,
- }))}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Create
-
-
-
-
- >
- );
-};
-export default Trade;
diff --git a/cmd/token-wallet/frontend/src/components/Transfer.jsx b/cmd/token-wallet/frontend/src/components/Transfer.jsx
deleted file mode 100644
index 4770076..0000000
--- a/cmd/token-wallet/frontend/src/components/Transfer.jsx
+++ /dev/null
@@ -1,210 +0,0 @@
-import React, { useEffect, useState } from "react";
-import {
- Divider,
- Space,
- App,
- Card,
- Form,
- Input,
- InputNumber,
- Button,
- Select,
-} from "antd";
-import { PlusOutlined } from "@ant-design/icons";
-import {
- GetBalance,
- Transfer as Send,
- AddAddressBook,
- GetAddressBook,
-} from "../../wailsjs/go/main/App";
-import FundsCheck from "./FundsCheck";
-
-const Transfer = () => {
- const { message } = App.useApp();
- const [balance, setBalance] = useState([]);
- const [transferForm] = Form.useForm();
- const key = "updatable";
-
- const getBalance = async () => {
- const bals = await GetBalance();
- console.log(bals);
- const parsedBalances = [];
- for (let i = 0; i < bals.length; i++) {
- parsedBalances.push({ value: bals[i].ID, label: bals[i].Bal });
- }
- setBalance(parsedBalances);
- };
-
- const [addresses, setAddresses] = useState([]);
- const [newNickname, setNewNickname] = useState("");
- const [newAddress, setNewAddress] = useState("");
- const [addAllowed, setAddAllowed] = useState(false);
-
- const onNicknameChange = (event) => {
- setNewNickname(event.target.value);
- if (event.target.value.length > 0 && newAddress.length > 10) {
- setAddAllowed(true);
- } else {
- setAddAllowed(false);
- }
- };
- const onAddressChange = (event) => {
- setNewAddress(event.target.value);
- if (newNickname.length > 0 && event.target.value.length > 10) {
- setAddAllowed(true);
- } else {
- setAddAllowed(false);
- }
- };
-
- const getAddresses = async () => {
- const caddresses = await GetAddressBook();
- setAddresses(caddresses);
- };
-
- const addAddress = (e) => {
- e.preventDefault();
- (async () => {
- try {
- await AddAddressBook(newNickname, newAddress);
- setNewNickname("");
- setNewAddress("");
- await getAddresses();
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishTransfer = (values) => {
- console.log("Success:", values);
- transferForm.resetFields();
-
- message.open({
- key,
- type: "loading",
- content: "Processing Transaction...",
- duration: 0,
- });
- (async () => {
- try {
- const start = new Date().getTime();
- await Send(values.Asset, values.Address, values.Amount, values.Memo);
- const finish = new Date().getTime();
- message.open({
- key,
- type: "success",
- content: `Transaction Finalized (${finish - start} ms)`,
- });
- getBalance();
- } catch (e) {
- message.open({
- key,
- type: "error",
- content: e.toString(),
- });
- }
- })();
- };
-
- const onFinishTransferFailed = (errorInfo) => {
- console.log("Failed:", errorInfo);
- };
-
- useEffect(() => {
- getBalance();
- getAddresses();
- }, []);
-
- return (
- <>
-
- >
- );
-};
-export default Transfer;
diff --git a/cmd/token-wallet/frontend/src/main.jsx b/cmd/token-wallet/frontend/src/main.jsx
deleted file mode 100644
index 27ed8cb..0000000
--- a/cmd/token-wallet/frontend/src/main.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from "react";
-import { createRoot } from "react-dom/client";
-import { createHashRouter, RouterProvider } from "react-router-dom";
-import routes from "./routes";
-
-const container = document.getElementById("root");
-
-const root = createRoot(container);
-
-const router = createHashRouter(routes, { basename: "/" });
-
-root.render(
-
-
-
-);
diff --git a/cmd/token-wallet/frontend/src/routes.jsx b/cmd/token-wallet/frontend/src/routes.jsx
deleted file mode 100644
index 6a53095..0000000
--- a/cmd/token-wallet/frontend/src/routes.jsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import App from "./App";
-
-import Explorer from "./components/Explorer";
-import Faucet from "./components/Faucet";
-import Mint from "./components/Mint";
-import Transfer from "./components/Transfer";
-import Trade from "./components/Trade";
-import Feed from "./components/Feed";
-
-const routes = [
- {
- path: "/",
- element: ,
- children: [
- { index: true, element: },
- {
- path: "explorer",
- element: ,
- },
- {
- path: "faucet",
- element: ,
- },
- {
- path: "mint",
- element: ,
- },
- {
- path: "transfer",
- element: ,
- },
- {
- path: "trade",
- element: ,
- },
- {
- path: "feed",
- element: ,
- },
- ],
- },
-];
-
-export default routes;
diff --git a/cmd/token-wallet/frontend/src/style.css b/cmd/token-wallet/frontend/src/style.css
deleted file mode 100644
index 276a7f3..0000000
--- a/cmd/token-wallet/frontend/src/style.css
+++ /dev/null
@@ -1,18 +0,0 @@
-html {
- background-color: rgba(27, 38, 54, 1);
- text-align: center;
- color: white;
-}
-
-body {
- margin: 0;
- color: white;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
- "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
- sans-serif;
-}
-
-#app {
- height: 100vh;
- text-align: center;
-}
diff --git a/cmd/token-wallet/frontend/vite.config.js b/cmd/token-wallet/frontend/vite.config.js
deleted file mode 100644
index 4955065..0000000
--- a/cmd/token-wallet/frontend/vite.config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import {defineConfig} from 'vite'
-import react from '@vitejs/plugin-react'
-
-// https://vitejs.dev/config/
-export default defineConfig({
- plugins: [react()]
-})
diff --git a/cmd/token-wallet/frontend/wailsjs/go/main/App.d.ts b/cmd/token-wallet/frontend/wailsjs/go/main/App.d.ts
deleted file mode 100755
index 502ac4f..0000000
--- a/cmd/token-wallet/frontend/wailsjs/go/main/App.d.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
-// This file is automatically generated. DO NOT EDIT
-import {backend} from '../models';
-
-export function AddAddressBook(arg1:string,arg2:string):Promise;
-
-export function AddAsset(arg1:string):Promise;
-
-export function CreateAsset(arg1:string,arg2:string,arg3:string):Promise;
-
-export function GetAccountStats():Promise>;
-
-export function GetAddress():Promise;
-
-export function GetAddressBook():Promise>;
-
-export function GetAllAssets():Promise>;
-
-export function GetBalance():Promise>;
-
-export function GetChainID():Promise;
-
-export function GetCommitHash():Promise;
-
-export function GetFaucetSolutions():Promise;
-
-export function GetFeed():Promise>;
-
-export function GetFeedInfo():Promise;
-
-export function GetLatestBlocks():Promise>;
-
-export function GetMyAssets():Promise>;
-
-export function GetTransactionStats():Promise>;
-
-export function GetTransactions():Promise;
-
-export function GetUnitPrices():Promise>;
-
-export function Message(arg1:string,arg2:string):Promise;
-
-export function MintAsset(arg1:string,arg2:string,arg3:string):Promise;
-
-export function OpenLink(arg1:string):Promise;
-
-export function StartFaucetSearch():Promise;
-
-export function Transfer(arg1:string,arg2:string,arg3:string,arg4:string):Promise;
diff --git a/cmd/token-wallet/frontend/wailsjs/go/main/App.js b/cmd/token-wallet/frontend/wailsjs/go/main/App.js
deleted file mode 100755
index b0b8fbb..0000000
--- a/cmd/token-wallet/frontend/wailsjs/go/main/App.js
+++ /dev/null
@@ -1,95 +0,0 @@
-// @ts-check
-// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
-// This file is automatically generated. DO NOT EDIT
-
-export function AddAddressBook(arg1, arg2) {
- return window['go']['main']['App']['AddAddressBook'](arg1, arg2);
-}
-
-export function AddAsset(arg1) {
- return window['go']['main']['App']['AddAsset'](arg1);
-}
-
-export function CreateAsset(arg1, arg2, arg3) {
- return window['go']['main']['App']['CreateAsset'](arg1, arg2, arg3);
-}
-
-export function GetAccountStats() {
- return window['go']['main']['App']['GetAccountStats']();
-}
-
-export function GetAddress() {
- return window['go']['main']['App']['GetAddress']();
-}
-
-export function GetAddressBook() {
- return window['go']['main']['App']['GetAddressBook']();
-}
-
-export function GetAllAssets() {
- return window['go']['main']['App']['GetAllAssets']();
-}
-
-export function GetBalance() {
- return window['go']['main']['App']['GetBalance']();
-}
-
-export function GetChainID() {
- return window['go']['main']['App']['GetChainID']();
-}
-
-export function GetCommitHash() {
- return window['go']['main']['App']['GetCommitHash']();
-}
-
-export function GetFaucetSolutions() {
- return window['go']['main']['App']['GetFaucetSolutions']();
-}
-
-export function GetFeed() {
- return window['go']['main']['App']['GetFeed']();
-}
-
-export function GetFeedInfo() {
- return window['go']['main']['App']['GetFeedInfo']();
-}
-
-export function GetLatestBlocks() {
- return window['go']['main']['App']['GetLatestBlocks']();
-}
-
-export function GetMyAssets() {
- return window['go']['main']['App']['GetMyAssets']();
-}
-
-export function GetTransactionStats() {
- return window['go']['main']['App']['GetTransactionStats']();
-}
-
-export function GetTransactions() {
- return window['go']['main']['App']['GetTransactions']();
-}
-
-export function GetUnitPrices() {
- return window['go']['main']['App']['GetUnitPrices']();
-}
-
-export function Message(arg1, arg2) {
- return window['go']['main']['App']['Message'](arg1, arg2);
-}
-
-export function MintAsset(arg1, arg2, arg3) {
- return window['go']['main']['App']['MintAsset'](arg1, arg2, arg3);
-}
-
-export function OpenLink(arg1) {
- return window['go']['main']['App']['OpenLink'](arg1);
-}
-
-export function StartFaucetSearch() {
- return window['go']['main']['App']['StartFaucetSearch']();
-}
-
-export function Transfer(arg1, arg2, arg3, arg4) {
- return window['go']['main']['App']['Transfer'](arg1, arg2, arg3, arg4);
-}
diff --git a/cmd/token-wallet/frontend/wailsjs/runtime/package.json b/cmd/token-wallet/frontend/wailsjs/runtime/package.json
deleted file mode 100755
index 1e7c8a5..0000000
--- a/cmd/token-wallet/frontend/wailsjs/runtime/package.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "@wailsapp/runtime",
- "version": "2.0.0",
- "description": "Wails Javascript runtime library",
- "main": "runtime.js",
- "types": "runtime.d.ts",
- "scripts": {
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/wailsapp/wails.git"
- },
- "keywords": [
- "Wails",
- "Javascript",
- "Go"
- ],
- "author": "Lea Anthony ",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/wailsapp/wails/issues"
- },
- "homepage": "https://github.com/wailsapp/wails#readme"
-}
diff --git a/cmd/token-wallet/frontend/wailsjs/runtime/runtime.d.ts b/cmd/token-wallet/frontend/wailsjs/runtime/runtime.d.ts
deleted file mode 100755
index a3723f9..0000000
--- a/cmd/token-wallet/frontend/wailsjs/runtime/runtime.d.ts
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The electron alternative for Go
-(c) Lea Anthony 2019-present
-*/
-
-export interface Position {
- x: number;
- y: number;
-}
-
-export interface Size {
- w: number;
- h: number;
-}
-
-export interface Screen {
- isCurrent: boolean;
- isPrimary: boolean;
- width : number
- height : number
-}
-
-// Environment information such as platform, buildtype, ...
-export interface EnvironmentInfo {
- buildType: string;
- platform: string;
- arch: string;
-}
-
-// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
-// emits the given event. Optional data may be passed with the event.
-// This will trigger any event listeners.
-export function EventsEmit(eventName: string, ...data: any): void;
-
-// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
-export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
-
-// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
-// sets up a listener for the given event name, but will only trigger a given number times.
-export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
-
-// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
-// sets up a listener for the given event name, but will only trigger once.
-export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
-
-// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
-// unregisters the listener for the given event name.
-export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
-
-// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
-// unregisters all listeners.
-export function EventsOffAll(): void;
-
-// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
-// logs the given message as a raw message
-export function LogPrint(message: string): void;
-
-// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
-// logs the given message at the `trace` log level.
-export function LogTrace(message: string): void;
-
-// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
-// logs the given message at the `debug` log level.
-export function LogDebug(message: string): void;
-
-// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
-// logs the given message at the `error` log level.
-export function LogError(message: string): void;
-
-// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
-// logs the given message at the `fatal` log level.
-// The application will quit after calling this method.
-export function LogFatal(message: string): void;
-
-// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
-// logs the given message at the `info` log level.
-export function LogInfo(message: string): void;
-
-// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
-// logs the given message at the `warning` log level.
-export function LogWarning(message: string): void;
-
-// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
-// Forces a reload by the main application as well as connected browsers.
-export function WindowReload(): void;
-
-// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
-// Reloads the application frontend.
-export function WindowReloadApp(): void;
-
-// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
-// Sets the window AlwaysOnTop or not on top.
-export function WindowSetAlwaysOnTop(b: boolean): void;
-
-// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
-// *Windows only*
-// Sets window theme to system default (dark/light).
-export function WindowSetSystemDefaultTheme(): void;
-
-// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
-// *Windows only*
-// Sets window to light theme.
-export function WindowSetLightTheme(): void;
-
-// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
-// *Windows only*
-// Sets window to dark theme.
-export function WindowSetDarkTheme(): void;
-
-// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
-// Centers the window on the monitor the window is currently on.
-export function WindowCenter(): void;
-
-// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
-// Sets the text in the window title bar.
-export function WindowSetTitle(title: string): void;
-
-// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
-// Makes the window full screen.
-export function WindowFullscreen(): void;
-
-// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
-// Restores the previous window dimensions and position prior to full screen.
-export function WindowUnfullscreen(): void;
-
-// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
-// Returns the state of the window, i.e. whether the window is in full screen mode or not.
-export function WindowIsFullscreen(): Promise;
-
-// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
-// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
-
-// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
-// Gets the width and height of the window.
-export function WindowGetSize(): Promise;
-
-// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
-// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
-// Setting a size of 0,0 will disable this constraint.
-export function WindowSetMaxSize(width: number, height: number): void;
-
-// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
-// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
-// Setting a size of 0,0 will disable this constraint.
-export function WindowSetMinSize(width: number, height: number): void;
-
-// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
-// Sets the window position relative to the monitor the window is currently on.
-export function WindowSetPosition(x: number, y: number): void;
-
-// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
-// Gets the window position relative to the monitor the window is currently on.
-export function WindowGetPosition(): Promise;
-
-// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
-// Hides the window.
-export function WindowHide(): void;
-
-// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
-// Shows the window, if it is currently hidden.
-export function WindowShow(): void;
-
-// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
-// Maximises the window to fill the screen.
-export function WindowMaximise(): void;
-
-// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
-// Toggles between Maximised and UnMaximised.
-export function WindowToggleMaximise(): void;
-
-// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
-// Restores the window to the dimensions and position prior to maximising.
-export function WindowUnmaximise(): void;
-
-// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
-// Returns the state of the window, i.e. whether the window is maximised or not.
-export function WindowIsMaximised(): Promise;
-
-// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
-// Minimises the window.
-export function WindowMinimise(): void;
-
-// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
-// Restores the window to the dimensions and position prior to minimising.
-export function WindowUnminimise(): void;
-
-// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
-// Returns the state of the window, i.e. whether the window is minimised or not.
-export function WindowIsMinimised(): Promise;
-
-// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
-// Returns the state of the window, i.e. whether the window is normal or not.
-export function WindowIsNormal(): Promise;
-
-// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
-// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
-export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
-
-// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
-// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
-export function ScreenGetAll(): Promise;
-
-// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
-// Opens the given URL in the system browser.
-export function BrowserOpenURL(url: string): void;
-
-// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
-// Returns information about the environment
-export function Environment(): Promise;
-
-// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
-// Quits the application.
-export function Quit(): void;
-
-// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
-// Hides the application.
-export function Hide(): void;
-
-// [Show](https://wails.io/docs/reference/runtime/intro#show)
-// Shows the application.
-export function Show(): void;
-
-// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
-// Returns the current text stored on clipboard
-export function ClipboardGetText(): Promise;
-
-// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
-// Sets a text on the clipboard
-export function ClipboardSetText(text: string): Promise;
diff --git a/cmd/token-wallet/frontend/wailsjs/runtime/runtime.js b/cmd/token-wallet/frontend/wailsjs/runtime/runtime.js
deleted file mode 100755
index bd4f371..0000000
--- a/cmd/token-wallet/frontend/wailsjs/runtime/runtime.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- _ __ _ __
-| | / /___ _(_) /____
-| | /| / / __ `/ / / ___/
-| |/ |/ / /_/ / / (__ )
-|__/|__/\__,_/_/_/____/
-The electron alternative for Go
-(c) Lea Anthony 2019-present
-*/
-
-export function LogPrint(message) {
- window.runtime.LogPrint(message);
-}
-
-export function LogTrace(message) {
- window.runtime.LogTrace(message);
-}
-
-export function LogDebug(message) {
- window.runtime.LogDebug(message);
-}
-
-export function LogInfo(message) {
- window.runtime.LogInfo(message);
-}
-
-export function LogWarning(message) {
- window.runtime.LogWarning(message);
-}
-
-export function LogError(message) {
- window.runtime.LogError(message);
-}
-
-export function LogFatal(message) {
- window.runtime.LogFatal(message);
-}
-
-export function EventsOnMultiple(eventName, callback, maxCallbacks) {
- return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
-}
-
-export function EventsOn(eventName, callback) {
- return EventsOnMultiple(eventName, callback, -1);
-}
-
-export function EventsOff(eventName, ...additionalEventNames) {
- return window.runtime.EventsOff(eventName, ...additionalEventNames);
-}
-
-export function EventsOnce(eventName, callback) {
- return EventsOnMultiple(eventName, callback, 1);
-}
-
-export function EventsEmit(eventName) {
- let args = [eventName].slice.call(arguments);
- return window.runtime.EventsEmit.apply(null, args);
-}
-
-export function WindowReload() {
- window.runtime.WindowReload();
-}
-
-export function WindowReloadApp() {
- window.runtime.WindowReloadApp();
-}
-
-export function WindowSetAlwaysOnTop(b) {
- window.runtime.WindowSetAlwaysOnTop(b);
-}
-
-export function WindowSetSystemDefaultTheme() {
- window.runtime.WindowSetSystemDefaultTheme();
-}
-
-export function WindowSetLightTheme() {
- window.runtime.WindowSetLightTheme();
-}
-
-export function WindowSetDarkTheme() {
- window.runtime.WindowSetDarkTheme();
-}
-
-export function WindowCenter() {
- window.runtime.WindowCenter();
-}
-
-export function WindowSetTitle(title) {
- window.runtime.WindowSetTitle(title);
-}
-
-export function WindowFullscreen() {
- window.runtime.WindowFullscreen();
-}
-
-export function WindowUnfullscreen() {
- window.runtime.WindowUnfullscreen();
-}
-
-export function WindowIsFullscreen() {
- return window.runtime.WindowIsFullscreen();
-}
-
-export function WindowGetSize() {
- return window.runtime.WindowGetSize();
-}
-
-export function WindowSetSize(width, height) {
- window.runtime.WindowSetSize(width, height);
-}
-
-export function WindowSetMaxSize(width, height) {
- window.runtime.WindowSetMaxSize(width, height);
-}
-
-export function WindowSetMinSize(width, height) {
- window.runtime.WindowSetMinSize(width, height);
-}
-
-export function WindowSetPosition(x, y) {
- window.runtime.WindowSetPosition(x, y);
-}
-
-export function WindowGetPosition() {
- return window.runtime.WindowGetPosition();
-}
-
-export function WindowHide() {
- window.runtime.WindowHide();
-}
-
-export function WindowShow() {
- window.runtime.WindowShow();
-}
-
-export function WindowMaximise() {
- window.runtime.WindowMaximise();
-}
-
-export function WindowToggleMaximise() {
- window.runtime.WindowToggleMaximise();
-}
-
-export function WindowUnmaximise() {
- window.runtime.WindowUnmaximise();
-}
-
-export function WindowIsMaximised() {
- return window.runtime.WindowIsMaximised();
-}
-
-export function WindowMinimise() {
- window.runtime.WindowMinimise();
-}
-
-export function WindowUnminimise() {
- window.runtime.WindowUnminimise();
-}
-
-export function WindowSetBackgroundColour(R, G, B, A) {
- window.runtime.WindowSetBackgroundColour(R, G, B, A);
-}
-
-export function ScreenGetAll() {
- return window.runtime.ScreenGetAll();
-}
-
-export function WindowIsMinimised() {
- return window.runtime.WindowIsMinimised();
-}
-
-export function WindowIsNormal() {
- return window.runtime.WindowIsNormal();
-}
-
-export function BrowserOpenURL(url) {
- window.runtime.BrowserOpenURL(url);
-}
-
-export function Environment() {
- return window.runtime.Environment();
-}
-
-export function Quit() {
- window.runtime.Quit();
-}
-
-export function Hide() {
- window.runtime.Hide();
-}
-
-export function Show() {
- window.runtime.Show();
-}
-
-export function ClipboardGetText() {
- return window.runtime.ClipboardGetText();
-}
-
-export function ClipboardSetText(text) {
- return window.runtime.ClipboardSetText(text);
-}
\ No newline at end of file
diff --git a/cmd/token-wallet/main.go b/cmd/token-wallet/main.go
deleted file mode 100644
index 05821ac..0000000
--- a/cmd/token-wallet/main.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-// See the file LICENSE for licensing terms.
-
-package main
-
-import (
- "embed"
-
- "github.com/wailsapp/wails/v2"
- "github.com/wailsapp/wails/v2/pkg/options"
- "github.com/wailsapp/wails/v2/pkg/options/assetserver"
- "github.com/wailsapp/wails/v2/pkg/options/linux"
- "github.com/wailsapp/wails/v2/pkg/options/mac"
-)
-
-//nolint:typecheck
-//go:embed all:frontend/dist
-var assets embed.FS
-
-//go:embed build/appicon.png
-var icon []byte
-
-func main() {
- // Create an instance of the app structure
- app := NewApp()
-
- // Create application with options
- err := wails.Run(&options.App{
- Title: "Token Wallet",
- Width: 1280,
- MinWidth: 1280,
- Height: 768,
- MinHeight: 768,
- AssetServer: &assetserver.Options{
- Assets: assets,
- },
- BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
- OnStartup: app.startup,
- OnShutdown: app.shutdown,
- Bind: []interface{}{
- app,
- },
- Mac: &mac.Options{
- TitleBar: &mac.TitleBar{
- TitlebarAppearsTransparent: false,
- HideTitle: false,
- HideTitleBar: false,
- FullSizeContent: false,
- UseToolbar: false,
- HideToolbarSeparator: true,
- },
- Appearance: mac.NSAppearanceNameDarkAqua,
- WebviewIsTransparent: false,
- WindowIsTranslucent: false,
- About: &mac.AboutInfo{
- Title: "Token Wallet",
- Icon: icon,
- },
- },
- Linux: &linux.Options{
- Icon: icon,
- WindowIsTranslucent: false,
- WebviewGpuPolicy: linux.WebviewGpuPolicyAlways,
- },
- })
- if err != nil {
- println("Error:", err.Error())
- }
-}
diff --git a/cmd/token-wallet/scripts/build.sh b/cmd/token-wallet/scripts/build.sh
deleted file mode 100755
index 20efb16..0000000
--- a/cmd/token-wallet/scripts/build.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-# See the file LICENSE for licensing terms.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-# Set the CGO flags to use the portable version of BLST
-#
-# We use "export" here instead of just setting a bash variable because we need
-# to pass this flag to all child processes spawned by the shell.
-export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
-
-PUBLISH=${PUBLISH:-true}
-
-# Install wails
-go install -v github.com/wailsapp/wails/v2/cmd/wails@v2.5.1
-
-# Build file for local arch
-#
-# Don't use upx: https://github.com/upx/upx/issues/446
-wails build -clean -platform darwin/universal
-
-OUTPUT=build/bin/Token\ Wallet.app
-if [ ! -d "$OUTPUT" ]; then
- exit 1
-fi
-
-# Remove any previous build artifacts
-rm -rf token-wallet.zip
-
-# Exit early if not publishing
-if [ ${PUBLISH} == false ]; then
- echo "not publishing app"
- ditto -c -k --keepParent build/bin/Token\ Wallet.app token-wallet.zip
- exit 0
-fi
-echo "publishing app"
-
-# Sign code
-codesign -s ${APP_SIGNING_KEY_ID} --deep --timestamp -o runtime -v build/bin/Token\ Wallet.app
-ditto -c -k --keepParent build/bin/Token\ Wallet.app token-wallet.zip
-
-# Need to sign to allow for app to be opened on other computers
-xcrun altool --notarize-app --primary-bundle-id com.ava-labs.token-wallet --username ${APPLE_NOTARIZATION_USERNAME} --password "@keychain:altool" --file token-wallet.zip
-
-# Log until exit
-read -p "Input APPLE_NOTARIZATION_REQUEST_ID: " APPLE_NOTARIZATION_REQUEST_ID
-while true
-do
- xcrun altool --notarization-info ${APPLE_NOTARIZATION_REQUEST_ID} -u ${APPLE_NOTARIZATION_USERNAME} -p "@keychain:altool"
- sleep 15
-done
diff --git a/cmd/token-wallet/scripts/dev.sh b/cmd/token-wallet/scripts/dev.sh
deleted file mode 100755
index 9c2f18c..0000000
--- a/cmd/token-wallet/scripts/dev.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
-# See the file LICENSE for licensing terms.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-# Set the CGO flags to use the portable version of BLST
-#
-# We use "export" here instead of just setting a bash variable because we need
-# to pass this flag to all child processes spawned by the shell.
-export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
-
-# Install wails
-go install -v github.com/wailsapp/wails/v2/cmd/wails@v2.5.1
-
-# Start development environment
-wails dev
diff --git a/cmd/token-wallet/wails.json b/cmd/token-wallet/wails.json
deleted file mode 100644
index 79a2d00..0000000
--- a/cmd/token-wallet/wails.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "$schema": "https://wails.io/schemas/config.v2.json",
- "name": "Token Wallet",
- "outputfilename": "token-wallet",
- "frontend:install": "npm install",
- "frontend:build": "npm run build",
- "frontend:dev:watcher": "npm run dev",
- "frontend:dev:serverUrl": "auto",
- "author": {
- "name": "Patrick O'Grady",
- "email": "contact@patrickogrady.xyz"
- }
-}
diff --git a/compose.yml b/compose.yml
index de56a17..e7b411c 100644
--- a/compose.yml
+++ b/compose.yml
@@ -19,7 +19,7 @@ services:
- "7060:6060"
volumes:
- "l1_data:/db"
- - "${PWD}/genesis-l1.json:/genesis.json"
- - "${PWD}/test-jwt-secret.txt:/config/test-jwt-secret.txt"
+ - "./genesis-l1.json:/genesis.json"
+ - "./test-jwt-secret.txt:/config/test-jwt-secret.txt"
environment:
GETH_MINER_RECOMMIT: 100ms
\ No newline at end of file
diff --git a/config/config.go b/config/config.go
index b165586..d784966 100644
--- a/config/config.go
+++ b/config/config.go
@@ -9,16 +9,18 @@ import (
"strings"
"time"
+ "github.com/AnomalyFi/hypersdk/codec"
"github.com/AnomalyFi/hypersdk/config"
"github.com/AnomalyFi/hypersdk/gossiper"
+ "github.com/AnomalyFi/hypersdk/rpc"
"github.com/AnomalyFi/hypersdk/trace"
"github.com/AnomalyFi/hypersdk/vm"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/profiler"
+ "github.com/AnomalyFi/nodekit-seq/archiver"
"github.com/AnomalyFi/nodekit-seq/consts"
- "github.com/AnomalyFi/nodekit-seq/utils"
"github.com/AnomalyFi/nodekit-seq/version"
)
@@ -34,6 +36,12 @@ const (
type Config struct {
*config.Config
+ // Concurrency
+ AuthVerificationCores int `json:"authVerificationCores"`
+ RootGenerationCores int `json:"rootGenerationCores"`
+ TransactionExecutionCores int `json:"transactionExecutionCores"`
+ StateFetchConcurrency int `json:"stateFetchConcurrency"`
+
// Gossip
GossipMaxSize int `json:"gossipMaxSize"`
GossipProposerDiff int `json:"gossipProposerDiff"`
@@ -49,25 +57,22 @@ type Config struct {
ContinuousProfilerDir string `json:"continuousProfilerDir"` // "*" is replaced with rand int
// Streaming settings
- StreamingBacklogSize int `json:"streamingBacklogSize"`
+ StreamingBacklogSize int `json:"streamingBacklogSize"`
+ StoreBlockResultsOnDisk bool `json:"storeBlockResultsOnDisk"`
// Mempool
- MempoolSize int `json:"mempoolSize"`
- MempoolPayerSize int `json:"mempoolPayerSize"`
- MempoolExemptPayers []string `json:"mempoolExemptPayers"`
+ MempoolSize int `json:"mempoolSize"`
+ MempoolSponsorSize int `json:"mempoolSponsorSize"`
+ MempoolExemptSponsors []string `json:"mempoolExemptSponsors"`
- // Order Book
- //
- // This is denoted as -
- MaxOrdersPerPair int `json:"maxOrdersPerPair"`
- TrackedPairs []string `json:"trackedPairs"` // which asset ID pairs we care about
+ // Whitelisted Address: Address used to get fee discounts, or are allowed to perform specific actions like submitting proofs.
+ WhitelistedAddresses []string `json:"whitelistedAddresses"`
// Misc
- VerifySignatures bool `json:"verifySignatures"`
+ VerifyAuth bool `json:"verifyAuth"`
StoreTransactions bool `json:"storeTransactions"`
TestMode bool `json:"testMode"` // makes gossip/building manual
LogLevel logging.Level `json:"logLevel"`
- Parallelism int `json:"parallelism"`
// State Sync
StateSyncServerDelay time.Duration `json:"stateSyncServerDelay"` // for testing
@@ -76,9 +81,19 @@ type Config struct {
ETHRPCAddr string `json:"ethRPCAddr"`
ETHWSAddr string `json:"ethWSAddr"`
- loaded bool
- nodeID ids.NodeID
- parsedExemptPayers [][]byte
+ // Archiver
+ ArchiverConfig archiver.ORMArchiverConfig `json:"archiverConfig"`
+
+ // Arcadia
+ ArcadiaURL string `json:"arcadiaURL"`
+
+ // Validator RPC Port
+ ValRPCConfig rpc.JSONRPCValServerConfig `json:"valRPCConfig"`
+
+ loaded bool
+ nodeID ids.NodeID
+ parsedExemptSponsors []codec.Address
+ parsedWhiteListedAddresses []codec.Address
}
func New(nodeID ids.NodeID, b []byte) (*Config, error) {
@@ -91,15 +106,25 @@ func New(nodeID ids.NodeID, b []byte) (*Config, error) {
c.loaded = true
}
- // Parse any exempt payers (usually used when a single account is
+ // Parse any exempt sponsors (usually used when a single account is
// broadcasting many txs at once)
- c.parsedExemptPayers = make([][]byte, len(c.MempoolExemptPayers))
- for i, payer := range c.MempoolExemptPayers {
- p, err := utils.ParseAddress(payer)
+ c.parsedExemptSponsors = make([]codec.Address, len(c.MempoolExemptSponsors))
+ for i, sponsor := range c.MempoolExemptSponsors {
+ p, err := codec.ParseAddressBech32(consts.HRP, sponsor)
if err != nil {
return nil, err
}
- c.parsedExemptPayers[i] = p[:]
+ c.parsedExemptSponsors[i] = p
+ }
+
+ // Parse whitelisted address. These addresses are authorized to perform certain actions.
+ c.parsedWhiteListedAddresses = make([]codec.Address, len(c.WhitelistedAddresses))
+ for i, addr := range c.WhitelistedAddresses {
+ p, err := codec.ParseAddressBech32(consts.HRP, addr)
+ if err != nil {
+ return nil, err
+ }
+ c.parsedWhiteListedAddresses[i] = p
}
return c, nil
}
@@ -112,24 +137,32 @@ func (c *Config) setDefault() {
c.GossipProposerDepth = gcfg.GossipProposerDepth
c.NoGossipBuilderDiff = gcfg.NoGossipBuilderDiff
c.VerifyTimeout = gcfg.VerifyTimeout
- c.Parallelism = c.Config.GetParallelism()
+ c.AuthVerificationCores = c.Config.GetAuthVerificationCores()
+ c.RootGenerationCores = c.Config.GetRootGenerationCores()
+ c.TransactionExecutionCores = c.Config.GetTransactionExecutionCores()
+ c.StateFetchConcurrency = c.Config.GetStateFetchConcurrency()
c.MempoolSize = c.Config.GetMempoolSize()
- c.MempoolPayerSize = c.Config.GetMempoolPayerSize()
+ c.MempoolSponsorSize = c.Config.GetMempoolSponsorSize()
c.StateSyncServerDelay = c.Config.GetStateSyncServerDelay()
c.StreamingBacklogSize = c.Config.GetStreamingBacklogSize()
- c.VerifySignatures = c.Config.GetVerifySignatures()
+ c.VerifyAuth = c.Config.GetVerifyAuth()
c.StoreTransactions = defaultStoreTransactions
- c.MaxOrdersPerPair = defaultMaxOrdersPerPair
+ c.StoreBlockResultsOnDisk = c.Config.GetStoreBlockResultsOnDisk()
c.ETHRPCAddr = c.Config.GetETHL1RPC()
c.ETHWSAddr = c.Config.GetETHL1WS()
+ c.ArcadiaURL = c.Config.GetArcadiaURL()
+ c.ValRPCConfig = *c.Config.GetValServerConfig()
}
-func (c *Config) GetLogLevel() logging.Level { return c.LogLevel }
-func (c *Config) GetTestMode() bool { return c.TestMode }
-func (c *Config) GetParallelism() int { return c.Parallelism }
-func (c *Config) GetMempoolSize() int { return c.MempoolSize }
-func (c *Config) GetMempoolPayerSize() int { return c.MempoolPayerSize }
-func (c *Config) GetMempoolExemptPayers() [][]byte { return c.parsedExemptPayers }
+func (c *Config) GetLogLevel() logging.Level { return c.LogLevel }
+func (c *Config) GetTestMode() bool { return c.TestMode }
+func (c *Config) GetAuthVerificationCores() int { return c.AuthVerificationCores }
+func (c *Config) GetRootGenerationCores() int { return c.RootGenerationCores }
+func (c *Config) GetTransactionExecutionCores() int { return c.TransactionExecutionCores }
+func (c *Config) GetStateFetchConcurrency() int { return c.StateFetchConcurrency }
+func (c *Config) GetMempoolSize() int { return c.MempoolSize }
+func (c *Config) GetMempoolSponsorSize() int { return c.MempoolSponsorSize }
+func (c *Config) GetMempoolExemptSponsors() []codec.Address { return c.parsedExemptSponsors }
func (c *Config) GetTraceConfig() *trace.Config {
return &trace.Config{
Enabled: c.TraceEnabled,
@@ -141,12 +174,13 @@ func (c *Config) GetTraceConfig() *trace.Config {
}
func (c *Config) GetStateSyncServerDelay() time.Duration { return c.StateSyncServerDelay }
func (c *Config) GetStreamingBacklogSize() int { return c.StreamingBacklogSize }
+func (c *Config) GetStoreBlockResultsOnDisk() bool { return c.StoreBlockResultsOnDisk }
func (c *Config) GetContinuousProfilerConfig() *profiler.Config {
if len(c.ContinuousProfilerDir) == 0 {
return &profiler.Config{Enabled: false}
}
// Replace all instances of "*" with nodeID. This is useful when
- // running multiple instances of tokenvm on the same machine.
+ // running multiple instances of seqvm on the same machine.
c.ContinuousProfilerDir = strings.ReplaceAll(c.ContinuousProfilerDir, "*", c.nodeID.String())
return &profiler.Config{
Enabled: true,
@@ -155,8 +189,18 @@ func (c *Config) GetContinuousProfilerConfig() *profiler.Config {
MaxNumFiles: defaultContinuousProfilerMaxFiles,
}
}
-func (c *Config) GetVerifySignatures() bool { return c.VerifySignatures }
+func (c *Config) GetVerifyAuth() bool { return c.VerifyAuth }
func (c *Config) GetStoreTransactions() bool { return c.StoreTransactions }
func (c *Config) Loaded() bool { return c.loaded }
func (c *Config) GetETHL1RPC() string { return c.ETHRPCAddr }
func (c *Config) GetETHL1WS() string { return c.ETHWSAddr }
+func (c *Config) GetArcadiaURL() string { return c.ArcadiaURL }
+func (*Config) GetValServerConfig() *rpc.JSONRPCValServerConfig {
+ return &rpc.JSONRPCValServerConfig{
+ DerivePort: true,
+ }
+}
+
+func (c *Config) GetParsedWhiteListedAddress() []codec.Address {
+ return c.parsedWhiteListedAddresses
+}
diff --git a/consts/consts.go b/consts/consts.go
index 99cf26c..2a523a2 100644
--- a/consts/consts.go
+++ b/consts/consts.go
@@ -6,22 +6,20 @@ package consts
import (
"github.com/AnomalyFi/hypersdk/chain"
"github.com/AnomalyFi/hypersdk/codec"
- "github.com/AnomalyFi/hypersdk/consts"
"github.com/ava-labs/avalanchego/ids"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
)
const (
- HRP = "token"
- Name = "tokenvm"
- Symbol = "TKN"
+ HRP = "seq"
+ Name = "seqvm"
+ Symbol = "SEQ"
Decimals = 9
)
var ID ids.ID
func init() {
- b := make([]byte, consts.IDLen)
+ b := make([]byte, ids.IDLen)
copy(b, []byte(Name))
vmID, err := ids.ToID(b)
if err != nil {
@@ -33,6 +31,6 @@ func init() {
// Instantiate registry here so it can be imported by any package. We set these
// values in [controller/registry].
var (
- ActionRegistry *codec.TypeParser[chain.Action, *warp.Message, bool]
- AuthRegistry *codec.TypeParser[chain.Auth, *warp.Message, bool]
+ ActionRegistry *codec.TypeParser[chain.Action, bool]
+ AuthRegistry *codec.TypeParser[chain.Auth, bool]
)
diff --git a/controller/controller.go b/controller/controller.go
index e7f404f..2921a7b 100644
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -6,9 +6,13 @@ package controller
import (
"context"
"fmt"
+ "net/http"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
"github.com/AnomalyFi/hypersdk/builder"
"github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/fees"
"github.com/AnomalyFi/hypersdk/gossiper"
hrpc "github.com/AnomalyFi/hypersdk/rpc"
hstorage "github.com/AnomalyFi/hypersdk/storage"
@@ -16,17 +20,15 @@ import (
ametrics "github.com/ava-labs/avalanchego/api/metrics"
"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/snow"
- "github.com/ava-labs/avalanchego/snow/engine/common"
"go.uber.org/zap"
"github.com/AnomalyFi/nodekit-seq/actions"
+ "github.com/AnomalyFi/nodekit-seq/archiver"
"github.com/AnomalyFi/nodekit-seq/auth"
"github.com/AnomalyFi/nodekit-seq/config"
"github.com/AnomalyFi/nodekit-seq/consts"
"github.com/AnomalyFi/nodekit-seq/genesis"
-
- // "github.com/AnomalyFi/nodekit-seq/orderbook"
-
+ rollupregistry "github.com/AnomalyFi/nodekit-seq/rollup_registry"
"github.com/AnomalyFi/nodekit-seq/rpc"
"github.com/AnomalyFi/nodekit-seq/storage"
"github.com/AnomalyFi/nodekit-seq/version"
@@ -42,7 +44,9 @@ type Controller struct {
config *config.Config
stateManager *StateManager
- jsonRPCServer *rpc.JSONRPCServer
+ jsonRPCServer *rpc.JSONRPCServer
+ archiver *archiver.ORMArchiver
+ rollupRegistry *rollupregistry.RollupRegistry
metrics *metrics
@@ -106,27 +110,36 @@ func (c *Controller) Initialize(
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err
}
- // TODO: tune Pebble config based on each sub-db focus
+
c.metaDB = metaDB
- if err != nil {
- return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err
- }
// Create handlers
//
// hypersdk handler are initiatlized automatically, you just need to
// initialize custom handlers here.
- apis := map[string]*common.HTTPHandler{}
+ apis := map[string]http.Handler{}
jsonRPCServer := rpc.NewJSONRPCServer(c)
c.jsonRPCServer = jsonRPCServer
jsonRPCHandler, err := hrpc.NewJSONRPCHandler(
consts.Name,
jsonRPCServer,
- common.NoLock,
)
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err
}
+
+ if c.config.ArchiverConfig.ArchiverType == "sqlite" {
+ c.config.ArchiverConfig.DSN = "/tmp/sqlite." + snowCtx.NodeID.String() + ".db"
+ snowCtx.Log.Debug("setting archiver to", zap.String("dsn", c.config.ArchiverConfig.DSN))
+ }
+ // snowCtx.NodeID.String()
+ c.archiver, err = archiver.NewORMArchiverFromConfig(&c.config.ArchiverConfig)
+ if err != nil {
+ return nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, err
+ }
+
+ c.rollupRegistry = rollupregistry.NewRollupRegistr()
+
apis[rpc.JSONRPCEndpoint] = jsonRPCHandler
// Create builder and gossiper
@@ -157,17 +170,21 @@ func (c *Controller) Initialize(
func (c *Controller) Rules(t int64) chain.Rules {
// TODO: extend with [UpgradeBytes]
- return c.genesis.Rules(t, c.snowCtx.NetworkID, c.snowCtx.ChainID)
+ return c.genesis.Rules(t, c.snowCtx.NetworkID, c.snowCtx.ChainID, c.config.GetParsedWhiteListedAddress())
}
func (c *Controller) StateManager() chain.StateManager {
return c.stateManager
}
-func (c *Controller) UnitPrices(ctx context.Context) (chain.Dimensions, error) {
+func (c *Controller) UnitPrices(ctx context.Context) (fees.Dimensions, error) {
return c.inner.UnitPrices(ctx)
}
+func (c *Controller) NameSpacesPrice(ctx context.Context, namespaces []string) ([]uint64, error) {
+ return c.inner.NameSpacesPrice(ctx, namespaces)
+}
+
func (c *Controller) Submit(
ctx context.Context,
verifySig bool,
@@ -181,10 +198,14 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er
batch := c.metaDB.NewBatch()
defer batch.Reset()
- if err := c.jsonRPCServer.AcceptBlock(blk); err != nil {
- c.inner.Logger().Fatal("unable to accept block in json-rpc server", zap.Error(err))
- }
+ go func() {
+ err := c.archiver.InsertBlock(blk)
+ if err != nil {
+ c.Logger().Debug("err inserting block", zap.Error(err))
+ }
+ }()
+ rollups := make([]*hactions.RollupInfo, 0)
results := blk.Results()
for i, tx := range blk.Txs {
result := results[i]
@@ -195,7 +216,7 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er
tx.ID(),
blk.GetTimestamp(),
result.Success,
- result.Consumed,
+ result.Units,
result.Fee,
)
if err != nil {
@@ -203,24 +224,26 @@ func (c *Controller) Accepted(ctx context.Context, blk *chain.StatelessBlock) er
}
}
if result.Success {
- switch tx.Action.(type) {
- case *actions.CreateAsset:
- c.metrics.createAsset.Inc()
- case *actions.MintAsset:
- c.metrics.mintAsset.Inc()
- case *actions.BurnAsset:
- c.metrics.burnAsset.Inc()
- case *actions.Transfer:
- c.metrics.transfer.Inc()
- case *actions.SequencerMsg:
- c.metrics.sequencerMsg.Inc()
- case *actions.ImportAsset:
- c.metrics.importAsset.Inc()
- case *actions.ExportAsset:
- c.metrics.exportAsset.Inc()
+ for _, act := range tx.Actions {
+ switch act.(type) { //nolint:gocritic,gosimple
+ case *actions.Transfer:
+ c.metrics.transfer.Inc()
+ case *actions.SequencerMsg:
+ c.metrics.sequencerMsg.Inc()
+ case *actions.Auction:
+ c.metrics.auction.Inc()
+ case *actions.RollupRegistration:
+ reg := act.(*actions.RollupRegistration) //nolint:gosimple
+ rollups = append(rollups, ®.Info)
+ c.metrics.rollupRegister.Inc()
+ case *actions.EpochExit:
+ c.metrics.epochExit.Inc()
+ }
}
}
}
+ currentEpoch := blk.Hght / uint64(c.inner.Rules(blk.Tmstmp).GetEpochLength())
+ c.rollupRegistry.Update(currentEpoch, rollups)
return batch.Write()
}
diff --git a/controller/metrics.go b/controller/metrics.go
index bddc1d8..ed5ee71 100644
--- a/controller/metrics.go
+++ b/controller/metrics.go
@@ -11,81 +11,58 @@ import (
)
type metrics struct {
- createAsset prometheus.Counter
- mintAsset prometheus.Counter
- burnAsset prometheus.Counter
-
transfer prometheus.Counter
- importAsset prometheus.Counter
- exportAsset prometheus.Counter
- importBlock prometheus.Counter
- exportBlock prometheus.Counter
sequencerMsg prometheus.Counter
+ auction prometheus.Counter
+
+ rollupRegister prometheus.Counter
+ epochExit prometheus.Counter
}
func newMetrics(gatherer ametrics.MultiGatherer) (*metrics, error) {
m := &metrics{
- createAsset: prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "actions",
- Name: "create_asset",
- Help: "number of create asset actions",
- }),
- mintAsset: prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "actions",
- Name: "mint_asset",
- Help: "number of mint asset actions",
- }),
- burnAsset: prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "actions",
- Name: "burn_asset",
- Help: "number of burn asset actions",
- }),
transfer: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "actions",
Name: "transfer",
Help: "number of transfer actions",
}),
- importAsset: prometheus.NewCounter(prometheus.CounterOpts{
- Namespace: "actions",
- Name: "import_asset",
- Help: "number of import asset actions",
- }),
- exportAsset: prometheus.NewCounter(prometheus.CounterOpts{
+
+ sequencerMsg: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "actions",
- Name: "export_asset",
- Help: "number of export asset actions",
+ Name: "sequencer_msg",
+ Help: "number of sequencer msg actions",
}),
- importBlock: prometheus.NewCounter(prometheus.CounterOpts{
+
+ auction: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "actions",
- Name: "import_block",
- Help: "number of import block actions",
+ Name: "auction",
+ Help: "number of auction actions",
}),
- exportBlock: prometheus.NewCounter(prometheus.CounterOpts{
+
+ rollupRegister: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "actions",
- Name: "export_block",
- Help: "number of export block actions",
+ Name: "rollup_register",
+ Help: "number of rollup register actions",
}),
- sequencerMsg: prometheus.NewCounter(prometheus.CounterOpts{
+
+ epochExit: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "actions",
- Name: "sequencer_msg",
- Help: "number of sequencer msg actions",
+ Name: "epoch_exit",
+ Help: "number of epoch exit actions",
}),
}
r := prometheus.NewRegistry()
errs := wrappers.Errs{}
errs.Add(
- r.Register(m.createAsset),
- r.Register(m.mintAsset),
- r.Register(m.burnAsset),
-
r.Register(m.transfer),
- r.Register(m.importBlock),
- r.Register(m.exportBlock),
- r.Register(m.importAsset),
- r.Register(m.exportAsset),
r.Register(m.sequencerMsg),
+ r.Register(m.auction),
+
+ r.Register(m.rollupRegister),
+ r.Register(m.epochExit),
+
gatherer.Register(consts.Name, r),
)
return m, errs.Err
diff --git a/controller/resolutions.go b/controller/resolutions.go
index a149899..ab3ed72 100644
--- a/controller/resolutions.go
+++ b/controller/resolutions.go
@@ -6,9 +6,13 @@ package controller
import (
"context"
- "github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/fees"
+
+ "github.com/AnomalyFi/nodekit-seq/archiver"
"github.com/AnomalyFi/nodekit-seq/genesis"
+ rollupregistry "github.com/AnomalyFi/nodekit-seq/rollup_registry"
"github.com/AnomalyFi/nodekit-seq/storage"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/trace"
@@ -30,33 +34,64 @@ func (c *Controller) Tracer() trace.Tracer {
func (c *Controller) GetTransaction(
ctx context.Context,
txID ids.ID,
-) (bool, int64, bool, chain.Dimensions, uint64, error) {
+) (bool, int64, bool, fees.Dimensions, uint64, error) {
return storage.GetTransaction(ctx, c.metaDB, txID)
}
-func (c *Controller) GetAssetFromState(
+func (c *Controller) GetBalanceFromState(
ctx context.Context,
- asset ids.ID,
-) (bool, []byte, uint8, []byte, uint64, ed25519.PublicKey, bool, error) {
- return storage.GetAssetFromState(ctx, c.inner.ReadState, asset)
+ addr codec.Address,
+) (uint64, error) {
+ return storage.GetBalanceFromState(ctx, c.inner.ReadState, addr)
}
-func (c *Controller) GetBalanceFromState(
+func (c *Controller) GetRollupRegistryFromState(
ctx context.Context,
- pk ed25519.PublicKey,
- asset ids.ID,
-) (uint64, error) {
- return storage.GetBalanceFromState(ctx, c.inner.ReadState, pk, asset)
+) ([][]byte, error) {
+ return storage.GetRollupRegistryFromState(ctx, c.inner.ReadState)
}
-func (c *Controller) GetLoanFromState(
+func (c *Controller) GetEpochExitsFromState(
ctx context.Context,
- asset ids.ID,
- destination ids.ID,
-) (uint64, error) {
- return storage.GetLoanFromState(ctx, c.inner.ReadState, asset, destination)
+ epoch uint64,
+) (*hactions.EpochExitInfo, error) {
+ info, err := storage.GetEpochExitsFromState(ctx, c.inner.ReadState, epoch)
+ if err != nil {
+ return nil, err
+ }
+ return info, nil
+}
+
+func (c *Controller) GetRollupInfoFromState(
+ ctx context.Context,
+ namespace []byte,
+) (*hactions.RollupInfo, error) {
+ return storage.GetRollupInfoFromState(ctx, c.inner.ReadState, namespace)
+}
+
+func (c *Controller) GetBuilderFromState(
+ ctx context.Context,
+ epoch uint64,
+) ([]byte, error) {
+ return storage.GetArcadiaBuilderFromState(ctx, c.inner.ReadState, epoch)
}
func (c *Controller) GetAcceptedBlockWindow() int {
return c.config.GetAcceptedBlockWindow()
}
+
+func (c *Controller) Archiver() *archiver.ORMArchiver {
+ return c.archiver
+}
+
+func (c *Controller) RollupRegistry() *rollupregistry.RollupRegistry {
+ return c.rollupRegistry
+}
+
+func (c *Controller) NetworkID() uint32 {
+ return c.snowCtx.NetworkID
+}
+
+func (c *Controller) ChainID() ids.ID {
+ return c.snowCtx.ChainID
+}
diff --git a/controller/state_manager.go b/controller/state_manager.go
index aa26dc5..ae2e753 100644
--- a/controller/state_manager.go
+++ b/controller/state_manager.go
@@ -4,10 +4,17 @@
package controller
import (
+ "context"
+
"github.com/AnomalyFi/nodekit-seq/storage"
- "github.com/ava-labs/avalanchego/ids"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/state"
)
+var _ (chain.StateManager) = (*StateManager)(nil)
+
type StateManager struct{}
func (*StateManager) HeightKey() []byte {
@@ -19,13 +26,40 @@ func (*StateManager) TimestampKey() []byte {
}
func (*StateManager) FeeKey() []byte {
- return storage.HeightKey()
+ return storage.FeeKey()
+}
+
+func (*StateManager) FeeMarketKey() (k []byte) {
+ return storage.FeeMarketKey()
+}
+
+func (*StateManager) SponsorStateKeys(addr codec.Address) state.Keys {
+ return state.Keys{
+ string(storage.BalanceKey(addr)): state.Read | state.Write,
+ }
}
-func (*StateManager) IncomingWarpKeyPrefix(sourceChainID ids.ID, msgID ids.ID) []byte {
- return storage.IncomingWarpKeyPrefix(sourceChainID, msgID)
+func (*StateManager) CanDeduct(
+ ctx context.Context,
+ addr codec.Address,
+ im state.Immutable,
+ amount uint64,
+) error {
+ bal, err := storage.GetBalance(ctx, im, addr)
+ if err != nil {
+ return err
+ }
+ if bal < amount {
+ return storage.ErrInvalidBalance
+ }
+ return nil
}
-func (*StateManager) OutgoingWarpKeyPrefix(txID ids.ID) []byte {
- return storage.OutgoingWarpKeyPrefix(txID)
+func (*StateManager) Deduct(
+ ctx context.Context,
+ addr codec.Address,
+ mu state.Mutable,
+ amount uint64,
+) error {
+ return storage.SubBalance(ctx, mu, addr, amount)
}
diff --git a/genesis/genesis.go b/genesis/genesis.go
index 48cd393..5952feb 100644
--- a/genesis/genesis.go
+++ b/genesis/genesis.go
@@ -8,18 +8,19 @@ import (
"encoding/json"
"fmt"
- "github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/trace"
+ "github.com/ava-labs/avalanchego/x/merkledb"
+
smath "github.com/ava-labs/avalanchego/utils/math"
- "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/fees"
+
hconsts "github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
"github.com/AnomalyFi/hypersdk/state"
"github.com/AnomalyFi/hypersdk/vm"
"github.com/AnomalyFi/nodekit-seq/consts"
"github.com/AnomalyFi/nodekit-seq/storage"
- "github.com/AnomalyFi/nodekit-seq/utils"
)
var _ vm.Genesis = (*Genesis)(nil)
@@ -30,37 +31,38 @@ type CustomAllocation struct {
}
type Genesis struct {
- // Address prefix
- HRP string `json:"hrp"`
+ // State Parameters
+ StateBranchFactor merkledb.BranchFactor `json:"stateBranchFactor"`
// Chain Parameters
MinBlockGap int64 `json:"minBlockGap"` // ms
MinEmptyBlockGap int64 `json:"minEmptyBlockGap"` // ms
+ EpochLength int64 `json:"epochLength"` // number of SEQ blocks
// Chain Fee Parameters
- MinUnitPrice chain.Dimensions `json:"minUnitPrice"`
- UnitPriceChangeDenominator chain.Dimensions `json:"unitPriceChangeDenominator"`
- WindowTargetUnits chain.Dimensions `json:"windowTargetUnits"` // 10s
- MaxBlockUnits chain.Dimensions `json:"maxBlockUnits"` // must be possible to reach before block too large
+ MinUnitPrice fees.Dimensions `json:"minUnitPrice"`
+ UnitPriceChangeDenominator fees.Dimensions `json:"unitPriceChangeDenominator"`
+ WindowTargetUnits fees.Dimensions `json:"windowTargetUnits"` // 10s
+ MaxBlockUnits fees.Dimensions `json:"maxBlockUnits"` // must be possible to reach before block too large
+
+ // Fee Market Parameters
+ FeeMarketMinUnits uint64 `json:"feeMarketMinUnits"`
+ FeeMarketWindowTargetUnits uint64 `json:"feeMarketWindowTargetUnits"`
+ FeeMarketPriceChangeDenominator uint64 `json:"feeMarketPriceChangeDenominator"`
// Tx Parameters
- ValidityWindow int64 `json:"validityWindow"` // ms
+ ValidityWindow int64 `json:"validityWindow"` // ms
+ MaxActionsPerTx uint8 `json:"maxActionsPerTx"`
+ MaxOutputsPerAction uint8 `json:"maxOutputsPerAction"`
// Tx Fee Parameters
- BaseComputeUnits uint64 `json:"baseUnits"`
- BaseWarpComputeUnits uint64 `json:"baseWarpUnits"`
- WarpComputeUnitsPerSigner uint64 `json:"warpUnitsPerSigner"`
- OutgoingWarpComputeUnits uint64 `json:"outgoingWarpComputeUnits"`
- ColdStorageKeyReadUnits uint64 `json:"coldStorageKeyReadUnits"`
- ColdStorageValueReadUnits uint64 `json:"coldStorageValueReadUnits"` // per chunk
- WarmStorageKeyReadUnits uint64 `json:"warmStorageKeyReadUnits"`
- WarmStorageValueReadUnits uint64 `json:"warmStorageValueReadUnits"` // per chunk
- StorageKeyCreateUnits uint64 `json:"storageKeyCreateUnits"`
- StorageValueCreateUnits uint64 `json:"storageKeyValueUnits"` // per chunk
- ColdStorageKeyModificationUnits uint64 `json:"coldStorageKeyModificationUnits"`
- ColdStorageValueModificationUnits uint64 `json:"coldStorageValueModificationUnits"` // per chunk
- WarmStorageKeyModificationUnits uint64 `json:"warmStorageKeyModificationUnits"`
- WarmStorageValueModificationUnits uint64 `json:"warmStorageValueModificationUnits"` // per chunk
+ BaseComputeUnits uint64 `json:"baseUnits"`
+ StorageKeyReadUnits uint64 `json:"storageKeyReadUnits"`
+ StorageValueReadUnits uint64 `json:"storageValueReadUnits"` // per chunk
+ StorageKeyAllocateUnits uint64 `json:"storageKeyAllocateUnits"`
+ StorageValueAllocateUnits uint64 `json:"storageValueAllocateUnits"` // per chunk
+ StorageKeyWriteUnits uint64 `json:"storageKeyWriteUnits"`
+ StorageValueWriteUnits uint64 `json:"storageValueWriteUnits"` // per chunk
// Allocations
CustomAllocation []*CustomAllocation `json:"customAllocation"`
@@ -68,41 +70,42 @@ type Genesis struct {
func Default() *Genesis {
return &Genesis{
- HRP: consts.HRP,
+ // State Parameters
+ StateBranchFactor: merkledb.BranchFactor16,
// Chain Parameters
MinBlockGap: 1_000,
MinEmptyBlockGap: 1_000,
- // MinEmptyBlockGap used to be 2_500
+ EpochLength: 6,
// Chain Fee Parameters
- MinUnitPrice: chain.Dimensions{100, 100, 100, 100, 100},
- UnitPriceChangeDenominator: chain.Dimensions{48, 48, 48, 48, 48},
- WindowTargetUnits: chain.Dimensions{20_000_000, 1_000, 1_000, 1_000, 1_000},
- MaxBlockUnits: chain.Dimensions{1_800_000, 2_000, 2_000, 2_000, 2_000},
+ MinUnitPrice: fees.Dimensions{100, 100, 100, 100, 100},
+ UnitPriceChangeDenominator: fees.Dimensions{48, 48, 48, 48, 48},
+ WindowTargetUnits: fees.Dimensions{20_000_000, 1_000, 1_000, 1_000, 1_000},
+ MaxBlockUnits: fees.Dimensions{1_800_000, 2_000, 2_000, 2_000, 2_000},
+
+ // Fee Market Parameters
+ FeeMarketMinUnits: 100,
+ FeeMarketWindowTargetUnits: 600 * 1024, // 600 KiB
+ FeeMarketPriceChangeDenominator: 48,
// Tx Parameters
- ValidityWindow: 60 * hconsts.MillisecondsPerSecond, // ms
+ ValidityWindow: 60 * hconsts.MillisecondsPerSecond, // ms
+ MaxActionsPerTx: 16,
+ MaxOutputsPerAction: 1,
// Tx Fee Compute Parameters
- BaseComputeUnits: 1,
- BaseWarpComputeUnits: 1_024,
- WarpComputeUnitsPerSigner: 128,
- OutgoingWarpComputeUnits: 1_024,
+ BaseComputeUnits: 1,
// Tx Fee Storage Parameters
//
// TODO: tune this
- ColdStorageKeyReadUnits: 5,
- ColdStorageValueReadUnits: 2,
- WarmStorageKeyReadUnits: 1,
- WarmStorageValueReadUnits: 1,
- StorageKeyCreateUnits: 20,
- StorageValueCreateUnits: 5,
- ColdStorageKeyModificationUnits: 10,
- ColdStorageValueModificationUnits: 3,
- WarmStorageKeyModificationUnits: 5,
- WarmStorageValueModificationUnits: 3,
+ StorageKeyReadUnits: 5,
+ StorageValueReadUnits: 2,
+ StorageKeyAllocateUnits: 20,
+ StorageValueAllocateUnits: 5,
+ StorageKeyWriteUnits: 10,
+ StorageValueWriteUnits: 3,
}
}
@@ -120,33 +123,28 @@ func (g *Genesis) Load(ctx context.Context, tracer trace.Tracer, mu state.Mutabl
ctx, span := tracer.Start(ctx, "Genesis.Load")
defer span.End()
- if consts.HRP != g.HRP {
- return ErrInvalidHRP
+ if err := g.StateBranchFactor.Valid(); err != nil {
+ return err
}
supply := uint64(0)
for _, alloc := range g.CustomAllocation {
- pk, err := utils.ParseAddress(alloc.Address)
+ pk, err := codec.ParseAddressBech32(consts.HRP, alloc.Address)
if err != nil {
+ fmt.Println("here here here parse address bech32")
return err
}
supply, err = smath.Add64(supply, alloc.Balance)
if err != nil {
return err
}
- if err := storage.SetBalance(ctx, mu, pk, ids.Empty, alloc.Balance); err != nil {
+ if err := storage.SetBalance(ctx, mu, pk, alloc.Balance); err != nil {
return fmt.Errorf("%w: addr=%s, bal=%d", err, alloc.Address, alloc.Balance)
}
}
- return storage.SetAsset(
- ctx,
- mu,
- ids.Empty,
- []byte(consts.Symbol),
- consts.Decimals,
- []byte(consts.Name),
- supply,
- ed25519.EmptyPublicKey,
- false,
- )
+ return nil
+}
+
+func (g *Genesis) GetStateBranchFactor() merkledb.BranchFactor {
+ return g.StateBranchFactor
}
diff --git a/genesis/rules.go b/genesis/rules.go
index dc0251d..4309217 100644
--- a/genesis/rules.go
+++ b/genesis/rules.go
@@ -5,7 +5,11 @@ package genesis
import (
"github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/fees"
"github.com/ava-labs/avalanchego/ids"
+
+ "github.com/AnomalyFi/nodekit-seq/storage"
)
var _ chain.Rules = (*Rules)(nil)
@@ -13,21 +17,14 @@ var _ chain.Rules = (*Rules)(nil)
type Rules struct {
g *Genesis
- networkID uint32
- chainID ids.ID
+ networkID uint32
+ chainID ids.ID
+ parsedWhiteListedAddress []codec.Address
}
// TODO: use upgradeBytes
-func (g *Genesis) Rules(_ int64, networkID uint32, chainID ids.ID) *Rules {
- return &Rules{g, networkID, chainID}
-}
-
-func (*Rules) GetWarpConfig(ids.ID) (bool, uint64, uint64) {
- // We allow inbound transfers from all sources as long as 80% of stake has
- // signed a message.
- //
- // This is safe because the tokenvm scopes all assets by their source chain.
- return true, 4, 5
+func (g *Genesis) Rules(_ int64, networkID uint32, chainID ids.ID, parsedWhiteListedAddresses []codec.Address) *Rules {
+ return &Rules{g, networkID, chainID, parsedWhiteListedAddresses}
}
func (r *Rules) NetworkID() uint32 {
@@ -50,78 +47,81 @@ func (r *Rules) GetValidityWindow() int64 {
return r.g.ValidityWindow
}
-func (r *Rules) GetMaxBlockUnits() chain.Dimensions {
- return r.g.MaxBlockUnits
+func (r *Rules) GetEpochLength() int64 {
+ return r.g.EpochLength
}
-func (r *Rules) GetBaseComputeUnits() uint64 {
- return r.g.BaseComputeUnits
+func (r *Rules) GetMaxActionsPerTx() uint8 {
+ return r.g.MaxActionsPerTx
}
-func (r *Rules) GetBaseWarpComputeUnits() uint64 {
- return r.g.BaseWarpComputeUnits
+func (r *Rules) GetMaxOutputsPerAction() uint8 {
+ return r.g.MaxOutputsPerAction
}
-func (r *Rules) GetWarpComputeUnitsPerSigner() uint64 {
- return r.g.WarpComputeUnitsPerSigner
+func (r *Rules) GetMaxBlockUnits() fees.Dimensions {
+ return r.g.MaxBlockUnits
}
-func (r *Rules) GetOutgoingWarpComputeUnits() uint64 {
- return r.g.OutgoingWarpComputeUnits
+func (r *Rules) GetBaseComputeUnits() uint64 {
+ return r.g.BaseComputeUnits
}
-func (r *Rules) GetColdStorageKeyReadUnits() uint64 {
- return r.g.ColdStorageKeyReadUnits
+func (*Rules) GetSponsorStateKeysMaxChunks() []uint16 {
+ return []uint16{storage.BalanceChunks}
}
-func (r *Rules) GetColdStorageValueReadUnits() uint64 {
- return r.g.ColdStorageValueReadUnits
+func (r *Rules) GetStorageKeyReadUnits() uint64 {
+ return r.g.StorageKeyReadUnits
}
-func (r *Rules) GetWarmStorageKeyReadUnits() uint64 {
- return r.g.WarmStorageKeyReadUnits
+func (r *Rules) GetStorageValueReadUnits() uint64 {
+ return r.g.StorageValueReadUnits
}
-func (r *Rules) GetWarmStorageValueReadUnits() uint64 {
- return r.g.WarmStorageValueReadUnits
+func (r *Rules) GetStorageKeyAllocateUnits() uint64 {
+ return r.g.StorageKeyAllocateUnits
}
-func (r *Rules) GetStorageKeyCreateUnits() uint64 {
- return r.g.StorageKeyCreateUnits
+func (r *Rules) GetStorageValueAllocateUnits() uint64 {
+ return r.g.StorageValueAllocateUnits
}
-func (r *Rules) GetStorageValueCreateUnits() uint64 {
- return r.g.StorageValueCreateUnits
+func (r *Rules) GetStorageKeyWriteUnits() uint64 {
+ return r.g.StorageKeyWriteUnits
}
-func (r *Rules) GetColdStorageKeyModificationUnits() uint64 {
- return r.g.ColdStorageKeyModificationUnits
+func (r *Rules) GetStorageValueWriteUnits() uint64 {
+ return r.g.StorageValueWriteUnits
}
-func (r *Rules) GetColdStorageValueModificationUnits() uint64 {
- return r.g.ColdStorageValueModificationUnits
+func (r *Rules) GetMinUnitPrice() fees.Dimensions {
+ return r.g.MinUnitPrice
}
-func (r *Rules) GetWarmStorageKeyModificationUnits() uint64 {
- return r.g.WarmStorageKeyModificationUnits
+func (r *Rules) GetUnitPriceChangeDenominator() fees.Dimensions {
+ return r.g.UnitPriceChangeDenominator
}
-func (r *Rules) GetWarmStorageValueModificationUnits() uint64 {
- return r.g.WarmStorageValueModificationUnits
+func (r *Rules) GetWindowTargetUnits() fees.Dimensions {
+ return r.g.WindowTargetUnits
}
-func (r *Rules) GetMinUnitPrice() chain.Dimensions {
- return r.g.MinUnitPrice
+func (r *Rules) GetFeeMarketPriceChangeDenominator() uint64 {
+ return r.g.FeeMarketPriceChangeDenominator
}
-func (r *Rules) GetUnitPriceChangeDenominator() chain.Dimensions {
- return r.g.UnitPriceChangeDenominator
+func (r *Rules) GetFeeMarketWindowTargetUnits() uint64 {
+ return r.g.FeeMarketWindowTargetUnits
}
-func (r *Rules) GetWindowTargetUnits() chain.Dimensions {
- return r.g.WindowTargetUnits
+func (r *Rules) GetFeeMarketMinUnitPrice() uint64 {
+ return r.g.FeeMarketMinUnits
}
-func (*Rules) FetchCustom(string) (any, bool) {
+func (r *Rules) FetchCustom(s string) (any, bool) {
+ if s == "whitelisted.Addresses" {
+ return r.parsedWhiteListedAddress, false
+ }
return nil, false
}
diff --git a/go.mod b/go.mod
index 6c0a813..f1a045c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,34 +1,32 @@
module github.com/AnomalyFi/nodekit-seq
-go 1.21
-
-toolchain go1.21.6
+go 1.21.12
require (
- github.com/AnomalyFi/hypersdk v0.9.3-beta.3
- github.com/ava-labs/avalanche-network-runner v1.7.2
- github.com/ava-labs/avalanchego v1.10.10
- github.com/ethereum/go-ethereum v1.12.0
- github.com/fatih/color v1.13.0
- github.com/onsi/ginkgo/v2 v2.8.1
- github.com/onsi/gomega v1.26.0
+ github.com/AnomalyFi/hypersdk v0.9.7-arcadia.16
+ github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0
+ github.com/ava-labs/avalanchego v1.11.10
+ github.com/ethereum/go-ethereum v1.13.14
+ github.com/fatih/color v1.16.0
+ github.com/onsi/ginkgo/v2 v2.13.1
github.com/prometheus/client_golang v1.16.0
github.com/spf13/cobra v1.7.0
- github.com/tidwall/btree v1.5.0
- github.com/wailsapp/wails/v2 v2.5.1
- go.uber.org/zap v1.24.0
- golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e
- golang.org/x/net v0.17.0
+ github.com/stretchr/testify v1.8.4
+ go.uber.org/zap v1.26.0
+ gorm.io/driver/postgres v1.5.9
+ gorm.io/driver/sqlite v1.5.6
+ gorm.io/gorm v1.25.10
)
require (
+ filippo.io/edwards25519 v1.0.0 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
- github.com/Microsoft/go-winio v0.5.2 // indirect
+ github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/NYTimes/gziphandler v1.1.1 // indirect
- github.com/VictoriaMetrics/fastcache v1.10.0 // indirect
- github.com/ava-labs/coreth v0.12.5-rc.6 // indirect
+ github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
+ github.com/ava-labs/coreth v0.13.7 // indirect
github.com/beorn7/perks v1.0.1 // indirect
- github.com/bep/debounce v1.2.1 // indirect
+ github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
github.com/btcsuite/btcd/btcutil v1.1.3 // indirect
github.com/celestiaorg/nmt v0.20.0 // indirect
@@ -37,32 +35,37 @@ require (
github.com/chzyer/readline v1.5.1 // indirect
github.com/cockroachdb/errors v1.9.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
- github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c // indirect
+ github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect
github.com/cockroachdb/redact v1.1.3 // indirect
+ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
+ github.com/consensys/bavard v0.1.13 // indirect
+ github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+ github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect
+ github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
- github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect
- github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
+ github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect
+ github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
+ github.com/fjl/memsize v0.0.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
+ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
- github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
- github.com/go-stack/stack v1.8.1 // indirect
+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
- github.com/golang/mock v1.6.0 // indirect
- github.com/golang/protobuf v1.5.3 // indirect
+ github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
- github.com/google/go-cmp v0.6.0 // indirect
github.com/google/pprof v0.0.0-20230406165453-00490a63f317 // indirect
- github.com/google/uuid v1.3.1 // indirect
+ github.com/google/renameio/v2 v2.0.0 // indirect
+ github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/rpc v1.2.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
@@ -71,36 +74,37 @@ require (
github.com/hashicorp/go-bexpr v0.1.10 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
- github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect
+ github.com/hdevalence/ed25519consensus v0.2.0 // indirect
+ github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
- github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
- github.com/huin/goupnp v1.0.3 // indirect
+ github.com/holiman/uint256 v1.2.4 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
+ github.com/jackc/pgpassfile v1.0.0 // indirect
+ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
+ github.com/jackc/pgx/v5 v5.5.5 // indirect
+ github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jackpal/gateway v1.0.6 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
- github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+ github.com/jinzhu/inflection v1.0.0 // indirect
+ github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
- github.com/labstack/echo/v4 v4.10.2 // indirect
- github.com/labstack/gommon v0.4.0 // indirect
- github.com/leaanthony/go-ansi-parser v1.6.0 // indirect
- github.com/leaanthony/gosod v1.0.3 // indirect
- github.com/leaanthony/slicer v1.6.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.0 // indirect
+ github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect
- github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/openzipkin/zipkin-go v0.4.1 // indirect
- github.com/otiai10/copy v1.11.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pires/go-proxyproto v0.6.2 // indirect
@@ -111,30 +115,23 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
- github.com/rogpeppe/go-internal v1.10.0 // indirect
+ github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
- github.com/samber/lo v1.38.1 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
- github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.8.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.12.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
- github.com/stretchr/testify v1.8.4 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
- github.com/tklauser/go-sysconf v0.3.5 // indirect
- github.com/tklauser/numcpus v0.2.2 // indirect
- github.com/tkrajina/go-reflector v0.5.6 // indirect
+ github.com/tklauser/go-sysconf v0.3.12 // indirect
+ github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
- github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect
- github.com/valyala/bytebufferpool v1.0.0 // indirect
- github.com/valyala/fasttemplate v1.2.2 // indirect
- github.com/wailsapp/mimetype v1.4.1 // indirect
+ github.com/urfave/cli/v2 v2.25.7 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opentelemetry.io/otel v1.22.0 // indirect
@@ -146,29 +143,34 @@ require (
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
- go.uber.org/atomic v1.10.0 // indirect
- go.uber.org/mock v0.2.0 // indirect
+ go.uber.org/atomic v1.11.0 // indirect
+ go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/crypto v0.22.0 // indirect
+ golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e // indirect
golang.org/x/mod v0.14.0 // indirect
- golang.org/x/sync v0.4.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
- golang.org/x/term v0.13.0 // indirect
- golang.org/x/text v0.13.0 // indirect
+ golang.org/x/net v0.24.0 // indirect
+ golang.org/x/sync v0.7.0 // indirect
+ golang.org/x/sys v0.19.0 // indirect
+ golang.org/x/term v0.19.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
+ golang.org/x/tools v0.17.0 // indirect
gonum.org/v1/gonum v0.11.0 // indirect
- google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect
- google.golang.org/grpc v1.60.1 // indirect
- google.golang.org/protobuf v1.32.0 // indirect
+ google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
+ google.golang.org/grpc v1.62.0 // indirect
+ google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
- gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+ rsc.io/tmplfunc v0.0.3 // indirect
)
-replace github.com/ava-labs/avalanchego => github.com/AnomalyFi/avalanchego v1.10.10-beta.2
+// replace github.com/ava-labs/avalanchego => github.com/AnomalyFi/avalanchego v1.10.10-beta.2
+
+// replace github.com/ava-labs/coreth => github.com/AnomalyFi/coreth v0.12.5-rc.6.1
-replace github.com/ava-labs/coreth => github.com/AnomalyFi/coreth v0.12.5-rc.6.1
+// replace github.com/AnomalyFi/hypersdk => ../hypersdk
diff --git a/go.sum b/go.sum
index 4db992b..81db740 100644
--- a/go.sum
+++ b/go.sum
@@ -36,43 +36,43 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
+filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
-github.com/AnomalyFi/avalanchego v1.10.10-beta.2 h1:834Wu95CB7BKMOb10+MD4U2qZfl4jAOgtuGC9lxSJyw=
-github.com/AnomalyFi/avalanchego v1.10.10-beta.2/go.mod h1:WsVfXvqJmLr7cuCTbQJd/TgUaa6zd9I2f9MCtCuhxLw=
-github.com/AnomalyFi/coreth v0.12.5-rc.6.1 h1:+zrraDQQL2u6uH845LT8XciCP0I7QxPy9xLujZ2pugA=
-github.com/AnomalyFi/coreth v0.12.5-rc.6.1/go.mod h1:dM5+4lelJ37pYjWJ3ZAC0EK78OGhBSINycycZVoRQ4s=
-github.com/AnomalyFi/hypersdk v0.9.3-beta.3 h1:ddQ4Zcy8WEnZ5GrZu91joyBjnrERleawa4OSviPxTlg=
-github.com/AnomalyFi/hypersdk v0.9.3-beta.3/go.mod h1:ygZ/2T0Td1RPjyTpsCHGJnLlmk7nCYQJSpgQPANaocE=
+github.com/AnomalyFi/hypersdk v0.9.7-arcadia.16 h1:bwkpHWSs/fzelJp97iU+npoS5KAGcz48EloGSD23Jdc=
+github.com/AnomalyFi/hypersdk v0.9.7-arcadia.16/go.mod h1:0Vj2PdwSFN7pat4Sno39IfmtOiv/gO9mxZXyRKnoKtI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
-github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
+github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
-github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
-github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
-github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY=
-github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8=
+github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40=
+github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
-github.com/ava-labs/avalanche-network-runner v1.7.2 h1:XFad/wZfYzDnqbLzPAPPRYU3a1Zc8QT8x5dtLTS3lUo=
-github.com/ava-labs/avalanche-network-runner v1.7.2/go.mod h1:naLveusSrP7YgTAqRykD1SyLOAUilCp9jGjk3MDxoPI=
+github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0 h1:xNbCMNqenaDr0bb35j27sqwa+C8t8BgRz51vXd6q0QM=
+github.com/ava-labs/avalanche-network-runner v1.7.4-rc.0/go.mod h1:B7Ynk/avkCk49CCIWbM4j1UrPlqIi0IHCPAB2MZNvLw=
+github.com/ava-labs/avalanchego v1.11.10 h1:QujciF5OEp5FwAoe/RciFF/i47rxU5rkEr6fVuUBS1Q=
+github.com/ava-labs/avalanchego v1.11.10/go.mod h1:POgZPryqe80OeHCDNrXrPOKoFre736iFuMgmUBeKaLc=
+github.com/ava-labs/coreth v0.13.7 h1:k8T9u/ROifl8f7oXjHRc1KvSISRl9txvy7gGVmHEz6g=
+github.com/ava-labs/coreth v0.13.7/go.mod h1:tXDujonxXFOF6oK5HS2EmgtSXJK3Gy6RpZxb5WzR9rM=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
-github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
-github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
-github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
+github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
+github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA=
@@ -104,7 +104,6 @@ github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
-github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -123,24 +122,35 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
+github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
+github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8=
github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk=
github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
-github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c h1:BvCMEtKLZrlcBY2li3COY2q9335JHRK9bC8YTsx60/E=
-github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c/go.mod h1:9lRMC4XN3/BLPtIp6kAKwIaHu369NOf2rMucPzipz50=
+github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A=
+github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo=
github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ=
github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
+github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
+github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
+github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
+github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
+github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ=
+github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
+github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=
+github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -160,8 +170,8 @@ github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwu
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
-github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE=
-github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
+github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo=
+github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -174,16 +184,18 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
-github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0=
-github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs=
+github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY=
+github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
+github.com/ethereum/go-ethereum v1.13.14 h1:EwiY3FZP94derMCIam1iW4HFVrSgIcpsu0HwTQtm6CQ=
+github.com/ethereum/go-ethereum v1.13.14/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
-github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
-github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
-github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
-github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
-github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA=
+github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
+github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
+github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
@@ -192,6 +204,8 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
+github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE=
+github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc=
github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c=
github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0=
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
@@ -210,13 +224,14 @@ github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
-github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
+github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
-github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
-github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
@@ -228,12 +243,13 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog=
-github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
-github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
+github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
+github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -244,8 +260,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -262,8 +276,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -306,9 +320,12 @@ github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8q
github.com/google/pprof v0.0.0-20230406165453-00490a63f317 h1:hFhpt7CTmR3DX+b4R19ydQFtofxT0Sv3QsKNMVQYTMQ=
github.com/google/pprof v0.0.0-20230406165453-00490a63f317/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
+github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
+github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
-github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
@@ -333,16 +350,17 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuW
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw=
-github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU=
+github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU=
+github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
+github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4=
+github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
-github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8=
-github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
+github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
+github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
-github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y=
-github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -356,14 +374,24 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
+github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
+github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
+github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackpal/gateway v1.0.6 h1:/MJORKvJEwNVldtGVJC2p2cwCnsSoLn3hl3zxmZT7tk=
github.com/jackpal/gateway v1.0.6/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
-github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
-github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -397,20 +425,7 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
-github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
-github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
-github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
-github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
-github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
-github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
-github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg=
-github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
-github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
-github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
-github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
-github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
-github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -418,11 +433,8 @@ github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamh
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
-github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
-github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@@ -432,11 +444,13 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
@@ -449,6 +463,9 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
+github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
+github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
+github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@@ -480,22 +497,18 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
-github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU=
-github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc=
+github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
+github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
-github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
-github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
+github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
+github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/openzipkin/zipkin-go v0.4.1 h1:kNd/ST2yLLWhaWrkgchya40TJabe8Hioj9udfPcEO5A=
github.com/openzipkin/zipkin-go v0.4.1/go.mod h1:qY0VqDSN1pOBN94dBc6w2GJlWLiovAyg7Qt6/I9HecM=
-github.com/otiai10/copy v1.11.0 h1:OKBD80J/mLBrwnzXqGtFCzprFSGioo30JcmR4APsNwc=
-github.com/otiai10/copy v1.11.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww=
-github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
-github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -530,16 +543,14 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
-github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU=
github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
@@ -547,11 +558,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
-github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
@@ -574,12 +582,11 @@ github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobt
github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
@@ -595,41 +602,30 @@ github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5f
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/thepudds/fzgen v0.4.2 h1:HlEHl5hk2/cqEomf2uK5SA/FeJc12s/vIHmOG+FbACw=
github.com/thepudds/fzgen v0.4.2/go.mod h1:kHCWdsv5tdnt32NIHYDdgq083m6bMtaY0M+ipiO9xWE=
-github.com/tidwall/btree v1.5.0 h1:iV0yVY/frd7r6qGBXfEYs7DH0gTDgrKTrDjS7xt/IyQ=
-github.com/tidwall/btree v1.5.0/go.mod h1:LGm8L/DZjPLmeWGjv5kFrY8dL4uVhMmzmmLYmsObdKE=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
-github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
-github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
-github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
-github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
-github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
-github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
+github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
+github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
+github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
-github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
-github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
+github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
+github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
-github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
-github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
-github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
-github.com/wailsapp/wails/v2 v2.5.1 h1:mfG+2kWqQXYOwdgI43HEILjOZDXbk5woPYI3jP2b+js=
-github.com/wailsapp/wails/v2 v2.5.1/go.mod h1:jbOZbcr/zm79PxXxAjP8UoVlDd9wLW3uDs+isIthDfs=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
@@ -672,16 +668,16 @@ go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx
go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
-go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
-go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
+go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
-go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU=
-go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM=
+go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
+go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
-go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
+go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -695,8 +691,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
+golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -777,13 +773,12 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
+golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -805,8 +800,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -826,7 +821,6 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -845,7 +839,6 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -854,9 +847,7 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -867,23 +858,25 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
-golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
+golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
+golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -894,8 +887,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -955,9 +948,10 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
+golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1029,12 +1023,12 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0=
-google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk=
-google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU=
-google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY=
+google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
+google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
+google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU=
+google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -1053,8 +1047,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
-google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
+google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
+google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1067,8 +1061,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1084,8 +1078,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
-gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
-gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1099,6 +1091,12 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
+gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
+gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
+gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
+gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
+gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1109,3 +1107,5 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
+rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
diff --git a/registry/registry.go b/registry/registry.go
index a83d537..fb94274 100644
--- a/registry/registry.go
+++ b/registry/registry.go
@@ -7,7 +7,6 @@ import (
"github.com/AnomalyFi/hypersdk/chain"
"github.com/AnomalyFi/hypersdk/codec"
"github.com/ava-labs/avalanchego/utils/wrappers"
- "github.com/ava-labs/avalanchego/vms/platformvm/warp"
"github.com/AnomalyFi/nodekit-seq/actions"
"github.com/AnomalyFi/nodekit-seq/auth"
@@ -16,26 +15,20 @@ import (
// Setup types
func init() {
- consts.ActionRegistry = codec.NewTypeParser[chain.Action, *warp.Message]()
- consts.AuthRegistry = codec.NewTypeParser[chain.Auth, *warp.Message]()
+ consts.ActionRegistry = codec.NewTypeParser[chain.Action]()
+ consts.AuthRegistry = codec.NewTypeParser[chain.Auth]()
errs := &wrappers.Errs{}
errs.Add(
// When registering new actions, ALWAYS make sure to append at the end.
consts.ActionRegistry.Register((&actions.Transfer{}).GetTypeID(), actions.UnmarshalTransfer, false),
-
- consts.ActionRegistry.Register((&actions.CreateAsset{}).GetTypeID(), actions.UnmarshalCreateAsset, false),
- consts.ActionRegistry.Register((&actions.MintAsset{}).GetTypeID(), actions.UnmarshalMintAsset, false),
- consts.ActionRegistry.Register((&actions.BurnAsset{}).GetTypeID(), actions.UnmarshalBurnAsset, false),
-
- consts.ActionRegistry.Register((&actions.ImportAsset{}).GetTypeID(), actions.UnmarshalImportAsset, true),
- consts.ActionRegistry.Register((&actions.ExportAsset{}).GetTypeID(), actions.UnmarshalExportAsset, false),
- consts.ActionRegistry.Register((&actions.ImportBlockMsg{}).GetTypeID(), actions.UnmarshalImportBlockMsg, true),
- consts.ActionRegistry.Register((&actions.ExportBlockMsg{}).GetTypeID(), actions.UnmarshalExportBlockMsg, false),
consts.ActionRegistry.Register((&actions.SequencerMsg{}).GetTypeID(), actions.UnmarshalSequencerMsg, false),
-
+ consts.ActionRegistry.Register((&actions.RollupRegistration{}).GetTypeID(), actions.UnmarshalRollupRegister, false),
+ consts.ActionRegistry.Register((&actions.EpochExit{}).GetTypeID(), actions.UnmarshalEpochExit, false),
+ consts.ActionRegistry.Register((&actions.Auction{}).GetTypeID(), actions.UnmarshalAuction, false),
// When registering new auth, ALWAYS make sure to append at the end.
consts.AuthRegistry.Register((&auth.ED25519{}).GetTypeID(), auth.UnmarshalED25519, false),
+ consts.AuthRegistry.Register((&auth.BLS{}).GetTypeID(), auth.UnmarshalBLS, false),
)
if errs.Errored() {
panic(errs.Err)
diff --git a/rollup_registry/registry.go b/rollup_registry/registry.go
new file mode 100644
index 0000000..0a0e952
--- /dev/null
+++ b/rollup_registry/registry.go
@@ -0,0 +1,60 @@
+package rollupregistry
+
+import (
+ "maps"
+ "sync"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+type RollupRegistryOnlyRead interface {
+ RollupsValidAtEpoch(epoch uint64) []*hactions.RollupInfo
+}
+
+type RollupRegistryAllPerm interface {
+ RollupRegistryOnlyRead
+ Update(currentEpoch uint64, rollups []*hactions.RollupInfo)
+}
+
+var _ RollupRegistryAllPerm = (*RollupRegistry)(nil)
+
+type RollupRegistry struct {
+ rollups map[ids.ID]*hactions.RollupInfo
+ rollupsL sync.RWMutex
+}
+
+func NewRollupRegistr() *RollupRegistry {
+ return &RollupRegistry{
+ rollups: make(map[ids.ID]*hactions.RollupInfo),
+ }
+}
+
+func (r *RollupRegistry) RollupsValidAtEpoch(epoch uint64) []*hactions.RollupInfo {
+ r.rollupsL.RLock()
+ defer r.rollupsL.RUnlock()
+
+ ret := make([]*hactions.RollupInfo, 0)
+ for _, rollup := range r.rollups {
+ if !rollup.ValidAtEpoch(epoch) {
+ continue
+ }
+
+ ret = append(ret, rollup)
+ }
+
+ return ret
+}
+
+func (r *RollupRegistry) Update(currentEpoch uint64, rollups []*hactions.RollupInfo) {
+ r.rollupsL.Lock()
+ defer r.rollupsL.Unlock()
+
+ for _, rollup := range rollups {
+ r.rollups[rollup.ID()] = rollup
+ }
+
+ maps.DeleteFunc(r.rollups, func(_ ids.ID, rollup *hactions.RollupInfo) bool {
+ return rollup.Exited(currentEpoch)
+ })
+}
diff --git a/rpc/consts.go b/rpc/consts.go
index 58f7c95..54483c7 100644
--- a/rpc/consts.go
+++ b/rpc/consts.go
@@ -4,7 +4,5 @@
package rpc
const (
- JSONRPCEndpoint = "/tokenapi"
-
- ordersToSend = 128
+ JSONRPCEndpoint = "/seqapi"
)
diff --git a/rpc/dependencies.go b/rpc/dependencies.go
index c635687..48f657f 100644
--- a/rpc/dependencies.go
+++ b/rpc/dependencies.go
@@ -6,25 +6,39 @@ package rpc
import (
"context"
+ hactions "github.com/AnomalyFi/hypersdk/actions"
"github.com/AnomalyFi/hypersdk/chain"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/fees"
+ "github.com/AnomalyFi/nodekit-seq/archiver"
"github.com/AnomalyFi/nodekit-seq/genesis"
+ rollupregistry "github.com/AnomalyFi/nodekit-seq/rollup_registry"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/trace"
+ "github.com/ava-labs/avalanchego/utils/logging"
)
type Controller interface {
+ NetworkID() uint32
+ ChainID() ids.ID
Genesis() *genesis.Genesis
Tracer() trace.Tracer
- GetTransaction(context.Context, ids.ID) (bool, int64, bool, chain.Dimensions, uint64, error)
- GetAssetFromState(context.Context, ids.ID) (bool, []byte, uint8, []byte, uint64, ed25519.PublicKey, bool, error)
- GetBalanceFromState(context.Context, ed25519.PublicKey, ids.ID) (uint64, error)
- GetLoanFromState(context.Context, ids.ID, ids.ID) (uint64, error)
- UnitPrices(ctx context.Context) (chain.Dimensions, error)
+ GetTransaction(context.Context, ids.ID) (bool, int64, bool, fees.Dimensions, uint64, error)
+ GetBalanceFromState(context.Context, codec.Address) (uint64, error)
+ GetEpochExitsFromState(ctx context.Context, epoch uint64) (*hactions.EpochExitInfo, error)
+ GetBuilderFromState(ctx context.Context, epoch uint64) ([]byte, error)
+ GetRollupInfoFromState(ctx context.Context, namespace []byte) (*hactions.RollupInfo, error)
+ GetRollupRegistryFromState(ctx context.Context) ([][]byte, error)
+ UnitPrices(ctx context.Context) (fees.Dimensions, error)
+ NameSpacesPrice(ctx context.Context, namespaces []string) ([]uint64, error)
GetAcceptedBlockWindow() int
Submit(
ctx context.Context,
verifySig bool,
txs []*chain.Transaction,
) (errs []error)
+ Logger() logging.Logger
+ // TODO: update this to only have read permission
+ Archiver() *archiver.ORMArchiver
+ RollupRegistry() *rollupregistry.RollupRegistry
}
diff --git a/rpc/errors.go b/rpc/errors.go
index 3f91757..691ab58 100644
--- a/rpc/errors.go
+++ b/rpc/errors.go
@@ -8,4 +8,5 @@ import "errors"
var (
ErrTxNotFound = errors.New("tx not found")
ErrAssetNotFound = errors.New("asset not found")
+ ErrTxFailed = errors.New("tx result failed")
)
diff --git a/rpc/jsonrpc_client.go b/rpc/jsonrpc_client.go
index cf1dbfb..13d3f73 100644
--- a/rpc/jsonrpc_client.go
+++ b/rpc/jsonrpc_client.go
@@ -5,19 +5,20 @@ package rpc
import (
"context"
- "fmt"
"strings"
- "sync"
"github.com/ava-labs/avalanchego/ids"
+ hactions "github.com/AnomalyFi/hypersdk/actions"
"github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
"github.com/AnomalyFi/hypersdk/requester"
"github.com/AnomalyFi/hypersdk/rpc"
"github.com/AnomalyFi/hypersdk/utils"
"github.com/AnomalyFi/nodekit-seq/consts"
"github.com/AnomalyFi/nodekit-seq/genesis"
_ "github.com/AnomalyFi/nodekit-seq/registry" // ensure registry populated
+ "github.com/AnomalyFi/nodekit-seq/types"
)
type JSONRPCClient struct {
@@ -26,8 +27,6 @@ type JSONRPCClient struct {
networkID uint32
chainID ids.ID
g *genesis.Genesis
- assetsL sync.Mutex
- assets map[ids.ID]*AssetReply
}
// New creates a new client object.
@@ -39,10 +38,25 @@ func NewJSONRPCClient(uri string, networkID uint32, chainID ids.ID) *JSONRPCClie
requester: req,
networkID: networkID,
chainID: chainID,
- assets: map[ids.ID]*AssetReply{},
}
}
+func (cli *JSONRPCClient) SubmitMsgTx(ctx context.Context, chainID string, networkID uint32, secondaryChainID []byte, data [][]byte) (string, error) {
+ resp := new(SubmitMsgTxReply)
+ err := cli.requester.SendRequest(
+ ctx,
+ "submitMsgTx",
+ &SubmitMsgTxArgs{
+ ChainID: chainID,
+ NetworkID: networkID,
+ SecondaryChainID: secondaryChainID,
+ Data: data,
+ },
+ resp,
+ )
+ return resp.TxID, err
+}
+
func (cli *JSONRPCClient) Genesis(ctx context.Context) (*genesis.Genesis, error) {
if cli.g != nil {
return cli.g, nil
@@ -81,66 +95,13 @@ func (cli *JSONRPCClient) Tx(ctx context.Context, id ids.ID) (bool, bool, int64,
return true, resp.Success, resp.Timestamp, resp.Fee, nil
}
-func (cli *JSONRPCClient) Asset(
- ctx context.Context,
- asset ids.ID,
- useCache bool,
-) (bool, []byte, uint8, []byte, uint64, string, bool, error) {
- cli.assetsL.Lock()
- r, ok := cli.assets[asset]
- cli.assetsL.Unlock()
- if ok && useCache {
- return true, r.Symbol, r.Decimals, r.Metadata, r.Supply, r.Owner, r.Warp, nil
- }
- resp := new(AssetReply)
- err := cli.requester.SendRequest(
- ctx,
- "asset",
- &AssetArgs{
- Asset: asset,
- },
- resp,
- )
- switch {
- // We use string parsing here because the JSON-RPC library we use may not
- // allows us to perform errors.Is.
- case err != nil && strings.Contains(err.Error(), ErrAssetNotFound.Error()):
- return false, nil, 0, nil, 0, "", false, nil
- case err != nil:
- return false, nil, 0, nil, 0, "", false, err
- }
- cli.assetsL.Lock()
- cli.assets[asset] = resp
- cli.assetsL.Unlock()
- return true, resp.Symbol, resp.Decimals, resp.Metadata, resp.Supply, resp.Owner, resp.Warp, nil
-}
-
-func (cli *JSONRPCClient) Balance(ctx context.Context, addr string, asset ids.ID) (uint64, error) {
+func (cli *JSONRPCClient) Balance(ctx context.Context, addr string) (uint64, error) {
resp := new(BalanceReply)
err := cli.requester.SendRequest(
ctx,
"balance",
&BalanceArgs{
Address: addr,
- Asset: asset,
- },
- resp,
- )
- return resp.Amount, err
-}
-
-func (cli *JSONRPCClient) Loan(
- ctx context.Context,
- asset ids.ID,
- destination ids.ID,
-) (uint64, error) {
- resp := new(LoanReply)
- err := cli.requester.SendRequest(
- ctx,
- "loan",
- &LoanArgs{
- Asset: asset,
- Destination: destination,
},
resp,
)
@@ -150,16 +111,15 @@ func (cli *JSONRPCClient) Loan(
func (cli *JSONRPCClient) GetBlockHeadersByHeight(
ctx context.Context,
height uint64,
- end int64,
-) (*BlockHeadersResponse, error) {
- resp := new(BlockHeadersResponse)
- // TODO does this need to be lowercase for the string?
+ endTimeStamp int64,
+) (*types.BlockHeadersResponse, error) {
+ resp := new(types.BlockHeadersResponse)
err := cli.requester.SendRequest(
ctx,
- "getblockheadersbyheight",
- &GetBlockHeadersByHeightArgs{
- Height: height,
- End: end,
+ "getBlockHeadersByHeight",
+ &types.GetBlockHeadersByHeightArgs{
+ Height: height,
+ EndTimeStamp: endTimeStamp,
},
resp,
)
@@ -169,35 +129,33 @@ func (cli *JSONRPCClient) GetBlockHeadersByHeight(
func (cli *JSONRPCClient) GetBlockHeadersID(
ctx context.Context,
id string,
- end int64,
-) (*BlockHeadersResponse, error) {
- resp := new(BlockHeadersResponse)
- // TODO does this need to be lowercase for the string?
+ endTimeStamp int64,
+) (*types.BlockHeadersResponse, error) {
+ resp := new(types.BlockHeadersResponse)
err := cli.requester.SendRequest(
ctx,
- "getblockheadersid",
- &GetBlockHeadersIDArgs{
- ID: id,
- End: end,
+ "getBlockHeadersID",
+ &types.GetBlockHeadersIDArgs{
+ ID: id,
+ EndTimeStamp: endTimeStamp,
},
resp,
)
return resp, err
}
-func (cli *JSONRPCClient) GetBlockHeadersByStart(
+func (cli *JSONRPCClient) GetBlockHeadersByStartTimeStamp(
ctx context.Context,
- start int64,
- end int64,
-) (*BlockHeadersResponse, error) {
- resp := new(BlockHeadersResponse)
- // TODO does this need to be lowercase for the string?
+ startTimeStamp int64,
+ endTimeStamp int64,
+) (*types.BlockHeadersResponse, error) {
+ resp := new(types.BlockHeadersResponse)
err := cli.requester.SendRequest(
ctx,
- "getBlockHeadersByStart",
- &GetBlockHeadersByStartArgs{
- Start: start,
- End: end,
+ "getBlockHeadersByStartTimeStamp",
+ &types.GetBlockHeadersByStartTimeStampArgs{
+ StartTimeStamp: startTimeStamp,
+ EndTimeStamp: endTimeStamp,
},
resp,
)
@@ -207,13 +165,12 @@ func (cli *JSONRPCClient) GetBlockHeadersByStart(
func (cli *JSONRPCClient) GetBlockTransactions(
ctx context.Context,
id string,
-) (*TransactionResponse, error) {
- resp := new(TransactionResponse)
- // TODO does this need to be lowercase for the string?
+) (*types.SEQTransactionResponse, error) {
+ resp := new(types.SEQTransactionResponse)
err := cli.requester.SendRequest(
ctx,
- "getblocktransactions",
- &GetBlockTransactionsArgs{
+ "getBlockTransactions",
+ &types.GetBlockTransactionsArgs{
ID: id,
},
resp,
@@ -225,13 +182,12 @@ func (cli *JSONRPCClient) GetBlockTransactionsByNamespace(
ctx context.Context,
height uint64,
namespace string,
-) (*SEQTransactionResponse, error) {
- resp := new(SEQTransactionResponse)
- // TODO does this need to be lowercase for the string?
+) (*types.SEQTransactionResponse, error) {
+ resp := new(types.SEQTransactionResponse)
err := cli.requester.SendRequest(
ctx,
- "getblocktransactions",
- &GetBlockTransactionsByNamespaceArgs{
+ "getBlockTransactionsByNamespace",
+ &types.GetBlockTransactionsByNamespaceArgs{
Height: height,
Namespace: namespace,
},
@@ -245,12 +201,12 @@ func (cli *JSONRPCClient) GetCommitmentBlocks(
first uint64,
height uint64,
maxBlocks int,
-) (*SequencerWarpBlockResponse, error) {
- resp := new(SequencerWarpBlockResponse)
+) (*types.SequencerWarpBlockResponse, error) {
+ resp := new(types.SequencerWarpBlockResponse)
err := cli.requester.SendRequest(
ctx,
"getCommitmentBlocks",
- &GetBlockCommitmentArgs{
+ &types.GetBlockCommitmentArgs{
First: first,
CurrentHeight: height,
MaxBlocks: maxBlocks,
@@ -271,48 +227,22 @@ func (cli *JSONRPCClient) GetAcceptedBlockWindow(ctx context.Context) (int, erro
return *resp, err
}
-func (cli *JSONRPCClient) SubmitMsgTx(ctx context.Context, chainID string, networkID uint32, secondaryChainID []byte, data []byte) (string, error) {
- resp := new(SubmitMsgTxReply)
- err := cli.requester.SendRequest(
- ctx,
- "submitMsgTx",
- &SubmitMsgTxArgs{
- ChainId: chainID,
- NetworkID: networkID,
- SecondaryChainId: secondaryChainID,
- Data: data,
- },
- resp,
- )
- return resp.TxID, err
-}
-
// TODO add more methods
func (cli *JSONRPCClient) WaitForBalance(
ctx context.Context,
addr string,
- asset ids.ID,
min uint64,
) error {
- exists, symbol, decimals, _, _, _, _, err := cli.Asset(ctx, asset, true)
- if err != nil {
- return err
- }
- if !exists {
- return fmt.Errorf("%s does not exist", asset)
- }
-
return rpc.Wait(ctx, func(ctx context.Context) (bool, error) {
- balance, err := cli.Balance(ctx, addr, asset)
+ balance, err := cli.Balance(ctx, addr)
if err != nil {
return false, err
}
shouldExit := balance >= min
if !shouldExit {
utils.Outf(
- "{{yellow}}waiting for %s %s on %s{{/}}\n",
- utils.FormatBalance(min, decimals),
- symbol,
+ "{{yellow}}waiting for %s balance: %s{{/}}\n",
+ utils.FormatBalance(min, consts.Decimals),
addr,
)
}
@@ -337,6 +267,74 @@ func (cli *JSONRPCClient) WaitForTransaction(ctx context.Context, txID ids.ID) (
return success, fee, nil
}
+func (cli *JSONRPCClient) RollupRegistry(ctx context.Context) ([][]byte, error) {
+ resp := new(types.RegistryReply)
+ err := cli.requester.SendRequest(
+ ctx,
+ "getRollupRegistry",
+ nil,
+ resp,
+ )
+ return resp.Namespaces, err
+}
+
+func (cli *JSONRPCClient) GetRollupInfo(ctx context.Context, namespace []byte) (*hactions.RollupInfo, error) {
+ resp := new(types.GetRollupInfoReply)
+ err := cli.requester.SendRequest(
+ ctx,
+ "getRollupInfo",
+ &types.GetRollupInfoArgs{Namespace: namespace},
+ resp,
+ )
+ return &resp.Info, err
+}
+
+func (cli *JSONRPCClient) GetAllRollupInfo(ctx context.Context) (*types.GetAllRollupInfoReply, error) {
+ resp := new(types.GetAllRollupInfoReply)
+ err := cli.requester.SendRequest(
+ ctx,
+ "getAllRollupInfo",
+ nil,
+ resp,
+ )
+ return resp, err
+}
+
+func (cli *JSONRPCClient) GetValidRollupsAtEpoch(ctx context.Context, epoch uint64) (*types.GetRollupsInfoAtEpochReply, error) {
+ resp := new(types.GetRollupsInfoAtEpochReply)
+ err := cli.requester.SendRequest(
+ ctx,
+ "getValidRollupsAtEpoch",
+ types.GetRollupsInfoAtEpochArgs{Epoch: epoch},
+ resp,
+ )
+ return resp, err
+}
+
+func (cli *JSONRPCClient) GetEpochExits(ctx context.Context, epoch uint64) (*hactions.EpochExitInfo, error) {
+ resp := new(types.EpochExitsReply)
+ args := &types.EpochExitsArgs{Epoch: epoch}
+ err := cli.requester.SendRequest(
+ ctx,
+ "getEpochExits",
+ args,
+ resp,
+ )
+ return resp.Info, err
+}
+
+func (cli *JSONRPCClient) GetBuilder(ctx context.Context, epoch uint64) (*[]byte, error) {
+ resp := new(types.GetBuilderReply)
+ args := &types.GetBuilderArgs{Epoch: epoch}
+ err := cli.requester.SendRequest(
+ ctx,
+ "getBuilder",
+ args,
+ resp,
+ )
+ return &resp.BuilderPubKey, err
+}
+
var _ chain.Parser = (*Parser)(nil)
type Parser struct {
@@ -350,7 +348,7 @@ func (p *Parser) ChainID() ids.ID {
}
func (p *Parser) Rules(t int64) chain.Rules {
- return p.genesis.Rules(t, p.networkID, p.chainID)
+ return p.genesis.Rules(t, p.networkID, p.chainID, []codec.Address{})
}
func (*Parser) Registry() (chain.ActionRegistry, chain.AuthRegistry) {
diff --git a/rpc/jsonrpc_server.go b/rpc/jsonrpc_server.go
index 59f8f64..ae5eb97 100644
--- a/rpc/jsonrpc_server.go
+++ b/rpc/jsonrpc_server.go
@@ -6,55 +6,34 @@ package rpc
import (
"context"
"encoding/hex"
- "errors"
"fmt"
- "math/big"
"net/http"
"time"
"github.com/ava-labs/avalanchego/ids"
+ hactions "github.com/AnomalyFi/hypersdk/actions"
"github.com/AnomalyFi/hypersdk/chain"
- seqconsts "github.com/AnomalyFi/nodekit-seq/consts"
-
"github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/rpc"
+ "github.com/AnomalyFi/hypersdk/fees"
"github.com/AnomalyFi/hypersdk/utils"
- "github.com/AnomalyFi/nodekit-seq/actions"
"github.com/AnomalyFi/nodekit-seq/auth"
- "github.com/AnomalyFi/nodekit-seq/genesis"
- "github.com/AnomalyFi/nodekit-seq/types"
+ seqconsts "github.com/AnomalyFi/nodekit-seq/consts"
- sequtils "github.com/AnomalyFi/nodekit-seq/utils"
+ "github.com/AnomalyFi/hypersdk/codec"
- "github.com/tidwall/btree"
+ "github.com/AnomalyFi/nodekit-seq/actions"
+ "github.com/AnomalyFi/nodekit-seq/genesis"
+ "github.com/AnomalyFi/nodekit-seq/types"
)
type JSONRPCServer struct {
- c Controller
- headers *types.ShardedMap[string, *chain.StatefulBlock]
- // map[ids.ID]*chain.StatefulBlock // Map block ID to block header
-
- blocksWithValidTxs *types.ShardedMap[string, *types.SequencerBlock]
-
- // map[ids.ID]*types.SequencerBlock // Map block ID to block header
-
- idsByHeight btree.Map[uint64, ids.ID] // Map block ID to block height
-
- // tmstp, height
- blocks btree.Map[int64, uint64]
+ c Controller
}
func NewJSONRPCServer(c Controller) *JSONRPCServer {
- headers := types.NewShardedMap[string, *chain.StatefulBlock](10000, 10, types.HashString)
- blocksWithValidTxs := types.NewShardedMap[string, *types.SequencerBlock](10000, 10, types.HashString)
-
return &JSONRPCServer{
- c: c,
- headers: headers,
- blocksWithValidTxs: blocksWithValidTxs,
- idsByHeight: btree.Map[uint64, ids.ID]{},
- blocks: btree.Map[int64, uint64]{},
+ c: c,
}
}
@@ -68,24 +47,27 @@ func (j *JSONRPCServer) Genesis(_ *http.Request, _ *struct{}, reply *GenesisRepl
}
type SubmitMsgTxArgs struct {
- ChainId string `json:"chain_id"`
- NetworkID uint32 `json:"network_id"`
- SecondaryChainId []byte `json:"secondary_chain_id"`
- Data []byte `json:"data"`
+ ChainID string `json:"chain_id"`
+ NetworkID uint32 `json:"network_id"`
+ SecondaryChainID []byte `json:"secondary_chain_id"`
+ Data [][]byte `json:"data"`
}
type SubmitMsgTxReply struct {
TxID string `json:"txId"`
}
+// This method submits SequencerMsg actions to the chain, without any priority fee.
+// Note: This method will be removed in the future, as it is only used for testing.
func (j *JSONRPCServer) SubmitMsgTx(
req *http.Request,
args *SubmitMsgTxArgs,
reply *SubmitMsgTxReply,
) error {
- ctx := context.Background()
+ ctx, span := j.c.Tracer().Start(req.Context(), "Server.SubmitMsgTx")
+ defer span.End()
- chainId, err := ids.FromString(args.ChainId)
+ chainID, err := ids.FromString(args.ChainID)
if err != nil {
return err
}
@@ -95,11 +77,17 @@ func (j *JSONRPCServer) SubmitMsgTx(
return err
}
- parser := j.ServerParser(ctx, args.NetworkID, chainId)
+ parser := j.ServerParser(ctx, args.NetworkID, chainID)
- priv, err := ed25519.HexToKey(
+ privBytes, err := codec.LoadHex(
"323b1d8f4eed5f0da9da93071b034f2dce9d2d22692c172f3cb252a64ddfafd01b057de320297c29ad0c1f589ea216869cf1938d88c9fbd70d6748323dbf2fa7", //nolint:lll
+ ed25519.PrivateKeyLen,
)
+ if err != nil {
+ return err
+ }
+
+ priv := ed25519.PrivateKey(privBytes)
factory := auth.NewED25519Factory(priv)
tpriv, err := ed25519.GeneratePrivateKey()
@@ -107,44 +95,68 @@ func (j *JSONRPCServer) SubmitMsgTx(
return err
}
- trsender := tpriv.PublicKey()
- action := &actions.SequencerMsg{
- FromAddress: trsender,
- Data: args.Data,
- ChainId: args.SecondaryChainId,
+ rsender := auth.NewED25519Address(tpriv.PublicKey())
+
+ acts := make([]chain.Action, 0, len(args.Data))
+ for _, data := range args.Data {
+ act := actions.SequencerMsg{
+ FromAddress: rsender,
+ Data: data,
+ ChainID: args.SecondaryChainID,
+ RelayerID: 0,
+ }
+ acts = append(acts, &act)
}
- // TODO need to define action, authFactory
- maxUnits, err := chain.EstimateMaxUnits(parser.Rules(time.Now().UnixMilli()), action, factory, nil)
+
+ maxUnits, feeMarketUnits, err := chain.EstimateUnits(parser.Rules(time.Now().UnixMilli()), acts, factory)
+ if err != nil {
+ return err
+ }
+ maxFee, err := fees.MulSum(unitPrices, maxUnits)
if err != nil {
return err
}
- maxFee, err := chain.MulSum(unitPrices, maxUnits)
+
+ nss := make([]string, 0)
+ for ns := range feeMarketUnits {
+ nss = append(nss, ns)
+ }
+
+ nsPrices, err := j.c.NameSpacesPrice(ctx, nss)
if err != nil {
return err
}
- // TODO above is generateTransaction below is generateTransactionManual
+ for i, ns := range nss {
+ maxFee += nsPrices[i] * feeMarketUnits[ns]
+ }
+
+ // Add 20% to the max fee
+ maxFee += (maxFee / 5)
now := time.Now().UnixMilli()
rules := parser.Rules(now)
base := &chain.Base{
Timestamp: utils.UnixRMilli(now, rules.GetValidityWindow()),
- ChainID: chainId,
+ ChainID: chainID,
MaxFee: maxFee,
}
// Build transaction
actionRegistry, authRegistry := parser.Registry()
- tx := chain.NewTx(base, nil, action, false)
+ tx := chain.NewTx(base, acts)
tx, err = tx.Sign(factory, actionRegistry, authRegistry)
if err != nil {
return fmt.Errorf("%w: failed to sign transaction", err)
}
- // TODO above is new!
-
- if err := tx.AuthAsyncVerify()(); err != nil {
+ msg, err := tx.Digest()
+ if err != nil {
+ // Should never occur because populated during unmarshal
+ return err
+ }
+ if err := tx.Auth.Verify(ctx, msg); err != nil {
return err
}
txID := tx.ID()
@@ -152,22 +164,15 @@ func (j *JSONRPCServer) SubmitMsgTx(
return j.c.Submit(ctx, false, []*chain.Transaction{tx})[0]
}
-type account struct {
- priv ed25519.PrivateKey
- factory *auth.ED25519Factory
- rsender ed25519.PublicKey
- sender string
-}
-
type TxArgs struct {
TxID ids.ID `json:"txId"`
}
type TxReply struct {
- Timestamp int64 `json:"timestamp"`
- Success bool `json:"success"`
- Units chain.Dimensions `json:"units"`
- Fee uint64 `json:"fee"`
+ Timestamp int64 `json:"timestamp"`
+ Success bool `json:"success"`
+ Units fees.Dimensions `json:"units"`
+ Fee uint64 `json:"fee"`
}
func (j *JSONRPCServer) Tx(req *http.Request, args *TxArgs, reply *TxReply) error {
@@ -188,42 +193,8 @@ func (j *JSONRPCServer) Tx(req *http.Request, args *TxArgs, reply *TxReply) erro
return nil
}
-type AssetArgs struct {
- Asset ids.ID `json:"asset"`
-}
-
-type AssetReply struct {
- Symbol []byte `json:"symbol"`
- Decimals uint8 `json:"decimals"`
- Metadata []byte `json:"metadata"`
- Supply uint64 `json:"supply"`
- Owner string `json:"owner"`
- Warp bool `json:"warp"`
-}
-
-func (j *JSONRPCServer) Asset(req *http.Request, args *AssetArgs, reply *AssetReply) error {
- ctx, span := j.c.Tracer().Start(req.Context(), "Server.Asset")
- defer span.End()
-
- exists, symbol, decimals, metadata, supply, owner, warp, err := j.c.GetAssetFromState(ctx, args.Asset)
- if err != nil {
- return err
- }
- if !exists {
- return ErrAssetNotFound
- }
- reply.Symbol = symbol
- reply.Decimals = decimals
- reply.Metadata = metadata
- reply.Supply = supply
- reply.Owner = sequtils.Address(owner)
- reply.Warp = warp
- return err
-}
-
type BalanceArgs struct {
Address string `json:"address"`
- Asset ids.ID `json:"asset"`
}
type BalanceReply struct {
@@ -234,11 +205,11 @@ func (j *JSONRPCServer) Balance(req *http.Request, args *BalanceArgs, reply *Bal
ctx, span := j.c.Tracer().Start(req.Context(), "Server.Balance")
defer span.End()
- addr, err := sequtils.ParseAddress(args.Address)
+ addr, err := codec.ParseAddressBech32(seqconsts.HRP, args.Address)
if err != nil {
return err
}
- balance, err := j.c.GetBalanceFromState(ctx, addr, args.Asset)
+ balance, err := j.c.GetBalanceFromState(ctx, addr)
if err != nil {
return err
}
@@ -246,528 +217,222 @@ func (j *JSONRPCServer) Balance(req *http.Request, args *BalanceArgs, reply *Bal
return err
}
-type LoanArgs struct {
- Destination ids.ID `json:"destination"`
- Asset ids.ID `json:"asset"`
-}
-
-type LoanReply struct {
- Amount uint64 `json:"amount"`
-}
-
-func (j *JSONRPCServer) Loan(req *http.Request, args *LoanArgs, reply *LoanReply) error {
- ctx, span := j.c.Tracer().Start(req.Context(), "Server.Loan")
+func (j *JSONRPCServer) GetBlockHeadersByHeight(req *http.Request, args *types.GetBlockHeadersByHeightArgs, reply *types.BlockHeadersResponse) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetBlockHeadersByHeight")
defer span.End()
-
- amount, err := j.c.GetLoanFromState(ctx, args.Asset, args.Destination)
+ headers, err := j.c.Archiver().GetBlockHeadersByHeight(args)
if err != nil {
return err
}
- reply.Amount = amount
- return nil
-}
-
-type BlockInfo struct {
- BlockId string `json:"id"`
- Timestamp int64 `json:"timestamp"`
- L1Head uint64 `json:"l1_head"`
- Height uint64 `json:"height"`
-}
-
-type BlockHeadersResponse struct {
- From uint64 `json:"from"`
- Blocks []BlockInfo `json:"blocks"`
- Prev BlockInfo `json:"prev"`
- Next BlockInfo `json:"next"`
-}
-// TODO need to fix this. Tech debt
-type TransactionResponse struct {
- Txs []*chain.Transaction `json:"txs"`
- BlockId string `json:"id"`
-}
-
-type SEQTransactionResponse struct {
- Txs []*types.SEQTransaction `json:"txs"`
- BlockId string `json:"id"`
-}
-
-type SequencerWarpBlockResponse struct {
- Blocks []SequencerWarpBlock `json:"blocks"`
-}
-
-type SequencerWarpBlock struct {
- BlockId string `json:"id"`
- Timestamp int64 `json:"timestamp"`
- L1Head uint64 `json:"l1_head"`
- Height *big.Int `json:"height"`
- BlockRoot *big.Int `json:"root"`
- ParentRoot *big.Int `json:"parent"`
-}
+ reply.From = headers.From
+ reply.Blocks = headers.Blocks
+ reply.Prev = headers.Prev
+ reply.Next = headers.Next
-type GetBlockHeadersByHeightArgs struct {
- Height uint64 `json:"height"`
- End int64 `json:"end"`
-}
-
-type GetBlockHeadersIDArgs struct {
- ID string `json:"id"`
- End int64 `json:"end"`
-}
-
-type GetBlockHeadersByStartArgs struct {
- Start int64 `json:"start"`
- End int64 `json:"end"`
-}
-
-type GetBlockTransactionsArgs struct {
- ID string `json:"block_id"`
-}
-
-type GetBlockCommitmentArgs struct {
- First uint64 `json:"first"`
- CurrentHeight uint64 `json:"current_height"`
- MaxBlocks int `json:"max_blocks"`
-}
-
-type GetBlockTransactionsByNamespaceArgs struct {
- Height uint64 `json:"height"`
- Namespace string `json:"namespace"`
+ return nil
}
-func (j *JSONRPCServer) GetBlockHeadersByHeight(req *http.Request, args *GetBlockHeadersByHeightArgs, reply *BlockHeadersResponse) error {
- Prev := BlockInfo{}
-
- if args.Height > 1 {
- prevBlkId, success := j.idsByHeight.Get(args.Height - 1)
- if success {
- blk, found := j.headers.Get(prevBlkId.String())
- if !found {
- return errors.New("Could not find Block")
- }
-
- // tmp := blk.Tmstmp / 1000
+func (j *JSONRPCServer) GetBlockHeadersID(req *http.Request, args *types.GetBlockHeadersIDArgs, reply *types.BlockHeadersResponse) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetBlockHeadersID")
+ defer span.End()
- Prev = BlockInfo{
- BlockId: prevBlkId.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- }
- }
+ headers, err := j.c.Archiver().GetBlockHeadersByID(args)
+ if err != nil {
+ return err
}
- blocks := make([]BlockInfo, 0)
-
- Next := BlockInfo{}
-
- j.idsByHeight.Ascend(args.Height, func(heightKey uint64, id ids.ID) bool {
- // Does heightKey match the given block's height for the id
- blk, found := j.headers.Get(id.String())
- if !found {
- return false
- }
-
- // tmp := blk.Tmstmp / 1000
- if blk.Tmstmp >= args.End {
- Next = BlockInfo{
- BlockId: id.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- }
- return false
- }
-
- blocks = append(blocks, BlockInfo{
- BlockId: id.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- })
-
- return true
- })
-
- reply.From = args.Height
- reply.Blocks = blocks
- reply.Prev = Prev
- reply.Next = Next
+ reply.From = headers.From
+ reply.Blocks = headers.Blocks
+ reply.Prev = headers.Prev
+ reply.Next = headers.Next
return nil
}
-func (j *JSONRPCServer) GetBlockHeadersID(req *http.Request, args *GetBlockHeadersIDArgs, reply *BlockHeadersResponse) error {
+func (j *JSONRPCServer) GetBlockHeadersByStartTimeStamp(req *http.Request, args *types.GetBlockHeadersByStartTimeStampArgs, reply *types.BlockHeadersResponse) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetBlockHeadersByStartTimeStamp")
+ defer span.End()
// Parse query parameters
-
- var firstBlock uint64
- // var prevBlkId ids.ID
-
- if args.ID != "" {
- id, err := ids.FromString(args.ID)
- if err != nil {
- return err
- }
- // TODO make this into the response
- block, found := j.headers.Get(id.String())
- if !found {
- return errors.New("Could not find Block")
- }
-
- firstBlock = block.Hght
- // Handle hash parameter
- // ...
- } else {
- firstBlock = 1
- // Handle error or default case
- // TODO add error potentially
- // http.Error(writer, "Invalid parameters", http.StatusBadRequest)
- // TODO used to return nil but changed
- // return nil
- }
-
- // prevBlkId, success := j.idsByHeight.Get(firstBlock - 1)
-
- Prev := BlockInfo{}
- if firstBlock > 1 {
- // j.idsByHeight.Descend(firstBlock, func(heightKey uint64, id ids.ID) bool {
-
- // prevBlkId = id
- // return false
- // })
- prevBlkId, success := j.idsByHeight.Get(firstBlock - 1)
-
- if success {
- blk, found := j.headers.Get(prevBlkId.String())
- if !found {
- return errors.New("Could not find Previous Block")
- }
-
- Prev = BlockInfo{
- BlockId: prevBlkId.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- }
- } else {
- return errors.New("Could not find Previous Block")
- }
+ headers, err := j.c.Archiver().GetBlockHeadersAfterTimestamp(args)
+ if err != nil {
+ return err
}
- blocks := make([]BlockInfo, 0)
-
- Next := BlockInfo{}
-
- j.idsByHeight.Ascend(firstBlock, func(heightKey uint64, id ids.ID) bool {
- // Does heightKey match the given block's height for the id
- blk, found := j.headers.Get(id.String())
- if !found {
- return false
- }
-
- if blk.Tmstmp >= args.End {
- // tmp := blk.Tmstmp / 1000
-
- Next = BlockInfo{
- BlockId: id.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- }
- return false
- }
-
- if blk.Hght == heightKey {
- // tmp := blk.Tmstmp / 1000
-
- blocks = append(blocks, BlockInfo{
- BlockId: id.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- })
- }
- return true
- })
-
- // res := BlockHeadersResponse{From: firstBlock, Blocks: blocks, Prev: Prev, Next: Next}
-
- // reply = &res
- reply.From = firstBlock
- reply.Blocks = blocks
- reply.Prev = Prev
- reply.Next = Next
- // TODO add blocks to the list of blocks contained in this time window
- // Marshal res to JSON and send the response
+ reply.From = headers.From
+ reply.Blocks = headers.Blocks
+ reply.Prev = headers.Prev
+ reply.Next = headers.Next
return nil
}
-func (j *JSONRPCServer) GetBlockHeadersByStart(req *http.Request, args *GetBlockHeadersByStartArgs, reply *BlockHeadersResponse) error {
+func (j *JSONRPCServer) GetBlockTransactions(req *http.Request, args *types.GetBlockTransactionsArgs, reply *types.SEQTransactionResponse) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetBlockTransactions")
+ defer span.End()
// Parse query parameters
- var firstBlock uint64
-
- j.blocks.Ascend(args.Start, func(tmstp int64, height uint64) bool {
- firstBlock = height
- return false
- })
+ // TODO either the firstBlock height is equal to height or use the hash to get it or if none of the above work then use the btree to get it
+ if args.ID == "" {
+ return fmt.Errorf("block id not provided")
+ }
- Prev := BlockInfo{}
- if firstBlock > 1 {
- prevBlkId, success := j.idsByHeight.Get(firstBlock - 1)
+ parser := j.ServerParser(req.Context(), j.c.NetworkID(), j.c.ChainID())
- if success {
- blk, found := j.headers.Get(prevBlkId.String())
- if !found {
- return fmt.Errorf("Could not find Previous Block: %d ", firstBlock)
- }
+ blk, err := j.c.Archiver().GetBlockByID(args.ID, parser)
+ if err != nil {
+ return err
+ }
- // tmp := blk.Tmstmp / 1000
- Prev = BlockInfo{
- BlockId: prevBlkId.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
+ // only append sequencer msg actions
+ for _, tx := range blk.Txs {
+ for k, action := range tx.Actions {
+ if action.GetTypeID() == actions.MsgID {
+ ns := hex.EncodeToString(action.NMTNamespace())
+ reply.Txs = append(reply.Txs, &types.SEQTransaction{
+ Namespace: ns,
+ Transaction: action.(*actions.SequencerMsg).Data, // eth format tx binary
+ Index: uint64(k),
+ TxID: tx.ID().String(), // TODO: what should be the TxID for multi action tx?
+ })
}
- } else {
- return fmt.Errorf("Could not find Previous Block: %d, idsByHeight height %d, blocks height %d ", firstBlock, j.idsByHeight.Len(), j.blocks.Len())
}
}
- blocks := make([]BlockInfo, 0)
+ reply.BlockID = args.ID
- Next := BlockInfo{}
+ return nil
+}
- j.idsByHeight.Ascend(firstBlock, func(heightKey uint64, id ids.ID) bool {
- // Does heightKey match the given block's height for the id
- blk, found := j.headers.Get(id.String())
+func (j *JSONRPCServer) GetCommitmentBlocks(req *http.Request, args *types.GetBlockCommitmentArgs, reply *types.SequencerWarpBlockResponse) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetCommitmentBlocks")
+ defer span.End()
+ parser := j.ServerParser(req.Context(), j.c.NetworkID(), j.c.ChainID())
+ warpResp, err := j.c.Archiver().GetCommitmentBlocks(args, parser)
+ if err != nil {
+ return err
+ }
+ reply.Blocks = warpResp.Blocks
- if !found {
- return false
- }
+ return nil
+}
- if blk.Tmstmp >= args.End {
+func (j *JSONRPCServer) GetBlockTransactionsByNamespace(req *http.Request, args *types.GetBlockTransactionsByNamespaceArgs, reply *types.SEQTransactionResponse) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetBlockTransactionsByNamespace")
+ defer span.End()
+ // TODO either the firstBlock height is equal to height or use the hash to get it or if none of the above work then use the btree to get it
+ parser := j.ServerParser(req.Context(), j.c.NetworkID(), j.c.ChainID())
- // tmp := blk.Tmstmp / 1000
+ blk, err := j.c.Archiver().GetBlockByHeight(args.Height, parser)
+ if err != nil {
+ return err
+ }
+ blkID, err := blk.ID()
+ if err != nil {
+ return err
+ }
- Next = BlockInfo{
- BlockId: id.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
+ // only append sequencer msg actions
+ for _, tx := range blk.Txs {
+ for k, action := range tx.Actions {
+ if action.GetTypeID() == actions.MsgID {
+ ns := hex.EncodeToString(action.NMTNamespace())
+ if args.Namespace != ns {
+ continue
+ }
+ reply.Txs = append(reply.Txs, &types.SEQTransaction{
+ Namespace: ns,
+ Transaction: action.(*actions.SequencerMsg).Data, // eth format tx binary
+ Index: uint64(k), // might be duplicate
+ TxID: tx.ID().String(),
+ })
}
- return false
}
+ }
- // tmp := blk.Tmstmp / 1000
-
- blocks = append(blocks, BlockInfo{
- BlockId: id.String(),
- Timestamp: blk.Tmstmp,
- L1Head: uint64(blk.L1Head),
- Height: blk.Hght,
- })
-
- // if blk.Hght == heightKey {
- // tmp := blk.Tmstmp / 1000
-
- // blocks = append(blocks, BlockInfo{
- // BlockId: id.String(),
- // Timestamp: tmp,
- // L1Head: l1Head.Uint64(),
- // Height: blk.Hght,
- // })
- // fmt.Println("Match Found")
- // fmt.Println("Blocks Length After Append:", len(blocks))
-
- // }
-
- return true
- })
-
- // Marshal res to JSON and send the response
-
- reply.From = firstBlock
- reply.Blocks = blocks
- reply.Prev = Prev
- reply.Next = Next
+ reply.BlockID = blkID.String()
return nil
}
-func (j *JSONRPCServer) GetBlockTransactions(req *http.Request, args *GetBlockTransactionsArgs, reply *TransactionResponse) error {
- // Parse query parameters
+func (j *JSONRPCServer) GetEpochExits(req *http.Request, args *types.EpochExitsArgs, reply *types.EpochExitsReply) error {
+ ctx, span := j.c.Tracer().Start(req.Context(), "Server.GetEpochExits")
+ defer span.End()
- // TODO either the firstBlock height is equal to height or use the hash to get it or if none of the above work then use the btree to get it
- if args.ID != "" {
- return nil
+ info, err := j.c.GetEpochExitsFromState(ctx, args.Epoch)
+ if err != nil {
+ return err
}
+ reply.Info = info
+ return err
+}
- // id, err := ids.FromString(args.ID)
- // if err != nil {
- // return err
- // }
-
- block, success := j.headers.Get(args.ID)
+func (j *JSONRPCServer) GetBuilder(req *http.Request, args *types.GetBuilderArgs, reply *types.GetBuilderReply) error {
+ ctx, span := j.c.Tracer().Start(req.Context(), "Server.GetBuilder")
+ defer span.End()
- if !success {
- return errors.New("Txs Not Found")
+ builder, err := j.c.GetBuilderFromState(ctx, args.Epoch)
+ if err != nil {
+ return err
}
-
- reply.Txs = block.Txs
- reply.BlockId = args.ID
-
+ reply.BuilderPubKey = builder
return nil
}
-func (j *JSONRPCServer) GetCommitmentBlocks(req *http.Request, args *GetBlockCommitmentArgs, reply *SequencerWarpBlockResponse) error {
- // Parse query parameters
+func (j *JSONRPCServer) GetRollupRegistry(req *http.Request, _ *struct{}, reply *types.RegistryReply) error {
+ ctx, span := j.c.Tracer().Start(req.Context(), "Server.GetRollupRegistry")
+ defer span.End()
- // TODO either the firstBlock height is equal to height or use the hash to get it or if none of the above work then use the btree to get it
- if args.First < 1 {
- return nil
+ namespaces, err := j.c.GetRollupRegistryFromState(ctx)
+ if err != nil {
+ return err
}
-
- blocks := make([]SequencerWarpBlock, 0)
-
- j.idsByHeight.Ascend(args.First, func(heightKey uint64, id ids.ID) bool {
- // Does heightKey match the given block's height for the id
- if len(blocks) >= args.MaxBlocks {
- return false
- }
-
- blockTemp, success := j.headers.Get(id.String())
- if !success {
- return success
- }
-
- header := &types.Header{
- Height: blockTemp.Hght,
- Timestamp: uint64(blockTemp.Tmstmp),
- L1Head: uint64(blockTemp.L1Head),
- TransactionsRoot: types.NmtRoot{
- Root: id[:],
- },
- }
-
- comm := header.Commit()
-
- // TODO swapped these 2 functions so now it exits earlier. Need to test
- if blockTemp.Hght >= args.CurrentHeight {
- // root := types.NewU256().SetBytes(blockTemp.StateRoot)
- // bigRoot := root.Int
- parentRoot := types.NewU256().SetBytes(blockTemp.Prnt)
- bigParentRoot := parentRoot.Int
-
- blocks = append(blocks, SequencerWarpBlock{
- BlockId: id.String(),
- Timestamp: blockTemp.Tmstmp,
- L1Head: uint64(blockTemp.L1Head),
- Height: big.NewInt(int64(blockTemp.Hght)),
- BlockRoot: &comm.Uint256().Int,
- ParentRoot: &bigParentRoot,
- })
- return false
- }
-
- if blockTemp.Hght == heightKey {
- // root := types.NewU256().SetBytes(blockTemp.StateRoot)
- // bigRoot := root.Int
- parentRoot := types.NewU256().SetBytes(blockTemp.Prnt)
- bigParentRoot := parentRoot.Int
-
- blocks = append(blocks, SequencerWarpBlock{
- BlockId: id.String(),
- Timestamp: blockTemp.Tmstmp,
- L1Head: uint64(blockTemp.L1Head),
- Height: big.NewInt(int64(blockTemp.Hght)),
- BlockRoot: &comm.Uint256().Int,
- ParentRoot: &bigParentRoot,
- })
- }
-
- return true
- })
-
- reply.Blocks = blocks
-
- return nil
+ reply.Namespaces = namespaces
+ return err
}
-func (j *JSONRPCServer) GetBlockTransactionsByNamespace(req *http.Request, args *GetBlockTransactionsByNamespaceArgs, reply *SEQTransactionResponse) error {
- BlkId, success := j.idsByHeight.Get(args.Height)
+func (j *JSONRPCServer) GetRollupInfo(req *http.Request, args *types.GetRollupInfoArgs, reply *types.GetRollupInfoReply) error {
+ ctx, span := j.c.Tracer().Start(req.Context(), "Server.GetRollupInfo")
+ defer span.End()
- if !success {
- return errors.New("Txs Not Found For Namespace")
+ info, err := j.c.GetRollupInfoFromState(ctx, args.Namespace)
+ if err != nil {
+ return err
}
-
- block, found := j.blocksWithValidTxs.Get(BlkId.String())
- if !found {
- return fmt.Errorf("Could not find Block: %s ", BlkId.String())
+ if info == nil {
+ return fmt.Errorf("not such rollup in state")
}
- txs := block.Txs[args.Namespace]
-
- reply.Txs = txs
- reply.BlockId = BlkId.String()
-
+ reply.Info = *info
return nil
}
-func (j *JSONRPCServer) AcceptBlock(blk *chain.StatelessBlock) error {
- ctx := context.Background()
- msg, err := rpc.PackBlockMessage(blk)
+func (j *JSONRPCServer) GetAllRollupInfo(req *http.Request, _ *struct{}, reply *types.GetAllRollupInfoReply) error {
+ ctx, span := j.c.Tracer().Start(req.Context(), "Server.GetAllRollupInfo")
+ defer span.End()
+
+ namespaces, err := j.c.GetRollupRegistryFromState(ctx)
if err != nil {
return err
}
- parser := j.ServerParser(ctx, 1, ids.Empty)
-
- block, results, _, id, err := rpc.UnpackBlockMessage(msg, parser)
-
- // TODO I should experiment with TTL
- j.headers.Put(id.String(), block)
- // j.headers[id.String()] = block
- j.idsByHeight.Set(block.Hght, *id)
- j.blocks.Set(block.Tmstmp, block.Hght)
-
- // TODO I need to call CommitmentManager.AcceptBlock here because otherwise the unpacking will be a pain
- seq_txs := make(map[string][]*types.SEQTransaction)
-
- for i, tx := range blk.Txs {
- result := results[i]
-
- if result.Success {
- switch action := tx.Action.(type) {
- case *actions.SequencerMsg:
- hx := hex.EncodeToString(action.ChainId)
- if seq_txs[hx] == nil {
- seq_txs[hx] = make([]*types.SEQTransaction, 0)
- }
- new_tx := types.SEQTransaction{
- Namespace: hx,
- Tx_id: tx.ID().String(),
- Transaction: action.Data,
- Index: uint64(i),
- }
- seq_txs[hx] = append(seq_txs[hx], &new_tx)
- }
+ reply.Info = make(map[uint64][]hactions.RollupInfo)
+ for _, ns := range namespaces {
+ info, err := j.c.GetRollupInfoFromState(ctx, ns)
+ if err != nil {
+ return err
}
-
- }
-
- sequencerBlock := &types.SequencerBlock{
- StateRoot: blk.StateRoot,
- Prnt: blk.Prnt,
- Tmstmp: blk.Tmstmp,
- Hght: blk.Hght,
- Txs: seq_txs,
+ l := reply.Info[info.StartEpoch]
+ l = append(l, *info)
+ reply.Info[info.StartEpoch] = l
}
- // TODO need to fix this
- j.blocksWithValidTxs.Put(id.String(), sequencerBlock)
+ return nil
+}
+func (j *JSONRPCServer) GetValidRollupsAtEpoch(_ *http.Request, args *types.GetRollupsInfoAtEpochArgs, reply *types.GetRollupsInfoAtEpochReply) error {
+ registry := j.c.RollupRegistry()
+ reply.Rollups = registry.RollupsValidAtEpoch(args.Epoch)
return nil
}
@@ -784,21 +449,23 @@ func (p *ServerParser) ChainID() ids.ID {
}
func (p *ServerParser) Rules(t int64) chain.Rules {
- return p.genesis.Rules(t, p.networkID, p.chainID)
+ return p.genesis.Rules(t, p.networkID, p.chainID, []codec.Address{})
}
func (*ServerParser) Registry() (chain.ActionRegistry, chain.AuthRegistry) {
return seqconsts.ActionRegistry, seqconsts.AuthRegistry
}
-func (j *JSONRPCServer) ServerParser(ctx context.Context, networkId uint32, chainId ids.ID) chain.Parser {
+func (j *JSONRPCServer) ServerParser(_ context.Context, networkID uint32, chainID ids.ID) chain.Parser {
g := j.c.Genesis()
// The only thing this is using is the ActionRegistry and AuthRegistry so this should be fine
- return &Parser{networkId, chainId, g}
+ return &ServerParser{networkID, chainID, g}
}
func (j *JSONRPCServer) GetAcceptedBlockWindow(req *http.Request, _ *struct{}, reply *int) error {
+ _, span := j.c.Tracer().Start(req.Context(), "Server.GetAcceptedBlockWindow")
+ defer span.End()
*reply = j.c.GetAcceptedBlockWindow()
return nil
}
diff --git a/rpc/multi_jsonrpc_client.go b/rpc/multi_jsonrpc_client.go
new file mode 100644
index 0000000..4540747
--- /dev/null
+++ b/rpc/multi_jsonrpc_client.go
@@ -0,0 +1,106 @@
+package rpc
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/crypto/bls"
+ "github.com/AnomalyFi/hypersdk/crypto/ed25519"
+ "github.com/AnomalyFi/hypersdk/fees"
+ hrpc "github.com/AnomalyFi/hypersdk/rpc"
+ "github.com/AnomalyFi/hypersdk/utils"
+ "github.com/AnomalyFi/nodekit-seq/auth"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+// MultiJSONRPCClient holds SEQ and HyperSDK json rpc clients together along with authFactory.
+type MultiJSONRPCClient struct {
+ SeqCli *JSONRPCClient
+ HCli *hrpc.JSONRPCClient
+ AuthFac chain.AuthFactory
+}
+
+// NewMultiJSONRPCClientWithED25519Factory creates a new MultiJsonRPCClient object with ED25519 auth factory.
+func NewMultiJSONRPCClientWithED25519Factory(uri string, networkID uint32, chainID ids.ID, privBytes []byte) *MultiJSONRPCClient {
+ priv := ed25519.PrivateKey(privBytes)
+ factory := auth.NewED25519Factory(priv)
+ return &MultiJSONRPCClient{
+ SeqCli: NewJSONRPCClient(uri, networkID, chainID),
+ HCli: hrpc.NewJSONRPCClient(uri),
+ AuthFac: factory,
+ }
+}
+
+// NewMultiJSONRPCClientWithBLSFactory creates a new MultiJsonRPCClient object with BLS auth factory.
+func NewMultiJSONRPCClientWithBLSFactory(uri string, networkID uint32, chainID ids.ID, privBytes []byte) *MultiJSONRPCClient {
+ priv, _ := bls.PrivateKeyFromBytes(privBytes)
+ factory := auth.NewBLSFactory(priv)
+ return &MultiJSONRPCClient{
+ SeqCli: NewJSONRPCClient(uri, networkID, chainID),
+ HCli: hrpc.NewJSONRPCClient(uri),
+ AuthFac: factory,
+ }
+}
+
+// GenerateAndSubmitTx generates and submits a transaction with the given actions and priority fee.
+func (multi *MultiJSONRPCClient) GenerateAndSubmitTx(ctx context.Context, actions []chain.Action, priorityFee uint64) (ids.ID, error) {
+ parser, err := multi.SeqCli.Parser(ctx)
+ if err != nil {
+ return ids.Empty, err
+ }
+
+ unitPrices, err := multi.HCli.UnitPrices(ctx, true)
+ if err != nil {
+ return ids.Empty, err
+ }
+
+ units, feeMarketUnits, err := chain.EstimateUnits(parser.Rules(time.Now().UnixMilli()), actions, multi.AuthFac)
+ if err != nil {
+ return ids.Empty, err
+ }
+
+ fee, err := fees.MulSum(unitPrices, units)
+ if err != nil {
+ return ids.Empty, err
+ }
+
+ nss := make([]string, 0)
+ for ns := range feeMarketUnits {
+ nss = append(nss, ns)
+ }
+
+ nsPrices, err := multi.HCli.NameSpacesPrice(ctx, nss)
+ if err != nil {
+ return ids.Empty, err
+ }
+
+ for i, ns := range nss {
+ fee += nsPrices[i] * feeMarketUnits[ns]
+ }
+
+ // add priority fee(if any) into the max Fee.
+ fee += priorityFee
+ // set max fee 20% higher than the pessimistic estimation.
+ fee += (fee / 5)
+
+ now := time.Now().UnixMilli()
+ rules := parser.Rules(now)
+
+ base := &chain.Base{
+ Timestamp: utils.UnixRMilli(now, rules.GetValidityWindow()),
+ ChainID: multi.SeqCli.chainID,
+ PriorityFee: priorityFee,
+ MaxFee: fee,
+ }
+
+ // Build transaction
+ actionRegistry, authRegistry := parser.Registry()
+ tx := chain.NewTx(base, actions)
+ tx, err = tx.Sign(multi.AuthFac, actionRegistry, authRegistry)
+ if err != nil {
+ return ids.Empty, fmt.Errorf("%w: failed to sign transaction", err)
+ }
+ return multi.HCli.SubmitTx(ctx, tx.Bytes())
+}
diff --git a/scripts/build.ash_compatible.release.sh b/scripts/build.ash_compatible.release.sh
index 26c7e47..345061b 100755
--- a/scripts/build.ash_compatible.release.sh
+++ b/scripts/build.ash_compatible.release.sh
@@ -13,7 +13,7 @@ set -o pipefail
export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
# Root directory
-TOKENVM_PATH=$(
+SEQVM_PATH=$(
cd "$(dirname "${BASH_SOURCE[0]}")"
cd .. && pwd
)
@@ -26,38 +26,28 @@ if [[ $# -eq 1 ]]; then
BINARY_PATH=$(realpath $1)
elif [[ $# -eq 0 ]]; then
# Set default binary directory location
- name="tokenvm"
- BINARY_PATH=$TOKENVM_PATH/build/$name
+ name="seqvm"
+ BINARY_PATH=$SEQVM_PATH/build/$name
else
- echo "Invalid arguments to build tokenvm. Requires zero (default location) or one argument to specify binary location."
+ echo "Invalid arguments to build seqvm. Requires zero (default location) or one argument to specify binary location."
exit 1
fi
-cd $TOKENVM_PATH
+cd $SEQVM_PATH
-echo "Building tokenvm in $BINARY_PATH"
+echo "Building seqvm in $BINARY_PATH"
mkdir -p $(dirname $BINARY_PATH)
-go build -o $BINARY_PATH ./cmd/tokenvm
+go build -o $BINARY_PATH ./cmd/seqvm
-CLI_PATH=$TOKENVM_PATH/build/token-cli
-echo "Building token-cli in $CLI_PATH"
+CLI_PATH=$SEQVM_PATH/build/seq-cli
+echo "Building seq-cli in $CLI_PATH"
mkdir -p $(dirname $CLI_PATH)
-go build -o $CLI_PATH ./cmd/token-cli
-
-FAUCET_PATH=$TOKENVM_PATH/build/token-faucet
-echo "Building token-faucet in $FAUCET_PATH"
-mkdir -p $(dirname $FAUCET_PATH)
-go build -o $FAUCET_PATH ./cmd/token-faucet
-
-FEED_PATH=$TOKENVM_PATH/build/token-feed
-echo "Building token-feed in $FEED_PATH"
-mkdir -p $(dirname $FEED_PATH)
-go build -o $FEED_PATH ./cmd/token-feed
+go build -o $CLI_PATH ./cmd/seq-cli
# Pack the binaries into a Ash-compatible tarball
AVALANCHEGO_VM_VERSION=${AVALANCHEGO_VM_VERSION:-0.0.999}
-echo "Packing binaries into a Ash-compatible tarball tokenvm_"$AVALANCHEGO_VM_VERSION"_linux_amd64.tar.gz"
-cd "$TOKENVM_PATH/build"
-tar -czf tokenvm_"$AVALANCHEGO_VM_VERSION"_linux_amd64.tar.gz *
-echo "Creating checksums file tokenvm_"$AVALANCHEGO_VM_VERSION"_checksums.txt"
-sha256sum tokenvm_"$AVALANCHEGO_VM_VERSION"_linux_amd64.tar.gz > tokenvm_"$AVALANCHEGO_VM_VERSION"_checksums.txt
+echo "Packing binaries into a Ash-compatible tarball seqvm_"$AVALANCHEGO_VM_VERSION"_linux_amd64.tar.gz"
+cd "$SEQVM_PATH/build"
+tar -czf seqvm_"$AVALANCHEGO_VM_VERSION"_linux_amd64.tar.gz *
+echo "Creating checksums file seqvm_"$AVALANCHEGO_VM_VERSION"_checksums.txt"
+sha256sum seqvm_"$AVALANCHEGO_VM_VERSION"_linux_amd64.tar.gz > seqvm_"$AVALANCHEGO_VM_VERSION"_checksums.txt
diff --git a/scripts/build.sh b/scripts/build.sh
index dba83df..a3a802a 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -13,7 +13,7 @@ set -o pipefail
export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
# Root directory
-TOKENVM_PATH=$(
+SEQVM_PATH=$(
cd "$(dirname "${BASH_SOURCE[0]}")"
cd .. && pwd
)
@@ -26,30 +26,20 @@ if [[ $# -eq 1 ]]; then
BINARY_PATH=$(realpath $1)
elif [[ $# -eq 0 ]]; then
# Set default binary directory location
- name="tHBYNu8ikqo4MWMHehC9iKB9mR5tB3DWzbkYmTfe9buWQ5GZ8"
- BINARY_PATH=$TOKENVM_PATH/build/$name
+ name="speGsUhsx6qC4P2vCCcneVKm57DJNxWgGdGydxAZW53jzaNHj"
+ BINARY_PATH=$SEQVM_PATH/build/$name
else
- echo "Invalid arguments to build tokenvm. Requires zero (default location) or one argument to specify binary location."
+ echo "Invalid arguments to build seqvm. Requires zero (default location) or one argument to specify binary location."
exit 1
fi
-cd $TOKENVM_PATH
+cd $SEQVM_PATH
-echo "Building tokenvm in $BINARY_PATH"
+echo "Building seqvm in $BINARY_PATH"
mkdir -p $(dirname $BINARY_PATH)
-go build -o $BINARY_PATH ./cmd/tokenvm
+go build -o $BINARY_PATH ./cmd/seqvm
-CLI_PATH=$TOKENVM_PATH/build/token-cli
-echo "Building token-cli in $CLI_PATH"
+CLI_PATH=$SEQVM_PATH/build/seq-cli
+echo "Building seq-cli in $CLI_PATH"
mkdir -p $(dirname $CLI_PATH)
-go build -o $CLI_PATH ./cmd/token-cli
-
-FAUCET_PATH=$TOKENVM_PATH/build/token-faucet
-echo "Building token-faucet in $FAUCET_PATH"
-mkdir -p $(dirname $FAUCET_PATH)
-go build -o $FAUCET_PATH ./cmd/token-faucet
-
-FEED_PATH=$TOKENVM_PATH/build/token-feed
-echo "Building token-feed in $FEED_PATH"
-mkdir -p $(dirname $FEED_PATH)
-go build -o $FEED_PATH ./cmd/token-feed
\ No newline at end of file
+go build -o $CLI_PATH ./cmd/seq-cli
diff --git a/scripts/fix.lint.sh b/scripts/fix.lint.sh
index 723b6c0..2b43d79 100755
--- a/scripts/fix.lint.sh
+++ b/scripts/fix.lint.sh
@@ -12,11 +12,11 @@ if ! [[ "$0" =~ scripts/fix.lint.sh ]]; then
exit 255
fi
-echo "adding license header"
-go install -v github.com/palantir/go-license@latest
-files=()
-while IFS= read -r line; do files+=("$line"); done < <(find . -type f -name '*.go' ! -name '*.pb.go' ! -name 'mock_*.go')
-go-license --config=./license.yml "${files[@]}"
+# echo "adding license header"
+# go install -v github.com/palantir/go-license@latest
+# files=()
+# while IFS= read -r line; do files+=("$line"); done < <(find . -type f -name '*.go' ! -name '*.pb.go' ! -name 'mock_*.go')
+# go-license --config=./license.yml "${files[@]}"
echo "gofumpt files"
go install mvdan.cc/gofumpt@latest
diff --git a/scripts/run.sh b/scripts/run.sh
index 8fb4a43..b9b4641 100755
--- a/scripts/run.sh
+++ b/scripts/run.sh
@@ -17,27 +17,41 @@ if ! [[ "$0" =~ scripts/run.sh ]]; then
exit 255
fi
-VERSION=v1.10.10-beta.2
+VERSION=v1.11.10
MAX_UINT64=18446744073709551615
MODE=${MODE:-run}
-LOGLEVEL=${LOGLEVEL:-info}
+LOG_LEVEL=${LOG_LEVEL:-INFO}
+AGO_LOG_LEVEL=${AGO_LOG_LEVEL:-INFO}
+AGO_LOG_DISPLAY_LEVEL=${AGO_LOG_DISPLAY_LEVEL:-INFO}
STATESYNC_DELAY=${STATESYNC_DELAY:-0}
-MIN_BLOCK_GAP=${MIN_BLOCK_GAP:-100}
+MIN_BLOCK_GAP=${MIN_BLOCK_GAP:-2000}
+MIN_EMPTY_BLOCK_GAP=${MIN_EMPTY_BLOCK_GAP:-2000}
+EPOCH_LENGTH=${EPOCH_LENGTH:-6} # 6 SEQ blocks
STORE_TXS=${STORE_TXS:-false}
UNLIMITED_USAGE=${UNLIMITED_USAGE:-false}
STORE_BLOCK_RESULTS_ON_DISK=${STORE_BLOCK_RESULTS_ON_DISK:-true}
ETHL1RPC=${ETHL1RPC:-http://localhost:8545}
ETHL1WS=${ETHL1WS:-ws://localhost:8546}
-if [[ ${MODE} != "run" && ${MODE} != "run-single" ]]; then
- LOGLEVEL=debug
+ARCADIA_URL=${ARCADIA_URL:-http://localhost:12345}
+ADDRESS=${ADDRESS:-seq1qrzvk4zlwj9zsacqgtufx7zvapd3quufqpxk5rsdd4633m4wz2fdjlydh3t}
+if [[ ${MODE} != "run" ]]; then
+ LOG_LEVEL=INFO
+ AGO_LOG_DISPLAY_LEVEL=INFO
STATESYNC_DELAY=100000000 # 100ms
MIN_BLOCK_GAP=250 #ms
+ MIN_EMPTY_BLOCK_GAP=250 #ms
+ EPOCH_LENGTH=48
STORE_TXS=true
UNLIMITED_USAGE=true
fi
+DB_PATH="/tmp/sqlite.NodeID*.db"
+if compgen -G "$DB_PATH" > /dev/null; then
+ rm $DB_PATH
+fi
+
WINDOW_TARGET_UNITS="40000000,450000,450000,450000,450000"
-MAX_BLOCK_UNITS="1800000,15000,15000,2500,15000"
+MAX_BLOCK_UNITS="1800000,15000,15000,10000,15000"
if ${UNLIMITED_USAGE}; then
WINDOW_TARGET_UNITS="${MAX_UINT64},${MAX_UINT64},${MAX_UINT64},${MAX_UINT64},${MAX_UINT64}"
# If we don't limit the block size, AvalancheGo will reject the block.
@@ -45,20 +59,22 @@ if ${UNLIMITED_USAGE}; then
fi
echo "Running with:"
-echo LOGLEVEL: ${LOGLEVEL}
-echo VERSION: ${VERSION}
-echo MODE: ${MODE}
-echo STATESYNC_DELAY \(ns\): ${STATESYNC_DELAY}
-echo MIN_BLOCK_GAP \(ms\): ${MIN_BLOCK_GAP}
-echo STORE_TXS: ${STORE_TXS}
-echo WINDOW_TARGET_UNITS: ${WINDOW_TARGET_UNITS}
-echo MAX_BLOCK_UNITS: ${MAX_BLOCK_UNITS}
+echo LOG_LEVEL: "${LOG_LEVEL}"
+echo AGO_LOG_LEVEL: "${AGO_LOG_LEVEL}"
+echo AGO_LOG_DISPLAY_LEVEL: "${AGO_LOG_DISPLAY_LEVEL}"
+echo VERSION: "${VERSION}"
+echo MODE: "${MODE}"
+echo STATESYNC_DELAY \(ns\): "${STATESYNC_DELAY}"
+echo MIN_BLOCK_GAP \(ms\): "${MIN_BLOCK_GAP}"
+echo EPOCH_LENGTH : "${EPOCH_LENGTH}"
+echo STORE_TXS: "${STORE_TXS}"
+echo WINDOW_TARGET_UNITS: "${WINDOW_TARGET_UNITS}"
+echo MAX_BLOCK_UNITS: "${MAX_BLOCK_UNITS}"
+echo ADDRESS: "${ADDRESS}"
############################
# build avalanchego
# https://github.com/ava-labs/avalanchego/releases
-GOARCH=$(go env GOARCH)
-GOOS=$(go env GOOS)
TMPDIR=/tmp/hypersdk
echo "working directory: $TMPDIR"
@@ -71,22 +87,22 @@ if [ ! -f "$AVALANCHEGO_PATH" ]; then
CWD=$(pwd)
# Clear old folders
- rm -rf ${TMPDIR}/avalanchego-${VERSION}
- mkdir -p ${TMPDIR}/avalanchego-${VERSION}
- rm -rf ${TMPDIR}/avalanchego-src
- mkdir -p ${TMPDIR}/avalanchego-src
+ rm -rf "${TMPDIR}"/avalanchego-"${VERSION}"
+ mkdir -p "${TMPDIR}"/avalanchego-"${VERSION}"
+ rm -rf "${TMPDIR}"/avalanchego-src
+ mkdir -p "${TMPDIR}"/avalanchego-src
# Download src
- cd ${TMPDIR}/avalanchego-src
- git clone https://github.com/AnomalyFi/avalanchego.git
+ cd "${TMPDIR}"/avalanchego-src
+ git clone https://github.com/ava-labs/avalanchego.git
cd avalanchego
- git checkout ${VERSION}
+ git checkout "${VERSION}"
# Build avalanchego
./scripts/build.sh
- mv build/avalanchego ${TMPDIR}/avalanchego-${VERSION}
+ mv build/avalanchego "${TMPDIR}"/avalanchego-"${VERSION}"
- cd ${CWD}
+ cd "${CWD}"
else
echo "using previously built avalanchego"
fi
@@ -94,21 +110,21 @@ fi
############################
############################
-echo "building tokenvm"
+echo "building seqvm"
# delete previous (if exists)
-rm -f ${TMPDIR}/avalanchego-${VERSION}/plugins/tHBYNu8ikqo4MWMHehC9iKB9mR5tB3DWzbkYmTfe9buWQ5GZ8
+rm -f "${TMPDIR}"/avalanchego-"${VERSION}"/plugins/speGsUhsx6qC4P2vCCcneVKm57DJNxWgGdGydxAZW53jzaNHj
# rebuild with latest code
go build \
--o ${TMPDIR}/avalanchego-${VERSION}/plugins/tHBYNu8ikqo4MWMHehC9iKB9mR5tB3DWzbkYmTfe9buWQ5GZ8 \
-./cmd/tokenvm
+-o "${TMPDIR}"/avalanchego-"${VERSION}"/plugins/speGsUhsx6qC4P2vCCcneVKm57DJNxWgGdGydxAZW53jzaNHj \
+./cmd/seqvm
-echo "building token-cli"
-go build -v -o ${TMPDIR}/token-cli ./cmd/token-cli
+echo "building seq-cli"
+go build -v -o "${TMPDIR}"/seq-cli ./cmd/seq-cli
# log everything in the avalanchego directory
-find ${TMPDIR}/avalanchego-${VERSION}
+find "${TMPDIR}"/avalanchego-"${VERSION}"
############################
@@ -119,24 +135,33 @@ find ${TMPDIR}/avalanchego-${VERSION}
# Make sure to replace this address with your own address
# if you are starting your own devnet (otherwise anyone can access
# funds using the included demo.pk)
+# Sum of balances should be less than max uint64.
+# builder address: seq1qxg2p2au72mweweuyu3dx8dhla6gyky630azwsvnc69tvg0m6qx9uqms9wx
+# opnode address: seq1qy94dndd0wzru9gvq3ayw52ngcd2fuhyptt58f4a3eppjzpx573qg9cr7sm
echo "creating allocations file"
-cat < ${TMPDIR}/allocations.json
-[{"address":"token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp", "balance":10000000000000000000}]
+cat < "${TMPDIR}"/allocations.json
+[
+ {"address":"${ADDRESS}", "balance":1000000000000000000},
+ {"address":"seq1qy94dndd0wzru9gvq3ayw52ngcd2fuhyptt58f4a3eppjzpx573qg9cr7sm", "balance":1000000000000000000},
+ {"address":"seq1qxg2p2au72mweweuyu3dx8dhla6gyky630azwsvnc69tvg0m6qx9uqms9wx", "balance":1000000000000000000}
+]
EOF
GENESIS_PATH=$2
if [[ -z "${GENESIS_PATH}" ]]; then
echo "creating VM genesis file with allocations"
- rm -f ${TMPDIR}/tokenvm.genesis
- ${TMPDIR}/token-cli genesis generate ${TMPDIR}/allocations.json \
- --window-target-units ${WINDOW_TARGET_UNITS} \
- --max-block-units ${MAX_BLOCK_UNITS} \
- --min-block-gap ${MIN_BLOCK_GAP} \
- --genesis-file ${TMPDIR}/tokenvm.genesis
+ rm -f "${TMPDIR}"/seqvm.genesis
+ "${TMPDIR}"/seq-cli genesis generate "${TMPDIR}"/allocations.json \
+ --window-target-units "${WINDOW_TARGET_UNITS}" \
+ --max-block-units "${MAX_BLOCK_UNITS}" \
+ --min-block-gap "${MIN_BLOCK_GAP}" \
+ --min-empty-block-gap "${MIN_EMPTY_BLOCK_GAP}" \
+ --epoch-length "${EPOCH_LENGTH}" \
+ --genesis-file "${TMPDIR}"/seqvm.genesis
else
echo "copying custom genesis file"
- rm -f ${TMPDIR}/tokenvm.genesis
- cp ${GENESIS_PATH} ${TMPDIR}/tokenvm.genesis
+ rm -f "${TMPDIR}"/seqvm.genesis
+ cp "${GENESIS_PATH}" "${TMPDIR}"/seqvm.genesis
fi
############################
@@ -147,38 +172,52 @@ fi
# else malicious entities can attempt to stuff memory with dust orders to cause
# an OOM.
echo "creating vm config"
-rm -f ${TMPDIR}/tokenvm.config
-rm -rf ${TMPDIR}/tokenvm-e2e-profiles
-cat < ${TMPDIR}/tokenvm.config
+rm -f "${TMPDIR}"/seqvm.config
+rm -rf "${TMPDIR}"/seqvm-e2e-profiles
+cat < "${TMPDIR}"/seqvm.config
{
"mempoolSize": 10000000,
- "mempoolPayerSize": 10000000,
- "mempoolExemptPayers":["token1rvzhmceq997zntgvravfagsks6w0ryud3rylh4cdvayry0dl97nsjzf3yp"],
- "parallelism": 5,
- "verifySignatures":true,
+ "mempoolSponsorSize": 10000000,
+ "mempoolExemptSponsors":["${ADDRESS}"],
+ "whitelistedAddresses":["${ADDRESS}"],
+ "authVerificationCores": 2,
+ "rootGenerationCores": 2,
+ "transactionExecutionCores": 2,
+ "verifyAuth": true,
"storeTransactions": ${STORE_TXS},
"streamingBacklogSize": 10000000,
- "trackedPairs":["*"],
- "logLevel": "${LOGLEVEL}",
- "continuousProfilerDir":"${TMPDIR}/tokenvm-e2e-profiles/*",
+ "logLevel": "${LOG_LEVEL}",
+ "continuousProfilerDir":"${TMPDIR}/seqvm-e2e-profiles/*",
+ "traceEnabled":false,
+ "traceSampleRate":1,
"stateSyncServerDelay": ${STATESYNC_DELAY},
"storeBlockResultsOnDisk": ${STORE_BLOCK_RESULTS_ON_DISK},
"ethRPCAddr": "${ETHL1RPC}",
- "ethWSAddr": "${ETHL1WS}"
+ "ethWSAddr": "${ETHL1WS}",
+ "arcadiaURL": "${ARCADIA_URL}",
+ "archiverConfig": {
+ "enabled": true,
+ "archiverType": "sqlite",
+ "dsn": "/tmp/default.db"
+ },
+ "valRPCConfig": {
+ "derivePort": true,
+ "port": 0
+ }
}
EOF
-mkdir -p ${TMPDIR}/tokenvm-e2e-profiles
+mkdir -p "${TMPDIR}"/seqvm-e2e-profiles
############################
############################
echo "creating subnet config"
-rm -f ${TMPDIR}/tokenvm.subnet
-cat < ${TMPDIR}/tokenvm.subnet
+rm -f "${TMPDIR}"/seqvm.subnet
+cat < "${TMPDIR}"/seqvm.subnet
{
"proposerMinBlockDelay": 0,
- "proposerNumHistoricalBlocks": 768
+ "proposerNumHistoricalBlocks": 50000
}
EOF
@@ -187,7 +226,7 @@ EOF
############################
echo "building e2e.test"
# to install the ginkgo binary (required for test build and run)
-go install -v github.com/onsi/ginkgo/v2/ginkgo@v2.1.4
+go install -v github.com/onsi/ginkgo/v2/ginkgo@v2.13.1
# alert the user if they do not have $GOPATH properly configured
if ! command -v ginkgo &> /dev/null
@@ -204,9 +243,9 @@ ACK_GINKGO_RC=true ginkgo build ./tests/e2e
# download avalanche-network-runner
# https://github.com/ava-labs/avalanche-network-runner
ANR_REPO_PATH=github.com/ava-labs/avalanche-network-runner
-ANR_VERSION=v1.7.2
+ANR_VERSION=v1.8.1
# version set
-go install -v ${ANR_REPO_PATH}@${ANR_VERSION}
+go install -v "${ANR_REPO_PATH}"@"${ANR_VERSION}"
#################################
# run "avalanche-network-runner" server
@@ -226,7 +265,6 @@ $BIN server \
--log-level verbo \
--port=":12352" \
--grpc-gateway-port=":12353" &
-PID=${!}
############################
# By default, it runs all e2e test cases!
@@ -254,18 +292,20 @@ echo "running e2e tests"
./tests/e2e/e2e.test \
--ginkgo.v \
--network-runner-log-level verbo \
---network-runner-grpc-endpoint="0.0.0.0:12352" \
---network-runner-grpc-gateway-endpoint="0.0.0.0:12353" \
---avalanchego-path=${AVALANCHEGO_PATH} \
---avalanchego-plugin-dir=${AVALANCHEGO_PLUGIN_DIR} \
---vm-genesis-path=${TMPDIR}/tokenvm.genesis \
---vm-config-path=${TMPDIR}/tokenvm.config \
---subnet-config-path=${TMPDIR}/tokenvm.subnet \
---output-path=${TMPDIR}/avalanchego-${VERSION}/output.yaml \
---mode=${MODE}
+--avalanchego-log-level "${AGO_LOG_LEVEL}" \
+--avalanchego-log-display-level "${AGO_LOG_DISPLAY_LEVEL}" \
+--network-runner-grpc-endpoint="127.0.0.1:12352" \
+--network-runner-grpc-gateway-endpoint="127.0.0.1:12353" \
+--avalanchego-path="${AVALANCHEGO_PATH}" \
+--avalanchego-plugin-dir="${AVALANCHEGO_PLUGIN_DIR}" \
+--vm-genesis-path="${TMPDIR}"/seqvm.genesis \
+--vm-config-path="${TMPDIR}"/seqvm.config \
+--subnet-config-path="${TMPDIR}"/seqvm.subnet \
+--output-path="${TMPDIR}"/avalanchego-"${VERSION}"/output.yaml \
+--mode="${MODE}"
############################
-if [[ ${MODE} == "run" || ${MODE} == "run-single" ]]; then
+if [[ ${MODE} == "run" ]]; then
echo "cluster is ready!"
# We made it past initialization and should avoid shutting down the network
KEEPALIVE=true
diff --git a/scripts/tests.integration.sh b/scripts/tests.integration.sh
old mode 100644
new mode 100755
diff --git a/scripts/tests.lint.sh b/scripts/tests.lint.sh
index 0c3c46d..72c8bc5 100755
--- a/scripts/tests.lint.sh
+++ b/scripts/tests.lint.sh
@@ -29,7 +29,7 @@ fi
# by default, "./scripts/lint.sh" runs all lint tests
# to run only "license_header" test
# TESTS='license_header' ./scripts/lint.sh
-TESTS=${TESTS:-"golangci_lint license_header"}
+TESTS=${TESTS:-"golangci_lint"}
# https://github.com/golangci/golangci-lint/releases
function test_golangci_lint {
diff --git a/scripts/tests.load.sh b/scripts/tests.load.sh
old mode 100644
new mode 100755
diff --git a/storage/arcadia.go b/storage/arcadia.go
new file mode 100644
index 0000000..854f5d6
--- /dev/null
+++ b/storage/arcadia.go
@@ -0,0 +1,72 @@
+package storage
+
+import (
+ "context"
+ "encoding/binary"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/ava-labs/avalanchego/database"
+)
+
+func ArcadiaBidKey(epoch uint64) []byte {
+ return hactions.ArcadiaBidKey(epoch)
+}
+
+func StoreArcadiaBidInfo(
+ ctx context.Context,
+ mu state.Mutable,
+ epoch uint64,
+ bidPrice uint64,
+ bidderPublicKey []byte, // 48 bytes
+ bidderSignature []byte, // 96 bytes
+) error {
+ k := ArcadiaBidKey(epoch)
+ v := make([]byte, 8+48+96)
+ binary.BigEndian.PutUint64(v[:8], bidPrice)
+ copy(v[8:], bidderPublicKey)
+ copy(v[8+48:], bidderSignature)
+ return mu.Insert(ctx, k, v)
+}
+
+func GetArcadiaBidValue(
+ ctx context.Context,
+ im state.Immutable,
+ epoch uint64,
+) (uint64, error) {
+ k := ArcadiaBidKey(epoch)
+ v, err := im.GetValue(ctx, k)
+ if err != nil {
+ return 0, err
+ }
+ return binary.BigEndian.Uint64(v[:8]), nil
+}
+
+func GetArcadiaBuilderInfoAndSignature(
+ ctx context.Context,
+ im state.Immutable,
+ epoch uint64,
+) ([]byte, []byte, error) {
+ k := ArcadiaBidKey(epoch)
+ v, err := im.GetValue(ctx, k)
+ if err != nil {
+ return nil, nil, err
+ }
+ return v[8 : 8+48], v[8+48:], nil
+}
+
+func GetArcadiaBuilderFromState(
+ ctx context.Context,
+ f ReadState,
+ epoch uint64,
+) ([]byte, error) {
+ k := ArcadiaBidKey(epoch)
+ values, errs := f(ctx, [][]byte{k})
+ if errs[0] == database.ErrNotFound {
+ return nil, nil
+ }
+ if errs[0] != nil {
+ return nil, errs[0]
+ }
+ return values[0][8 : 8+48], nil
+}
diff --git a/storage/balance.go b/storage/balance.go
new file mode 100644
index 0000000..9140e4f
--- /dev/null
+++ b/storage/balance.go
@@ -0,0 +1,154 @@
+package storage
+
+import (
+ "context"
+ "encoding/binary"
+ "errors"
+ "fmt"
+
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/state"
+ tconsts "github.com/AnomalyFi/nodekit-seq/consts"
+ "github.com/ava-labs/avalanchego/database"
+ smath "github.com/ava-labs/avalanchego/utils/math"
+)
+
+// [accountPrefix] + [address]
+func BalanceKey(pk codec.Address) (k []byte) {
+ k = balanceKeyPool.Get().([]byte)
+ k[0] = balancePrefix
+ copy(k[1:], pk[:])
+ binary.BigEndian.PutUint16(k[1+codec.AddressLen:], BalanceChunks)
+ return
+}
+
+// If locked is 0, then account does not exist
+func GetBalance(
+ ctx context.Context,
+ im state.Immutable,
+ addr codec.Address,
+) (uint64, error) {
+ key, bal, _, err := getBalance(ctx, im, addr)
+ balanceKeyPool.Put(key)
+ return bal, err
+}
+
+func getBalance(
+ ctx context.Context,
+ im state.Immutable,
+ addr codec.Address,
+) ([]byte, uint64, bool, error) {
+ k := BalanceKey(addr)
+ bal, exists, err := innerGetBalance(im.GetValue(ctx, k))
+ return k, bal, exists, err
+}
+
+// Used to serve RPC queries
+func GetBalanceFromState(
+ ctx context.Context,
+ f ReadState,
+ addr codec.Address,
+) (uint64, error) {
+ k := BalanceKey(addr)
+ values, errs := f(ctx, [][]byte{k})
+ bal, _, err := innerGetBalance(values[0], errs[0])
+ balanceKeyPool.Put(k)
+ return bal, err
+}
+
+func innerGetBalance(
+ v []byte,
+ err error,
+) (uint64, bool, error) {
+ if errors.Is(err, database.ErrNotFound) {
+ return 0, false, nil
+ }
+ if err != nil {
+ return 0, false, err
+ }
+ return binary.BigEndian.Uint64(v), true, nil
+}
+
+func SetBalance(
+ ctx context.Context,
+ mu state.Mutable,
+ addr codec.Address,
+ balance uint64,
+) error {
+ k := BalanceKey(addr)
+ return setBalance(ctx, mu, k, balance)
+}
+
+func setBalance(
+ ctx context.Context,
+ mu state.Mutable,
+ key []byte,
+ balance uint64,
+) error {
+ return mu.Insert(ctx, key, binary.BigEndian.AppendUint64(nil, balance))
+}
+
+func DeleteBalance(
+ ctx context.Context,
+ mu state.Mutable,
+ addr codec.Address,
+) error {
+ return mu.Remove(ctx, BalanceKey(addr))
+}
+
+func AddBalance(
+ ctx context.Context,
+ mu state.Mutable,
+ addr codec.Address,
+ amount uint64,
+ create bool,
+) error {
+ key, bal, exists, err := getBalance(ctx, mu, addr)
+ if err != nil {
+ return err
+ }
+ // Don't add balance if account doesn't exist. This
+ // can be useful when processing fee refunds.
+ if !exists && !create {
+ return nil
+ }
+ nbal, err := smath.Add64(bal, amount)
+ if err != nil {
+ return fmt.Errorf(
+ "%w: could not add balance (bal=%d, addr=%v, amount=%d)",
+ ErrInvalidBalance,
+ bal,
+ codec.MustAddressBech32(tconsts.HRP, addr),
+ amount,
+ )
+ }
+ return setBalance(ctx, mu, key, nbal)
+}
+
+func SubBalance(
+ ctx context.Context,
+ mu state.Mutable,
+ addr codec.Address,
+ amount uint64,
+) error {
+ key, bal, _, err := getBalance(ctx, mu, addr)
+ if err != nil {
+ return err
+ }
+ nbal, err := smath.Sub(bal, amount)
+ if err != nil {
+ return fmt.Errorf(
+ "%w: could not subtract balance (bal=%d, addr=%v, amount=%d)",
+ ErrInvalidBalance,
+ bal,
+ codec.MustAddressBech32(tconsts.HRP, addr),
+ amount,
+ )
+ }
+ if nbal == 0 {
+ // If there is no balance left, we should delete the record instead of
+ // setting it to 0.
+ return mu.Remove(ctx, key)
+ }
+ return setBalance(ctx, mu, key, nbal)
+}
diff --git a/storage/epoch_exit.go b/storage/epoch_exit.go
new file mode 100644
index 0000000..7afde73
--- /dev/null
+++ b/storage/epoch_exit.go
@@ -0,0 +1,96 @@
+package storage
+
+import (
+ "context"
+ "errors"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/ava-labs/avalanchego/database"
+)
+
+func EpochExitsKey(epoch uint64) []byte {
+ return hactions.EpochExitsKey(epoch)
+}
+
+// This should get all the exits for 1 epoch
+func GetEpochExits(
+ ctx context.Context,
+ im state.Immutable,
+ epoch uint64,
+) (*hactions.EpochExitInfo, bool, error) {
+ _, ep, exists, err := getEpochExits(ctx, im, epoch)
+ return ep, exists, err
+}
+
+func getEpochExits(
+ ctx context.Context,
+ im state.Immutable,
+ epoch uint64,
+) ([]byte, *hactions.EpochExitInfo, bool, error) {
+ k := EpochExitsKey(epoch)
+ epochExit, exists, err := innerGetEpochExits(im.GetValue(ctx, k))
+ return k, epochExit, exists, err
+}
+
+// Used to serve RPC queries
+func GetEpochExitsFromState(
+ ctx context.Context,
+ f ReadState,
+ epoch uint64,
+) (*hactions.EpochExitInfo, error) {
+ k := EpochExitsKey(epoch)
+ values, errs := f(ctx, [][]byte{k})
+ epochExit, _, err := innerGetEpochExits(values[0], errs[0])
+ return epochExit, err
+}
+
+func innerGetEpochExits(
+ v []byte,
+ err error,
+) (*hactions.EpochExitInfo, bool, error) {
+ if errors.Is(err, database.ErrNotFound) {
+ return nil, false, nil
+ }
+ if err != nil {
+ return nil, false, err
+ }
+ p := codec.NewReader(v, consts.NetworkSizeLimit)
+ info, err := hactions.UnmarshalEpochExitsInfo(p)
+ if err != nil {
+ return nil, false, err
+ }
+ return info, true, nil
+}
+
+func SetEpochExits(
+ ctx context.Context,
+ mu state.Mutable,
+ epoch uint64,
+ info *hactions.EpochExitInfo,
+) error {
+ k := EpochExitsKey(epoch)
+ return setEpochExits(ctx, mu, k, info)
+}
+
+func setEpochExits(
+ ctx context.Context,
+ mu state.Mutable,
+ key []byte,
+ info *hactions.EpochExitInfo,
+) error {
+ var size int
+ for _, e := range info.Exits {
+ size += e.Size()
+ }
+
+ p := codec.NewWriter(size, consts.NetworkSizeLimit)
+ info.Marshal(p)
+ if err := p.Err(); err != nil {
+ return err
+ }
+ infoBytes := p.Bytes()
+ return mu.Insert(ctx, key, infoBytes)
+}
diff --git a/storage/rollup_info.go b/storage/rollup_info.go
new file mode 100644
index 0000000..e849acd
--- /dev/null
+++ b/storage/rollup_info.go
@@ -0,0 +1,83 @@
+package storage
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/ava-labs/avalanchego/database"
+)
+
+func RollupInfoKey(namespace []byte) []byte {
+ return hactions.RollupInfoKey(namespace)
+}
+
+func GetRollupInfo(
+ ctx context.Context,
+ im state.Immutable,
+ namespace []byte,
+) (*hactions.RollupInfo, error) {
+ k := RollupInfoKey(namespace)
+ rollup, _, err := innerGetRollupInfo(im.GetValue(ctx, k))
+ return rollup, err
+}
+
+// Used to serve RPC queries
+func GetRollupInfoFromState(
+ ctx context.Context,
+ f ReadState,
+ namespace []byte,
+) (*hactions.RollupInfo, error) {
+ k := RollupInfoKey(namespace)
+ values, errs := f(ctx, [][]byte{k})
+ rollup, _, err := innerGetRollupInfo(values[0], errs[0])
+ return rollup, err
+}
+
+func innerGetRollupInfo(
+ v []byte,
+ err error,
+) (*hactions.RollupInfo, bool, error) { //nolint:unparam
+ if errors.Is(err, database.ErrNotFound) {
+ return nil, false, nil
+ }
+ if err != nil {
+ return nil, false, err
+ }
+ p := codec.NewReader(v, consts.NetworkSizeLimit)
+ info, err := hactions.UnmarshalRollupInfo(p)
+ if err != nil {
+ return nil, false, err
+ }
+ return info, true, nil
+}
+
+func SetRollupInfo(
+ ctx context.Context,
+ mu state.Mutable,
+ namespace []byte,
+ info *hactions.RollupInfo,
+) error {
+ k := RollupInfoKey(namespace)
+ p := codec.NewWriter(info.Size(), consts.NetworkSizeLimit)
+ info.Marshal(p)
+ if err := p.Err(); err != nil {
+ return err
+ }
+ infoBytes := p.Bytes()
+ fmt.Printf("key: %s, value: %s\n", string(k), string(infoBytes))
+ return mu.Insert(ctx, k, infoBytes)
+}
+
+func DelRollupInfo(
+ ctx context.Context,
+ mu state.Mutable,
+ namespace []byte,
+) error {
+ k := RollupInfoKey(namespace)
+ return mu.Remove(ctx, k)
+}
diff --git a/storage/rollup_registry.go b/storage/rollup_registry.go
new file mode 100644
index 0000000..6d62f59
--- /dev/null
+++ b/storage/rollup_registry.go
@@ -0,0 +1,68 @@
+package storage
+
+import (
+ "context"
+ "errors"
+
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/state"
+ "github.com/ava-labs/avalanchego/database"
+)
+
+func RollupRegistryKey() []byte {
+ return hactions.RollupRegistryKey()
+}
+
+func GetRollupRegistry(
+ ctx context.Context,
+ im state.Immutable,
+) ([][]byte, error) {
+ k := RollupRegistryKey()
+ namespaces, _, err := innerGetRegistry(im.GetValue(ctx, k))
+ return namespaces, err
+}
+
+// Used to serve RPC queries
+func GetRollupRegistryFromState(
+ ctx context.Context,
+ f ReadState,
+) ([][]byte, error) {
+ k := RollupRegistryKey()
+ values, errs := f(ctx, [][]byte{k})
+ namespaces, _, err := innerGetRegistry(values[0], errs[0])
+ if err != nil {
+ return nil, err
+ }
+ return namespaces, nil
+}
+
+func innerGetRegistry(
+ v []byte,
+ err error,
+) ([][]byte, bool, error) { //nolint:unparam
+ if errors.Is(err, database.ErrNotFound) {
+ return nil, false, nil
+ }
+ if err != nil {
+ return nil, false, err
+ }
+ namespaces, err := UnpackNamespaces(v)
+ if err != nil {
+ return nil, false, err
+ }
+
+ return namespaces, true, nil
+}
+
+func SetRollupRegistry(
+ ctx context.Context,
+ mu state.Mutable,
+ namespaces [][]byte,
+) error {
+ k := RollupRegistryKey()
+ packed, err := PackNamespaces(namespaces)
+ if err != nil {
+ return err
+ }
+ return mu.Insert(ctx, k, packed)
+}
diff --git a/storage/storage.go b/storage/storage.go
index 8fd36c6..4e75634 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -6,64 +6,31 @@ package storage
import (
"context"
"encoding/binary"
- "errors"
- "fmt"
"sync"
- "github.com/AnomalyFi/hypersdk/chain"
+ "github.com/AnomalyFi/hypersdk/codec"
+
"github.com/AnomalyFi/hypersdk/consts"
- "github.com/AnomalyFi/hypersdk/crypto/ed25519"
- "github.com/AnomalyFi/hypersdk/state"
- "github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/ids"
- smath "github.com/ava-labs/avalanchego/utils/math"
-
- "github.com/AnomalyFi/nodekit-seq/utils"
)
type ReadState func(context.Context, [][]byte) ([][]byte, []error)
-// Metadata
-// 0x0/ (tx)
-// -> [txID] => timestamp
-//
-// State
-// 0x0/ (balance)
-// -> [owner|asset] => balance
-// 0x1/ (assets)
-// -> [asset] => metadataLen|metadata|supply|owner|warp
-// 0x2/ (orders)
-// -> [txID] => in|out|rate|remaining|owner
-// 0x3/ (loans)
-// -> [assetID|destination] => amount
-// 0x4/ (hypersdk-height)
-// 0x5/ (hypersdk-timestamp)
-// 0x6/ (hypersdk-fee)
-// 0x7/ (hypersdk-incoming warp)
-// 0x8/ (hypersdk-outgoing warp)
-
const (
// metaDB
txPrefix = 0x0
// stateDB
- balancePrefix = 0x0
- assetPrefix = 0x1
- orderPrefix = 0x2
- loanPrefix = 0x3
- heightPrefix = 0x4
- timestampPrefix = 0x5
- feePrefix = 0x6
- incomingWarpPrefix = 0x7
- outgoingWarpPrefix = 0x8
- blockPrefix = 0x9
+ balancePrefix = 0x0
+ heightPrefix = 0x4
+ timestampPrefix = 0x5
+ feePrefix = 0x6
+ blockPrefix = 0x9
+ feeMarketPrefix = 0xa
)
const (
BalanceChunks uint16 = 1
- AssetChunks uint16 = 5
- OrderChunks uint16 = 2
- LoanChunks uint16 = 1
)
var (
@@ -72,522 +39,24 @@ var (
heightKey = []byte{heightPrefix}
timestampKey = []byte{timestampPrefix}
feeKey = []byte{feePrefix}
+ feeMarketKey = []byte{feeMarketPrefix}
balanceKeyPool = sync.Pool{
New: func() any {
- return make([]byte, 1+ed25519.PublicKeyLen+consts.IDLen+consts.Uint16Len)
+ return make([]byte, 1+codec.AddressLen+consts.Uint16Len)
},
}
)
-// [txPrefix] + [txID]
-func TxKey(id ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen)
- k[0] = txPrefix
- copy(k[1:], id[:])
- return
-}
-
-func StoreTransaction(
- _ context.Context,
- db database.KeyValueWriter,
- id ids.ID,
- t int64,
- success bool,
- units chain.Dimensions,
- fee uint64,
-) error {
- k := TxKey(id)
- v := make([]byte, consts.Uint64Len+1+chain.DimensionsLen+consts.Uint64Len)
- binary.BigEndian.PutUint64(v, uint64(t))
- if success {
- v[consts.Uint64Len] = successByte
- } else {
- v[consts.Uint64Len] = failureByte
- }
- copy(v[consts.Uint64Len+1:], units.Bytes())
- binary.BigEndian.PutUint64(v[consts.Uint64Len+1+chain.DimensionsLen:], fee)
- return db.Put(k, v)
-}
-
-func GetTransaction(
- _ context.Context,
- db database.KeyValueReader,
- id ids.ID,
-) (bool, int64, bool, chain.Dimensions, uint64, error) {
- k := TxKey(id)
- v, err := db.Get(k)
- if errors.Is(err, database.ErrNotFound) {
- return false, 0, false, chain.Dimensions{}, 0, nil
- }
- if err != nil {
- return false, 0, false, chain.Dimensions{}, 0, err
- }
- t := int64(binary.BigEndian.Uint64(v))
- success := true
- if v[consts.Uint64Len] == failureByte {
- success = false
- }
- d, err := chain.UnpackDimensions(v[consts.Uint64Len+1 : consts.Uint64Len+1+chain.DimensionsLen])
- if err != nil {
- return false, 0, false, chain.Dimensions{}, 0, err
- }
- fee := binary.BigEndian.Uint64(v[consts.Uint64Len+1+chain.DimensionsLen:])
- return true, t, success, d, fee, nil
-}
-
-// [accountPrefix] + [address] + [asset]
-func BalanceKey(pk ed25519.PublicKey, asset ids.ID) (k []byte) {
- k = balanceKeyPool.Get().([]byte)
- k[0] = balancePrefix
- copy(k[1:], pk[:])
- copy(k[1+ed25519.PublicKeyLen:], asset[:])
- binary.BigEndian.PutUint16(k[1+ed25519.PublicKeyLen+consts.IDLen:], BalanceChunks)
- return
-}
-
-// If locked is 0, then account does not exist
-func GetBalance(
- ctx context.Context,
- im state.Immutable,
- pk ed25519.PublicKey,
- asset ids.ID,
-) (uint64, error) {
- key, bal, _, err := getBalance(ctx, im, pk, asset)
- balanceKeyPool.Put(key)
- return bal, err
-}
-
-func getBalance(
- ctx context.Context,
- im state.Immutable,
- pk ed25519.PublicKey,
- asset ids.ID,
-) ([]byte, uint64, bool, error) {
- k := BalanceKey(pk, asset)
- bal, exists, err := innerGetBalance(im.GetValue(ctx, k))
- return k, bal, exists, err
-}
-
-// Used to serve RPC queries
-func GetBalanceFromState(
- ctx context.Context,
- f ReadState,
- pk ed25519.PublicKey,
- asset ids.ID,
-) (uint64, error) {
- k := BalanceKey(pk, asset)
- values, errs := f(ctx, [][]byte{k})
- bal, _, err := innerGetBalance(values[0], errs[0])
- balanceKeyPool.Put(k)
- return bal, err
-}
-
-func innerGetBalance(
- v []byte,
- err error,
-) (uint64, bool, error) {
- if errors.Is(err, database.ErrNotFound) {
- return 0, false, nil
- }
- if err != nil {
- return 0, false, err
- }
- return binary.BigEndian.Uint64(v), true, nil
-}
-
-func SetBalance(
- ctx context.Context,
- mu state.Mutable,
- pk ed25519.PublicKey,
- asset ids.ID,
- balance uint64,
-) error {
- k := BalanceKey(pk, asset)
- return setBalance(ctx, mu, k, balance)
-}
-
-func setBalance(
- ctx context.Context,
- mu state.Mutable,
- key []byte,
- balance uint64,
-) error {
- return mu.Insert(ctx, key, binary.BigEndian.AppendUint64(nil, balance))
-}
-
-func DeleteBalance(
- ctx context.Context,
- mu state.Mutable,
- pk ed25519.PublicKey,
- asset ids.ID,
-) error {
- return mu.Remove(ctx, BalanceKey(pk, asset))
-}
-
-func AddBalance(
- ctx context.Context,
- mu state.Mutable,
- pk ed25519.PublicKey,
- asset ids.ID,
- amount uint64,
- create bool,
-) error {
- key, bal, exists, err := getBalance(ctx, mu, pk, asset)
- if err != nil {
- return err
- }
- // Don't add balance if account doesn't exist. This
- // can be useful when processing fee refunds.
- if !exists && !create {
- return nil
- }
- nbal, err := smath.Add64(bal, amount)
- if err != nil {
- return fmt.Errorf(
- "%w: could not add balance (asset=%s, bal=%d, addr=%v, amount=%d)",
- ErrInvalidBalance,
- asset,
- bal,
- utils.Address(pk),
- amount,
- )
- }
- return setBalance(ctx, mu, key, nbal)
-}
-
-func SubBalance(
- ctx context.Context,
- mu state.Mutable,
- pk ed25519.PublicKey,
- asset ids.ID,
- amount uint64,
-) error {
- key, bal, _, err := getBalance(ctx, mu, pk, asset)
- if err != nil {
- return err
- }
- nbal, err := smath.Sub(bal, amount)
- if err != nil {
- return fmt.Errorf(
- "%w: could not subtract balance (asset=%s, bal=%d, addr=%v, amount=%d)",
- ErrInvalidBalance,
- asset,
- bal,
- utils.Address(pk),
- amount,
- )
- }
- if nbal == 0 {
- // If there is no balance left, we should delete the record instead of
- // setting it to 0.
- return mu.Remove(ctx, key)
- }
- return setBalance(ctx, mu, key, nbal)
-}
-
-// [assetPrefix] + [address]
-func AssetKey(asset ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen+consts.Uint16Len)
- k[0] = assetPrefix
- copy(k[1:], asset[:])
- binary.BigEndian.PutUint16(k[1+consts.IDLen:], AssetChunks)
- return
-}
-
-// Used to serve RPC queries
-func GetAssetFromState(
- ctx context.Context,
- f ReadState,
- asset ids.ID,
-) (bool, []byte, uint8, []byte, uint64, ed25519.PublicKey, bool, error) {
- values, errs := f(ctx, [][]byte{AssetKey(asset)})
- return innerGetAsset(values[0], errs[0])
-}
-
-func GetAsset(
- ctx context.Context,
- im state.Immutable,
- asset ids.ID,
-) (bool, []byte, uint8, []byte, uint64, ed25519.PublicKey, bool, error) {
- k := AssetKey(asset)
- return innerGetAsset(im.GetValue(ctx, k))
-}
-
-func innerGetAsset(
- v []byte,
- err error,
-) (bool, []byte, uint8, []byte, uint64, ed25519.PublicKey, bool, error) {
- if errors.Is(err, database.ErrNotFound) {
- return false, nil, 0, nil, 0, ed25519.EmptyPublicKey, false, nil
- }
- if err != nil {
- return false, nil, 0, nil, 0, ed25519.EmptyPublicKey, false, err
- }
- symbolLen := binary.BigEndian.Uint16(v)
- symbol := v[consts.Uint16Len : consts.Uint16Len+symbolLen]
- decimals := v[consts.Uint16Len+symbolLen]
- metadataLen := binary.BigEndian.Uint16(v[consts.Uint16Len+symbolLen+consts.Uint8Len:])
- metadata := v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len : consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen]
- supply := binary.BigEndian.Uint64(v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen:])
- var pk ed25519.PublicKey
- copy(pk[:], v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen+consts.Uint64Len:])
- warp := v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen+consts.Uint64Len+ed25519.PublicKeyLen] == 0x1
- return true, symbol, decimals, metadata, supply, pk, warp, nil
-}
-
-func SetAsset(
- ctx context.Context,
- mu state.Mutable,
- asset ids.ID,
- symbol []byte,
- decimals uint8,
- metadata []byte,
- supply uint64,
- owner ed25519.PublicKey,
- warp bool,
-) error {
- k := AssetKey(asset)
- symbolLen := len(symbol)
- metadataLen := len(metadata)
- v := make([]byte, consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen+consts.Uint64Len+ed25519.PublicKeyLen+1)
- binary.BigEndian.PutUint16(v, uint16(symbolLen))
- copy(v[consts.Uint16Len:], symbol)
- v[consts.Uint16Len+symbolLen] = decimals
- binary.BigEndian.PutUint16(v[consts.Uint16Len+symbolLen+consts.Uint8Len:], uint16(metadataLen))
- copy(v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len:], metadata)
- binary.BigEndian.PutUint64(v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen:], supply)
- copy(v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen+consts.Uint64Len:], owner[:])
- b := byte(0x0)
- if warp {
- b = 0x1
- }
- v[consts.Uint16Len+symbolLen+consts.Uint8Len+consts.Uint16Len+metadataLen+consts.Uint64Len+ed25519.PublicKeyLen] = b
- return mu.Insert(ctx, k, v)
-}
-
-func DeleteAsset(ctx context.Context, mu state.Mutable, asset ids.ID) error {
- k := AssetKey(asset)
- return mu.Remove(ctx, k)
-}
-
-// [orderPrefix] + [txID]
-func OrderKey(txID ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen+consts.Uint16Len)
- k[0] = orderPrefix
- copy(k[1:], txID[:])
- binary.BigEndian.PutUint16(k[1+consts.IDLen:], OrderChunks)
- return
-}
-
-func SetOrder(
- ctx context.Context,
- mu state.Mutable,
- txID ids.ID,
- in ids.ID,
- inTick uint64,
- out ids.ID,
- outTick uint64,
- supply uint64,
- owner ed25519.PublicKey,
-) error {
- k := OrderKey(txID)
- v := make([]byte, consts.IDLen*2+consts.Uint64Len*3+ed25519.PublicKeyLen)
- copy(v, in[:])
- binary.BigEndian.PutUint64(v[consts.IDLen:], inTick)
- copy(v[consts.IDLen+consts.Uint64Len:], out[:])
- binary.BigEndian.PutUint64(v[consts.IDLen*2+consts.Uint64Len:], outTick)
- binary.BigEndian.PutUint64(v[consts.IDLen*2+consts.Uint64Len*2:], supply)
- copy(v[consts.IDLen*2+consts.Uint64Len*3:], owner[:])
- return mu.Insert(ctx, k, v)
-}
-
-func GetOrder(
- ctx context.Context,
- im state.Immutable,
- order ids.ID,
-) (
- bool, // exists
- ids.ID, // in
- uint64, // inTick
- ids.ID, // out
- uint64, // outTick
- uint64, // remaining
- ed25519.PublicKey, // owner
- error,
-) {
- k := OrderKey(order)
- v, err := im.GetValue(ctx, k)
- return innerGetOrder(v, err)
-}
-
-// Used to serve RPC queries
-func GetOrderFromState(
- ctx context.Context,
- f ReadState,
- order ids.ID,
-) (
- bool, // exists
- ids.ID, // in
- uint64, // inTick
- ids.ID, // out
- uint64, // outTick
- uint64, // remaining
- ed25519.PublicKey, // owner
- error,
-) {
- values, errs := f(ctx, [][]byte{OrderKey(order)})
- return innerGetOrder(values[0], errs[0])
-}
-
-func innerGetOrder(v []byte, err error) (
- bool, // exists
- ids.ID, // in
- uint64, // inTick
- ids.ID, // out
- uint64, // outTick
- uint64, // remaining
- ed25519.PublicKey, // owner
- error,
-) {
- if errors.Is(err, database.ErrNotFound) {
- return false, ids.Empty, 0, ids.Empty, 0, 0, ed25519.EmptyPublicKey, nil
- }
- if err != nil {
- return false, ids.Empty, 0, ids.Empty, 0, 0, ed25519.EmptyPublicKey, err
- }
- var in ids.ID
- copy(in[:], v[:consts.IDLen])
- inTick := binary.BigEndian.Uint64(v[consts.IDLen:])
- var out ids.ID
- copy(out[:], v[consts.IDLen+consts.Uint64Len:consts.IDLen*2+consts.Uint64Len])
- outTick := binary.BigEndian.Uint64(v[consts.IDLen*2+consts.Uint64Len:])
- supply := binary.BigEndian.Uint64(v[consts.IDLen*2+consts.Uint64Len*2:])
- var owner ed25519.PublicKey
- copy(owner[:], v[consts.IDLen*2+consts.Uint64Len*3:])
- return true, in, inTick, out, outTick, supply, owner, nil
-}
-
-func DeleteOrder(ctx context.Context, mu state.Mutable, order ids.ID) error {
- k := OrderKey(order)
- return mu.Remove(ctx, k)
-}
-
-// [loanPrefix] + [asset] + [destination]
-func LoanKey(asset ids.ID, destination ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen*2+consts.Uint16Len)
- k[0] = loanPrefix
- copy(k[1:], asset[:])
- copy(k[1+consts.IDLen:], destination[:])
- binary.BigEndian.PutUint16(k[1+consts.IDLen*2:], LoanChunks)
- return
-}
-
func PrefixBlockKey(block ids.ID, parent ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen*2)
+ k = make([]byte, 1+ids.IDLen*2)
k[0] = blockPrefix
copy(k[1:], block[:])
- binary.BigEndian.PutUint16(k[1+consts.IDLen*2:], LoanChunks)
- copy(k[1+consts.IDLen:], parent[:])
+ binary.BigEndian.PutUint16(k[1+ids.IDLen*2:], BalanceChunks)
+ copy(k[1+ids.IDLen:], parent[:])
return
}
-// Used to serve RPC queries
-func GetLoanFromState(
- ctx context.Context,
- f ReadState,
- asset ids.ID,
- destination ids.ID,
-) (uint64, error) {
- values, errs := f(ctx, [][]byte{LoanKey(asset, destination)})
- return innerGetLoan(values[0], errs[0])
-}
-
-func innerGetLoan(v []byte, err error) (uint64, error) {
- if errors.Is(err, database.ErrNotFound) {
- return 0, nil
- }
- if err != nil {
- return 0, err
- }
- return binary.BigEndian.Uint64(v), nil
-}
-
-func GetLoan(
- ctx context.Context,
- im state.Immutable,
- asset ids.ID,
- destination ids.ID,
-) (uint64, error) {
- k := LoanKey(asset, destination)
- v, err := im.GetValue(ctx, k)
- return innerGetLoan(v, err)
-}
-
-func SetLoan(
- ctx context.Context,
- mu state.Mutable,
- asset ids.ID,
- destination ids.ID,
- amount uint64,
-) error {
- k := LoanKey(asset, destination)
- return mu.Insert(ctx, k, binary.BigEndian.AppendUint64(nil, amount))
-}
-
-func AddLoan(
- ctx context.Context,
- mu state.Mutable,
- asset ids.ID,
- destination ids.ID,
- amount uint64,
-) error {
- loan, err := GetLoan(ctx, mu, asset, destination)
- if err != nil {
- return err
- }
- nloan, err := smath.Add64(loan, amount)
- if err != nil {
- return fmt.Errorf(
- "%w: could not add loan (asset=%s, destination=%s, amount=%d)",
- ErrInvalidBalance,
- asset,
- destination,
- amount,
- )
- }
- return SetLoan(ctx, mu, asset, destination, nloan)
-}
-
-func SubLoan(
- ctx context.Context,
- mu state.Mutable,
- asset ids.ID,
- destination ids.ID,
- amount uint64,
-) error {
- loan, err := GetLoan(ctx, mu, asset, destination)
- if err != nil {
- return err
- }
- nloan, err := smath.Sub(loan, amount)
- if err != nil {
- return fmt.Errorf(
- "%w: could not subtract loan (asset=%s, destination=%s, amount=%d)",
- ErrInvalidBalance,
- asset,
- destination,
- amount,
- )
- }
- if nloan == 0 {
- // If there is no balance left, we should delete the record instead of
- // setting it to 0.
- return mu.Remove(ctx, LoanKey(asset, destination))
- }
- return SetLoan(ctx, mu, asset, destination, nloan)
-}
-
func HeightKey() (k []byte) {
return heightKey
}
@@ -600,17 +69,6 @@ func FeeKey() (k []byte) {
return feeKey
}
-func IncomingWarpKeyPrefix(sourceChainID ids.ID, msgID ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen*2)
- k[0] = incomingWarpPrefix
- copy(k[1:], sourceChainID[:])
- copy(k[1+consts.IDLen:], msgID[:])
- return k
-}
-
-func OutgoingWarpKeyPrefix(txID ids.ID) (k []byte) {
- k = make([]byte, 1+consts.IDLen)
- k[0] = outgoingWarpPrefix
- copy(k[1:], txID[:])
- return k
+func FeeMarketKey() (k []byte) {
+ return feeMarketKey
}
diff --git a/storage/transaction.go b/storage/transaction.go
new file mode 100644
index 0000000..3df7713
--- /dev/null
+++ b/storage/transaction.go
@@ -0,0 +1,68 @@
+package storage
+
+import (
+ "context"
+ "encoding/binary"
+ "errors"
+
+ "github.com/AnomalyFi/hypersdk/consts"
+ "github.com/AnomalyFi/hypersdk/fees"
+ "github.com/ava-labs/avalanchego/database"
+ "github.com/ava-labs/avalanchego/ids"
+)
+
+// [txPrefix] + [txID]
+func TxKey(id ids.ID) (k []byte) {
+ k = make([]byte, 1+ids.IDLen)
+ k[0] = txPrefix
+ copy(k[1:], id[:])
+ return
+}
+
+func StoreTransaction(
+ _ context.Context,
+ db database.KeyValueWriter,
+ id ids.ID,
+ t int64,
+ success bool,
+ units fees.Dimensions,
+ fee uint64,
+) error {
+ k := TxKey(id)
+ v := make([]byte, consts.Uint64Len+1+fees.DimensionsLen+consts.Uint64Len)
+ binary.BigEndian.PutUint64(v, uint64(t))
+ if success {
+ v[consts.Uint64Len] = successByte
+ } else {
+ v[consts.Uint64Len] = failureByte
+ }
+ copy(v[consts.Uint64Len+1:], units.Bytes())
+ binary.BigEndian.PutUint64(v[consts.Uint64Len+1+fees.DimensionsLen:], fee)
+ return db.Put(k, v)
+}
+
+func GetTransaction(
+ _ context.Context,
+ db database.KeyValueReader,
+ id ids.ID,
+) (bool, int64, bool, fees.Dimensions, uint64, error) {
+ k := TxKey(id)
+ v, err := db.Get(k)
+ if errors.Is(err, database.ErrNotFound) {
+ return false, 0, false, fees.Dimensions{}, 0, nil
+ }
+ if err != nil {
+ return false, 0, false, fees.Dimensions{}, 0, err
+ }
+ t := int64(binary.BigEndian.Uint64(v))
+ success := true
+ if v[consts.Uint64Len] == failureByte {
+ success = false
+ }
+ d, err := fees.UnpackDimensions(v[consts.Uint64Len+1 : consts.Uint64Len+1+fees.DimensionsLen])
+ if err != nil {
+ return false, 0, false, fees.Dimensions{}, 0, err
+ }
+ fee := binary.BigEndian.Uint64(v[consts.Uint64Len+1+fees.DimensionsLen:])
+ return true, t, success, d, fee, nil
+}
diff --git a/storage/utils.go b/storage/utils.go
new file mode 100644
index 0000000..714b330
--- /dev/null
+++ b/storage/utils.go
@@ -0,0 +1,36 @@
+package storage
+
+import (
+ hactions "github.com/AnomalyFi/hypersdk/actions"
+ "github.com/AnomalyFi/hypersdk/codec"
+ "github.com/AnomalyFi/hypersdk/consts"
+)
+
+func PackNamespaces(namespaces [][]byte) ([]byte, error) {
+ return hactions.PackNamespaces(namespaces)
+}
+
+func UnpackNamespaces(raw []byte) ([][]byte, error) {
+ return hactions.UnpackNamespaces(raw)
+}
+
+func PackEpochs(epochs []uint64) ([]byte, error) {
+ p := codec.NewWriter(len(epochs)*8, consts.NetworkSizeLimit)
+ p.PackInt(len(epochs))
+ for _, e := range epochs {
+ p.PackUint64(e)
+ }
+ return p.Bytes(), p.Err()
+}
+
+func UnpackEpochs(raw []byte) ([]uint64, error) {
+ p := codec.NewReader(raw, consts.NetworkSizeLimit)
+ eLen := p.UnpackInt(false)
+ epochs := make([]uint64, 0, eLen)
+ for i := 0; i < eLen; i++ {
+ e := p.UnpackUint64(true)
+ epochs = append(epochs, e)
+ }
+
+ return epochs, p.Err()
+}
diff --git a/test.log b/test.log
deleted file mode 100644
index 6af38e7..0000000
--- a/test.log
+++ /dev/null
@@ -1,1867 +0,0 @@
-Running with:
-VERSION: 1.10.1
-MODE: run-single
-STATESYNC_DELAY: 0
-PROPOSER_MIN_BLOCK_DELAY: 0
-using previously built avalanchego
-building tokenvm
-building token-cli
-/tmp/avalanchego-v1.10.1
-/tmp/avalanchego-v1.10.1/avalanchego
-/tmp/avalanchego-v1.10.1/plugins
-/tmp/avalanchego-v1.10.1/plugins/tHBYNu8ikqo4MWMHehC9iKB9mR5tB3DWzbkYmTfe9buWQ5GZ8
-creating allocations file
-creating VM genesis file with allocations
-[38;5;11mdatabase:[0m .token-cli
-created genesis and saved to /tmp/tokenvm.genesis
-creating vm config
-creating subnet config
-building e2e.test
-Compiled e2e.test
-launch avalanche-network-runner in the background
-running e2e tests
-[06-11|00:50:34.254] INFO server/server.go:169 dialing gRPC server for gRPC gateway {"port": ":12352"}
-[06-11|00:50:34.254] INFO server/server.go:159 serving gRPC server {"port": ":12352"}
-[06-11|00:50:34.257] INFO server/server.go:193 serving gRPC gateway {"port": ":12353"}
-[38;5;11mskipping tests[0m
-Running Suite: tokenvm e2e test suites - /home/anomalyfi/code/hypersdk/examples/tokenvm
-=======================================================================================
-Random Seed: [1m1686444634[0m
-
-Will run [1m4[0m of [1m4[0m specs
-[38;5;243m------------------------------[0m
-[0m[1m[BeforeSuite] [0m
-[38;5;243m/home/anomalyfi/code/hypersdk/examples/tokenvm/tests/e2e/e2e_test.go:157[0m
-[06-11|00:50:34.325] DEBUG client/client.go:70 dialing server at {"endpoint": "0.0.0.0:12352"}
-[38;5;10msending 'start' with binary path:[0m "/tmp/avalanchego-v1.10.1/avalanchego" ("tHBYNu8ikqo4MWMHehC9iKB9mR5tB3DWzbkYmTfe9buWQ5GZ8")
-[06-11|00:50:34.327] INFO client/client.go:139 start
-[06-11|00:50:34.328] INFO server/server.go:340 starting {"exec-path": "/tmp/avalanchego-v1.10.1/avalanchego", "num-nodes": 5, "track-subnets": "", "pid": 514258, "root-data-dir": "/tmp/network-runner-root-data_20230611_005034", "plugin-dir": "/tmp/avalanchego-v1.10.1/plugins", "chain-configs": null, "global-node-config": "{\n\t\t\t\t\"log-display-level\":\"info\",\n\t\t\t\t\"proposervm-use-current-height\":true,\n\t\t\t\t\"throttler-inbound-validator-alloc-size\":\"10737418240\",\n\t\t\t\t\"throttler-inbound-at-large-alloc-size\":\"10737418240\",\n\t\t\t\t\"throttler-inbound-node-max-processing-msgs\":\"100000\",\n\t\t\t\t\"throttler-inbound-bandwidth-refill-rate\":\"1073741824\",\n\t\t\t\t\"throttler-inbound-bandwidth-max-burst-size\":\"1073741824\",\n\t\t\t\t\"throttler-inbound-cpu-validator-alloc\":\"100000\",\n\t\t\t\t\"throttler-inbound-disk-validator-alloc\":\"10737418240000\",\n\t\t\t\t\"throttler-outbound-validator-alloc-size\":\"10737418240\",\n\t\t\t\t\"throttler-outbound-at-large-alloc-size\":\"10737418240\",\n\t\t\t\t\"snow-mixed-query-num-push-vdr\":\"10\",\n\t\t\t\t\"consensus-on-accept-gossip-validator-size\":\"10\",\n\t\t\t\t\"consensus-on-accept-gossip-peer-size\":\"10\",\n\t\t\t\t\"network-compression-type\":\"none\",\n\t\t\t\t\"consensus-app-concurrency\":\"512\"\n\t\t\t}"}
-[06-11|00:50:34.329] INFO ux/output.go:13 [0;34m[;1mcreate and run local network[0;0m[0;0m
-[06-11|00:50:34.329] INFO local/network.go:419 creating network {"node-num": 5}
-[06-11|00:50:34.728] INFO local/network.go:587 adding node {"node-name": "node1", "node-dir": "/tmp/network-runner-root-data_20230611_005034/node1", "log-dir": "/tmp/network-runner-root-data_20230611_005034/node1/logs", "db-dir": "/tmp/network-runner-root-data_20230611_005034/node1/db", "p2p-port": 9651, "api-port": 9650}
-[06-11|00:50:34.728] DEBUG local/network.go:597 starting node {"name": "node1", "binaryPath": "/tmp/avalanchego-v1.10.1/avalanchego", "args": ["--network-max-reconnect-delay=1s", "--staking-tls-key-file=/tmp/network-runner-root-data_20230611_005034/node1/staking.key", "--proposervm-use-current-height=true", "--consensus-on-accept-gossip-peer-size=10", "--throttler-inbound-at-large-alloc-size=10737418240", "--log-dir=/tmp/network-runner-root-data_20230611_005034/node1/logs", "--throttler-inbound-validator-alloc-size=10737418240", "--staking-port=9651", "--genesis=/tmp/network-runner-root-data_20230611_005034/node1/genesis.json", "--chain-config-dir=/tmp/network-runner-root-data_20230611_005034/node1/chainConfigs", "--subnet-config-dir=/tmp/network-runner-root-data_20230611_005034/node1/subnetConfigs", "--index-enabled=true", "--db-dir=/tmp/network-runner-root-data_20230611_005034/node1/db", "--http-port=9650", "--throttler-inbound-disk-validator-alloc=10737418240000", "--consensus-on-accept-gossip-validator-size=10", "--plugin-dir=/tmp/avalanchego-v1.10.1/plugins", "--throttler-inbound-cpu-validator-alloc=100000", "--bootstrap-ids=", "--bootstrap-ips=", "--public-ip=127.0.0.1", "--network-compression-type=none", "--staking-tls-cert-file=/tmp/network-runner-root-data_20230611_005034/node1/staking.crt", "--throttler-inbound-bandwidth-max-burst-size=1073741824", "--throttler-inbound-bandwidth-refill-rate=1073741824", "--api-ipcs-enabled=true", "--throttler-outbound-validator-alloc-size=10737418240", "--network-peer-list-gossip-frequency=250ms", "--staking-signer-key-file=/tmp/network-runner-root-data_20230611_005034/node1/signer.key", "--data-dir=/tmp/network-runner-root-data_20230611_005034/node1", "--snow-mixed-query-num-push-vdr=10", "--consensus-app-concurrency=512", "--log-level=DEBUG", "--network-id=1337", "--throttler-inbound-node-max-processing-msgs=100000", "--throttler-outbound-at-large-alloc-size=10737418240", "--health-check-frequency=2s", "--api-admin-enabled=true", "--log-display-level=info"]}
-[06-11|00:50:35.065] INFO local/network.go:587 adding node {"node-name": "node2", "node-dir": "/tmp/network-runner-root-data_20230611_005034/node2", "log-dir": "/tmp/network-runner-root-data_20230611_005034/node2/logs", "db-dir": "/tmp/network-runner-root-data_20230611_005034/node2/db", "p2p-port": 9653, "api-port": 9652}
-[06-11|00:50:35.066] DEBUG local/network.go:597 starting node {"name": "node2", "binaryPath": "/tmp/avalanchego-v1.10.1/avalanchego", "args": ["--consensus-app-concurrency=512", "--network-peer-list-gossip-frequency=250ms", "--db-dir=/tmp/network-runner-root-data_20230611_005034/node2/db", "--staking-port=9653", "--network-max-reconnect-delay=1s", "--health-check-frequency=2s", "--api-ipcs-enabled=true", "--chain-config-dir=/tmp/network-runner-root-data_20230611_005034/node2/chainConfigs", "--consensus-on-accept-gossip-peer-size=10", "--api-admin-enabled=true", "--public-ip=127.0.0.1", "--http-port=9652", "--staking-signer-key-file=/tmp/network-runner-root-data_20230611_005034/node2/signer.key", "--staking-tls-key-file=/tmp/network-runner-root-data_20230611_005034/node2/staking.key", "--subnet-config-dir=/tmp/network-runner-root-data_20230611_005034/node2/subnetConfigs", "--snow-mixed-query-num-push-vdr=10", "--log-display-level=info", "--consensus-on-accept-gossip-validator-size=10", "--staking-tls-cert-file=/tmp/network-runner-root-data_20230611_005034/node2/staking.crt", "--bootstrap-ids=NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", "--throttler-inbound-cpu-validator-alloc=100000", "--network-id=1337", "--network-compression-type=none", "--bootstrap-ips=[::1]:9651", "--throttler-inbound-bandwidth-refill-rate=1073741824", "--log-level=DEBUG", "--log-dir=/tmp/network-runner-root-data_20230611_005034/node2/logs", "--throttler-inbound-node-max-processing-msgs=100000", "--throttler-inbound-validator-alloc-size=10737418240", "--throttler-inbound-at-large-alloc-size=10737418240", "--throttler-inbound-bandwidth-max-burst-size=1073741824", "--proposervm-use-current-height=true", "--throttler-outbound-validator-alloc-size=10737418240", "--plugin-dir=/tmp/avalanchego-v1.10.1/plugins", "--throttler-inbound-disk-validator-alloc=10737418240000", "--index-enabled=true", "--genesis=/tmp/network-runner-root-data_20230611_005034/node2/genesis.json", "--data-dir=/tmp/network-runner-root-data_20230611_005034/node2", "--throttler-outbound-at-large-alloc-size=10737418240"]}
-[0;36m[node1] [06-11|00:50:35.116] WARN app/app.go:153 P2P IP is private, you will not be publicly discoverable {"ip": "127.0.0.1"}
-[0;0m[0;36m[node1] [06-11|00:50:35.117] INFO node/node.go:1251 initializing node {"version": "avalanche/1.10.1", "nodeID": "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", "nodePOP": {"publicKey":"0xb3ebbe748a1f06d19ee25d4e345ba8d6b5a426498a140c2519b518e3e6224abd7895075892f361acf24c10af968bc7de","proofOfPossession":"0xa2569a137e65d3a507c4f1f7ffac74ec05916ba44dfbbb84d42c2736a2bc1e8be14038d3aeeeac7c78e19ecdde69d830051959f22559641a3f9e42377d7f64580acdc383c5c9e22f7f1114712a543c6997d6dc59c88555423497d9fff41fa79a"}, "providedFlags": {"api-admin-enabled":true,"api-ipcs-enabled":true,"bootstrap-ids":"","bootstrap-ips":"","chain-config-dir":"/tmp/network-runner-root-data_20230611_005034/node1/chainConfigs","consensus-app-concurrency":"512","consensus-on-accept-gossip-peer-size":"10","consensus-on-accept-gossip-validator-size":"10","data-dir":"/tmp/network-runner-root-data_20230611_005034/node1","db-dir":"/tmp/network-runner-root-data_20230611_005034/node1/db","genesis":"/tmp/network-runner-root-data_20230611_005034/node1/genesis.json","health-check-frequency":"2s","http-port":"9650","index-enabled":true,"log-dir":"/tmp/network-runner-root-data_20230611_005034/node1/logs","log-display-level":"info","log-level":"DEBUG","network-compression-type":"none","network-id":"1337","network-max-reconnect-delay":"1s","network-peer-list-gossip-frequency":"250ms","plugin-dir":"/tmp/avalanchego-v1.10.1/plugins","proposervm-use-current-height":true,"public-ip":"127.0.0.1","snow-mixed-query-num-push-vdr":"10","staking-port":"9651","staking-signer-key-file":"/tmp/network-runner-root-data_20230611_005034/node1/signer.key","staking-tls-cert-file":"/tmp/network-runner-root-data_20230611_005034/node1/staking.crt","staking-tls-key-file":"/tmp/network-runner-root-data_20230611_005034/node1/staking.key","subnet-config-dir":"/tmp/network-runner-root-data_20230611_005034/node1/subnetConfigs","throttler-inbound-at-large-alloc-size":"10737418240","throttler-inbound-bandwidth-max-burst-size":"1073741824","throttler-inbound-bandwidth-refill-rate":"1073741824","throttler-inbound-cpu-validator-alloc":"100000","throttler-inbound-disk-validator-alloc":"1.073741824e+13","throttler-inbound-node-max-processing-msgs":"100000","throttler-inbound-validator-alloc-size":"10737418240","throttler-outbound-at-large-alloc-size":"10737418240","throttler-outbound-validator-alloc-size":"10737418240"}, "config": {"httpConfig":{"readTimeout":30000000000,"readHeaderTimeout":30000000000,"writeHeaderTimeout":30000000000,"idleTimeout":120000000000,"apiConfig":{"authConfig":{"apiRequireAuthToken":false},"indexerConfig":{"indexAPIEnabled":true,"indexAllowIncomplete":false},"ipcConfig":{"ipcAPIEnabled":true,"ipcPath":"/tmp","ipcDefaultChainIDs":null},"adminAPIEnabled":true,"infoAPIEnabled":true,"keystoreAPIEnabled":false,"metricsAPIEnabled":true,"healthAPIEnabled":true},"httpHost":"127.0.0.1","httpPort":9650,"httpsEnabled":false,"apiAllowedOrigins":["*"],"shutdownTimeout":10000000000,"shutdownWait":0},"ipConfig":{"ip":{"ip":"127.0.0.1","port":9651},"ipResolutionFrequency":300000000000,"attemptedNATTraversal":false},"stakingConfig":{"uptimeRequirement":0.8,"minValidatorStake":2000000000000,"maxValidatorStake":3000000000000000,"minDelegatorStake":25000000000,"minDelegationFee":20000,"minStakeDuration":86400000000000,"maxStakeDuration":31536000000000000,"rewardConfig":{"maxConsumptionRate":120000,"minConsumptionRate":100000,"mintingPeriod":31536000000000000,"supplyCap":720000000000000000},"enableStaking":true,"disabledStakingWeight":100,"stakingKeyPath":"/tmp/network-runner-root-data_20230611_005034/node1/staking.key","stakingCertPath":"/tmp/network-runner-root-data_20230611_005034/node1/staking.crt","stakingSignerPath":"/tmp/network-runner-root-data_20230611_005034/node1/signer.key"},"txFeeConfig":{"txFee":1000000,"createAssetTxFee":1000000,"createSubnetTxFee":100000000,"transformSubnetTxFee":100000000,"createBlockchainTxFee":100000000,"addPrimaryNetworkValidatorFee":0,"addPrimaryNetworkDelegatorFee":0,"addSubnetValidatorFee":1000000,"addSubnetDelegatorFee":1000000},"stateSyncConfig":{"stateSyncIDs":null,"stateSyncIPs":null},"bootstrapConfig":{"retryBootstrap":true,"retryBootstrapWarnFrequency":50,"bootstrapBeaconConnectionTimeout":60000000000,"bootstrapAncestorsMaxContainersSent":2000,"bootstrapAncestorsMaxContainersReceived":2000,"bootstrapMaxTimeGetAncestors":50000000,"bootstrapIDs":null,"bootstrapIPs":null},"databaseConfig":{"path":"/tmp/network-runner-root-data_20230611_005034/node1/db/network-1337","name":"leveldb"},"avaxAssetID":"BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC","networkID":1337,"healthCheckFreq":2000000000,"networkConfig":{"healthConfig":{"minConnectedPeers":1,"maxTimeSinceMsgReceived":60000000000,"maxTimeSinceMsgSent":60000000000,"maxPortionSendQueueBytesFull":0.9,"maxSendFailRate":0.9,"sendFailRateHalflife":10000000000},"peerListGossipConfig":{"peerListNumValidatorIPs":15,"peerListValidatorGossipSize":20,"peerListNonValidatorGossipSize":0,"peerListPeersGossipSize":10,"peerListGossipFreq":250000000},"timeoutConfigs":{"pingPongTimeout":30000000000,"readHandshakeTimeout":15000000000},"delayConfig":{"initialReconnectDelay":1000000000,"maxReconnectDelay":1000000000},"throttlerConfig":{"inboundConnUpgradeThrottlerConfig":{"upgradeCooldown":10000000000,"maxRecentConnsUpgraded":2560},"inboundMsgThrottlerConfig":{"byteThrottlerConfig":{"vdrAllocSize":10737418240,"atLargeAllocSize":10737418240,"nodeMaxAtLargeBytes":2097152},"bandwidthThrottlerConfig":{"bandwidthRefillRate":1073741824,"bandwidthMaxBurstRate":1073741824},"cpuThrottlerConfig":{"maxRecheckDelay":5000000000},"diskThrottlerConfig":{"maxRecheckDelay":5000000000},"maxProcessingMsgsPerNode":100000},"outboundMsgThrottlerConfig":{"vdrAllocSize":10737418240,"atLargeAllocSize":10737418240,"nodeMaxAtLargeBytes":2097152},"maxInboundConnsPerSec":256},"proxyEnabled":false,"proxyReadHeaderTimeout":3000000000,"dialerConfig":{"throttleRps":50,"connectionTimeout":30000000000},"tlsKeyLogFile":"","namespace":"","myNodeID":"NodeID-111111111111111111116DBWJs","myIP":null,"networkID":0,"maxClockDifference":60000000000,"pingFrequency":22500000000,"allowPrivateIPs":true,"compressionType":"none","uptimeMetricFreq":30000000000,"requireValidatorToConnect":false,"maximumInboundMessageTimeout":10000000000,"peerReadBufferSize":8192,"peerWriteBufferSize":8192},"adaptiveTimeoutConfig":{"initialTimeout":5000000000,"minimumTimeout":2000000000,"maximumTimeout":10000000000,"timeoutCoefficient":2,"timeoutHalflife":300000000000},"benchlistConfig":{"threshold":10,"minimumFailingDuration":150000000000,"duration":900000000000,"maxPortion":0.08333333333333333},"profilerConfig":{"dir":"/tmp/network-runner-root-data_20230611_005034/node1/profiles","enabled":false,"freq":900000000000,"maxNumFiles":5},"loggingConfig":{"maxSize":8,"maxFiles":7,"maxAge":0,"directory":"/tmp/network-runner-root-data_20230611_005034/node1/logs","compress":false,"disableWriterDisplaying":false,"logLevel":"DEBUG","displayLevel":"INFO","logFormat":"PLAIN"},"pluginDir":"/tmp/avalanchego-v1.10.1/plugins","fdLimit":32768,"meterVMEnabled":true,"routerHealthConfig":{"maxDropRate":1,"maxDropRateHalflife":10000000000,"maxOutstandingRequests":1024,"maxOutstandingDuration":300000000000,"maxRunTimeRequests":10000000000},"consensusShutdownTimeout":30000000000,"consensusGossipFreq":10000000000,"consensusAppConcurrency":512,"trackedSubnets":[],"subnetConfigs":{"11111111111111111111111111111111LpoYY":{"gossipAcceptedFrontierValidatorSize":0,"gossipAcceptedFrontierNonValidatorSize":0,"gossipAcceptedFrontierPeerSize":15,"gossipOnAcceptValidatorSize":10,"gossipOnAcceptNonValidatorSize":0,"gossipOnAcceptPeerSize":10,"appGossipValidatorSize":10,"appGossipNonValidatorSize":0,"appGossipPeerSize":0,"validatorOnly":false,"allowedNodes":null,"consensusParameters":{"k":20,"alpha":15,"betaVirtuous":20,"betaRogue":20,"concurrentRepolls":4,"optimalProcessing":10,"maxOutstandingItems":256,"maxItemProcessingTime":30000000000,"mixedQueryNumPushVdr":10,"mixedQueryNumPushNonVdr":0},"proposerMinBlockDelay":1000000000,"minPercentConnectedStakeHealthy":0}},"chainAliases":null,"systemTrackerProcessingHalflife":15000000000,"systemTrackerFrequency":500000000,"systemTrackerCPUHalflife":15000000000,"systemTrackerDiskHalflife":60000000000,"cpuTargeterConfig":{"vdrAlloc":100000,"maxNonVdrUsage":44.800000000000004,"maxNonVdrNodeUsage":7},"diskTargeterConfig":{"vdrAlloc":10737418240000,"maxNonVdrUsage":1073741824000,"maxNonVdrNodeUsage":1073741824000},"requiredAvailableDiskSpace":536870912,"warningThresholdAvailableDiskSpace":1073741824,"traceConfig":{"exporterConfig":{"type":"unknown","endpoint":"","headers":null,"insecure":false},"enabled":false,"traceSampleRate":0},"minPercentConnectedStakeHealthy":{"11111111111111111111111111111111LpoYY":0.8},"useCurrentHeight":true,"chainDataDir":"/tmp/network-runner-root-data_20230611_005034/node1/chainData"}}
-[0;0m[0;36m[node1] [06-11|00:50:35.118] INFO node/node.go:582 initializing API server
-[0;0m[0;36m[node1] [06-11|00:50:35.118] INFO server/server.go:147 API created {"allowedOrigins": ["*"]}
-[0;0m[0;36m[node1] [06-11|00:50:35.118] INFO node/node.go:912 initializing metrics API
-[0;0m[0;36m[node1] [06-11|00:50:35.118] INFO server/server.go:308 adding route {"url": "/ext/metrics", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.118] INFO leveldb/db.go:208 creating leveldb {"config": {"blockCacheCapacity":12582912,"blockSize":0,"compactionExpandLimitFactor":0,"compactionGPOverlapsFactor":0,"compactionL0Trigger":0,"compactionSourceLimitFactor":0,"compactionTableSize":0,"compactionTableSizeMultiplier":0,"compactionTableSizeMultiplierPerLevel":null,"compactionTotalSize":0,"compactionTotalSizeMultiplier":0,"disableSeeksCompaction":true,"openFilesCacheCapacity":1024,"writeBuffer":6291456,"filterBitsPerKey":10,"maxManifestFileSize":9223372036854775807,"metricUpdateFrequency":10000000000}}
-[0;0m[0;36m[node1] [06-11|00:50:35.147] INFO node/node.go:452 initializing database {"dbVersion": "v1.4.5"}
-[0;0m[0;36m[node1] [06-11|00:50:35.148] INFO node/node.go:869 initializing keystore
-[0;0m[0;36m[node1] [06-11|00:50:35.148] INFO node/node.go:877 skipping keystore API initialization because it has been disabled
-[0;0m[0;36m[node1] [06-11|00:50:35.148] INFO node/node.go:861 initializing SharedMemory
-[0;0m[0;36m[node1] [06-11|00:50:35.169] INFO node/node.go:232 initializing networking {"currentNodeIP": "127.0.0.1:9651"}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO node/node.go:1032 initializing Health API
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/readiness"}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/health"}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/liveness"}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO node/node.go:642 adding the default VM aliases
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO node/node.go:763 initializing VMs
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/vm/rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/vm/jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.171] INFO server/server.go:308 adding route {"url": "/ext/vm/mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6", "endpoint": "/rpc"}
-[0;0m[0;36m[node1] [06-11|00:50:35.246] INFO subprocess/runtime.go:143 plugin handshake succeeded {"addr": "127.0.0.1:46325"}
-[0;0m[0;36m[node1] runtime engine: received shutdown signal: SIGTERM
-[0;0m[0;36m[node1] vm server: graceful termination success
-[0;0m[0;36m[node1] [06-11|00:50:35.253] INFO subprocess/runtime.go:111 stdout collector shutdown
-[0;0m[0;36m[node1] [06-11|00:50:35.253] INFO subprocess/runtime.go:124 stderr collector shutdown
-[0;0m[0;36m[node1] [06-11|00:50:35.322] INFO subprocess/runtime.go:143 plugin handshake succeeded {"addr": "127.0.0.1:33491"}
-[0;0m[0;36m[node1] [06-11|00:50:35.324] INFO node/node.go:935 initializing admin API
-[0;0m[0;36m[node1] [06-11|00:50:35.324] INFO server/server.go:308 adding route {"url": "/ext/admin", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.324] INFO node/node.go:984 initializing info API
-[0;0m[0;36m[node1] [06-11|00:50:35.327] INFO server/server.go:308 adding route {"url": "/ext/info", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.327] WARN node/node.go:1138 initializing deprecated ipc API
-[0;0m[0;36m[node1] [06-11|00:50:35.327] INFO server/server.go:308 adding route {"url": "/ext/ipcs", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.327] INFO node/node.go:1148 initializing chain aliases
-[0;0m[0;36m[node1] [06-11|00:50:35.327] INFO node/node.go:1175 initializing API aliases
-[0;0m[0;36m[node1] [06-11|00:50:35.328] INFO node/node.go:957 skipping profiler initialization because it has been disabled
-[0;0m[0;36m[node1] [06-11|00:50:35.328] INFO node/node.go:561 initializing chains
-[0;0m[0;36m[node1] [06-11|00:50:35.328] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "11111111111111111111111111111111LpoYY", "vmID": "rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT"}
-[0;0m[0;36m[node1] [06-11|00:50:35.330] INFO chains/manager.go:1102 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[0;36m[node1] [06-11|00:50:35.333] INFO platformvm/vm.go:228 initializing last accepted {"blkID": "2EYLCg5YdYRx9h3g3odqDB49o35ekw6NtXqJaom7pb3Rpvmonc"}
-[0;0m[0;36m[node1] [06-11|00:50:35.336] INFO
snowman/transitive.go:89 initializing consensus engine
-[0;0m[0;36m[node1] [06-11|00:50:35.337] INFO server/server.go:269 adding route {"url": "/ext/bc/11111111111111111111111111111111LpoYY", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.337] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.337] INFO server/server.go:308 adding route {"url": "/ext/index/P", "endpoint": "/block"}
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO
bootstrap/bootstrapper.go:115 starting bootstrapper
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO
common/bootstrapper.go:310 bootstrapping skipped {"reason": "no provided bootstraps"}
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO
bootstrap/bootstrapper.go:554 executing blocks {"numPendingJobs": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO
queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO
bootstrap/bootstrapper.go:599 waiting for the remaining chains in this subnet to finish syncing
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO chains/manager.go:1338 starting chain creator
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "vmID": "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6"}
-[0;0m[0;36m[node1] [06-11|00:50:35.338] INFO server/server.go:184 HTTP API server listening {"host": "127.0.0.1", "port": 9650}
-[0;0m[0;36m[node1] [06-11|00:50:35.339] INFO chains/manager.go:1102 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.340] github.com/ava-labs/coreth/plugin/evm/vm.go:353: Initializing Coreth VM Version=v0.12.0 Config="{SnowmanAPIEnabled:false CorethAdminAPIEnabled:false CorethAdminAPIDir: EnabledEthAPIs:[eth eth-filter net web3 internal-eth internal-blockchain internal-transaction internal-account] ContinuousProfilerDir: ContinuousProfilerFrequency:15m0s ContinuousProfilerMaxFiles:5 RPCGasCap:50000000 RPCTxFeeCap:100 TrieCleanCache:512 TrieCleanJournal: TrieCleanRejournal:0s TrieDirtyCache:256 TrieDirtyCommitTarget:20 SnapshotCache:256 Preimages:false SnapshotAsync:true SnapshotVerify:false Pruning:true AcceptorQueueLimit:64 CommitInterval:4096 AllowMissingTries:false PopulateMissingTries: PopulateMissingTriesParallelism:1024 MetricsExpensiveEnabled:false LocalTxsEnabled:false TxPoolJournal:transactions.rlp TxPoolRejournal:1h0m0s TxPoolPriceLimit:1 TxPoolPriceBump:10 TxPoolAccountSlots:16 TxPoolGlobalSlots:5120 TxPoolAccountQueue:64 TxPoolGlobalQueue:1024 APIMaxDuration:0s WSCPURefillRate:0s WSCPUMaxStored:0s MaxBlocksPerRequest:0 AllowUnfinalizedQueries:false AllowUnprotectedTxs:false AllowUnprotectedTxHashes:[0xfefb2da535e927b85fe68eb81cb2e4a5827c905f78381a01ef2322aa9b0aee8e] KeystoreDirectory: KeystoreExternalSigner: KeystoreInsecureUnlockAllowed:false RemoteTxGossipOnlyEnabled:false TxRegossipFrequency:1m0s TxRegossipMaxSize:15 LogLevel:debug LogJSONFormat:false OfflinePruning:false OfflinePruningBloomFilterSize:512 OfflinePruningDataDirectory: MaxOutboundActiveRequests:16 MaxOutboundActiveCrossChainRequests:64 StateSyncEnabled: StateSyncSkipResume:false StateSyncServerTrieCache:64 StateSyncIDs: StateSyncCommitInterval:16384 StateSyncMinBlocks:300000 StateSyncRequestSize:1024 InspectDatabase:false SkipUpgradeCheck:false AcceptedCacheSize:32 TxLookupLimit:0}"
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.341] github.com/ava-labs/coreth/trie/database.go:735: Persisted trie from memory database nodes=1 size=151.00B time="12.117µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.341] github.com/ava-labs/coreth/plugin/evm/vm.go:429: lastAccepted = 0xb81c22ceb61ecbb2efaaf4199f82a7c870850b45f41cc9490edf0e06be0e6bb9
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:35.341] github.com/ava-labs/coreth/accounts/keystore/file_cache.go:100: FS scan times list="50.76µs" set=583ns diff="1.084µs"
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.341] github.com/ava-labs/coreth/eth/backend.go:134: Allocated memory caches trie clean=512.00MiB trie dirty=256.00MiB snapshot clean=256.00MiB
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.341] github.com/ava-labs/coreth/eth/backend.go:171: Initialising Ethereum protocol network=43112 dbversion=
-[0;0m[0;36m[node1] WARN [06-11|00:50:35.341] github.com/ava-labs/coreth/eth/backend.go:177: Upgrade blockchain database version from= to=8
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.341] github.com/ava-labs/coreth/core/genesis.go:176: Writing genesis to database
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/trie/database.go:735: Persisted trie from memory database nodes=1 size=151.00B time="18.909µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:306:
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:307: ---------------------------------------------------------------------------------------------------------------------------------------------------------
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: Chain ID: 43112
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: Consensus: Dummy Consensus Engine
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: Hard Forks:
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Homestead: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - DAO Fork: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Tangerine Whistle (EIP 150): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Spurious Dragon/1 (EIP 155): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Spurious Dragon/2 (EIP 158): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Byzantium: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Constantinople: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Petersburg: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Istanbul: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Muir Glacier: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 1 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.3.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 2 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.4.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 3 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.5.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 4 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.6.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 5 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase P6 Timestamp 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 6 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase Post-6 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Banff Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.9.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - Cortina Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.10.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309: - DUpgrade Timestamp (https://github.com/ava-labs/avalanchego/releases/tag/v1.11.0)
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:311: ---------------------------------------------------------------------------------------------------------------------------------------------------------
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.342] github.com/ava-labs/coreth/core/blockchain.go:312:
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.343] github.com/ava-labs/coreth/core/blockchain.go:710: Loaded most recent local header number=0 hash=b81c22..0e6bb9 age=54y2mo2w
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/blockchain.go:711: Loaded most recent local full block number=0 hash=b81c22..0e6bb9 age=54y2mo2w
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/blockchain.go:1722: Loaded Acceptor tip hash=000000..000000
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/blockchain.go:1730: Skipping state reprocessing root=3cbfcc..68c8b4
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/blockchain.go:544: Not warming accepted cache because there are no accepted blocks
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/blockchain.go:567: Starting Acceptor queue length=64
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:35.344] github.com/ava-labs/coreth/core/tx_pool.go:1408: Reinjecting stale transactions count=0
-[0;0m[0;36m[node1] WARN [06-11|00:50:35.344] github.com/ava-labs/coreth/core/rawdb/accessors_metadata.go:111: Error reading unclean shutdown markers error="not found"
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/tx_pool.go:505: Transaction pool price threshold updated price=470,000,000,000
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/tx_pool.go:505: Transaction pool price threshold updated price=225,000,000,000
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.344] github.com/ava-labs/coreth/core/tx_pool.go:505: Transaction pool price threshold updated price=0
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.345] github.com/ava-labs/coreth/plugin/evm/atomic_tx_repository.go:115: Initializing atomic transaction repository from scratch
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.345] github.com/ava-labs/coreth/plugin/evm/atomic_tx_repository.go:191: Completed atomic transaction repository migration lastAcceptedHeight=0 duration="163.072µs"
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.345] github.com/ava-labs/coreth/plugin/evm/atomic_tx_repository.go:438: atomic tx repository RepairForBonusBlocks complete repairedEntries=0
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.346] github.com/ava-labs/coreth/plugin/evm/atomic_backend.go:132: initializing atomic trie lastCommittedHeight=0
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.346] github.com/ava-labs/coreth/plugin/evm/atomic_backend.go:210: finished initializing atomic trie lastAcceptedHeight=0 lastAcceptedAtomicRoot=56e81f..63b421 heightsIndexed=0 lastCommittedRoot=56e81f..63b421 lastCommittedHeight=0 time="91.043µs"
-[0;0m[0;36m[node1] [06-11|00:50:35.347] INFO proposervm/vm.go:356 block height index was successfully verified
-[0;0m[0;36m[node1] [06-11|00:50:35.350] INFO snowman/transitive.go:89 initializing consensus engine
-[0;0m[0;36m[node1] INFO [06-11|00:50:35.352] github.com/ava-labs/coreth/plugin/evm/vm.go:1171: Enabled APIs: eth, eth-filter, net, web3, internal-eth, internal-blockchain, internal-transaction, internal-account, avax
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:35.352] github.com/ava-labs/coreth/rpc/websocket.go:104: Allowed origin(s) for WS RPC interface [*]
-[0;0m[0;36m[node1] [06-11|00:50:35.352] INFO server/server.go:269 adding route {"url": "/ext/bc/23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "endpoint": "/avax"}
-[0;0m[0;36m[node1] [06-11|00:50:35.353] INFO server/server.go:269 adding route {"url": "/ext/bc/23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "endpoint": "/rpc"}
-[0;0m[0;36m[node1] [06-11|00:50:35.353] INFO server/server.go:269 adding route {"url": "/ext/bc/23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "endpoint": "/ws"}
-[0;0m[0;36m[node1] [06-11|00:50:35.353] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.353] INFO server/server.go:308 adding route {"url": "/ext/index/C", "endpoint": "/block"}
-[0;0m[0;36m[node1] [06-11|00:50:35.354] INFO syncer/state_syncer.go:385 starting state sync
-[0;0m[0;36m[node1] [06-11|00:50:35.354] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "vmID": "jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq"}
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:35.354] github.com/ava-labs/coreth/peer/network.go:486: adding new peer nodeID=NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:35.354] github.com/ava-labs/coreth/peer/network.go:496: skipping registering self as peer
-[0;0m[0;36m[node1] [06-11|00:50:35.357] INFO avm/vm.go:636 initializing genesis asset {"txID": "BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC"}
-[0;0m[0;36m[node1] [06-11|00:50:35.357] INFO avm/vm.go:619 fee asset is established {"alias": "AVAX", "assetID": "BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC"}
-[0;0m[0;36m[node1] [06-11|00:50:35.357] INFO avm/vm.go:275 address transaction indexing is disabled
-[0;0m[0;36m[node1] [06-11|00:50:35.358] INFO chains/manager.go:756 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[0;36m[node1] [06-11|00:50:35.361] INFO snowman/transitive.go:89 initializing consensus engine
-[0;0m[0;36m[node1] [06-11|00:50:35.362] INFO server/server.go:269 adding route {"url": "/ext/bc/qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "endpoint": "/events"}
-[0;0m[0;36m[node1] [06-11|00:50:35.363] INFO server/server.go:269 adding route {"url": "/ext/bc/qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "endpoint": ""}
-[0;0m[0;36m[node1] [06-11|00:50:35.363] INFO server/server.go:269 adding route {"url": "/ext/bc/qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "endpoint": "/wallet"}
-[0;0m[0;36m[node1] [06-11|00:50:35.363] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.363] INFO server/server.go:308 adding route {"url": "/ext/index/X", "endpoint": "/block"}
-[0;0m[0;36m[node1] [06-11|00:50:35.363] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.363] INFO server/server.go:308 adding route {"url": "/ext/index/X", "endpoint": "/vtx"}
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO server/server.go:308 adding route {"url": "/ext/index/X", "endpoint": "/tx"}
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO bootstrap/bootstrapper.go:290 starting bootstrap
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO bootstrap/bootstrapper.go:347 accepted stop vertex {"vtxID": "sj8adpSGCc7k7aWFNkiugYvUSHGq9xUvJPb8VzdVPXv9u2b5X"}
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO bootstrap/bootstrapper.go:571 executing transactions
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO bootstrap/bootstrapper.go:588 executing vertices
-[0;0m[0;36m[node1] [06-11|00:50:35.364] INFO queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[0;36m[node1] [06-11|00:50:35.365] INFO bootstrap/bootstrapper.go:115 starting bootstrapper
-[0;0m[1;34m[node2] [06-11|00:50:35.424] WARN app/app.go:153 P2P IP is private, you will not be publicly discoverable {"ip": "127.0.0.1"}
-[0;0m[1;34m[node2] [06-11|00:50:35.425] INFO node/node.go:1251 initializing node {"version": "avalanche/1.10.1", "nodeID": "NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ", "nodePOP": {"publicKey":"0x8b49c4259529a801cc961c72248773b550379ff718a49f4ccc0e1f2ac338fe204432329aa1712f408f97eee12b22dd05","proofOfPossession":"0xaf92674c3615d462527675da121b06023b116ddebc6e163919e562ab7cbe6adf20515cd2fc17c3e2d2d59953f285229e15f04302187bef5a4aa3ebdea1d18bf34047be654dd12491e882fb90b17b3cbde99ad43fc5cd0c26828bbe49a4b9456c"}, "providedFlags": {"api-admin-enabled":true,"api-ipcs-enabled":true,"bootstrap-ids":"NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg","bootstrap-ips":"[::1]:9651","chain-config-dir":"/tmp/network-runner-root-data_20230611_005034/node2/chainConfigs","consensus-app-concurrency":"512","consensus-on-accept-gossip-peer-size":"10","consensus-on-accept-gossip-validator-size":"10","data-dir":"/tmp/network-runner-root-data_20230611_005034/node2","db-dir":"/tmp/network-runner-root-data_20230611_005034/node2/db","genesis":"/tmp/network-runner-root-data_20230611_005034/node2/genesis.json","health-check-frequency":"2s","http-port":"9652","index-enabled":true,"log-dir":"/tmp/network-runner-root-data_20230611_005034/node2/logs","log-display-level":"info","log-level":"DEBUG","network-compression-type":"none","network-id":"1337","network-max-reconnect-delay":"1s","network-peer-list-gossip-frequency":"250ms","plugin-dir":"/tmp/avalanchego-v1.10.1/plugins","proposervm-use-current-height":true,"public-ip":"127.0.0.1","snow-mixed-query-num-push-vdr":"10","staking-port":"9653","staking-signer-key-file":"/tmp/network-runner-root-data_20230611_005034/node2/signer.key","staking-tls-cert-file":"/tmp/network-runner-root-data_20230611_005034/node2/staking.crt","staking-tls-key-file":"/tmp/network-runner-root-data_20230611_005034/node2/staking.key","subnet-config-dir":"/tmp/network-runner-root-data_20230611_005034/node2/subnetConfigs","throttler-inbound-at-large-alloc-size":"10737418240","throttler-inbound-bandwidth-max-burst-size":"1073741824","throttler-inbound-bandwidth-refill-rate":"1073741824","throttler-inbound-cpu-validator-alloc":"100000","throttler-inbound-disk-validator-alloc":"1.073741824e+13","throttler-inbound-node-max-processing-msgs":"100000","throttler-inbound-validator-alloc-size":"10737418240","throttler-outbound-at-large-alloc-size":"10737418240","throttler-outbound-validator-alloc-size":"10737418240"}, "config": {"httpConfig":{"readTimeout":30000000000,"readHeaderTimeout":30000000000,"writeHeaderTimeout":30000000000,"idleTimeout":120000000000,"apiConfig":{"authConfig":{"apiRequireAuthToken":false},"indexerConfig":{"indexAPIEnabled":true,"indexAllowIncomplete":false},"ipcConfig":{"ipcAPIEnabled":true,"ipcPath":"/tmp","ipcDefaultChainIDs":null},"adminAPIEnabled":true,"infoAPIEnabled":true,"keystoreAPIEnabled":false,"metricsAPIEnabled":true,"healthAPIEnabled":true},"httpHost":"127.0.0.1","httpPort":9652,"httpsEnabled":false,"apiAllowedOrigins":["*"],"shutdownTimeout":10000000000,"shutdownWait":0},"ipConfig":{"ip":{"ip":"127.0.0.1","port":9653},"ipResolutionFrequency":300000000000,"attemptedNATTraversal":false},"stakingConfig":{"uptimeRequirement":0.8,"minValidatorStake":2000000000000,"maxValidatorStake":3000000000000000,"minDelegatorStake":25000000000,"minDelegationFee":20000,"minStakeDuration":86400000000000,"maxStakeDuration":31536000000000000,"rewardConfig":{"maxConsumptionRate":120000,"minConsumptionRate":100000,"mintingPeriod":31536000000000000,"supplyCap":720000000000000000},"enableStaking":true,"disabledStakingWeight":100,"stakingKeyPath":"/tmp/network-runner-root-data_20230611_005034/node2/staking.key","stakingCertPath":"/tmp/network-runner-root-data_20230611_005034/node2/staking.crt","stakingSignerPath":"/tmp/network-runner-root-data_20230611_005034/node2/signer.key"},"txFeeConfig":{"txFee":1000000,"createAssetTxFee":1000000,"createSubnetTxFee":100000000,"transformSubnetTxFee":100000000,"createBlockchainTxFee":100000000,"addPrimaryNetworkValidatorFee":0,"addPrimaryNetworkDelegatorFee":0,"addSubnetValidatorFee":1000000,"addSubnetDelegatorFee":1000000},"stateSyncConfig":{"stateSyncIDs":null,"stateSyncIPs":null},"bootstrapConfig":{"retryBootstrap":true,"retryBootstrapWarnFrequency":50,"bootstrapBeaconConnectionTimeout":60000000000,"bootstrapAncestorsMaxContainersSent":2000,"bootstrapAncestorsMaxContainersReceived":2000,"bootstrapMaxTimeGetAncestors":50000000,"bootstrapIDs":["NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg"],"bootstrapIPs":[{"ip":"::1","port":9651}]},"databaseConfig":{"path":"/tmp/network-runner-root-data_20230611_005034/node2/db/network-1337","name":"leveldb"},"avaxAssetID":"BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC","networkID":1337,"healthCheckFreq":2000000000,"networkConfig":{"healthConfig":{"minConnectedPeers":1,"maxTimeSinceMsgReceived":60000000000,"maxTimeSinceMsgSent":60000000000,"maxPortionSendQueueBytesFull":0.9,"maxSendFailRate":0.9,"sendFailRateHalflife":10000000000},"peerListGossipConfig":{"peerListNumValidatorIPs":15,"peerListValidatorGossipSize":20,"peerListNonValidatorGossipSize":0,"peerListPeersGossipSize":10,"peerListGossipFreq":250000000},"timeoutConfigs":{"pingPongTimeout":30000000000,"readHandshakeTimeout":15000000000},"delayConfig":{"initialReconnectDelay":1000000000,"maxReconnectDelay":1000000000},"throttlerConfig":{"inboundConnUpgradeThrottlerConfig":{"upgradeCooldown":10000000000,"maxRecentConnsUpgraded":2560},"inboundMsgThrottlerConfig":{"byteThrottlerConfig":{"vdrAllocSize":10737418240,"atLargeAllocSize":10737418240,"nodeMaxAtLargeBytes":2097152},"bandwidthThrottlerConfig":{"bandwidthRefillRate":1073741824,"bandwidthMaxBurstRate":1073741824},"cpuThrottlerConfig":{"maxRecheckDelay":5000000000},"diskThrottlerConfig":{"maxRecheckDelay":5000000000},"maxProcessingMsgsPerNode":100000},"outboundMsgThrottlerConfig":{"vdrAllocSize":10737418240,"atLargeAllocSize":10737418240,"nodeMaxAtLargeBytes":2097152},"maxInboundConnsPerSec":256},"proxyEnabled":false,"proxyReadHeaderTimeout":3000000000,"dialerConfig":{"throttleRps":50,"connectionTimeout":30000000000},"tlsKeyLogFile":"","namespace":"","myNodeID":"NodeID-111111111111111111116DBWJs","myIP":null,"networkID":0,"maxClockDifference":60000000000,"pingFrequency":22500000000,"allowPrivateIPs":true,"compressionType":"none","uptimeMetricFreq":30000000000,"requireValidatorToConnect":false,"maximumInboundMessageTimeout":10000000000,"peerReadBufferSize":8192,"peerWriteBufferSize":8192},"adaptiveTimeoutConfig":{"initialTimeout":5000000000,"minimumTimeout":2000000000,"maximumTimeout":10000000000,"timeoutCoefficient":2,"timeoutHalflife":300000000000},"benchlistConfig":{"threshold":10,"minimumFailingDuration":150000000000,"duration":900000000000,"maxPortion":0.08333333333333333},"profilerConfig":{"dir":"/tmp/network-runner-root-data_20230611_005034/node2/profiles","enabled":false,"freq":900000000000,"maxNumFiles":5},"loggingConfig":{"maxSize":8,"maxFiles":7,"maxAge":0,"directory":"/tmp/network-runner-root-data_20230611_005034/node2/logs","compress":false,"disableWriterDisplaying":false,"logLevel":"DEBUG","displayLevel":"INFO","logFormat":"PLAIN"},"pluginDir":"/tmp/avalanchego-v1.10.1/plugins","fdLimit":32768,"meterVMEnabled":true,"routerHealthConfig":{"maxDropRate":1,"maxDropRateHalflife":10000000000,"maxOutstandingRequests":1024,"maxOutstandingDuration":300000000000,"maxRunTimeRequests":10000000000},"consensusShutdownTimeout":30000000000,"consensusGossipFreq":10000000000,"consensusAppConcurrency":512,"trackedSubnets":[],"subnetConfigs":{"11111111111111111111111111111111LpoYY":{"gossipAcceptedFrontierValidatorSize":0,"gossipAcceptedFrontierNonValidatorSize":0,"gossipAcceptedFrontierPeerSize":15,"gossipOnAcceptValidatorSize":10,"gossipOnAcceptNonValidatorSize":0,"gossipOnAcceptPeerSize":10,"appGossipValidatorSize":10,"appGossipNonValidatorSize":0,"appGossipPeerSize":0,"validatorOnly":false,"allowedNodes":null,"consensusParameters":{"k":20,"alpha":15,"betaVirtuous":20,"betaRogue":20,"concurrentRepolls":4,"optimalProcessing":10,"maxOutstandingItems":256,"maxItemProcessingTime":30000000000,"mixedQueryNumPushVdr":10,"mixedQueryNumPushNonVdr":0},"proposerMinBlockDelay":1000000000,"minPercentConnectedStakeHealthy":0}},"chainAliases":null,"systemTrackerProcessingHalflife":15000000000,"systemTrackerFrequency":500000000,"systemTrackerCPUHalflife":15000000000,"systemTrackerDiskHalflife":60000000000,"cpuTargeterConfig":{"vdrAlloc":100000,"maxNonVdrUsage":44.800000000000004,"maxNonVdrNodeUsage":7},"diskTargeterConfig":{"vdrAlloc":10737418240000,"maxNonVdrUsage":1073741824000,"maxNonVdrNodeUsage":1073741824000},"requiredAvailableDiskSpace":536870912,"warningThresholdAvailableDiskSpace":1073741824,"traceConfig":{"exporterConfig":{"type":"unknown","endpoint":"","headers":null,"insecure":false},"enabled":false,"traceSampleRate":0},"minPercentConnectedStakeHealthy":{"11111111111111111111111111111111LpoYY":0.8},"useCurrentHeight":true,"chainDataDir":"/tmp/network-runner-root-data_20230611_005034/node2/chainData"}}
-[0;0m[1;34m[node2] [06-11|00:50:35.426] INFO node/node.go:582 initializing API server
-[0;0m[1;34m[node2] [06-11|00:50:35.426] INFO server/server.go:147 API created {"allowedOrigins": ["*"]}
-[0;0m[1;34m[node2] [06-11|00:50:35.426] INFO node/node.go:912 initializing metrics API
-[0;0m[1;34m[node2] [06-11|00:50:35.426] INFO server/server.go:308 adding route {"url": "/ext/metrics", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.426] INFO leveldb/db.go:208 creating leveldb {"config": {"blockCacheCapacity":12582912,"blockSize":0,"compactionExpandLimitFactor":0,"compactionGPOverlapsFactor":0,"compactionL0Trigger":0,"compactionSourceLimitFactor":0,"compactionTableSize":0,"compactionTableSizeMultiplier":0,"compactionTableSizeMultiplierPerLevel":null,"compactionTotalSize":0,"compactionTotalSizeMultiplier":0,"disableSeeksCompaction":true,"openFilesCacheCapacity":1024,"writeBuffer":6291456,"filterBitsPerKey":10,"maxManifestFileSize":9223372036854775807,"metricUpdateFrequency":10000000000}}
-[0;0m[06-11|00:50:35.449] INFO local/network.go:587 adding node {"node-name": "node3", "node-dir": "/tmp/network-runner-root-data_20230611_005034/node3", "log-dir": "/tmp/network-runner-root-data_20230611_005034/node3/logs", "db-dir": "/tmp/network-runner-root-data_20230611_005034/node3/db", "p2p-port": 9655, "api-port": 9654}
-[06-11|00:50:35.449] DEBUG local/network.go:597 starting node {"name": "node3", "binaryPath": "/tmp/avalanchego-v1.10.1/avalanchego", "args": ["--index-enabled=true", "--bootstrap-ips=[::1]:9651,[::1]:9653", "--throttler-outbound-at-large-alloc-size=10737418240", "--throttler-inbound-node-max-processing-msgs=100000", "--health-check-frequency=2s", "--log-display-level=info", "--log-level=DEBUG", "--staking-port=9655", "--throttler-outbound-validator-alloc-size=10737418240", "--api-admin-enabled=true", "--genesis=/tmp/network-runner-root-data_20230611_005034/node3/genesis.json", "--network-compression-type=none", "--http-port=9654", "--proposervm-use-current-height=true", "--log-dir=/tmp/network-runner-root-data_20230611_005034/node3/logs", "--throttler-inbound-bandwidth-max-burst-size=1073741824", "--throttler-inbound-bandwidth-refill-rate=1073741824", "--network-peer-list-gossip-frequency=250ms", "--throttler-inbound-at-large-alloc-size=10737418240", "--bootstrap-ids=NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg,NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ", "--throttler-inbound-validator-alloc-size=10737418240", "--consensus-on-accept-gossip-validator-size=10", "--subnet-config-dir=/tmp/network-runner-root-data_20230611_005034/node3/subnetConfigs", "--db-dir=/tmp/network-runner-root-data_20230611_005034/node3/db", "--public-ip=127.0.0.1", "--snow-mixed-query-num-push-vdr=10", "--consensus-on-accept-gossip-peer-size=10", "--network-id=1337", "--staking-tls-cert-file=/tmp/network-runner-root-data_20230611_005034/node3/staking.crt", "--throttler-inbound-disk-validator-alloc=10737418240000", "--plugin-dir=/tmp/avalanchego-v1.10.1/plugins", "--chain-config-dir=/tmp/network-runner-root-data_20230611_005034/node3/chainConfigs", "--staking-tls-key-file=/tmp/network-runner-root-data_20230611_005034/node3/staking.key", "--data-dir=/tmp/network-runner-root-data_20230611_005034/node3", "--api-ipcs-enabled=true", "--throttler-inbound-cpu-validator-alloc=100000", "--staking-signer-key-file=/tmp/network-runner-root-data_20230611_005034/node3/signer.key", "--network-max-reconnect-delay=1s", "--consensus-app-concurrency=512"]}
-[1;34m[node2] [06-11|00:50:35.458] INFO node/node.go:452 initializing database {"dbVersion": "v1.4.5"}
-[0;0m[1;34m[node2] [06-11|00:50:35.458] INFO node/node.go:869 initializing keystore
-[0;0m[1;34m[node2] [06-11|00:50:35.458] INFO node/node.go:877 skipping keystore API initialization because it has been disabled
-[0;0m[1;34m[node2] [06-11|00:50:35.458] INFO node/node.go:861 initializing SharedMemory
-[0;0m[1;34m[node2] [06-11|00:50:35.481] INFO node/node.go:232 initializing networking {"currentNodeIP": "127.0.0.1:9653"}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO node/node.go:1032 initializing Health API
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/readiness"}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/health"}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/liveness"}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO node/node.go:642 adding the default VM aliases
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO node/node.go:763 initializing VMs
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/vm/rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/vm/jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.482] INFO server/server.go:308 adding route {"url": "/ext/vm/mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6", "endpoint": "/rpc"}
-[0;0m[1;34m[node2] [06-11|00:50:35.549] INFO subprocess/runtime.go:143 plugin handshake succeeded {"addr": "127.0.0.1:41317"}
-[0;0m[1;34m[node2] runtime engine: received shutdown signal: SIGTERM
-[0;0m[1;34m[node2] vm server: graceful termination success
-[0;0m[1;34m[node2] [06-11|00:50:35.556] INFO subprocess/runtime.go:124 stderr collector shutdown
-[0;0m[1;34m[node2] [06-11|00:50:35.556] INFO subprocess/runtime.go:111 stdout collector shutdown
-[0;0m[1;34m[node2] [06-11|00:50:35.622] INFO subprocess/runtime.go:143 plugin handshake succeeded {"addr": "127.0.0.1:40245"}
-[0;0m[1;34m[node2] [06-11|00:50:35.625] INFO node/node.go:935 initializing admin API
-[0;0m[1;34m[node2] [06-11|00:50:35.625] INFO server/server.go:308 adding route {"url": "/ext/admin", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.625] INFO node/node.go:984 initializing info API
-[0;0m[1;34m[node2] [06-11|00:50:35.627] INFO server/server.go:308 adding route {"url": "/ext/info", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.627] WARN node/node.go:1138 initializing deprecated ipc API
-[0;0m[1;34m[node2] [06-11|00:50:35.627] INFO server/server.go:308 adding route {"url": "/ext/ipcs", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.628] INFO node/node.go:1148 initializing chain aliases
-[0;0m[1;34m[node2] [06-11|00:50:35.628] INFO node/node.go:1175 initializing API aliases
-[0;0m[1;34m[node2] [06-11|00:50:35.628] INFO node/node.go:957 skipping profiler initialization because it has been disabled
-[0;0m[1;34m[node2] [06-11|00:50:35.628] INFO node/node.go:561 initializing chains
-[0;0m[1;34m[node2] [06-11|00:50:35.628] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "11111111111111111111111111111111LpoYY", "vmID": "rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT"}
-[0;0m[1;34m[node2] [06-11|00:50:35.630] INFO chains/manager.go:1102 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[1;34m[node2] [06-11|00:50:35.633] INFO platformvm/vm.go:228 initializing last accepted {"blkID": "2EYLCg5YdYRx9h3g3odqDB49o35ekw6NtXqJaom7pb3Rpvmonc"}
-[0;0m[1;34m[node2] [06-11|00:50:35.636] INFO
snowman/transitive.go:89 initializing consensus engine
-[0;0m[1;34m[node2] [06-11|00:50:35.637] INFO server/server.go:269 adding route {"url": "/ext/bc/11111111111111111111111111111111LpoYY", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.637] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.638] INFO server/server.go:308 adding route {"url": "/ext/index/P", "endpoint": "/block"}
-[0;0m[1;34m[node2] [06-11|00:50:35.638] INFO
bootstrap/bootstrapper.go:115 starting bootstrapper
-[0;0m[1;34m[node2] [06-11|00:50:35.638] INFO chains/manager.go:1338 starting chain creator
-[0;0m[1;34m[node2] [06-11|00:50:35.638] INFO server/server.go:184 HTTP API server listening {"host": "127.0.0.1", "port": 9652}
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:35.753] github.com/ava-labs/coreth/peer/network.go:486: adding new peer nodeID=NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ
-[0;0m[1;34m[node2] [06-11|00:50:35.755] INFO common/bootstrapper.go:244 bootstrapping started syncing {"numVerticesInFrontier": 1}
-[0;0m[1;34m[node2] [06-11|00:50:35.755] INFO
bootstrap/bootstrapper.go:554 executing blocks {"numPendingJobs": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.755] INFO
queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.755] INFO
bootstrap/bootstrapper.go:599 waiting for the remaining chains in this subnet to finish syncing
-[0;0m[1;34m[node2] [06-11|00:50:35.755] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "vmID": "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6"}
-[0;0m[1;34m[node2] [06-11|00:50:35.757] INFO chains/manager.go:1102 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.758] github.com/ava-labs/coreth/plugin/evm/vm.go:353: Initializing Coreth VM Version=v0.12.0 Config="{SnowmanAPIEnabled:false CorethAdminAPIEnabled:false CorethAdminAPIDir: EnabledEthAPIs:[eth eth-filter net web3 internal-eth internal-blockchain internal-transaction internal-account] ContinuousProfilerDir: ContinuousProfilerFrequency:15m0s ContinuousProfilerMaxFiles:5 RPCGasCap:50000000 RPCTxFeeCap:100 TrieCleanCache:512 TrieCleanJournal: TrieCleanRejournal:0s TrieDirtyCache:256 TrieDirtyCommitTarget:20 SnapshotCache:256 Preimages:false SnapshotAsync:true SnapshotVerify:false Pruning:true AcceptorQueueLimit:64 CommitInterval:4096 AllowMissingTries:false PopulateMissingTries: PopulateMissingTriesParallelism:1024 MetricsExpensiveEnabled:false LocalTxsEnabled:false TxPoolJournal:transactions.rlp TxPoolRejournal:1h0m0s TxPoolPriceLimit:1 TxPoolPriceBump:10 TxPoolAccountSlots:16 TxPoolGlobalSlots:5120 TxPoolAccountQueue:64 TxPoolGlobalQueue:1024 APIMaxDuration:0s WSCPURefillRate:0s WSCPUMaxStored:0s MaxBlocksPerRequest:0 AllowUnfinalizedQueries:false AllowUnprotectedTxs:false AllowUnprotectedTxHashes:[0xfefb2da535e927b85fe68eb81cb2e4a5827c905f78381a01ef2322aa9b0aee8e] KeystoreDirectory: KeystoreExternalSigner: KeystoreInsecureUnlockAllowed:false RemoteTxGossipOnlyEnabled:false TxRegossipFrequency:1m0s TxRegossipMaxSize:15 LogLevel:debug LogJSONFormat:false OfflinePruning:false OfflinePruningBloomFilterSize:512 OfflinePruningDataDirectory: MaxOutboundActiveRequests:16 MaxOutboundActiveCrossChainRequests:64 StateSyncEnabled: StateSyncSkipResume:false StateSyncServerTrieCache:64 StateSyncIDs: StateSyncCommitInterval:16384 StateSyncMinBlocks:300000 StateSyncRequestSize:1024 InspectDatabase:false SkipUpgradeCheck:false AcceptedCacheSize:32 TxLookupLimit:0}"
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.760] github.com/ava-labs/coreth/trie/database.go:735: Persisted trie from memory database nodes=1 size=151.00B time="13.075µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.760] github.com/ava-labs/coreth/plugin/evm/vm.go:429: lastAccepted = 0xb81c22ceb61ecbb2efaaf4199f82a7c870850b45f41cc9490edf0e06be0e6bb9
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:35.760] github.com/ava-labs/coreth/accounts/keystore/file_cache.go:100: FS scan times list="41.334µs" set=929ns diff="1.51µs"
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.760] github.com/ava-labs/coreth/eth/backend.go:134: Allocated memory caches trie clean=512.00MiB trie dirty=256.00MiB snapshot clean=256.00MiB
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.760] github.com/ava-labs/coreth/eth/backend.go:171: Initialising Ethereum protocol network=43112 dbversion=
-[0;0m[1;34m[node2] WARN [06-11|00:50:35.760] github.com/ava-labs/coreth/eth/backend.go:177: Upgrade blockchain database version from= to=8
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.760] github.com/ava-labs/coreth/core/genesis.go:176: Writing genesis to database
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.761] github.com/ava-labs/coreth/trie/database.go:735: Persisted trie from memory database nodes=1 size=151.00B time="39.98µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.761] github.com/ava-labs/coreth/core/blockchain.go:306:
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.761] github.com/ava-labs/coreth/core/blockchain.go:307: ---------------------------------------------------------------------------------------------------------------------------------------------------------
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.761] github.com/ava-labs/coreth/core/blockchain.go:309: Chain ID: 43112
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: Consensus: Dummy Consensus Engine
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: Hard Forks:
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Homestead: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - DAO Fork: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Tangerine Whistle (EIP 150): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Spurious Dragon/1 (EIP 155): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Spurious Dragon/2 (EIP 158): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Byzantium: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Constantinople: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Petersburg: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Istanbul: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Muir Glacier: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 1 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.3.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 2 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.4.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 3 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.5.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 4 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.6.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 5 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase P6 Timestamp 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 6 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase Post-6 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Banff Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.9.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - Cortina Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.10.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309: - DUpgrade Timestamp (https://github.com/ava-labs/avalanchego/releases/tag/v1.11.0)
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:311: ---------------------------------------------------------------------------------------------------------------------------------------------------------
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.762] github.com/ava-labs/coreth/core/blockchain.go:312:
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.764] github.com/ava-labs/coreth/core/blockchain.go:710: Loaded most recent local header number=0 hash=b81c22..0e6bb9 age=54y2mo2w
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.764] github.com/ava-labs/coreth/core/blockchain.go:711: Loaded most recent local full block number=0 hash=b81c22..0e6bb9 age=54y2mo2w
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.764] github.com/ava-labs/coreth/core/blockchain.go:1722: Loaded Acceptor tip hash=000000..000000
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.764] github.com/ava-labs/coreth/core/blockchain.go:1730: Skipping state reprocessing root=3cbfcc..68c8b4
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.764] github.com/ava-labs/coreth/core/blockchain.go:544: Not warming accepted cache because there are no accepted blocks
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.764] github.com/ava-labs/coreth/core/blockchain.go:567: Starting Acceptor queue length=64
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:35.764] github.com/ava-labs/coreth/core/tx_pool.go:1408: Reinjecting stale transactions count=0
-[0;0m[1;34m[node2] WARN [06-11|00:50:35.765] github.com/ava-labs/coreth/core/rawdb/accessors_metadata.go:111: Error reading unclean shutdown markers error="not found"
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.765] github.com/ava-labs/coreth/core/tx_pool.go:505: Transaction pool price threshold updated price=470,000,000,000
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.765] github.com/ava-labs/coreth/core/tx_pool.go:505: Transaction pool price threshold updated price=225,000,000,000
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.765] github.com/ava-labs/coreth/core/tx_pool.go:505: Transaction pool price threshold updated price=0
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.765] github.com/ava-labs/coreth/plugin/evm/atomic_tx_repository.go:115: Initializing atomic transaction repository from scratch
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.765] github.com/ava-labs/coreth/plugin/evm/atomic_tx_repository.go:191: Completed atomic transaction repository migration lastAcceptedHeight=0 duration="131.722µs"
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.766] github.com/ava-labs/coreth/plugin/evm/atomic_tx_repository.go:438: atomic tx repository RepairForBonusBlocks complete repairedEntries=0
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.766] github.com/ava-labs/coreth/plugin/evm/atomic_backend.go:132: initializing atomic trie lastCommittedHeight=0
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.766] github.com/ava-labs/coreth/plugin/evm/atomic_backend.go:210: finished initializing atomic trie lastAcceptedHeight=0 lastAcceptedAtomicRoot=56e81f..63b421 heightsIndexed=0 lastCommittedRoot=56e81f..63b421 lastCommittedHeight=0 time="64.664µs"
-[0;0m[1;34m[node2] [06-11|00:50:35.767] INFO proposervm/vm.go:356 block height index was successfully verified
-[0;0m[1;34m[node2] [06-11|00:50:35.771] INFO snowman/transitive.go:89 initializing consensus engine
-[0;0m[1;34m[node2] INFO [06-11|00:50:35.772] github.com/ava-labs/coreth/plugin/evm/vm.go:1171: Enabled APIs: eth, eth-filter, net, web3, internal-eth, internal-blockchain, internal-transaction, internal-account, avax
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:35.772] github.com/ava-labs/coreth/rpc/websocket.go:104: Allowed origin(s) for WS RPC interface [*]
-[0;0m[1;34m[node2] [06-11|00:50:35.773] INFO server/server.go:269 adding route {"url": "/ext/bc/23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "endpoint": "/avax"}
-[0;0m[1;34m[node2] [06-11|00:50:35.773] INFO server/server.go:269 adding route {"url": "/ext/bc/23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "endpoint": "/rpc"}
-[0;0m[1;34m[node2] [06-11|00:50:35.773] INFO server/server.go:269 adding route {"url": "/ext/bc/23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "endpoint": "/ws"}
-[0;0m[1;34m[node2] [06-11|00:50:35.773] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.773] INFO server/server.go:308 adding route {"url": "/ext/index/C", "endpoint": "/block"}
-[0;0m[1;34m[node2] [06-11|00:50:35.774] INFO syncer/state_syncer.go:385 starting state sync
-[0;0m[1;34m[node2] [06-11|00:50:35.774] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "vmID": "jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq"}
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:35.774] github.com/ava-labs/coreth/peer/network.go:486: adding new peer nodeID=NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:35.774] github.com/ava-labs/coreth/peer/network.go:496: skipping registering self as peer
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:35.774] github.com/ava-labs/coreth/peer/network.go:486: adding new peer nodeID=NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg
-[0;0m[1;34m[node2] [06-11|00:50:35.777] INFO avm/vm.go:636 initializing genesis asset {"txID": "BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC"}
-[0;0m[1;34m[node2] [06-11|00:50:35.777] INFO avm/vm.go:619 fee asset is established {"alias": "AVAX", "assetID": "BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC"}
-[0;0m[1;34m[node2] [06-11|00:50:35.777] INFO avm/vm.go:275 address transaction indexing is disabled
-[0;0m[1;34m[node2] [06-11|00:50:35.778] INFO chains/manager.go:756 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[1;34m[node2] [06-11|00:50:35.782] INFO snowman/transitive.go:89 initializing consensus engine
-[0;0m[1;34m[node2] [06-11|00:50:35.783] INFO server/server.go:269 adding route {"url": "/ext/bc/qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "endpoint": ""}
-[0;0m[1;34m[node2] [06-11|00:50:35.783] INFO server/server.go:269 adding route {"url": "/ext/bc/qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "endpoint": "/wallet"}
-[0;0m[1;34m[node2] [06-11|00:50:35.783] INFO server/server.go:269 adding route {"url": "/ext/bc/qzfF3A11KzpcHkkqznEyQgupQrCNS6WV6fTUTwZpEKqhj1QE7", "endpoint": "/events"}
-[0;0m[1;34m[node2] [06-11|00:50:35.783] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.783] INFO server/server.go:308 adding route {"url": "/ext/index/X", "endpoint": "/block"}
-[0;0m[1;34m[node2] [06-11|00:50:35.784] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.784] INFO server/server.go:308 adding route {"url": "/ext/index/X", "endpoint": "/vtx"}
-[0;0m[1;34m[node2] [06-11|00:50:35.784] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.784] INFO server/server.go:308 adding route {"url": "/ext/index/X", "endpoint": "/tx"}
-[0;0m[1;34m[node2] [06-11|00:50:35.784] INFO bootstrap/bootstrapper.go:290 starting bootstrap
-[0;0m[1;34m[node2] [06-11|00:50:35.784] INFO bootstrap/bootstrapper.go:347 accepted stop vertex {"vtxID": "sj8adpSGCc7k7aWFNkiugYvUSHGq9xUvJPb8VzdVPXv9u2b5X"}
-[0;0m[1;34m[node2] [06-11|00:50:35.785] INFO bootstrap/bootstrapper.go:571 executing transactions
-[0;0m[1;34m[node2] [06-11|00:50:35.785] INFO queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.785] INFO bootstrap/bootstrapper.go:588 executing vertices
-[0;0m[1;34m[node2] [06-11|00:50:35.785] INFO queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[1;34m[node2] [06-11|00:50:35.786] INFO bootstrap/bootstrapper.go:115 starting bootstrapper
-[0;0m[0;37m[node3] [06-11|00:50:35.793] WARN app/app.go:153 P2P IP is private, you will not be publicly discoverable {"ip": "127.0.0.1"}
-[0;0m[0;37m[node3] [06-11|00:50:35.794] INFO node/node.go:1251 initializing node {"version": "avalanche/1.10.1", "nodeID": "NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN", "nodePOP": {"publicKey":"0xb20ab07ea5cf8b77ab50f2071a6f1d2aab693c8bd89761430cd29de9fa0dbae83a32c7697d59ff1b06995b1596c16fa6","proofOfPossession":"0xa113145564d7ac540fade2526938fbd33233957901111328c86c4cbe7ed25f678173d95c54b3342fd7b723c3ed813f2b04fecf4a317205ce65638bb34bb58bb6746e74c63e6cbe5cb25c103b290ed270146b756d3901c8b0f99d083a44572c79"}, "providedFlags": {"api-admin-enabled":true,"api-ipcs-enabled":true,"bootstrap-ids":"NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg,NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ","bootstrap-ips":"[::1]:9651,[::1]:9653","chain-config-dir":"/tmp/network-runner-root-data_20230611_005034/node3/chainConfigs","consensus-app-concurrency":"512","consensus-on-accept-gossip-peer-size":"10","consensus-on-accept-gossip-validator-size":"10","data-dir":"/tmp/network-runner-root-data_20230611_005034/node3","db-dir":"/tmp/network-runner-root-data_20230611_005034/node3/db","genesis":"/tmp/network-runner-root-data_20230611_005034/node3/genesis.json","health-check-frequency":"2s","http-port":"9654","index-enabled":true,"log-dir":"/tmp/network-runner-root-data_20230611_005034/node3/logs","log-display-level":"info","log-level":"DEBUG","network-compression-type":"none","network-id":"1337","network-max-reconnect-delay":"1s","network-peer-list-gossip-frequency":"250ms","plugin-dir":"/tmp/avalanchego-v1.10.1/plugins","proposervm-use-current-height":true,"public-ip":"127.0.0.1","snow-mixed-query-num-push-vdr":"10","staking-port":"9655","staking-signer-key-file":"/tmp/network-runner-root-data_20230611_005034/node3/signer.key","staking-tls-cert-file":"/tmp/network-runner-root-data_20230611_005034/node3/staking.crt","staking-tls-key-file":"/tmp/network-runner-root-data_20230611_005034/node3/staking.key","subnet-config-dir":"/tmp/network-runner-root-data_20230611_005034/node3/subnetConfigs","throttler-inbound-at-large-alloc-size":"10737418240","throttler-inbound-bandwidth-max-burst-size":"1073741824","throttler-inbound-bandwidth-refill-rate":"1073741824","throttler-inbound-cpu-validator-alloc":"100000","throttler-inbound-disk-validator-alloc":"1.073741824e+13","throttler-inbound-node-max-processing-msgs":"100000","throttler-inbound-validator-alloc-size":"10737418240","throttler-outbound-at-large-alloc-size":"10737418240","throttler-outbound-validator-alloc-size":"10737418240"}, "config": {"httpConfig":{"readTimeout":30000000000,"readHeaderTimeout":30000000000,"writeHeaderTimeout":30000000000,"idleTimeout":120000000000,"apiConfig":{"authConfig":{"apiRequireAuthToken":false},"indexerConfig":{"indexAPIEnabled":true,"indexAllowIncomplete":false},"ipcConfig":{"ipcAPIEnabled":true,"ipcPath":"/tmp","ipcDefaultChainIDs":null},"adminAPIEnabled":true,"infoAPIEnabled":true,"keystoreAPIEnabled":false,"metricsAPIEnabled":true,"healthAPIEnabled":true},"httpHost":"127.0.0.1","httpPort":9654,"httpsEnabled":false,"apiAllowedOrigins":["*"],"shutdownTimeout":10000000000,"shutdownWait":0},"ipConfig":{"ip":{"ip":"127.0.0.1","port":9655},"ipResolutionFrequency":300000000000,"attemptedNATTraversal":false},"stakingConfig":{"uptimeRequirement":0.8,"minValidatorStake":2000000000000,"maxValidatorStake":3000000000000000,"minDelegatorStake":25000000000,"minDelegationFee":20000,"minStakeDuration":86400000000000,"maxStakeDuration":31536000000000000,"rewardConfig":{"maxConsumptionRate":120000,"minConsumptionRate":100000,"mintingPeriod":31536000000000000,"supplyCap":720000000000000000},"enableStaking":true,"disabledStakingWeight":100,"stakingKeyPath":"/tmp/network-runner-root-data_20230611_005034/node3/staking.key","stakingCertPath":"/tmp/network-runner-root-data_20230611_005034/node3/staking.crt","stakingSignerPath":"/tmp/network-runner-root-data_20230611_005034/node3/signer.key"},"txFeeConfig":{"txFee":1000000,"createAssetTxFee":1000000,"createSubnetTxFee":100000000,"transformSubnetTxFee":100000000,"createBlockchainTxFee":100000000,"addPrimaryNetworkValidatorFee":0,"addPrimaryNetworkDelegatorFee":0,"addSubnetValidatorFee":1000000,"addSubnetDelegatorFee":1000000},"stateSyncConfig":{"stateSyncIDs":null,"stateSyncIPs":null},"bootstrapConfig":{"retryBootstrap":true,"retryBootstrapWarnFrequency":50,"bootstrapBeaconConnectionTimeout":60000000000,"bootstrapAncestorsMaxContainersSent":2000,"bootstrapAncestorsMaxContainersReceived":2000,"bootstrapMaxTimeGetAncestors":50000000,"bootstrapIDs":["NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg","NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ"],"bootstrapIPs":[{"ip":"::1","port":9651},{"ip":"::1","port":9653}]},"databaseConfig":{"path":"/tmp/network-runner-root-data_20230611_005034/node3/db/network-1337","name":"leveldb"},"avaxAssetID":"BUuypiq2wyuLMvyhzFXcPyxPMCgSp7eeDohhQRqTChoBjKziC","networkID":1337,"healthCheckFreq":2000000000,"networkConfig":{"healthConfig":{"minConnectedPeers":1,"maxTimeSinceMsgReceived":60000000000,"maxTimeSinceMsgSent":60000000000,"maxPortionSendQueueBytesFull":0.9,"maxSendFailRate":0.9,"sendFailRateHalflife":10000000000},"peerListGossipConfig":{"peerListNumValidatorIPs":15,"peerListValidatorGossipSize":20,"peerListNonValidatorGossipSize":0,"peerListPeersGossipSize":10,"peerListGossipFreq":250000000},"timeoutConfigs":{"pingPongTimeout":30000000000,"readHandshakeTimeout":15000000000},"delayConfig":{"initialReconnectDelay":1000000000,"maxReconnectDelay":1000000000},"throttlerConfig":{"inboundConnUpgradeThrottlerConfig":{"upgradeCooldown":10000000000,"maxRecentConnsUpgraded":2560},"inboundMsgThrottlerConfig":{"byteThrottlerConfig":{"vdrAllocSize":10737418240,"atLargeAllocSize":10737418240,"nodeMaxAtLargeBytes":2097152},"bandwidthThrottlerConfig":{"bandwidthRefillRate":1073741824,"bandwidthMaxBurstRate":1073741824},"cpuThrottlerConfig":{"maxRecheckDelay":5000000000},"diskThrottlerConfig":{"maxRecheckDelay":5000000000},"maxProcessingMsgsPerNode":100000},"outboundMsgThrottlerConfig":{"vdrAllocSize":10737418240,"atLargeAllocSize":10737418240,"nodeMaxAtLargeBytes":2097152},"maxInboundConnsPerSec":256},"proxyEnabled":false,"proxyReadHeaderTimeout":3000000000,"dialerConfig":{"throttleRps":50,"connectionTimeout":30000000000},"tlsKeyLogFile":"","namespace":"","myNodeID":"NodeID-111111111111111111116DBWJs","myIP":null,"networkID":0,"maxClockDifference":60000000000,"pingFrequency":22500000000,"allowPrivateIPs":true,"compressionType":"none","uptimeMetricFreq":30000000000,"requireValidatorToConnect":false,"maximumInboundMessageTimeout":10000000000,"peerReadBufferSize":8192,"peerWriteBufferSize":8192},"adaptiveTimeoutConfig":{"initialTimeout":5000000000,"minimumTimeout":2000000000,"maximumTimeout":10000000000,"timeoutCoefficient":2,"timeoutHalflife":300000000000},"benchlistConfig":{"threshold":10,"minimumFailingDuration":150000000000,"duration":900000000000,"maxPortion":0.08333333333333333},"profilerConfig":{"dir":"/tmp/network-runner-root-data_20230611_005034/node3/profiles","enabled":false,"freq":900000000000,"maxNumFiles":5},"loggingConfig":{"maxSize":8,"maxFiles":7,"maxAge":0,"directory":"/tmp/network-runner-root-data_20230611_005034/node3/logs","compress":false,"disableWriterDisplaying":false,"logLevel":"DEBUG","displayLevel":"INFO","logFormat":"PLAIN"},"pluginDir":"/tmp/avalanchego-v1.10.1/plugins","fdLimit":32768,"meterVMEnabled":true,"routerHealthConfig":{"maxDropRate":1,"maxDropRateHalflife":10000000000,"maxOutstandingRequests":1024,"maxOutstandingDuration":300000000000,"maxRunTimeRequests":10000000000},"consensusShutdownTimeout":30000000000,"consensusGossipFreq":10000000000,"consensusAppConcurrency":512,"trackedSubnets":[],"subnetConfigs":{"11111111111111111111111111111111LpoYY":{"gossipAcceptedFrontierValidatorSize":0,"gossipAcceptedFrontierNonValidatorSize":0,"gossipAcceptedFrontierPeerSize":15,"gossipOnAcceptValidatorSize":10,"gossipOnAcceptNonValidatorSize":0,"gossipOnAcceptPeerSize":10,"appGossipValidatorSize":10,"appGossipNonValidatorSize":0,"appGossipPeerSize":0,"validatorOnly":false,"allowedNodes":null,"consensusParameters":{"k":20,"alpha":15,"betaVirtuous":20,"betaRogue":20,"concurrentRepolls":4,"optimalProcessing":10,"maxOutstandingItems":256,"maxItemProcessingTime":30000000000,"mixedQueryNumPushVdr":10,"mixedQueryNumPushNonVdr":0},"proposerMinBlockDelay":1000000000,"minPercentConnectedStakeHealthy":0}},"chainAliases":null,"systemTrackerProcessingHalflife":15000000000,"systemTrackerFrequency":500000000,"systemTrackerCPUHalflife":15000000000,"systemTrackerDiskHalflife":60000000000,"cpuTargeterConfig":{"vdrAlloc":100000,"maxNonVdrUsage":44.800000000000004,"maxNonVdrNodeUsage":7},"diskTargeterConfig":{"vdrAlloc":10737418240000,"maxNonVdrUsage":1073741824000,"maxNonVdrNodeUsage":1073741824000},"requiredAvailableDiskSpace":536870912,"warningThresholdAvailableDiskSpace":1073741824,"traceConfig":{"exporterConfig":{"type":"unknown","endpoint":"","headers":null,"insecure":false},"enabled":false,"traceSampleRate":0},"minPercentConnectedStakeHealthy":{"11111111111111111111111111111111LpoYY":0.8},"useCurrentHeight":true,"chainDataDir":"/tmp/network-runner-root-data_20230611_005034/node3/chainData"}}
-[0;0m[0;37m[node3] [06-11|00:50:35.794] INFO node/node.go:582 initializing API server
-[0;0m[0;37m[node3] [06-11|00:50:35.794] INFO server/server.go:147 API created {"allowedOrigins": ["*"]}
-[0;0m[0;37m[node3] [06-11|00:50:35.795] INFO node/node.go:912 initializing metrics API
-[0;0m[0;37m[node3] [06-11|00:50:35.795] INFO server/server.go:308 adding route {"url": "/ext/metrics", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.795] INFO leveldb/db.go:208 creating leveldb {"config": {"blockCacheCapacity":12582912,"blockSize":0,"compactionExpandLimitFactor":0,"compactionGPOverlapsFactor":0,"compactionL0Trigger":0,"compactionSourceLimitFactor":0,"compactionTableSize":0,"compactionTableSizeMultiplier":0,"compactionTableSizeMultiplierPerLevel":null,"compactionTotalSize":0,"compactionTotalSizeMultiplier":0,"disableSeeksCompaction":true,"openFilesCacheCapacity":1024,"writeBuffer":6291456,"filterBitsPerKey":10,"maxManifestFileSize":9223372036854775807,"metricUpdateFrequency":10000000000}}
-[0;0m[0;37m[node3] [06-11|00:50:35.814] INFO node/node.go:452 initializing database {"dbVersion": "v1.4.5"}
-[0;0m[0;37m[node3] [06-11|00:50:35.814] INFO node/node.go:869 initializing keystore
-[0;0m[0;37m[node3] [06-11|00:50:35.814] INFO node/node.go:877 skipping keystore API initialization because it has been disabled
-[0;0m[0;37m[node3] [06-11|00:50:35.814] INFO node/node.go:861 initializing SharedMemory
-[0;0m[0;37m[node3] [06-11|00:50:35.818] INFO node/node.go:232 initializing networking {"currentNodeIP": "127.0.0.1:9655"}
-[0;0m[0;37m[node3] [06-11|00:50:35.819] INFO node/node.go:1032 initializing Health API
-[0;0m[0;37m[node3] [06-11|00:50:35.820] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.820] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/readiness"}
-[0;0m[0;37m[node3] [06-11|00:50:35.820] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/health"}
-[0;0m[0;37m[node3] [06-11|00:50:35.820] INFO server/server.go:308 adding route {"url": "/ext/health", "endpoint": "/liveness"}
-[0;0m[0;37m[node3] [06-11|00:50:35.820] INFO node/node.go:642 adding the default VM aliases
-[0;0m[0;37m[node3] [06-11|00:50:35.821] INFO node/node.go:763 initializing VMs
-[0;0m[0;37m[node3] [06-11|00:50:35.821] INFO server/server.go:308 adding route {"url": "/ext/vm/rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.821] INFO server/server.go:308 adding route {"url": "/ext/vm/jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.821] INFO server/server.go:308 adding route {"url": "/ext/vm/mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6", "endpoint": "/rpc"}
-[0;0m[06-11|00:50:35.823] INFO local/network.go:587 adding node {"node-name": "node4", "node-dir": "/tmp/network-runner-root-data_20230611_005034/node4", "log-dir": "/tmp/network-runner-root-data_20230611_005034/node4/logs", "db-dir": "/tmp/network-runner-root-data_20230611_005034/node4/db", "p2p-port": 9657, "api-port": 9656}
-[06-11|00:50:35.824] DEBUG local/network.go:597 starting node {"name": "node4", "binaryPath": "/tmp/avalanchego-v1.10.1/avalanchego", "args": ["--http-port=9656", "--staking-signer-key-file=/tmp/network-runner-root-data_20230611_005034/node4/signer.key", "--bootstrap-ids=NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg,NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ,NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN", "--throttler-outbound-validator-alloc-size=10737418240", "--network-id=1337", "--throttler-outbound-at-large-alloc-size=10737418240", "--staking-port=9657", "--plugin-dir=/tmp/avalanchego-v1.10.1/plugins", "--api-ipcs-enabled=true", "--throttler-inbound-bandwidth-refill-rate=1073741824", "--db-dir=/tmp/network-runner-root-data_20230611_005034/node4/db", "--bootstrap-ips=[::1]:9651,[::1]:9653,[::1]:9655", "--throttler-inbound-node-max-processing-msgs=100000", "--staking-tls-cert-file=/tmp/network-runner-root-data_20230611_005034/node4/staking.crt", "--staking-tls-key-file=/tmp/network-runner-root-data_20230611_005034/node4/staking.key", "--chain-config-dir=/tmp/network-runner-root-data_20230611_005034/node4/chainConfigs", "--network-compression-type=none", "--log-display-level=info", "--throttler-inbound-cpu-validator-alloc=100000", "--public-ip=127.0.0.1", "--consensus-app-concurrency=512", "--genesis=/tmp/network-runner-root-data_20230611_005034/node4/genesis.json", "--data-dir=/tmp/network-runner-root-data_20230611_005034/node4", "--network-max-reconnect-delay=1s", "--snow-mixed-query-num-push-vdr=10", "--throttler-inbound-validator-alloc-size=10737418240", "--network-peer-list-gossip-frequency=250ms", "--subnet-config-dir=/tmp/network-runner-root-data_20230611_005034/node4/subnetConfigs", "--api-admin-enabled=true", "--index-enabled=true", "--throttler-inbound-bandwidth-max-burst-size=1073741824", "--throttler-inbound-disk-validator-alloc=10737418240000", "--consensus-on-accept-gossip-validator-size=10", "--log-dir=/tmp/network-runner-root-data_20230611_005034/node4/logs", "--health-check-frequency=2s", "--consensus-on-accept-gossip-peer-size=10", "--throttler-inbound-at-large-alloc-size=10737418240", "--proposervm-use-current-height=true", "--log-level=DEBUG"]}
-[0;37m[node3] [06-11|00:50:35.910] INFO subprocess/runtime.go:143 plugin handshake succeeded {"addr": "127.0.0.1:46279"}
-[0;0m[0;37m[node3] runtime engine: received shutdown signal: SIGTERM
-[0;0m[0;37m[node3] vm server: graceful termination success
-[0;0m[0;37m[node3] [06-11|00:50:35.916] INFO subprocess/runtime.go:111 stdout collector shutdown
-[0;0m[0;37m[node3] [06-11|00:50:35.916] INFO subprocess/runtime.go:124 stderr collector shutdown
-[0;0m[0;37m[node3] [06-11|00:50:35.992] INFO subprocess/runtime.go:143 plugin handshake succeeded {"addr": "127.0.0.1:33507"}
-[0;0m[0;37m[node3] [06-11|00:50:35.994] INFO node/node.go:935 initializing admin API
-[0;0m[0;37m[node3] [06-11|00:50:35.995] INFO server/server.go:308 adding route {"url": "/ext/admin", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.995] INFO node/node.go:984 initializing info API
-[0;0m[0;37m[node3] [06-11|00:50:35.997] INFO server/server.go:308 adding route {"url": "/ext/info", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.997] WARN node/node.go:1138 initializing deprecated ipc API
-[0;0m[0;37m[node3] [06-11|00:50:35.997] INFO server/server.go:308 adding route {"url": "/ext/ipcs", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:35.997] INFO node/node.go:1148 initializing chain aliases
-[0;0m[0;37m[node3] [06-11|00:50:35.997] INFO node/node.go:1175 initializing API aliases
-[0;0m[0;37m[node3] [06-11|00:50:35.998] INFO node/node.go:957 skipping profiler initialization because it has been disabled
-[0;0m[0;37m[node3] [06-11|00:50:35.998] INFO node/node.go:561 initializing chains
-[0;0m[0;37m[node3] [06-11|00:50:35.998] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "11111111111111111111111111111111LpoYY", "vmID": "rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT"}
-[0;0m[0;37m[node3] [06-11|00:50:36.000] INFO chains/manager.go:1102 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[0;37m[node3] [06-11|00:50:36.003] INFO platformvm/vm.go:228 initializing last accepted {"blkID": "2EYLCg5YdYRx9h3g3odqDB49o35ekw6NtXqJaom7pb3Rpvmonc"}
-[0;0m[0;37m[node3] [06-11|00:50:36.005] INFO
snowman/transitive.go:89 initializing consensus engine
-[0;0m[0;37m[node3] [06-11|00:50:36.006] INFO server/server.go:269 adding route {"url": "/ext/bc/11111111111111111111111111111111LpoYY", "endpoint": ""}
-[0;0m[0;37m[node3] [06-11|00:50:36.006] INFO indexer/index.go:100 created new index {"nextAcceptedIndex": 0}
-[0;0m[0;37m[node3] [06-11|00:50:36.006] INFO server/server.go:308 adding route {"url": "/ext/index/P", "endpoint": "/block"}
-[0;0m[0;37m[node3] [06-11|00:50:36.007] INFO
bootstrap/bootstrapper.go:115 starting bootstrapper
-[0;0m[0;37m[node3] [06-11|00:50:36.007] INFO chains/manager.go:1338 starting chain creator
-[0;0m[0;37m[node3] [06-11|00:50:36.007] INFO server/server.go:184 HTTP API server listening {"host": "127.0.0.1", "port": 9654}
-[0;0m[1;34m[node2] DEBUG[06-11|00:50:36.110] github.com/ava-labs/coreth/peer/network.go:486: adding new peer nodeID=NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN
-[0;0m[0;36m[node1] DEBUG[06-11|00:50:36.114] github.com/ava-labs/coreth/peer/network.go:486: adding new peer nodeID=NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN
-[0;0m[0;37m[node3] [06-11|00:50:36.116] INFO common/bootstrapper.go:244 bootstrapping started syncing {"numVerticesInFrontier": 1}
-[0;0m[0;37m[node3] [06-11|00:50:36.117] INFO
bootstrap/bootstrapper.go:554 executing blocks {"numPendingJobs": 0}
-[0;0m[0;37m[node3] [06-11|00:50:36.117] INFO
queue/jobs.go:224 executed operations {"numExecuted": 0}
-[0;0m[0;37m[node3] [06-11|00:50:36.117] INFO
bootstrap/bootstrapper.go:599 waiting for the remaining chains in this subnet to finish syncing
-[0;0m[0;37m[node3] [06-11|00:50:36.117] INFO chains/manager.go:319 creating chain {"subnetID": "11111111111111111111111111111111LpoYY", "chainID": "23JVJWr6QVJi91LuVNh8e2Cpd4vFe9ApVBzJf5yfq8hAFnd76Z", "vmID": "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6"}
-[0;0m[0;37m[node3] [06-11|00:50:36.118] INFO chains/manager.go:1102 creating proposervm wrapper {"activationTime": "[12-05|05:00:00.000]", "minPChainHeight": 0, "minBlockDelay": "1s"}
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.119] github.com/ava-labs/coreth/plugin/evm/vm.go:353: Initializing Coreth VM Version=v0.12.0 Config="{SnowmanAPIEnabled:false CorethAdminAPIEnabled:false CorethAdminAPIDir: EnabledEthAPIs:[eth eth-filter net web3 internal-eth internal-blockchain internal-transaction internal-account] ContinuousProfilerDir: ContinuousProfilerFrequency:15m0s ContinuousProfilerMaxFiles:5 RPCGasCap:50000000 RPCTxFeeCap:100 TrieCleanCache:512 TrieCleanJournal: TrieCleanRejournal:0s TrieDirtyCache:256 TrieDirtyCommitTarget:20 SnapshotCache:256 Preimages:false SnapshotAsync:true SnapshotVerify:false Pruning:true AcceptorQueueLimit:64 CommitInterval:4096 AllowMissingTries:false PopulateMissingTries: PopulateMissingTriesParallelism:1024 MetricsExpensiveEnabled:false LocalTxsEnabled:false TxPoolJournal:transactions.rlp TxPoolRejournal:1h0m0s TxPoolPriceLimit:1 TxPoolPriceBump:10 TxPoolAccountSlots:16 TxPoolGlobalSlots:5120 TxPoolAccountQueue:64 TxPoolGlobalQueue:1024 APIMaxDuration:0s WSCPURefillRate:0s WSCPUMaxStored:0s MaxBlocksPerRequest:0 AllowUnfinalizedQueries:false AllowUnprotectedTxs:false AllowUnprotectedTxHashes:[0xfefb2da535e927b85fe68eb81cb2e4a5827c905f78381a01ef2322aa9b0aee8e] KeystoreDirectory: KeystoreExternalSigner: KeystoreInsecureUnlockAllowed:false RemoteTxGossipOnlyEnabled:false TxRegossipFrequency:1m0s TxRegossipMaxSize:15 LogLevel:debug LogJSONFormat:false OfflinePruning:false OfflinePruningBloomFilterSize:512 OfflinePruningDataDirectory: MaxOutboundActiveRequests:16 MaxOutboundActiveCrossChainRequests:64 StateSyncEnabled: StateSyncSkipResume:false StateSyncServerTrieCache:64 StateSyncIDs: StateSyncCommitInterval:16384 StateSyncMinBlocks:300000 StateSyncRequestSize:1024 InspectDatabase:false SkipUpgradeCheck:false AcceptedCacheSize:32 TxLookupLimit:0}"
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.121] github.com/ava-labs/coreth/trie/database.go:735: Persisted trie from memory database nodes=1 size=151.00B time="22.274µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.121] github.com/ava-labs/coreth/plugin/evm/vm.go:429: lastAccepted = 0xb81c22ceb61ecbb2efaaf4199f82a7c870850b45f41cc9490edf0e06be0e6bb9
-[0;0m[0;37m[node3] DEBUG[06-11|00:50:36.121] github.com/ava-labs/coreth/accounts/keystore/file_cache.go:100: FS scan times list="34.386µs" set=872ns diff="6.771µs"
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.121] github.com/ava-labs/coreth/eth/backend.go:134: Allocated memory caches trie clean=512.00MiB trie dirty=256.00MiB snapshot clean=256.00MiB
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.121] github.com/ava-labs/coreth/eth/backend.go:171: Initialising Ethereum protocol network=43112 dbversion=
-[0;0m[0;37m[node3] WARN [06-11|00:50:36.121] github.com/ava-labs/coreth/eth/backend.go:177: Upgrade blockchain database version from= to=8
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.121] github.com/ava-labs/coreth/core/genesis.go:176: Writing genesis to database
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/trie/database.go:735: Persisted trie from memory database nodes=1 size=151.00B time="28.983µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:306:
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:307: ---------------------------------------------------------------------------------------------------------------------------------------------------------
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:309: Chain ID: 43112
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:309: Consensus: Dummy Consensus Engine
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:309:
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:309: Hard Forks:
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.122] github.com/ava-labs/coreth/core/blockchain.go:309: - Homestead: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - DAO Fork: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Tangerine Whistle (EIP 150): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Spurious Dragon/1 (EIP 155): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Spurious Dragon/2 (EIP 158): 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Byzantium: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Constantinople: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Petersburg: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Istanbul: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Muir Glacier: 0 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 1 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.3.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 2 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.4.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 3 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.5.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 4 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.6.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 5 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase P6 Timestamp 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase 6 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Apricot Phase Post-6 Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123] github.com/ava-labs/coreth/core/blockchain.go:309: - Banff Timestamp: 0 (https://github.com/ava-labs/avalanchego/releases/tag/v1.9.0)
-[0;0m[0;37m[node3] INFO [06-11|00:50:36.123]