Add wormhole chain

This is a squashed commit of all the changes in the wormhole_chain
directory from the development branch with the following changes:

 * Replace the vendored cosmos-sdk directory with a replace directive in
   the go.mod file pointing to the wormhole-foundation/cosmos-sdk repo.
 * Update the cosmos-sdk version to v0.45.7.
 * Rename starport -> ignite
 * Update to ignite version 0.23.0
 * Update go version in dockerfile to 1.19.0
 * Upgrade github.com/cosmos/ibc-go v1.2.0 => v1.2.2
 * Upgrade github.com/tendermint/spm v0.1.5 => v0.1.9
 * Add missing module names to the
   SetOrder{BeginBlockers,EndBlockers,InitGenesis} functions.
 * Fix the gentx memo in the genesis.json file.
This commit is contained in:
Developer Experience team at Tendermint 2021-11-16 12:23:52 +01:00 committed by Chirantan Ekbote
parent 0f7ddda602
commit 879be5bbc6
502 changed files with 291952 additions and 0 deletions

16
wormhole_chain/.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
vue/node_modules
vue/dist
vue/src/store/generated/
vue/
release/
testing/js/node_modules
!build
build/wormhole-chaind
build/data
validators/first_validator/keyring-test
validators/second_validator/keyring-test
ts-sdk/node_modules
ts-sdk/lib
.idea
*.iml

16
wormhole_chain/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "wormhole-chaind/main.go",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/wormhole-chaind/main.go",
"args": [
"start",
"--home", "${workspaceFolder}/build/",
]
},
],
}

31
wormhole_chain/Dockerfile Normal file
View File

@ -0,0 +1,31 @@
FROM docker.io/golang:1.19.0@sha256:4c00329e17be6fedd8bd4412df454a205348da00f9e0e5d763380a29eb096b75
#used for a readiness probe
RUN apt-get update
RUN apt install -y netcat
RUN apt install -y jq
RUN curl https://get.ignite.com/cli@v0.23.0 | bash && mv ignite /usr/local/bin/
WORKDIR /app
COPY ./wormhole_chain/go.mod .
COPY ./wormhole_chain/go.sum .
RUN go mod download
COPY ./wormhole_chain .
EXPOSE 26657
EXPOSE 26656
EXPOSE 6060
EXPOSE 9090
EXPOSE 1317
EXPOSE 4500
RUN unset GOPATH
RUN make client
RUN chmod +x /app/build/wormhole-chaind
RUN make validators
RUN /app/build/wormhole-chaind collect-gentxs --home /app/build
ENTRYPOINT ["/bin/bash","-c","/app/build/wormhole-chaind start"]

72
wormhole_chain/Makefile Normal file
View File

@ -0,0 +1,72 @@
PROTO_FILES=$(shell find proto -name "*.proto")
GO_FILES=$(shell find . -name "*.go")
IGNITE_EXPECTED_VERSION:=v0.23.0
IGNITE_ACTUAL_VERSION:=$(shell ignite version | awk '/Ignite CLI version:/ { print $$4 }')
# Address of the main tilt validator that the others should connect to
TILT_VALADDRESS=wormholevaloper1cyyzpxplxdzkeea7kwsydadg87357qna87hzv8
ifneq ("$(IGNITE_ACTUAL_VERSION)", "$(IGNITE_EXPECTED_VERSION)")
$(error "Expected ignite version $(IGNITE_EXPECTED_VERSION) but found $(IGNITE_ACTUAL_VERSION)")
endif
.PHONY: all
all: client vue validators
.PHONY: client
client: build/wormhole-chaind
.PHONY: validators
validators:
# These files change when the genesis file changes, so we need to make
# sure to copy them over
touch -m $@
rm -f build/config/gentx/gentx-c3f474217c930af3a4e998c4e52a57cee188ff43.json
./build/wormhole-chaind --home build/ gentx tiltGuardian "0uworm" --chain-id=wormholechain --min-self-delegation="0" --keyring-dir=keyring-test
# Copy config to validators/first_validator
cp build/config/priv_validator_key.json validators/first_validator/config/
cp build/config/node_key.json validators/first_validator/config/
mkdir -p validators/first_validator/keyring-test
cp build/keyring-test/* validators/first_validator/keyring-test/
# Copy these lines for each new validator
# We grab the validator's address from the gentx memo that it creates.
sed -E "s/(persistent_peers = \")[^@]*/\1$$(grep -lR MsgCreateValidator build/config/gentx | xargs grep -l $(TILT_VALADDRESS) | xargs jq '.body.memo' -r | cut -d@ -f1)/" validators/second_validator/config/config.toml -i
mkdir -p validators/second_validator/keyring-test
cp build/keyring-test/* validators/second_validator/keyring-test/
build/wormhole-chaind: cmd/wormhole-chaind/main.go $(GO_FILES) proto
go build -o $@ $<
proto: $(PROTO_FILES)
ignite generate proto-go
touch proto
vue: $(GO_FILES) proto
mkdir -p $@
touch -m $@
NODE_OPTIONS="" ignite generate vuex --proto-all-modules
# For now this is a phony target so we just rebuild it each time instead of
# tracking dependencies
.PHONY: ts-sdk
ts-sdk: vue
npm ci --prefix $@
npm run build --prefix $@
.PHONY: run
run: build/wormhole-chaind
./$< start --home build --log_level="debug"
.PHONY: test
test:
go test -v ./...
.PHONY: bootstrap
bootstrap:
npm run bootstrap --prefix testing/js
.PHONY: clean
clean:
rm -rf build/wormhole-chaind build/**/*.db build/**/*.wal vue
echo "{\"height\":\"0\",\"round\":0,\"step\":0}" > build/data/priv_validator_state.json

699
wormhole_chain/app/app.go Normal file
View File

@ -0,0 +1,699 @@
package app
import (
"io"
"net/http"
"os"
"path/filepath"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/cosmos/cosmos-sdk/x/bank"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/capability"
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
"github.com/cosmos/cosmos-sdk/x/crisis"
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/evidence"
evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
"github.com/cosmos/cosmos-sdk/x/feegrant"
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/x/gov"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/mint"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/cosmos/cosmos-sdk/x/params"
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal"
"github.com/cosmos/cosmos-sdk/x/slashing"
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/cosmos-sdk/x/upgrade"
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/cosmos/ibc-go/modules/apps/transfer"
ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/modules/core"
ibcclient "github.com/cosmos/ibc-go/modules/core/02-client"
ibcporttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
tmjson "github.com/tendermint/tendermint/libs/json"
"github.com/tendermint/tendermint/libs/log"
tmos "github.com/tendermint/tendermint/libs/os"
dbm "github.com/tendermint/tm-db"
"github.com/tendermint/spm/cosmoscmd"
"github.com/tendermint/spm/openapiconsole"
"github.com/certusone/wormhole-chain/docs"
tokenbridgemodule "github.com/certusone/wormhole-chain/x/tokenbridge"
tokenbridgemodulekeeper "github.com/certusone/wormhole-chain/x/tokenbridge/keeper"
tokenbridgemoduletypes "github.com/certusone/wormhole-chain/x/tokenbridge/types"
wormholemodule "github.com/certusone/wormhole-chain/x/wormhole"
wormholeclient "github.com/certusone/wormhole-chain/x/wormhole/client"
wormholemodulekeeper "github.com/certusone/wormhole-chain/x/wormhole/keeper"
wormholemoduletypes "github.com/certusone/wormhole-chain/x/wormhole/types"
// this line is used by starport scaffolding # stargate/app/moduleImport
)
const (
AccountAddressPrefix = "wormhole"
Name = "wormholechain"
)
// this line is used by starport scaffolding # stargate/wasm/app/enabledProposals
func getGovProposalHandlers() []govclient.ProposalHandler {
var govProposalHandlers []govclient.ProposalHandler
// this line is used by starport scaffolding # stargate/app/govProposalHandlers
govProposalHandlers = append(govProposalHandlers,
paramsclient.ProposalHandler,
distrclient.ProposalHandler,
upgradeclient.ProposalHandler,
upgradeclient.CancelProposalHandler,
wormholeclient.GuardianSetUpdateProposalHandler,
wormholeclient.WormholeGovernanceMessageProposalHandler,
// this line is used by starport scaffolding # stargate/app/govProposalHandler
)
return govProposalHandlers
}
var (
// DefaultNodeHome default home directories for the application daemon
DefaultNodeHome string
// ModuleBasics defines the module BasicManager is in charge of setting up basic,
// non-dependant module elements, such as codec registration
// and genesis verification.
ModuleBasics = module.NewBasicManager(
auth.AppModuleBasic{},
genutil.AppModuleBasic{},
bank.AppModuleBasic{},
capability.AppModuleBasic{},
staking.AppModuleBasic{},
mint.AppModuleBasic{},
distr.AppModuleBasic{},
gov.NewAppModuleBasic(getGovProposalHandlers()...),
params.AppModuleBasic{},
crisis.AppModuleBasic{},
slashing.AppModuleBasic{},
feegrantmodule.AppModuleBasic{},
ibc.AppModuleBasic{},
upgrade.AppModuleBasic{},
evidence.AppModuleBasic{},
transfer.AppModuleBasic{},
vesting.AppModuleBasic{},
wormholemodule.AppModuleBasic{},
tokenbridgemodule.AppModuleBasic{},
// this line is used by starport scaffolding # stargate/app/moduleBasic
)
// module account permissions
maccPerms = map[string][]string{
authtypes.FeeCollectorName: nil,
distrtypes.ModuleName: nil,
minttypes.ModuleName: {authtypes.Minter},
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
wormholemoduletypes.ModuleName: nil,
tokenbridgemoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking},
// this line is used by starport scaffolding # stargate/app/maccPerms
}
)
var (
_ cosmoscmd.CosmosApp = (*App)(nil)
_ servertypes.Application = (*App)(nil)
)
func init() {
userHomeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
DefaultNodeHome = filepath.Join(userHomeDir, "."+Name)
}
// App extends an ABCI application, but with most of its parameters exported.
// They are exported for convenience in creating helper functions, as object
// capabilities aren't needed for testing.
type App struct {
*baseapp.BaseApp
cdc *codec.LegacyAmino
appCodec codec.Codec
interfaceRegistry types.InterfaceRegistry
invCheckPeriod uint
// keys to access the substores
keys map[string]*sdk.KVStoreKey
tkeys map[string]*sdk.TransientStoreKey
memKeys map[string]*sdk.MemoryStoreKey
// keepers
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
CapabilityKeeper *capabilitykeeper.Keeper
StakingKeeper stakingkeeper.Keeper
SlashingKeeper slashingkeeper.Keeper
MintKeeper mintkeeper.Keeper
DistrKeeper distrkeeper.Keeper
GovKeeper govkeeper.Keeper
CrisisKeeper crisiskeeper.Keeper
UpgradeKeeper upgradekeeper.Keeper
ParamsKeeper paramskeeper.Keeper
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
EvidenceKeeper evidencekeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper
FeeGrantKeeper feegrantkeeper.Keeper
// make scoped keepers public for test purposes
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedTransferKeeper capabilitykeeper.ScopedKeeper
WormholeKeeper wormholemodulekeeper.Keeper
TokenbridgeKeeper tokenbridgemodulekeeper.Keeper
// this line is used by starport scaffolding # stargate/app/keeperDeclaration
// the module manager
mm *module.Manager
}
// New returns a reference to an initialized Gaia.
func New(
logger log.Logger,
db dbm.DB,
traceStore io.Writer,
loadLatest bool,
skipUpgradeHeights map[int64]bool,
homePath string,
invCheckPeriod uint,
encodingConfig cosmoscmd.EncodingConfig,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) cosmoscmd.App {
appCodec := encodingConfig.Marshaler
cdc := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
// TODO remove for prod
baseAppOptions = append(baseAppOptions, baseapp.SetTrace(true))
bApp := baseapp.NewBaseApp(Name, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey,
evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey,
wormholemoduletypes.StoreKey,
tokenbridgemoduletypes.StoreKey,
// this line is used by starport scaffolding # stargate/app/storeKey
)
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
app := &App{
BaseApp: bApp,
cdc: cdc,
appCodec: appCodec,
interfaceRegistry: interfaceRegistry,
invCheckPeriod: invCheckPeriod,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
// set the BaseApp's parameter store
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()))
// add capability keeper and ScopeToModule for ibc module
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
// grant capabilities for the ibc and ibc-transfer modules
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName)
// this line is used by starport scaffolding # stargate/app/scopedKeeper
// add keepers
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms,
)
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(),
)
app.WormholeKeeper = *wormholemodulekeeper.NewKeeper(
appCodec,
keys[wormholemoduletypes.StoreKey],
keys[wormholemoduletypes.MemStoreKey],
app.AccountKeeper,
app.BankKeeper,
)
wormholeModule := wormholemodule.NewAppModule(appCodec, app.WormholeKeeper)
stakingKeeper := stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.WormholeKeeper, app.GetSubspace(stakingtypes.ModuleName),
)
app.MintKeeper = mintkeeper.NewKeeper(
appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
)
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
)
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
)
app.CrisisKeeper = crisiskeeper.NewKeeper(
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
)
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp)
// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
// ... other modules keepers
// Create IBC Keeper
app.IBCKeeper = ibckeeper.NewKeeper(
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)
// register the proposal types
govRouter := govtypes.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
)
transferModule := transfer.NewAppModule(app.TransferKeeper)
// Create evidence Keeper for to register the IBC light client misbehaviour evidence route
evidenceKeeper := evidencekeeper.NewKeeper(
appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
)
// If evidence needs to be handled for the app, set routes in router here and seal
app.EvidenceKeeper = *evidenceKeeper
govRouter.AddRoute(wormholemoduletypes.RouterKey, wormholemodule.NewWormholeGovernanceProposalHandler(app.WormholeKeeper))
app.TokenbridgeKeeper = *tokenbridgemodulekeeper.NewKeeper(
appCodec,
keys[tokenbridgemoduletypes.StoreKey],
keys[tokenbridgemoduletypes.MemStoreKey],
app.AccountKeeper,
app.BankKeeper,
app.WormholeKeeper,
)
tokenbridgeModule := tokenbridgemodule.NewAppModule(appCodec, app.TokenbridgeKeeper)
app.GovKeeper = govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter,
)
// this line is used by starport scaffolding # stargate/app/keeperDefinition
// Create static IBC router, add transfer route, then set and seal it
ibcRouter := ibcporttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule)
// this line is used by starport scaffolding # ibc/app/router
app.IBCKeeper.SetRouter(ibcRouter)
/**** Module Options ****/
// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
// we prefer to be more strict in what arguments the modules expect.
var skipGenesisInvariants = cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants))
// NOTE: Any module instantiated in the module manager that is later modified
// must be passed by reference here.
app.mm = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, nil),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.WormholeKeeper),
upgrade.NewAppModule(app.UpgradeKeeper),
evidence.NewAppModule(app.EvidenceKeeper),
ibc.NewAppModule(app.IBCKeeper),
params.NewAppModule(app.ParamsKeeper),
transferModule,
wormholeModule,
tokenbridgeModule,
// this line is used by starport scaffolding # stargate/app/appModule
)
// During begin block slashing happens after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool, so as to keep the
// CanWithdrawInvariant invariant.
// NOTE: staking module is required if HistoricalEntries param > 0
app.mm.SetOrderBeginBlockers(
upgradetypes.ModuleName,
capabilitytypes.ModuleName,
minttypes.ModuleName,
distrtypes.ModuleName,
slashingtypes.ModuleName,
evidencetypes.ModuleName,
stakingtypes.ModuleName,
vestingtypes.ModuleName,
ibchost.ModuleName,
ibctransfertypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
govtypes.ModuleName,
crisistypes.ModuleName,
genutiltypes.ModuleName,
feegrant.ModuleName,
paramstypes.ModuleName,
wormholemoduletypes.ModuleName,
tokenbridgemoduletypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/beginBlockers
)
app.mm.SetOrderEndBlockers(
crisistypes.ModuleName,
govtypes.ModuleName,
stakingtypes.ModuleName,
capabilitytypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
distrtypes.ModuleName,
slashingtypes.ModuleName,
vestingtypes.ModuleName,
minttypes.ModuleName,
genutiltypes.ModuleName,
evidencetypes.ModuleName,
feegrant.ModuleName,
paramstypes.ModuleName,
upgradetypes.ModuleName,
ibchost.ModuleName,
ibctransfertypes.ModuleName,
wormholemoduletypes.ModuleName,
tokenbridgemoduletypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/endBlockers
)
// NOTE: The genutils module must occur after staking so that pools are
// properly initialized with tokens from genesis accounts.
// NOTE: Capability module must occur first so that it can initialize any capabilities
// so that other modules that want to create or claim capabilities afterwards in InitChain
// can do so safely.
// NOTE: The wormhole module must occur before staking so that the consensus
// guardian set is properly initialised before the staking module allocates
// voting power in its genesis handler
app.mm.SetOrderInitGenesis(
capabilitytypes.ModuleName,
authtypes.ModuleName,
banktypes.ModuleName,
distrtypes.ModuleName,
wormholemoduletypes.ModuleName,
stakingtypes.ModuleName,
vestingtypes.ModuleName,
slashingtypes.ModuleName,
govtypes.ModuleName,
minttypes.ModuleName,
crisistypes.ModuleName,
ibchost.ModuleName,
genutiltypes.ModuleName,
evidencetypes.ModuleName,
paramstypes.ModuleName,
upgradetypes.ModuleName,
ibctransfertypes.ModuleName,
feegrant.ModuleName,
tokenbridgemoduletypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/initGenesis
)
app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
app.mm.RegisterServices(module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()))
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)
// initialize BaseApp
app.SetInitChainer(app.InitChainer)
app.SetBeginBlocker(app.BeginBlocker)
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
app.SetEndBlocker(app.EndBlocker)
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
tmos.Exit(err.Error())
}
}
app.ScopedIBCKeeper = scopedIBCKeeper
app.ScopedTransferKeeper = scopedTransferKeeper
// this line is used by starport scaffolding # stargate/app/beforeInitReturn
return app
}
// Name returns the name of the App
func (app *App) Name() string { return app.BaseApp.Name() }
// BeginBlocker application updates every begin block
func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
return app.mm.BeginBlock(ctx, req)
}
// EndBlocker application updates every end block
func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
return app.mm.EndBlock(ctx, req)
}
// InitChainer application update at chain initialization
func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
var genesisState GenesisState
if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
panic(err)
}
app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap())
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
}
// LoadHeight loads a particular height
func (app *App) LoadHeight(height int64) error {
return app.LoadVersion(height)
}
// ModuleAccountAddrs returns all the app's module account addresses.
func (app *App) ModuleAccountAddrs() map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range maccPerms {
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
return modAccAddrs
}
// LegacyAmino returns SimApp's amino codec.
//
// NOTE: This is solely to be used for testing purposes as it may be desirable
// for modules to register their own custom testing types.
func (app *App) LegacyAmino() *codec.LegacyAmino {
return app.cdc
}
// AppCodec returns Gaia's app codec.
//
// NOTE: This is solely to be used for testing purposes as it may be desirable
// for modules to register their own custom testing types.
func (app *App) AppCodec() codec.Codec {
return app.appCodec
}
// InterfaceRegistry returns Gaia's InterfaceRegistry
func (app *App) InterfaceRegistry() types.InterfaceRegistry {
return app.interfaceRegistry
}
// GetKey returns the KVStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *App) GetKey(storeKey string) *sdk.KVStoreKey {
return app.keys[storeKey]
}
// GetTKey returns the TransientStoreKey for the provided store key.
//
// NOTE: This is solely to be used for testing purposes.
func (app *App) GetTKey(storeKey string) *sdk.TransientStoreKey {
return app.tkeys[storeKey]
}
// GetMemKey returns the MemStoreKey for the provided mem key.
//
// NOTE: This is solely used for testing purposes.
func (app *App) GetMemKey(storeKey string) *sdk.MemoryStoreKey {
return app.memKeys[storeKey]
}
// GetSubspace returns a param subspace for a given module name.
//
// NOTE: This is solely to be used for testing purposes.
func (app *App) GetSubspace(moduleName string) paramstypes.Subspace {
subspace, _ := app.ParamsKeeper.GetSubspace(moduleName)
return subspace
}
// RegisterAPIRoutes registers all application module routes with the provided
// API server.
func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
clientCtx := apiSvr.ClientCtx
rpc.RegisterRoutes(clientCtx, apiSvr.Router)
// Register legacy tx routes.
authrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
// Register new tx routes from grpc-gateway.
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// Register new tendermint queries routes from grpc-gateway.
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// Register legacy and grpc-gateway routes for all modules.
ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router)
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
// register app's OpenAPI routes.
apiSvr.Router.Handle("/static/openapi.yml", http.FileServer(http.FS(docs.Docs)))
apiSvr.Router.HandleFunc("/", openapiconsole.Handler(Name, "/static/openapi.yml"))
}
// RegisterTxService implements the Application.RegisterTxService method.
func (app *App) RegisterTxService(clientCtx client.Context) {
authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}
// RegisterTendermintService implements the Application.RegisterTendermintService method.
func (app *App) RegisterTendermintService(clientCtx client.Context) {
tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry)
}
// GetMaccPerms returns a copy of the module account permissions
func GetMaccPerms() map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}
// initParamsKeeper init params keeper and its subspaces
func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper {
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
paramsKeeper.Subspace(authtypes.ModuleName)
paramsKeeper.Subspace(banktypes.ModuleName)
paramsKeeper.Subspace(stakingtypes.ModuleName)
paramsKeeper.Subspace(minttypes.ModuleName)
paramsKeeper.Subspace(distrtypes.ModuleName)
paramsKeeper.Subspace(slashingtypes.ModuleName)
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
paramsKeeper.Subspace(ibchost.ModuleName)
paramsKeeper.Subspace(wormholemoduletypes.ModuleName)
paramsKeeper.Subspace(tokenbridgemoduletypes.ModuleName)
// this line is used by starport scaffolding # stargate/app/paramSubspace
return paramsKeeper
}

View File

@ -0,0 +1,185 @@
package app
import (
"encoding/json"
"log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
"github.com/cosmos/cosmos-sdk/x/staking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
// ExportAppStateAndValidators exports the state of the application for a genesis
// file.
func (app *App) ExportAppStateAndValidators(
forZeroHeight bool, jailAllowedAddrs []string,
) (servertypes.ExportedApp, error) {
// as if they could withdraw from the start of the next block
ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()})
// We export at last height + 1, because that's the height at which
// Tendermint will start InitChain.
height := app.LastBlockHeight() + 1
if forZeroHeight {
height = 0
app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs)
}
genState := app.mm.ExportGenesis(ctx, app.appCodec)
appState, err := json.MarshalIndent(genState, "", " ")
if err != nil {
return servertypes.ExportedApp{}, err
}
validators, err := staking.WriteValidators(ctx, app.StakingKeeper)
if err != nil {
return servertypes.ExportedApp{}, err
}
return servertypes.ExportedApp{
AppState: appState,
Validators: validators,
Height: height,
ConsensusParams: app.BaseApp.GetConsensusParams(ctx),
}, nil
}
// prepare for fresh start at zero height
// NOTE zero height genesis is a temporary feature which will be deprecated
// in favour of export at a block height
func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) {
applyAllowedAddrs := false
// check if there is a allowed address list
if len(jailAllowedAddrs) > 0 {
applyAllowedAddrs = true
}
allowedAddrsMap := make(map[string]bool)
for _, addr := range jailAllowedAddrs {
_, err := sdk.ValAddressFromBech32(addr)
if err != nil {
log.Fatal(err)
}
allowedAddrsMap[addr] = true
}
/* Just to be safe, assert the invariants on current state. */
app.CrisisKeeper.AssertInvariants(ctx)
/* Handle fee distribution state. */
// withdraw all validator commission
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
_, err := app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator())
if err != nil {
panic(err)
}
return false
})
// withdraw all delegator rewards
dels := app.StakingKeeper.GetAllDelegations(ctx)
for _, delegation := range dels {
_, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, delegation.GetDelegatorAddr(), delegation.GetValidatorAddr())
if err != nil {
panic(err)
}
}
// clear validator slash events
app.DistrKeeper.DeleteAllValidatorSlashEvents(ctx)
// clear validator historical rewards
app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx)
// set context height to zero
height := ctx.BlockHeight()
ctx = ctx.WithBlockHeight(0)
// reinitialize all validators
app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) {
// donate any unwithdrawn outstanding reward fraction tokens to the community pool
scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator())
feePool := app.DistrKeeper.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(scraps...)
app.DistrKeeper.SetFeePool(ctx, feePool)
app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator())
return false
})
// reinitialize all delegations
for _, del := range dels {
app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, del.GetDelegatorAddr(), del.GetValidatorAddr())
app.DistrKeeper.Hooks().AfterDelegationModified(ctx, del.GetDelegatorAddr(), del.GetValidatorAddr())
}
// reset context height
ctx = ctx.WithBlockHeight(height)
/* Handle staking state. */
// iterate through redelegations, reset creation height
app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) {
for i := range red.Entries {
red.Entries[i].CreationHeight = 0
}
app.StakingKeeper.SetRedelegation(ctx, red)
return false
})
// iterate through unbonding delegations, reset creation height
app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) {
for i := range ubd.Entries {
ubd.Entries[i].CreationHeight = 0
}
app.StakingKeeper.SetUnbondingDelegation(ctx, ubd)
return false
})
// Iterate through validators by power descending, reset bond heights, and
// update bond intra-tx counters.
store := ctx.KVStore(app.keys[stakingtypes.StoreKey])
iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey)
counter := int16(0)
for ; iter.Valid(); iter.Next() {
addr := sdk.ValAddress(iter.Key()[1:])
validator, found := app.StakingKeeper.GetValidator(ctx, addr)
if !found {
panic("expected validator, not found")
}
validator.UnbondingHeight = 0
if applyAllowedAddrs && !allowedAddrsMap[addr.String()] {
validator.Jailed = true
}
app.StakingKeeper.SetValidator(ctx, validator)
counter++
}
iter.Close()
if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil {
panic(err)
}
/* Handle slashing state. */
// reset start height on signing infos
app.SlashingKeeper.IterateValidatorSigningInfos(
ctx,
func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) {
info.StartHeight = 0
app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info)
return false
},
)
}

View File

@ -0,0 +1,21 @@
package app
import (
"encoding/json"
"github.com/cosmos/cosmos-sdk/codec"
)
// The genesis state of the blockchain is represented here as a map of raw json
// messages key'd by a identifier string.
// The identifier is used to determine which module genesis information belongs
// to so it may be appropriately routed during init chain.
// Within this application default genesis information is retrieved from
// the ModuleBasicManager which populates json from each BasicModule
// object provided to it during init.
type GenesisState map[string]json.RawMessage
// NewDefaultGenesisState generates the default state for the application.
func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState {
return ModuleBasics.DefaultGenesis(cdc)
}

View File

@ -0,0 +1,4 @@
{
"key": "349a5adb08e41f09f8e0e074",
"addrs": []
}

View File

@ -0,0 +1,58 @@
halt-height = 0
halt-time = 0
index-events = []
inter-block-cache = true
min-retain-blocks = 0
minimum-gas-prices = "0stake"
pruning = "default"
pruning-interval = "0"
pruning-keep-every = "0"
pruning-keep-recent = "0"
chain-id = "wormholechain"
[api]
address = "tcp://localhost:1317"
enable = true
enabled-unsafe-cors = true
max-open-connections = 1000
rpc-max-body-bytes = 1000000
rpc-read-timeout = 10
rpc-write-timeout = 0
swagger = false
[grpc]
address = "0.0.0.0:9090"
enable = true
[grpc-web]
address = "0.0.0.0:9091"
enable = true
enable-unsafe-cors = false
[rosetta]
address = ":8080"
blockchain = "app"
enable = false
network = "network"
offline = false
retries = 3
[rpc]
cors_allowed_origins = ["*"]
[state-sync]
snapshot-interval = 0
snapshot-keep-recent = 2
[telemetry]
enable-hostname = false
enable-hostname-label = false
enable-service-label = false
enabled = false
global-labels = []
prometheus-retention-time = 0
service-name = ""
[wasm]
lru_size = 0
query_gas_limit = 300000

View File

@ -0,0 +1,5 @@
broadcast-mode = "block"
chain-id = "wormholechain"
keyring-backend = "test"
node = "tcp://localhost:26657"
output = "text"

View File

@ -0,0 +1,401 @@
# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
# relative to the home directory (e.g. "data"). The home directory is
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
# or --home cmd flag.
#######################################################################
### Main Base Config Options ###
#######################################################################
# TCP or UNIX socket address of the ABCI application,
# or the name of an ABCI application compiled in with the Tendermint binary
proxy_app = "tcp://127.0.0.1:26658"
# A custom human readable name for this node
moniker = "mynode"
# If this node is many blocks behind the tip of the chain, FastSync
# allows them to catchup quickly by downloading blocks in parallel
# and verifying their commits
fast_sync = true
# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
# - pure go
# - stable
# * cleveldb (uses levigo wrapper)
# - fast
# - requires gcc
# - use cleveldb build tag (go build -tags cleveldb)
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
# - EXPERIMENTAL
# - may be faster is some use-cases (random reads - indexer)
# - use boltdb build tag (go build -tags boltdb)
# * rocksdb (uses github.com/tecbot/gorocksdb)
# - EXPERIMENTAL
# - requires gcc
# - use rocksdb build tag (go build -tags rocksdb)
# * badgerdb (uses github.com/dgraph-io/badger)
# - EXPERIMENTAL
# - use badgerdb build tag (go build -tags badgerdb)
db_backend = "goleveldb"
# Database directory
db_dir = "data"
# Output level for logging, including package level options
log_level = "debug"
# Output format: 'plain' (colored text) or 'json'
log_format = "plain"
##### additional base config options #####
# Path to the JSON file containing the initial validator set and other meta data
genesis_file = "config/genesis.json"
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
priv_validator_key_file = "config/priv_validator_key.json"
# Path to the JSON file containing the last sign state of a validator
priv_validator_state_file = "data/priv_validator_state.json"
# TCP or UNIX socket address for Tendermint to listen on for
# connections from an external PrivValidator process
priv_validator_laddr = ""
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
node_key_file = "config/node_key.json"
# Mechanism to connect to the ABCI application: socket | grpc
abci = "socket"
# If true, query the ABCI app on connecting to a new peer
# so the app can decide if we should keep the connection or not
filter_peers = false
#######################################################################
### Advanced Configuration Options ###
#######################################################################
#######################################################
### RPC Server Configuration Options ###
#######################################################
[rpc]
# TCP or UNIX socket address for the RPC server to listen on
laddr = "tcp://0.0.0.0:26657"
# A list of origins a cross-domain request can be executed from
# Default value '[]' disables cors support
# Use '["*"]' to allow any origin
cors_allowed_origins = ["*", ]
# A list of methods the client is allowed to use with cross-domain requests
cors_allowed_methods = ["HEAD", "GET", "POST", ]
# A list of non simple headers the client is allowed to use with cross-domain requests
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
# TCP or UNIX socket address for the gRPC server to listen on
# NOTE: This server only supports /broadcast_tx_commit
grpc_laddr = ""
# Maximum number of simultaneous connections.
# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
# If you want to accept a larger number than the default, make sure
# you increase your OS limits.
# 0 - unlimited.
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
# 1024 - 40 - 10 - 50 = 924 = ~900
grpc_max_open_connections = 900
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool
unsafe = false
# Maximum number of simultaneous connections (including WebSocket).
# Does not include gRPC connections. See grpc_max_open_connections
# If you want to accept a larger number than the default, make sure
# you increase your OS limits.
# 0 - unlimited.
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
# 1024 - 40 - 10 - 50 = 924 = ~900
max_open_connections = 900
# Maximum number of unique clientIDs that can /subscribe
# If you're using /broadcast_tx_commit, set to the estimated maximum number
# of broadcast_tx_commit calls per block.
max_subscription_clients = 100
# Maximum number of unique queries a given client can /subscribe to
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
# the estimated # maximum number of broadcast_tx_commit calls per block.
max_subscriptions_per_client = 5
# How long to wait for a tx to be committed during /broadcast_tx_commit.
# WARNING: Using a value larger than 10s will result in increasing the
# global HTTP write timeout, which applies to all connections and endpoints.
# See https://github.com/tendermint/tendermint/issues/3435
timeout_broadcast_tx_commit = "10s"
# Maximum size of request body, in bytes
max_body_bytes = 1000000
# Maximum size of request header, in bytes
max_header_bytes = 1048576
# The path to a file containing certificate that is used to create the HTTPS server.
# Might be either absolute path or path related to Tendermint's config directory.
# If the certificate is signed by a certificate authority,
# the certFile should be the concatenation of the server's certificate, any intermediates,
# and the CA's certificate.
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
# Otherwise, HTTP server is run.
tls_cert_file = ""
# The path to a file containing matching private key that is used to create the HTTPS server.
# Might be either absolute path or path related to Tendermint's config directory.
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
# Otherwise, HTTP server is run.
tls_key_file = ""
# pprof listen address (https://golang.org/pkg/net/http/pprof)
pprof_laddr = "0.0.0.0:6060"
#######################################################
### P2P Configuration Options ###
#######################################################
[p2p]
# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"
# Address to advertise to peers for them to dial
# If empty, will use the same port as the laddr,
# and will introspect on the listener or use UPnP
# to figure out the address. ip and port are required
# example: 159.89.10.97:26656
external_address = ""
# Comma separated list of seed nodes to connect to
seeds = ""
# Comma separated list of nodes to keep persistent connections to
persistent_peers = ""
# UPNP port forwarding
upnp = false
# Path to address book
addr_book_file = "config/addrbook.json"
# Set true for strict address routability rules
# Set false for private or local networks
addr_book_strict = true
# Maximum number of inbound peers
max_num_inbound_peers = 40
# Maximum number of outbound peers to connect to, excluding persistent peers
max_num_outbound_peers = 10
# List of node IDs, to which a connection will be (re)established ignoring any existing limits
unconditional_peer_ids = ""
# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
persistent_peers_max_dial_period = "0s"
# Time to wait before flushing messages out on the connection
flush_throttle_timeout = "100ms"
# Maximum size of a message packet payload, in bytes
max_packet_msg_payload_size = 1024
# Rate at which packets can be sent, in bytes/second
send_rate = 5120000
# Rate at which packets can be received, in bytes/second
recv_rate = 5120000
# Set true to enable the peer-exchange reactor
pex = true
# Seed mode, in which node constantly crawls the network and looks for
# peers. If another node asks it for addresses, it responds and disconnects.
#
# Does not work if the peer-exchange reactor is disabled.
seed_mode = false
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
private_peer_ids = ""
# Toggle to disable guard against peers connecting from the same ip.
allow_duplicate_ip = false
# Peer connection configuration.
handshake_timeout = "20s"
dial_timeout = "3s"
#######################################################
### Mempool Configuration Option ###
#######################################################
[mempool]
recheck = true
broadcast = true
wal_dir = ""
# Maximum number of transactions in the mempool
size = 5000
# Limit the total size of all txs in the mempool.
# This only accounts for raw transactions (e.g. given 1MB transactions and
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
max_txs_bytes = 1073741824
# Size of the cache (used to filter transactions we saw earlier) in transactions
cache_size = 10000
# Do not remove invalid transactions from the cache (default: false)
# Set to true if it's not possible for any invalid transaction to become valid
# again in the future.
keep-invalid-txs-in-cache = false
# Maximum size of a single transaction.
# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}.
max_tx_bytes = 1048576
# Maximum size of a batch of transactions to send to a peer
# Including space needed by encoding (one varint per transaction).
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
max_batch_bytes = 0
#######################################################
### State Sync Configuration Options ###
#######################################################
[statesync]
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
# the network to take and serve state machine snapshots. State sync is not attempted if the node
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
# starting from the height of the snapshot.
enable = false
# RPC servers (comma-separated) for light client verification of the synced state machine and
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
# header hash obtained from a trusted source, and a period during which validators can be trusted.
#
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
# weeks) during which they can be financially punished (slashed) for misbehavior.
rpc_servers = ""
trust_height = 0
trust_hash = ""
trust_period = "168h0m0s"
# Time to spend discovering snapshots before initiating a restore.
discovery_time = "15s"
# Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp).
# Will create a new, randomly named directory within, and remove it when done.
temp_dir = ""
# The timeout duration before re-requesting a chunk, possibly from a different
# peer (default: 1 minute).
chunk_request_timeout = "10s"
# The number of concurrent chunk fetchers to run (default: 1).
chunk_fetchers = "4"
#######################################################
### Fast Sync Configuration Connections ###
#######################################################
[fastsync]
# Fast Sync version to use:
# 1) "v0" (default) - the legacy fast sync implementation
# 2) "v1" - refactor of v0 version for better testability
# 2) "v2" - complete redesign of v0, optimized for testability & readability
version = "v0"
#######################################################
### Consensus Configuration Options ###
#######################################################
[consensus]
wal_file = "data/cs.wal/wal"
# How long we wait for a proposal block before prevoting nil
timeout_propose = "1s"
# How much timeout_propose increases with each round
timeout_propose_delta = "500ms"
# How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil)
timeout_prevote = "1s"
# How much the timeout_prevote increases with each round
timeout_prevote_delta = "500ms"
# How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil)
timeout_precommit = "1s"
# How much the timeout_precommit increases with each round
timeout_precommit_delta = "500ms"
# How long we wait after committing a block, before starting on the new
# height (this gives us a chance to receive some more precommits, even
# though we already have +2/3).
timeout_commit = "1s"
# How many blocks to look back to check existence of the node's consensus votes before joining consensus
# When non-zero, the node will panic upon restart
# if the same consensus key was used to sign {double_sign_check_height} last blocks.
# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic.
double_sign_check_height = 0
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
skip_timeout_commit = false
# EmptyBlocks mode and possible interval between empty blocks
create_empty_blocks = true
create_empty_blocks_interval = "0s"
# Reactor sleep duration parameters
peer_gossip_sleep_duration = "100ms"
peer_query_maj23_sleep_duration = "2s"
#######################################################
### Transaction Indexer Configuration Options ###
#######################################################
[tx_index]
# What indexer to use for transactions
#
# The application will set which txs to index. In some cases a node operator will be able
# to decide which txs to index based on configuration set in the application.
#
# Options:
# 1) "null"
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
indexer = "kv"
#######################################################
### Instrumentation Configuration Options ###
#######################################################
[instrumentation]
# When true, Prometheus metrics are served under /metrics on
# PrometheusListenAddr.
# Check out the documentation for the list of available metrics.
prometheus = false
# Address to listen for Prometheus collector(s) connections
prometheus_listen_addr = ":26660"
# Maximum number of simultaneous connections.
# If you want to accept a larger number than the default, make sure
# you increase your OS limits.
# 0 - unlimited.
max_open_connections = 3
# Instrumentation namespace
namespace = "tendermint"

View File

@ -0,0 +1,342 @@
{
"chain_id": "wormholechain",
"gentxs_dir": "build/config/gentx",
"moniker": "mynode",
"node_id": "c3f474217c930af3a4e998c4e52a57cee188ff43",
"app_state": {
"auth": {
"params": {
"max_memo_characters": "256",
"tx_sig_limit": "7",
"tx_size_cost_per_byte": "10",
"sig_verify_cost_ed25519": "590",
"sig_verify_cost_secp256k1": "1000"
},
"accounts": [
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq",
"pub_key": null,
"account_number": "0",
"sequence": "0"
},
{
"@type": "/cosmos.auth.v1beta1.BaseAccount",
"address": "wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr",
"pub_key": null,
"account_number": "0",
"sequence": "0"
}
]
},
"bank": {
"params": {
"send_enabled": [],
"default_send_enabled": true
},
"balances": [
{
"address": "wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr",
"coins": [
{
"denom": "utest",
"amount": "10000"
}
]
},
{
"address": "wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq",
"coins": [
{
"denom": "utest",
"amount": "20000"
}
]
}
],
"supply": [],
"denom_metadata": [
{
"description": "Wormholechain's native test asset",
"denom_units": [
{
"denom": "utest",
"exponent": 0,
"aliases": []
},
{
"denom": "test",
"exponent": 6,
"aliases": []
}
],
"base": "utest",
"display": "test",
"name": "Test Coin",
"symbol": "TEST"
},
{
"description": "Wormholechain's native staking asset",
"denom_units": [
{
"denom": "uworm",
"exponent": 0,
"aliases": []
},
{
"denom": "worm",
"exponent": 6,
"aliases": []
}
],
"base": "uworm",
"display": "worm",
"name": "Worm Coin",
"symbol": "WORM"
}
]
},
"capability": {
"index": "1",
"owners": []
},
"crisis": {
"constant_fee": {
"amount": "1000",
"denom": "worm"
}
},
"distribution": {
"delegator_starting_infos": [],
"delegator_withdraw_infos": [],
"fee_pool": {
"community_pool": []
},
"outstanding_rewards": [],
"params": {
"base_proposer_reward": "0.010000000000000000",
"bonus_proposer_reward": "0.040000000000000000",
"community_tax": "0.020000000000000000",
"withdraw_addr_enabled": true
},
"previous_proposer": "",
"validator_accumulated_commissions": [],
"validator_current_rewards": [],
"validator_historical_rewards": [],
"validator_slash_events": []
},
"evidence": {
"evidence": []
},
"feegrant": {
"allowances": []
},
"genutil": {
"gen_txs": [
{
"body": {
"messages": [
{
"@type": "/cosmos.staking.v1beta1.MsgCreateValidator",
"description": {
"moniker": "mynode",
"identity": "",
"website": "",
"security_contact": "",
"details": ""
},
"commission": {
"rate": "0.100000000000000000",
"max_rate": "0.200000000000000000",
"max_change_rate": "0.010000000000000000"
},
"min_self_delegation": "0",
"delegator_address": "wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq",
"validator_address": "wormholevaloper1cyyzpxplxdzkeea7kwsydadg87357qna87hzv8",
"pubkey": {
"@type": "/cosmos.crypto.ed25519.PubKey",
"key": "fnfoo/C+i+Ng1J8vct6wfvrTS9JeNIG5UeO87ZHKMkY="
},
"value": {
"denom": "uworm",
"amount": "0"
}
}
],
"memo": "c3f474217c930af3a4e998c4e52a57cee188ff43@172.16.14.80:26656",
"timeout_height": "0",
"extension_options": [],
"non_critical_extension_options": []
},
"auth_info": {
"signer_infos": [
{
"public_key": {
"@type": "/cosmos.crypto.secp256k1.PubKey",
"key": "AuwYyCUBxQiBGSUWebU46c+OrlApVsyGLHd4qhSDZeiG"
},
"mode_info": {
"single": {
"mode": "SIGN_MODE_DIRECT"
}
},
"sequence": "0"
}
],
"fee": {
"amount": [],
"gas_limit": "200000",
"payer": "",
"granter": ""
}
},
"signatures": [
"wksmbgHHl22UKLmZK3AuSIdPxfX5+BPmvhVxHJC3wB5dzE1l0n+qmMxpbEP/wr0Xi0aC/qIszss6VxVoUmiPKw=="
]
}
]
},
"gov": {
"deposit_params": {
"max_deposit_period": "172800s",
"min_deposit": [
{
"amount": "1000000",
"denom": "uworm"
}
]
},
"deposits": [],
"proposals": [],
"starting_proposal_id": "1",
"tally_params": {
"quorum": "0.334000000000000000",
"threshold": "0.500000000000000000",
"veto_threshold": "0.334000000000000000"
},
"votes": [],
"voting_params": {
"voting_period": "50s"
}
},
"ibc": {
"channel_genesis": {
"ack_sequences": [],
"acknowledgements": [],
"channels": [],
"commitments": [],
"next_channel_sequence": "0",
"receipts": [],
"recv_sequences": [],
"send_sequences": []
},
"client_genesis": {
"clients": [],
"clients_consensus": [],
"clients_metadata": [],
"create_localhost": false,
"next_client_sequence": "0",
"params": {
"allowed_clients": [
"06-solomachine",
"07-tendermint"
]
}
},
"connection_genesis": {
"client_connection_paths": [],
"connections": [],
"next_connection_sequence": "0",
"params": {
"max_expected_time_per_block": "30000000000"
}
}
},
"mint": {
"minter": {
"annual_provisions": "0.0",
"inflation": "0.0"
},
"params": {
"blocks_per_year": "6311520",
"goal_bonded": "0.67",
"inflation_max": "0.0",
"inflation_min": "0.0",
"inflation_rate_change": "0.0",
"mint_denom": "uworm"
}
},
"params": null,
"slashing": {
"missed_blocks": [],
"params": {
"downtime_jail_duration": "600s",
"min_signed_per_window": "0.500000000000000000",
"signed_blocks_window": "100",
"slash_fraction_double_sign": "0.050000000000000000",
"slash_fraction_downtime": "0.010000000000000000"
},
"signing_infos": []
},
"staking": {
"delegations": [],
"exported": false,
"last_total_power": "0",
"last_validator_powers": [],
"params": {
"bond_denom": "uworm",
"historical_entries": 10000,
"max_entries": 7,
"max_validators": 1,
"unbonding_time": "1814400s"
},
"redelegations": [],
"unbonding_delegations": [],
"validators": []
},
"tokenbridge": {
"chainRegistrationList": [],
"coinMetaRollbackProtectionList": [],
"config": null,
"replayProtectionList": []
},
"transfer": {
"denom_traces": [],
"params": {
"receive_enabled": true,
"send_enabled": true
},
"port_id": "transfer"
},
"upgrade": {},
"vesting": {},
"wormhole": {
"config": {
"chain_id": 3104,
"governance_chain": 1,
"governance_emitter": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ=",
"guardian_set_expiration": 86400
},
"consensusGuardianSetIndex": {
"index": 0
},
"guardianSetList": [
{
"expirationTime": 0,
"index": 0,
"keys": [
"vvpCnVfNGLf4pNkaLamrSvBdD74="
]
}
],
"guardianValidatorList": [
{
"guardianKey": "vvpCnVfNGLf4pNkaLamrSvBdD74=",
"validatorAddr": "wQggmD8zRWznvrOgRvWoP6NPAn0="
}
],
"replayProtectionList": [],
"sequenceCounterList": []
}
}
}

View File

@ -0,0 +1 @@
{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgCreateValidator","description":{"moniker":"mynode","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"0","delegator_address":"wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq","validator_address":"wormholevaloper1cyyzpxplxdzkeea7kwsydadg87357qna87hzv8","pubkey":{"@type":"/cosmos.crypto.ed25519.PubKey","key":"fnfoo/C+i+Ng1J8vct6wfvrTS9JeNIG5UeO87ZHKMkY="},"value":{"denom":"uworm","amount":"0"}}],"memo":"c3f474217c930af3a4e998c4e52a57cee188ff43@172.16.14.80:26656","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AuwYyCUBxQiBGSUWebU46c+OrlApVsyGLHd4qhSDZeiG"},"mode_info":{"single":{"mode":"SIGN_MODE_DIRECT"}},"sequence":"0"}],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":["wksmbgHHl22UKLmZK3AuSIdPxfX5+BPmvhVxHJC3wB5dzE1l0n+qmMxpbEP/wr0Xi0aC/qIszss6VxVoUmiPKw=="]}

View File

@ -0,0 +1 @@
{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"DTmqnA3oDbIvGv8ovgsXdtyKEow5/ryWBzr0RKi4uv4btEaX/5hbQOm2PYRKuZYG4u8ESjNCxMPut9CLVM2AEA=="}}

View File

@ -0,0 +1,11 @@
{
"address": "C3AE4256EAA0BA6D01041585F63AE7CAA69D6D33",
"pub_key": {
"type": "tendermint/PubKeyEd25519",
"value": "fnfoo/C+i+Ng1J8vct6wfvrTS9JeNIG5UeO87ZHKMkY="
},
"priv_key": {
"type": "tendermint/PrivKeyEd25519",
"value": "Zb3gQZSd8qNMyXUQdKmeqM/SSYeVDD80S4XPEsCAgPN+d+ij8L6L42DUny9y3rB++tNL0l40gblR47ztkcoyRg=="
}
}

View File

@ -0,0 +1,5 @@
{
"height": "0",
"round": 0,
"step": 0
}

View File

@ -0,0 +1 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMi0wNS0zMSAxNzowNjo1Mi42OTIyNTQxNDUgLTA1MDAgQ0RUIG09KzEwLjE2MzcxMjE5MiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6IlZmYzJzd3o1ZTlFOVYxZXUifQ.QxCznBeKdoMPaiLAW9z_bzw0Tu8KGb1uv7oP6roGx2G23I95FETScw.1Tzsdxl9aER5xGOC.BOocwpXC7mcx7kigzWJsopVujiXfuQ3inOOkfMxq20JJNcsztwwMxQ4rvqCv6KJAw7Ldy-VrjXE8qErp_Z6_p5KXyPLN0G3Ie-smKrQzquQYuH8Gbx2zyYaAyM3V2ObnI7G3LsKfGBKfMLGsxhwL-HzsDRUnK2U7x2p7SMVmHlrVMz8m5mBwCx-ynqko9vUmwewKXRUfaL1QvYA0xaJwxL_pa_U1fcmRuXPwJ_ed2vNIdJ6JwcTPzxihdYs-wPGuWPM.ejGdI847MWWxc_W_DKge8w

View File

@ -0,0 +1 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMi0wNS0zMSAxNzowNToyNy40ODgzODY2MTIgLTA1MDAgQ0RUIG09KzM3LjIyMjU5MTA4MCIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6Ik10d3dTMFR3N0NSM1FrLXgifQ.GO-ec6b-MW2eyfbyJS-bn8NRAQL190eRG17v4Dv2FYkKndmCVcydjA.bj6j7-hDIRppqn-L.3t7SVJY1U2RIAtLieEHP3DiVD7cD4mgaFIdGVQqmMthAID4-Ne07Iy_4IFxuas5oHVf_9yCqOALS1FTGUU1gcCSbrXdUufzflyexInWpb4l1jqGvYzZUcr7tD7WJDSWQbhxO8Ggcb_vF_jTRx8GU6pJeizLxMdD_0sA8C0pWn47oO2cC_N7jrx-g62K_t9JkbjvygCBuP2DIWvjLX6Ig59_lG_jB4BFUruhXo-drjQV5J7anLraqRsAn3nqSXQ.dfw5pq-rAcC9xFCkX8mD_g

View File

@ -0,0 +1 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMi0wNS0zMSAxNzowNjo1Mi42ODM3OTA1NSAtMDUwMCBDRFQgbT0rMTAuMTU1MjQ4NjU5IiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiMENfT3lsQU5vYnJyd0JHSSJ9.nd79n9a2KbrX6bNv51BzsOQnPcUbJmtqIbj5lJnbO826GHNfuoWVbg.gPGVIse3bHLLWxd-.YCi3Y7u-aO48IBln6Opjdl81LyZegP7YNF3WEhtDbvxYGpSj6Q8ggG1KIFJZRf6bKgy1B5PQo7mUtWKw5YFRyUCDctLJi-4V-FaWqykih6X8kf6gRQhVmCbz5JHv7V9K4Wm51A-UOfBi46rzbywuAXNBeYSgGw2ucWRyYhwXO5zB0X2vAZ6hUS4yTEraCz9RRvoRC9G5nfu3gSRSwCFCf3TSdyKp40c8tOlYPiTtavEgVNuvgzNEuzjXsxXY938APRUIckDSAa0-LSKeYx2et7O7HTWjVEIgNv-907u1sXqbA-DeuIq6_EhwwS5B2jTNhoAkp32mvpwLQC15Jdo7LskUbESQu8N3DrOUFXN8j-kYAH4Zh5HTEn5i4uz1tF_Tx1w.mlzvK0xujvbyS8xyVWXKMg

View File

@ -0,0 +1 @@
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMi0wNS0zMSAxNzowNToyNy40ODA1MzY2NTggLTA1MDAgQ0RUIG09KzM3LjIxNDc0MTE5MCIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6Im45Vl9EakdZZ1N0RXU1bnkifQ.BpH3FNLHuQW-ywr_XvufMJyyeaVlKEHGpsm7nPKOqnv2eBFXz09iGQ.mxA8P-a7Yhy68mjo.Gx6JJWO1kxGwB_oUZk5TcTB7VuG9W9iNFkZp07CgucjCVndd3iyFtjEbfuY8AJreBFachD9fFHbFscQyXrY1tbBwDSaYjqSti8Fz0GSa4y9uOKTsct_-UDD5LnEH88-qARA3tBTmKecliZnF1clHEYWq31SUgEJIgYFzqij7F-43qmjCtgSKqEovkW-q6LK-b_V0MGNDeOg-dcNERLwW8M3gIlyUirnktpVHk-qWXi0asB9bY0RbCyl_hhw5y32kmRwHYRzO-XVirzbV--b5f2UgQLWfELDbHkFiDQfO0wMFWpSqw4op5SBcPDxtsi4cx1U2948hg-CCw05rOtzXN-AqDbWqH-fO9DF16jXPg0xRyuHr75_gt-Qnag.ZtKP7Ql7fVYJXS18DCD4bQ

View File

@ -0,0 +1,24 @@
package main
import (
"os"
"github.com/certusone/wormhole-chain/app"
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
"github.com/tendermint/spm/cosmoscmd"
)
func main() {
rootCmd, _ := cosmoscmd.NewRootCmd(
app.Name,
app.AccountAddressPrefix,
app.DefaultNodeHome,
app.Name,
app.ModuleBasics,
app.New,
// this line is used by starport scaffolding # root/arguments
)
if err := svrcmd.Execute(rootCmd, app.DefaultNodeHome); err != nil {
os.Exit(1)
}
}

View File

@ -0,0 +1,73 @@
# Table of Contents
1. [Inbox](#org155bf00)
1. [Bootstrap chain](#org819971b)
2. [Onboarding guardians](#org60d7dc9)
<a id="org155bf00"></a>
# Inbox
<a id="org819971b"></a>
## TODO Bootstrap chain
The native token of the Wormhole chain is $WORM. This token is used both for
staking (governance) and fees. These tokens are already minted on Solana, and
they won't be available initially at the genesis of the chain. This presents
a number of difficulties around bootstrapping.
At genesis, the blockchain will be set up in the following way
1. The staking denom is set to the $WORM token (of which 0 exist on this chain at this moment)
2. Producing blocks uses Proof of Authority (PoA) consensus (i.e. no tokens are required to produce blocks)
3. Fees are set to 0
Then, the $WORM tokens can be transferred over from Solana, and staking (with
delegation) can be done. At this stage, two different consensus mechanisms will
be in place simultaneously: block validation and guardian set election will
still use PoA, with each guardian having a singular vote. All other governance
votes will reach consensus with DPoS by staking $WORM tokens.
<a id="org60d7dc9"></a>
## TODO Onboarding guardians
The validators of wormhole chain are going to be the 19 guardians. We need a
way to connect their existing guardian public keys with their wormhole chain
addresses. We will have a registration process where a validator can register a
guardian public key to their validator address. This will entail
signing their wormhole address with their guardian private key, and sending
that signature from their wormhole address. At this point, if the signature
matches, the wormhole address becomes associated with the guardian public key.
After this, the guardian is eligible to become a validator.
Wormhole chain uses the ECDSA secp256k1 signature scheme, which is the same as what
the guardian signatures use, so we could directly derive a wormhole account for
them, but we choose not to do this in order to allow guardian key rotation.
priv = ... // guardian private key
addr = sdk.AccAddress(priv.PubKey().Address())
In theory it is possible to have multiple active guardian sets simultaneously
(e.g. during the expiration period of the previous set). We only want one set of
guardians to be able to produce blocks, so we store the latest validator set
(which should typically by a pointer to the most recent guardian set). We have to
be careful here, because if we update the guardian set to a new set where a
superminority of guardians are not online yet, they won't be able to register
themselves after the switch, since block production will come to a halt, and the
chain becomes deadlocked.
Thus we must only change over block production due to a guardian set update if a supermajority of guardians
in the new guardian set are already registered.
At present, Guardian Set upgrade VAAs are signed by the Guardians off-chain. This can stay off-chain for as long as needed, but should eventually be moved on-chain.
## TODO Bootstraping the PoA Network
At time of writing, the Guardian Network is currently at Guardian Set 2, but will possibly be at set 3 or 4 by the time of launch.
It is likely not feasible to launch the chain with all 19 Guardians of the network hardcoded in the genesis block, as this would require the Guardians to determine their addresses off-chain, and have their information encoded in the genesis block.
As such, it is likely simpler to launch Wormhole Chain with a single validator (The guardian from Guardian Set 1), then have all the other Guardians perform real on-chain registrations for themselves, and then perform a Guardian Set upgrade directly to the current Guardian set.

View File

@ -0,0 +1,83 @@
# Wormhole Chain PoA Architecture Design
The Wormhole Chain is intended to operate via the same PoA mechanism as the rest of the Wormhole ecosystem. This entails the following:
- Two thirds of the Consensus Guardian Set are required for consensus. (In this case, block production.)
- Guardian Sets are upgraded via processing Guardian Set Upgrade Governance VAAs.
As such, the intent is that the 19 guardians will validate for Wormhole Chain, and Wormhole Chain consensus will be achieved when 14 Guardians vote to approve a block (via Tendermint). This means that we will need to hand-roll a PoA mechanism in the Cosmos-SDK on top of Tendermint and the normal Cosmos Staking module.
## High-Level PoA Design Overview
At any given time in the Wormhole Network, there is an "Latest Guardian Set". This is defined as the highest index Guardian Set, and is relevant outside of Wormhole Chain as well. The 'Latest Guardian Set' is meant to be the group of Guardians which is currently signing VAAs.
Because the Guardian keys are meant to sign VAAs, and not to produce blocks on a Cosmos blockchain, the Guardians will have to separately host validators for Wormhole Chain, with different addresses, and then associate the addresses of their validator nodes to their Guardian public keys.
Once an association has been created between the validator and its Guardian Key, the validator will be considered a 'Guardian Validator', and will be awarded 1 consensus voting power. The total voting power is equal to the size of the Consensus Guardian Set, and at least two thirds of the total voting power must vote to create a block.
The Consensus Guardian Set is a distinct term from the Latest Guardian Set. This is because the Guardian Set Upgrade VAA is submitted via a normal Wormhole Chain transaction. When a new Latest Guardian Set is created, many of the Guardians in the new set may not have yet registered as Guardian Validators. Thus, the older Guardian Set must remain marked as the Consensus Set until enough Guardians from the new set have registered.
## Validator Registration:
First, validators must be able to join the Wormhole Chain Tendermint network. Validator registration is identical to the stock Cosmos-SDK design. Validators may bond and unbond as they would for any other Cosmos Chain. However, all validators have 0 consensus voting power, unless they are registered as a Guardian Validator, wherein they will have 1 voting power.
## Mapping Validators to Guardians:
Bonded Validators may register as Guardian Validators by submitting a transaction on-chain. This requires the following criteria:
- The validator must be bonded.
- The validator must hash their Validator Address (Operator Address), sign it with one of the Guardian Keys from the Latest Guardian Set (Note: Latest set, not necessarily Consensus Set.), and then submit this signature in a transaction to the RegisterValidatorAsGuardian function.
- The transaction must be signed/sent from the Validator Address.
- The validator must not have already registered as a different Guardian from the same set.
A Guardian Public Key may only be registered to a single validator at a time. If a new validator proof is received for an existing Guardian Validator, the previous entry is overwritten. As an optional defense mechanism, the registration proofs could be limited to only Guardian Keys in the Latest set.
## Guardian Set Upgrades
Guardian Set upgrades are the trickiest operation to handle. When processing the Guardian Set Upgrade, the following steps happen:
- The Latest Guardian Set is changed to the new Guardian Set.
- If all Guardian Keys in the new Latest Guardian Set are registered, the Latest Guardian Set automatically becomes the new Consensus Guardian Set. Otherwise, the Latest Guardian Set will not become the Consensus Guardian Set until this threshold is met.
## Benefits of this implementation:
- Adequately meets the requirement that Guardians are responsible for consensus and block production on Wormhole Chain.
- Relatively robust with regard to chain 'bricks'. If at any point in the life of Wormhole Chain less than 14 of the Guardians in the Consensus Set are registered, the network will deadlock. There will not be enough Guardians registered to produce a block, and because no blocks are being produced, no registrations can be completed. This design does not change the Consensus Set unless a sufficient amount of Guardians are registered.
- Can swap out a massive set of Guardians all at once. Many other (simpler) designs for Guardian set swaps limit the number of Guardians which can be changed at once to only 6 to avoid network deadlocks. This design does not have this problem.
- No modifications to Cosmos SDK validator bonding.
### Cons
- Moderate complexity. This is more complicated than the most straightforward implementations, but gains important features and protections to prevent deadlocks.
- Not 100% immune to deadlocks. If less than 14 Guardians have valid registrations, the chain will permanently halt. This is prohibitively difficult to prevent with on-chain mechanisms, and unlikely to occur. Performing a simple hard fork in the scenario of a maimed Guardian Validator set is likely the safer and simpler option.
- Avoids some DOS scenarios by only allowing validator registrations for known Guardian Keys.
## Terms & Phrases:
### Guardian
- One of the entities approved to sign VAAs on the Wormhole network. Guardians are identified by the public key which they use to sign VAAs.
### Guardian Set
- A collection of Guardians which at one time was approved by the Wormhole network to produce VAAs. These collections are identified by their sequential 'Set Index'.
### Latest Guardian Set
- The highest index Guardian Set.
### Consensus Guardian Set
- The Guardian Set which is currently being used to produce blocks on Wormhole Chain. May be different from the Latest Guardian Set.
### Guardian Set Upgrade VAA
- A Wormhole network VAA which specifies a new Guardian Set. Emitting a new Guardian Set Upgrade VAA is the mechanism which creates a new Guardian Set.
### Validator
- A node on Wormhole Chain which is connected to the Tendermint peer network.
### Guardian Validator
- A Validator which is currently registered against a Guardian Public Key in the Consensus Guardian Set

View File

@ -0,0 +1,83 @@
# Wormhole Chain Roadmap
## Why Wormhole Chain?
At the time of writing, the Wormhole Guardian Network is a decentralized network of 19 validators operating in a Proof-of-Authority consensus mechanism. They validate using the guardiand program from the Wormhole core repository, and perform governance off-chain. There are currently no features to the Wormhole Guardian Network except the core function of observing and signing VAAs.
The roadmap is that as Wormhole grows and matures, it will add more advanced features, such as Accounting, Wormhole Pipes, Cross-Chain Queries, and more. It will also move its governance, VAA generation, and validator on-boarding to a formalized process, and change its governance structure from PoA to another mechanism (possibly a modified Proof of Stake mechanism).
Considering that future Wormhole governance is intended to be token based, and that many of these upcoming features are incentivized via fee or staking mechanisms, the obvious path forward is to launch a purpose-built blockchain to support this vision.
## Why Cosmos?
When building a new blockchain, there are not particularly many options. The primary options are:
- Fork an existing blockchain
- Use the Cosmos SDK
- Build one from scratch
- Implement into an existing environment (parachain), or implement as a layer 2.
There is not any blockchain in particular which stands out to be forked, and most forked blockchains (such as Ethereum), would require maintaining a smart-contract runtime, which is an unnecessary overhead for Wormhole Chain.
The Cosmos SDK is the most sensible choice, as its extensible 'module' system allows for the outlined features of Wormhole Chain to be easily added to the out-of-the-box runtime. Additionally, the Cosmos SDK's use of Tendermint for its consensus mechanism can easily be modified to support Proof of Authority for block production, while still allowing stake-weighted on-chain voting for governance. In the future, PoA can also be seamlessly swapped out for an entirely PoS system. Using the Cosmos SDK will also open up the opportunity for the Wormhole ecosystem to directly leverage the IBC protocol.
Because the Cosmos SDK is able to support the planned feature set of Wormhole Chain, building it from scratch would largely be a case of 'reinventing the wheel', and even potentially sacrifice features, such as IBC support.
The last option would be to implement the chain as a layer two, or integrate as a parachain in an existing environment like Polkadot. Both of these create dependencies and constraints for Wormhole which would make it hard to hand-roll a consensus mechanism or unilaterally develop new functionality.
## Wormhole Chain Explorer
Every blockchain should have an explorer, as it is a useful tool. The primary Cosmos blockchain explorers are shown here:
https://github.com/cosmos/awesome#block-explorers
Of the explorers listed, the two most popular and well-supported appear to be PingPub, and Big Dipper v2.
Big Dipper seems to be the more robust, popular, and feature-rich of the two. Its only downside appears to be that it (quite reasonably) requires an external database. It also has the added benefit of being built in React, which will be easier to support, and allow the blockchain explorer to be more easily merged with the existing Wormhole Network Explorer. For these reasons, it stands out as being the best production candidate.
PingPub (LOOK Explorer) has the benefit of only requiring an LCD connection. Because it is very easy to run, it may be useful as a development tool.
# Feature Roadmap
The upcoming Wormhole Chain features fall into four categories, roughly arranged in their dependency ordering.
- Basic Functionality
- Accounting
- Governance
- New Cross-Chain Functionality
## Basic Functionality
This category contains the critical features which allow Wormhole Chain to produce blocks, and for downstream functions to exist.
### Proof of Authority Block Production
The 19 Guardians of the current Wormhole Network will also serve as the 19 validators for the Wormhole Chain. Furthermore, new Guardians must be able to register as validators on the Wormhole Chain, so that the Guardian Set Upgrade VAAs can be submitted in a Wormhole Chain transaction to change its validator set, akin to the process on other chains.
### Core Bridge and Token Bridge
Wormhole Chain will contain critical functions for the Wormhole network, but it will also be another connected chain to the network. As such it will need an implementation of the Wormhole Core Bridge and Token Bridge.
## Accounting
Accounting is a defense-in-depth security mechanism, whereby the guardians will keep a running total of the circulating supply of each token on each chain, and refuse to issue VAAs for transfers which are logically impossible (as they must be the result of an exploit or 51% attack).
More advanced mechanisms of accounting are planned as well, which would track token custody at a finer level to detect and prevent exploits from propagating across chains.
There is also the option to move the current gossip network by which the guardians sign VAAs on-chain, which could allow for accounting to be more tightly integrated into the signing process.
## Governance
While block production will initially be PoA, the governance mechanism is intended to launch with on-chain voting in a PoS system.
In order to vote, users will have to transfer and stake $WORM tokens from another chain. The on-chain voting process should otherwise be quite similar to other Cosmos chains.
## New Cross-Chain Functionality
### Cross-Chain Queries
Cross Chain queries are a mechanism by which read-only data can be requested from a chain without actually submitting a transaction on that chain. For example, a user could request a VAA for the current balance of an Ethereum wallet by submitting a transaction Wormhole Chain. This would be a unified location to request data from any chain, and be a tremendous cost-saving mechanism over executing transactions on other L1s.
### Wormhole Pipes
Wormhole pipes are similar to Cross-Chain queries, but act via a 'Push' model whereby contracts can subscribe to systematically read data from other chains. Subscriptions would be managed via Wormhole Chain.
### Many others
Going forward, Wormhole Chain will be an excellent mechanism for both the public to interact with the Guardian network, and for the Guardians to communicate between themselves. As such, Wormhole Chain should become the primary mechanism by which requests are made to the Guardians, and how new oracle features are implemented.

View File

@ -0,0 +1,88 @@
# Develop
## prerequsites
- Go >= 1.16
- Starport: `curl https://get.starport.network/starport@v0.19.5! | sudo bash
- nodejs >= 16
## Building the blockchain
Run
```shell
make
```
This command creates a `build` directory and in particular, the
`build/wormhole-chaind` binary, which can be used to run and interact with the
blockchain.
You can start a local development instance by running
```shell
make run
```
Or equivalently
```shell
./build/wormhole-chaind --home build
```
If you want to reset the blockchain, just run
```shell
make clean
```
Then you can `make run` again.
## Running tests
Golang tests
make test
Client tests, run against the chain. Wormchain must be running via `starport chain serve`, `make run` or `tilt up`
cd ./ts-sdk
npm ci
npm run build
cd ../testing/js
npm ci
npm run test
## Interacting with the blockchain
You can interact with the blockchain by using the go binary:
```shell
./build/wormhole-chaind tx tokenbridge execute-governance-vaa 01000000000100e86068bfd49c7209f259110dc061012ca6d65318f3879325528c57cf3e4950ff1295dbde77a4c72f3aee29a32a07099257521674725be8eb8bbd801349a828c30100000001000000010001000000000000000000000000000000000000000000000000000000000000000400000000038502e100000000000000000000000000000000000000000000546f6b656e4272696467650100000001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f --from tiltGuardian --home build
```
Note the flags `--from tiltGuardian --home build`. These have to be passed
in each time you make a transaction (the `tiltGuardian` account is created in
`config.yml`). Queries don't need the `--from` flag.
## Scaffolding stuff with starport
TODO: expand explanation here
```shell
starport scaffold type guardian-key key:string --module wormhole --no-message
```
modify `proto/wormhole/guardian_key.proto` (string -> bytes)
```shell
starport scaffold message register-account-as-guardian guardian-pubkey:GuardianKey address-bech32:string signature:string --desc "Register a guardian public key with a wormhole chain address." --module wormhole --signer signer
```
Scaffold a query:
```shell
starport scaffold query latest_guardian_set_index --response LatestGuardianSetIndex --module wormhole
```
(then modify "wormhole_chain/x/wormhole/types/query.pb.go" to change the response type)

View File

@ -0,0 +1,6 @@
package docs
import "embed"
//go:embed static
var Docs embed.FS

View File

@ -0,0 +1,242 @@
{
"result": {
"query": "tm.event='Tx'",
"data": {
"type": "tendermint/event/Tx",
"value": {
"TxResult": {
"height": "8583",
"tx": "Cp0BCpoBCjAvY2VydHVzb25lLndvcm1ob2xlY2hhaW4udG9rZW5icmlkZ2UuTXNnVHJhbnNmZXISZgovd29ybWhvbGUxd3F3eXdrY2U1MG1nNjA3N2h1eTRqOXk4bHQ4MDk0M2tzNXVkenISDAoFdWhvbGUSAzEwMBgCIiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoBMBJYClAKRgofL2Nvc21vcy5jcnlwdG8uc2VjcDI1NmsxLlB1YktleRIjCiECkmL8JjZEbLMDlxC0PBT1z6jtPw4T5KOuBwbk/AsyNM8SBAoCCAEYDRIEEMCaDBpA7S2taziRjKoisL0iSt1wq6VJixB+t+9YMOOD1F5lm/hvG1uxOOxM90c+QNWpwIq3O4FwyjG6IrodNN+uNOIX0A==",
"result": {
"data": "CjIKMC9jZXJ0dXNvbmUud29ybWhvbGVjaGFpbi50b2tlbmJyaWRnZS5Nc2dUcmFuc2Zlcg==",
"log": [
{
"events": [
{
"type": "certusone.wormholechain.wormhole.EventPostedMessage",
"attributes": [
{
"key": "emitter",
"value": "AAAAAAAAAAAAAAAAFxHNY7LFRe5lRUFdPMC9pkJcQ8Q="
},
{ "key": "sequence", "value": "13" },
{ "key": "nonce", "value": "0" },
{
"key": "payload",
"value": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdWhvbGUMIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
}
]
},
{
"type": "coin_received",
"attributes": [
{
"key": "receiver",
"value": "wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z"
},
{ "key": "amount", "value": "100uworm" }
]
},
{
"type": "coin_spent",
"attributes": [
{
"key": "spender",
"value": "wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr"
},
{ "key": "amount", "value": "100uworm" }
]
},
{
"type": "message",
"attributes": [
{ "key": "action", "value": "Transfer" },
{
"key": "sender",
"value": "wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr"
}
]
},
{
"type": "transfer",
"attributes": [
{
"key": "recipient",
"value": "wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z"
},
{
"key": "sender",
"value": "wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr"
},
{ "key": "amount", "value": "100uworm" }
]
}
]
}
],
"gas_wanted": "200000",
"gas_used": "56956",
"events": [
{
"type": "tx",
"attributes": [
{
"key": "ZmVl",
"value": "",
"index": true
}
]
},
{
"type": "tx",
"attributes": [
{
"key": "YWNjX3NlcQ==",
"value": "d29ybWhvbGUxd3F3eXdrY2U1MG1nNjA3N2h1eTRqOXk4bHQ4MDk0M2tzNXVkenIvMTM=",
"index": true
}
]
},
{
"type": "tx",
"attributes": [
{
"key": "c2lnbmF0dXJl",
"value": "N1MydGF6aVJqS29pc0wwaVN0MXdxNlZKaXhCK3QrOVlNT09EMUY1bG0vaHZHMXV4T094TTkwYytRTldwd0lxM080Rnd5akc2SXJvZE5OK3VOT0lYMEE9PQ==",
"index": true
}
]
},
{
"type": "message",
"attributes": [
{
"key": "YWN0aW9u",
"value": "VHJhbnNmZXI=",
"index": true
}
]
},
{
"type": "coin_spent",
"attributes": [
{
"key": "c3BlbmRlcg==",
"value": "d29ybWhvbGUxd3F3eXdrY2U1MG1nNjA3N2h1eTRqOXk4bHQ4MDk0M2tzNXVkenI=",
"index": true
},
{
"key": "YW1vdW50",
"value": "MTAwdWhvbGU=",
"index": true
}
]
},
{
"type": "coin_received",
"attributes": [
{
"key": "cmVjZWl2ZXI=",
"value": "d29ybWhvbGUxenVndTZjYWpjNHo3dWUyOWc5d25lczlhNWVwOWNzN3l1N3JuM3o=",
"index": true
},
{
"key": "YW1vdW50",
"value": "MTAwdWhvbGU=",
"index": true
}
]
},
{
"type": "transfer",
"attributes": [
{
"key": "cmVjaXBpZW50",
"value": "d29ybWhvbGUxenVndTZjYWpjNHo3dWUyOWc5d25lczlhNWVwOWNzN3l1N3JuM3o=",
"index": true
},
{
"key": "c2VuZGVy",
"value": "d29ybWhvbGUxd3F3eXdrY2U1MG1nNjA3N2h1eTRqOXk4bHQ4MDk0M2tzNXVkenI=",
"index": true
},
{
"key": "YW1vdW50",
"value": "MTAwdWhvbGU=",
"index": true
}
]
},
{
"type": "message",
"attributes": [
{
"key": "c2VuZGVy",
"value": "d29ybWhvbGUxd3F3eXdrY2U1MG1nNjA3N2h1eTRqOXk4bHQ4MDk0M2tzNXVkenI=",
"index": true
}
]
},
{
"type": "certusone.wormholechain.wormhole.EventPostedMessage",
"attributes": [
{
"key": "ZW1pdHRlcg==",
"value": "IkFBQUFBQUFBQUFBQUFBQUFGeEhOWTdMRlJlNWxSVUZkUE1DOXBrSmNROFE9Ig==",
"index": true
},
{
"key": "c2VxdWVuY2U=",
"value": "IjEzIg==",
"index": true
},
{
"key": "bm9uY2U=",
"value": "MA==",
"index": true
},
{
"key": "cGF5bG9hZA==",
"value": "IkFRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUJrQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBZFdodmJHVU1JQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBSUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUE9PSI=",
"index": true
}
]
}
]
}
}
}
},
"events": {
"coin_spent.spender": ["wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr"],
"coin_received.amount": ["100uworm"],
"transfer.amount": ["100uworm"],
"tx.acc_seq": ["wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr/13"],
"message.action": ["Transfer"],
"certusone.wormholechain.wormhole.EventPostedMessage.nonce": ["0"],
"tx.hash": [
"0A623859DCEBE1DCAC077D6D8B459BBF6FB199B18FCC5A3B9518EB3F36F25BE5"
],
"tx.fee": [""],
"message.sender": ["wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr"],
"coin_received.receiver": [
"wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z"
],
"transfer.recipient": ["wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z"],
"certusone.wormholechain.wormhole.EventPostedMessage.sequence": ["13"],
"tx.height": ["8583"],
"tx.signature": [
"7S2taziRjKoisL0iSt1wq6VJixB+t+9YMOOD1F5lm/hvG1uxOOxM90c+QNWpwIq3O4FwyjG6IrodNN+uNOIX0A=="
],
"coin_spent.amount": ["100uworm"],
"certusone.wormholechain.wormhole.EventPostedMessage.payload": [
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdWhvbGUMIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
],
"tm.event": ["Tx"],
"transfer.sender": ["wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr"],
"certusone.wormholechain.wormhole.EventPostedMessage.emitter": [
"AAAAAAAAAAAAAAAAFxHNY7LFRe5lRUFdPMC9pkJcQ8Q="
]
}
}
}

View File

@ -0,0 +1,49 @@
# Register wormhole chain on other chains
The token bridge emitter address is
```
wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z
```
The wormhole (core module) address is:
```
wormhole1ap5vgur5zlgys8whugfegnn43emka567dtq0jl
```
This is deterministically generated from the module.
## Tiltnet
The VAA signed with the tiltnet guardian:
```
0100000000010047464c64a843f49766edc85c9b94b8b142a3315d6cad6c0045fe171f969b68bf52db1f81b9f40ec749b2ca27ebfe7da304c432f278bb9845448595d93a3519af0000000000d1ffc017000100000000000000000000000000000000000000000000000000000000000000045f2397a84b3f90ce20000000000000000000000000000000000000000000546f6b656e4272696467650100000c200000000000000000000000001711cd63b2c545ee6545415d3cc0bda6425c43c4
```
Rendered:
```
┌──────────────────────────────────────────────────────────────────────────────┐
│ Wormhole VAA v1 │ nonce: 3523198999 │ time: 0 │
│ guardian set #0#6855489806860783822 │ consistency: 32 │
├──────────────────────────────────────────────────────────────────────────────┤
│ Signature: │
#0: 47464c64a843f49766edc85c9b94b8b142a3315d6cad6c0045fe171f969b... │
├──────────────────────────────────────────────────────────────────────────────┤
│ Emitter: 11111111111111111111111111111115 (Solana) │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Chain registration (TokenBridge) │
│ Emitter chain: Wormhole │
│ Emitter address: wormhole1zugu6cajc4z7ue29g9wnes9a5ep9cs7yu7rn3z (Wormhole) │
└──────────────────────────────────────────────────────────────────────────────┘
```
## Testnet
TBD (need to be signed by testnet guardian)
## Mainnet
TBD (need to be signed by the most recent guardian set)

48392
wormhole_chain/docs/static/openapi.yml vendored Normal file

File diff suppressed because it is too large Load Diff

31
wormhole_chain/go.mod Normal file
View File

@ -0,0 +1,31 @@
module github.com/certusone/wormhole-chain
go 1.16
require (
github.com/certusone/wormhole/node v0.0.0-20211115153408-0a93202f6e5d
github.com/cosmos/cosmos-sdk v0.45.7
github.com/cosmos/ibc-go v1.2.2
github.com/ethereum/go-ethereum v1.10.6
github.com/gogo/protobuf v1.3.3
github.com/golang/glog v1.0.0 // indirect
github.com/golang/protobuf v1.5.2
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/holiman/uint256 v1.2.0
github.com/spf13/cast v1.5.0
github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.8.0
github.com/tendermint/spm v0.1.9
github.com/tendermint/tendermint v0.34.20
github.com/tendermint/tm-db v0.6.7
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd
google.golang.org/grpc v1.48.0
)
replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
github.com/cosmos/cosmos-sdk v0.45.7 => github.com/wormhole-foundation/cosmos-sdk v0.45.7-wormhole
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
google.golang.org/grpc => google.golang.org/grpc v1.33.2
)

2834
wormhole_chain/go.sum Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
--------------------------------------------------------------------------------
Registration (polygon)
ckiss@R2F2R41 wormhole-chaind % ./main tx tokenbridge execute-governance-vaa 0100000000010019db40bb49a6519e3d15d94cd3569c7a587152862ec99717d42df5dd57882d0e66dee89ff51c9e9b9517fda0d3237946412d0da31a468c18b0a6b50b4e46d5ec01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000489b7ee00000000000000000000000000000000000000000000546f6b656e4272696467650100000005000000000000000000000000377d55a7928c046e18eebb61977e714d2a76472a --from tiltGuardian --home ../../build
code: 0
codespace: ""
data: 0A3E0A3C2F6365727475736F6E652E776F726D686F6C65636861696E2E746F6B656E6272696467652E4D736745786563757465476F7665726E616E6365564141
gas_used: "49411"
gas_wanted: "200000"
height: "1686"
info: ""
logs:
- events:
- attributes:
- key: emitterAddress
value: '"AAAAAAAAAAAAAAAAN31Vp5KMBG4Y7rthl35xTSp2Ryo="'
- key: chainID
value: "5"
type: certusone.wormholechain.tokenbridge.EventChainRegistered
- attributes:
- key: action
value: ExecuteGovernanceVAA
type: message
log: ""
msg_index: 0
raw_log: '[{"events":[{"type":"certusone.wormholechain.tokenbridge.EventChainRegistered","attributes":[{"key":"emitterAddress","value":"\"AAAAAAAAAAAAAAAAN31Vp5KMBG4Y7rthl35xTSp2Ryo=\""},{"key":"chainID","value":"5"}]},{"type":"message","attributes":[{"key":"action","value":"ExecuteGovernanceVAA"}]}]}]'
timestamp: ""
tx: null
txhash: BA52B1E363322730E40BB203D73FBDBD93853CD1057C0DC975F2BC36B7E8A907
--------------------------------------------------------------------------------
Send 100 utest out
./main tx tokenbridge transfer 100utest 5 000000000000000000000000e99c31abdcbed4e6d31d276b04e02a6fd4b1a861 0 --from tiltGuardian --home ../../build
--------------------------------------------------------------------------------
Devnet guardian #2 keypair:
λ> toHexString (Crypto.exportKey devnetGuardianSecret')
"bfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"
λ> deriveEthPubkey devnetGuardianSecret'
a75a14f140c22d691bb0b19b4a51fae5b77f9d89
Create new
λ> myGuardianSetUpgrade
┌──────────────────────────────────────────────────────────────────────────────┐
│ Wormhole VAA v1 │ nonce: 1155723085 │ time: 0 │
│ guardian set #0 │ #5045183322996712854 │ consistency: 32 │
├──────────────────────────────────────────────────────────────────────────────┤
│ Signature: │
│ #0: 35a5da3648df687185296528e404d101f5a20f4f8915d94046e0e4243f6b... │
├──────────────────────────────────────────────────────────────────────────────┤
│ Emitter: 11111111111111111111111111111115 (Solana) │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Guardian set upgrade to #1 │
│ Keys: │
│ #0 : 0xa75a14f140c22d691bb0b19b4a51fae5b77f9d89 │
└──────────────────────────────────────────────────────────────────────────────┘
λ> serialiseVAA it
"0100000000010035a5da3648df687185296528e404d101f5a20f4f8915d94046e0e4243f6b443d12d5899f50a8b83fe77c9970c08f458068f7f48555b6fb11269d959d3372a7fd000000000044e2ef4d000100000000000000000000000000000000000000000000000000000000000000044604178071f1a5962000000000000000000000000000000000000000000000000000000000436f72650200000000000101a75a14f140c22d691bb0b19b4a51fae5b77f9d89"
λ> transfer uwormAddress solanaTokenBridge devnetWallet1 10000000000000000 Nothing
┌──────────────────────────────────────────────────────────────────────────────┐
│ Wormhole VAA v1 │ nonce: 1856355419 │ time: 0 │
│ guardian set #0 │ #2252519879372323853 │ consistency: 32 │
├──────────────────────────────────────────────────────────────────────────────┤
│ Signature: │
│ #0: 167fddaf3b94aa48975829abfa0f52b6f48ad97f67a6d62c928ad5159964... │
├──────────────────────────────────────────────────────────────────────────────┤
│ Emitter: ENG1wQ7CQKH8ibAJ1hSLmJgL9Ucg6DRDbj752ZAfidLA (Solana) │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Token transfer │
│ Amount: 100000000.0 │
│ Token: 2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ (Solana) │
│ Recipient: wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq (Wormhole) │
│ Fee: 0.0 │
└──────────────────────────────────────────────────────────────────────────────┘
λ> serialiseVAA it
"01000000000100167fddaf3b94aa48975829abfa0f52b6f48ad97f67a6d62c928ad5159964471d3b3f465077aa08dc5311f3adbc92e76d6e7a2c114cad4a09297cd150336520b100000000006ea5bc5b0001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f1f428ee55b7e3c0d2001000000000000000000000000000000000000000000000000002386f26fc10000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000c10820983f33456ce7beb3a046f5a83fa34f027d0c200000000000000000000000000000000000000000000000000000000000000000"
λ> transfer uwormAddress solanaTokenBridge devnetWallet2 20000000000000000 Nothing
┌──────────────────────────────────────────────────────────────────────────────┐
│ Wormhole VAA v1 │ nonce: 376017944 │ time: 0 │
│ guardian set #0 │ #95069053037693418 │ consistency: 32 │
├──────────────────────────────────────────────────────────────────────────────┤
│ Signature: │
│ #0: 03319407d687b0e337905d85e6bb23ca3cb04167c49e6585e5c6f2d5da4b... │
├──────────────────────────────────────────────────────────────────────────────┤
│ Emitter: ENG1wQ7CQKH8ibAJ1hSLmJgL9Ucg6DRDbj752ZAfidLA (Solana) │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Token transfer │
│ Amount: 200000000.0 │
│ Token: 2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ (Solana) │
│ Recipient: wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr (Wormhole) │
│ Fee: 0.0 │
└──────────────────────────────────────────────────────────────────────────────┘
λ> serialiseVAA it
"0100000000010003319407d687b0e337905d85e6bb23ca3cb04167c49e6585e5c6f2d5da4b1d5739e865bcf38e3ae8ba5bc9c967b3477a33df0ce659e9879f488dc3ccf176fb5e0000000000166994180001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f0151c0cccf71c9ea200100000000000000000000000000000000000000000000000000470de4df820000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000701c475b19a3f68d3fdebf09591487facef2d6360c200000000000000000000000000000000000000000000000000000000000000000"
λ> transfer uwormAddress solanaTokenBridge devnetWallet1 11000000000000000 Nothing
┌──────────────────────────────────────────────────────────────────────────────┐
│ Wormhole VAA v1 │ nonce: 1672020332 │ time: 0 │
│ guardian set #1 │ #14601047132816392294 │ consistency: 32 │
├──────────────────────────────────────────────────────────────────────────────┤
│ Signature: │
│ #0: 938362116fc18edca1adec84515c7a62387cff995e65d0833696f911284a... │
├──────────────────────────────────────────────────────────────────────────────┤
│ Emitter: ENG1wQ7CQKH8ibAJ1hSLmJgL9Ucg6DRDbj752ZAfidLA (Solana) │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Token transfer │
│ Amount: 110000000.0 │
│ Token: 2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ (Solana) │
│ Recipient: wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq (Wormhole) │
│ Fee: 0.0 │
└──────────────────────────────────────────────────────────────────────────────┘
λ> serialiseVAA it
"01000000010100938362116fc18edca1adec84515c7a62387cff995e65d0833696f911284a539e068a3097af551683bd07c92a5d5df53f8b7b2cce10a8ccf7fe136344815d995f010000000063a9016c0001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4fcaa15701f441c06620010000000000000000000000000000000000000000000000000027147114878000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000c10820983f33456ce7beb3a046f5a83fa34f027d0c200000000000000000000000000000000000000000000000000000000000000000"
λ> transfer uwormAddress solanaTokenBridge devnetWallet2 21000000000000000 Nothing
┌──────────────────────────────────────────────────────────────────────────────┐
│ Wormhole VAA v1 │ nonce: 2352732195 │ time: 0 │
│ guardian set #1 │ #1862301672562311566 │ consistency: 32 │
├──────────────────────────────────────────────────────────────────────────────┤
│ Signature: │
│ #0: cf6d0dac8dd15eb86f185bf9ebf53f7a15424b35adbc6a50c352e2b91c15... │
├──────────────────────────────────────────────────────────────────────────────┤
│ Emitter: ENG1wQ7CQKH8ibAJ1hSLmJgL9Ucg6DRDbj752ZAfidLA (Solana) │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Token transfer │
│ Amount: 210000000.0 │
│ Token: 2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ (Solana) │
│ Recipient: wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr (Wormhole) │
│ Fee: 0.0 │
└──────────────────────────────────────────────────────────────────────────────┘
λ> serialiseVAA it
"01000000010100cf6d0dac8dd15eb86f185bf9ebf53f7a15424b35adbc6a50c352e2b91c15a298411f79f5a7ed9989db4bf79c50d5d278182b73789dbb825d2a7e4c0a4c15d81601000000008c3bd8230001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f19d8398119b1418e2001000000000000000000000000000000000000000000000000004a9b6384488000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000701c475b19a3f68d3fdebf09591487facef2d6360c200000000000000000000000000000000000000000000000000000000000000000"

View File

@ -0,0 +1,12 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
message ChainRegistration {
uint32 chainID = 1;
bytes emitterAddress = 2;
}

View File

@ -0,0 +1,12 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
message CoinMetaRollbackProtection {
string index = 1;
uint64 lastUpdateSequence = 2;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
import "gogoproto/gogo.proto";
message Config {
}

View File

@ -0,0 +1,27 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
message EventChainRegistered{
uint32 chainID = 1;
bytes emitterAddress = 2;
}
message EventAssetRegistrationUpdate{
uint32 tokenChain = 1;
bytes tokenAddress = 2;
string name = 3;
string symbol = 4;
uint32 decimals = 5;
}
message EventTransferReceived{
uint32 tokenChain = 1;
bytes tokenAddress = 2;
string to = 3;
string feeRecipient = 4;
string amount = 5;
string fee = 6;
string localDenom = 7;
}

View File

@ -0,0 +1,20 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
import "tokenbridge/config.proto";
import "tokenbridge/replay_protection.proto";
import "tokenbridge/chain_registration.proto";
import "tokenbridge/coin_meta_rollback_protection.proto";
// this line is used by starport scaffolding # genesis/proto/import
import "gogoproto/gogo.proto";
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
// GenesisState defines the tokenbridge module's genesis state.
message GenesisState {
Config config = 1;
repeated ReplayProtection replayProtectionList = 2 [(gogoproto.nullable) = false];
repeated ChainRegistration chainRegistrationList = 3 [(gogoproto.nullable) = false];
repeated CoinMetaRollbackProtection coinMetaRollbackProtectionList = 4 [(gogoproto.nullable) = false];
// this line is used by starport scaffolding # genesis/proto/state
}

View File

@ -0,0 +1,113 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "tokenbridge/config.proto";
import "tokenbridge/replay_protection.proto";
import "tokenbridge/chain_registration.proto";
import "tokenbridge/coin_meta_rollback_protection.proto";
// this line is used by starport scaffolding # 1
import "gogoproto/gogo.proto";
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
// Query defines the gRPC querier service.
service Query {
// Queries a config by index.
rpc Config(QueryGetConfigRequest) returns (QueryGetConfigResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/config";
}
// Queries a replayProtection by index.
rpc ReplayProtection(QueryGetReplayProtectionRequest) returns (QueryGetReplayProtectionResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/replayProtection/{index}";
}
// Queries a list of replayProtection items.
rpc ReplayProtectionAll(QueryAllReplayProtectionRequest) returns (QueryAllReplayProtectionResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/replayProtection";
}
// Queries a chainRegistration by index.
rpc ChainRegistration(QueryGetChainRegistrationRequest) returns (QueryGetChainRegistrationResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/chainRegistration/{chainID}";
}
// Queries a list of chainRegistration items.
rpc ChainRegistrationAll(QueryAllChainRegistrationRequest) returns (QueryAllChainRegistrationResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/chainRegistration";
}
// Queries a coinMetaRollbackProtection by index.
rpc CoinMetaRollbackProtection(QueryGetCoinMetaRollbackProtectionRequest) returns (QueryGetCoinMetaRollbackProtectionResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/coinMetaRollbackProtection/{index}";
}
// Queries a list of coinMetaRollbackProtection items.
rpc CoinMetaRollbackProtectionAll(QueryAllCoinMetaRollbackProtectionRequest) returns (QueryAllCoinMetaRollbackProtectionResponse) {
option (google.api.http).get = "/certusone/wormholechain/tokenbridge/coinMetaRollbackProtection";
}
// this line is used by starport scaffolding # 2
}
message QueryGetConfigRequest {}
message QueryGetConfigResponse {
Config Config = 1 [(gogoproto.nullable) = false];
}
message QueryGetReplayProtectionRequest {
string index = 1;
}
message QueryGetReplayProtectionResponse {
ReplayProtection replayProtection = 1 [(gogoproto.nullable) = false];
}
message QueryAllReplayProtectionRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllReplayProtectionResponse {
repeated ReplayProtection replayProtection = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
message QueryGetChainRegistrationRequest {
uint32 chainID = 1;
}
message QueryGetChainRegistrationResponse {
ChainRegistration chainRegistration = 1 [(gogoproto.nullable) = false];
}
message QueryAllChainRegistrationRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllChainRegistrationResponse {
repeated ChainRegistration chainRegistration = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
message QueryGetCoinMetaRollbackProtectionRequest {
string index = 1;
}
message QueryGetCoinMetaRollbackProtectionResponse {
CoinMetaRollbackProtection coinMetaRollbackProtection = 1 [(gogoproto.nullable) = false];
}
message QueryAllCoinMetaRollbackProtectionRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllCoinMetaRollbackProtectionResponse {
repeated CoinMetaRollbackProtection coinMetaRollbackProtection = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// this line is used by starport scaffolding # 3

View File

@ -0,0 +1,12 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
message ReplayProtection {
string index = 1;
}

View File

@ -0,0 +1,56 @@
syntax = "proto3";
package certusone.wormholechain.tokenbridge;
import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
// this line is used by starport scaffolding # proto/tx/import
option go_package = "github.com/certusone/wormhole-chain/x/tokenbridge/types";
// Msg defines the Msg service.
service Msg {
rpc ExecuteGovernanceVAA(MsgExecuteGovernanceVAA) returns (MsgExecuteGovernanceVAAResponse);
rpc ExecuteVAA(MsgExecuteVAA) returns (MsgExecuteVAAResponse);
rpc AttestToken(MsgAttestToken) returns (MsgAttestTokenResponse);
rpc Transfer(MsgTransfer) returns (MsgTransferResponse);
// this line is used by starport scaffolding # proto/tx/rpc
}
message MsgExecuteGovernanceVAA {
string creator = 1;
bytes vaa = 2;
}
message MsgExecuteGovernanceVAAResponse {
}
message MsgExecuteVAA {
string creator = 1;
bytes vaa = 2;
}
message MsgExecuteVAAResponse {
}
message MsgAttestToken {
string creator = 1;
string denom = 2;
}
message MsgAttestTokenResponse {
}
message MsgTransfer {
string creator = 1;
cosmos.base.v1beta1.Coin amount = 2
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
uint32 toChain = 3;
bytes toAddress = 4;
string fee = 5;
}
message MsgTransferResponse {
}
// this line is used by starport scaffolding # proto/tx/message

View File

@ -0,0 +1,14 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
import "gogoproto/gogo.proto";
message Config {
uint64 guardian_set_expiration = 1;
bytes governance_emitter = 2;
uint32 governance_chain = 3;
uint32 chain_id = 4;
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
message ConsensusGuardianSetIndex {
uint32 index = 1;
}

View File

@ -0,0 +1,27 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
message EventGuardianSetUpdate{
uint32 old_index = 1;
uint32 new_index = 2;
}
message EventPostedMessage{
bytes emitter = 1;
uint64 sequence = 2;
uint32 nonce = 3;
uint64 time = 4;
bytes payload = 5;
}
message EventGuardianRegistered{
bytes guardian_key = 1;
bytes validator_key = 2;
}
message EventConsensusSetUpdate{
uint32 old_index = 1;
uint32 new_index = 2;
}

View File

@ -0,0 +1,24 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
import "wormhole/guardian_set.proto";
import "wormhole/config.proto";
import "wormhole/replay_protection.proto";
import "wormhole/sequence_counter.proto";
import "wormhole/consensus_guardian_set_index.proto";
import "wormhole/guardian_validator.proto";
// this line is used by starport scaffolding # genesis/proto/import
import "gogoproto/gogo.proto";
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
// GenesisState defines the wormhole module's genesis state.
message GenesisState {
repeated GuardianSet guardianSetList = 1 [(gogoproto.nullable) = false];
Config config = 2;
repeated ReplayProtection replayProtectionList = 3 [(gogoproto.nullable) = false];
repeated SequenceCounter sequenceCounterList = 4 [(gogoproto.nullable) = false];
ConsensusGuardianSetIndex consensusGuardianSetIndex = 5;
repeated GuardianValidator guardianValidatorList = 6 [(gogoproto.nullable) = false];
// this line is used by starport scaffolding # genesis/proto/state
}

View File

@ -0,0 +1,30 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
import "wormhole/guardian_set.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
// GuardianSetUpdateProposal defines a guardian set update governance proposal
message GuardianSetUpdateProposal {
option (gogoproto.equal) = true;
option (gogoproto.goproto_stringer) = false;
string title = 1;
string description = 2;
GuardianSet newGuardianSet = 3 [(gogoproto.nullable) = false];
}
// GovernanceWormholeMessageProposal defines a governance proposal to emit a generic message in the governance message
// format.
message GovernanceWormholeMessageProposal {
option (gogoproto.equal) = true;
option (gogoproto.goproto_stringer) = false;
string title = 1;
string description = 2;
uint32 action = 3;
bytes module = 4;
uint32 targetChain = 5;
bytes payload = 6;
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
message GuardianKey {
bytes key = 1;
}

View File

@ -0,0 +1,14 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
import "gogoproto/gogo.proto";
message GuardianSet {
option (gogoproto.equal) = true;
uint32 index = 1;
repeated bytes keys = 2;
uint64 expirationTime = 3;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
message GuardianValidator {
bytes guardianKey = 1;
bytes validatorAddr = 2;
}

View File

@ -0,0 +1,163 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
import "google/api/annotations.proto";
import "cosmos/base/query/v1beta1/pagination.proto";
import "wormhole/guardian_set.proto";
import "wormhole/config.proto";
import "wormhole/replay_protection.proto";
import "wormhole/sequence_counter.proto";
import "wormhole/consensus_guardian_set_index.proto";
import "wormhole/guardian_validator.proto";
// this line is used by starport scaffolding # 1
import "gogoproto/gogo.proto";
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
// Query defines the gRPC querier service.
service Query {
// Queries a guardianSet by index.
rpc GuardianSet(QueryGetGuardianSetRequest) returns (QueryGetGuardianSetResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/guardianSet/{index}";
}
// Queries a list of guardianSet items.
rpc GuardianSetAll(QueryAllGuardianSetRequest) returns (QueryAllGuardianSetResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/guardianSet";
}
// Queries a config by index.
rpc Config(QueryGetConfigRequest) returns (QueryGetConfigResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/config";
}
// Queries a replayProtection by index.
rpc ReplayProtection(QueryGetReplayProtectionRequest) returns (QueryGetReplayProtectionResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/replayProtection/{index}";
}
// Queries a list of replayProtection items.
rpc ReplayProtectionAll(QueryAllReplayProtectionRequest) returns (QueryAllReplayProtectionResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/replayProtection";
}
// Queries a sequenceCounter by index.
rpc SequenceCounter(QueryGetSequenceCounterRequest) returns (QueryGetSequenceCounterResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/sequenceCounter/{index}";
}
// Queries a list of sequenceCounter items.
rpc SequenceCounterAll(QueryAllSequenceCounterRequest) returns (QueryAllSequenceCounterResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/sequenceCounter";
}
// Queries a ConsensusGuardianSetIndex by index.
rpc ConsensusGuardianSetIndex(QueryGetConsensusGuardianSetIndexRequest) returns (QueryGetConsensusGuardianSetIndexResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/consensus_guardian_set_index";
}
// Queries a GuardianValidator by index.
rpc GuardianValidator(QueryGetGuardianValidatorRequest) returns (QueryGetGuardianValidatorResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/guardian_validator/{guardianKey}";
}
// Queries a list of GuardianValidator items.
rpc GuardianValidatorAll(QueryAllGuardianValidatorRequest) returns (QueryAllGuardianValidatorResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/guardian_validator";
}
// Queries a list of LatestGuardianSetIndex items.
rpc LatestGuardianSetIndex(QueryLatestGuardianSetIndexRequest) returns (QueryLatestGuardianSetIndexResponse) {
option (google.api.http).get = "/certusone/wormholechain/wormhole/latest_guardian_set_index";
}
// this line is used by starport scaffolding # 2
}
message QueryGetGuardianSetRequest {
uint32 index = 1;
}
message QueryGetGuardianSetResponse {
GuardianSet GuardianSet = 1 [(gogoproto.nullable) = false];
}
message QueryAllGuardianSetRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllGuardianSetResponse {
repeated GuardianSet GuardianSet = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
message QueryGetConfigRequest {}
message QueryGetConfigResponse {
Config Config = 1 [(gogoproto.nullable) = false];
}
message QueryGetReplayProtectionRequest {
string index = 1;
}
message QueryGetReplayProtectionResponse {
ReplayProtection replayProtection = 1 [(gogoproto.nullable) = false];
}
message QueryAllReplayProtectionRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllReplayProtectionResponse {
repeated ReplayProtection replayProtection = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
message QueryGetSequenceCounterRequest {
string index = 1;
}
message QueryGetSequenceCounterResponse {
SequenceCounter sequenceCounter = 1 [(gogoproto.nullable) = false];
}
message QueryAllSequenceCounterRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllSequenceCounterResponse {
repeated SequenceCounter sequenceCounter = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
message QueryGetConsensusGuardianSetIndexRequest {}
message QueryGetConsensusGuardianSetIndexResponse {
ConsensusGuardianSetIndex ConsensusGuardianSetIndex = 1 [(gogoproto.nullable) = false];
}
message QueryGetGuardianValidatorRequest {
bytes guardianKey = 1;
}
message QueryGetGuardianValidatorResponse {
GuardianValidator guardianValidator = 1 [(gogoproto.nullable) = false];
}
message QueryAllGuardianValidatorRequest {
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
message QueryAllGuardianValidatorResponse {
repeated GuardianValidator guardianValidator = 1 [(gogoproto.nullable) = false];
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
message QueryLatestGuardianSetIndexRequest {
}
message QueryLatestGuardianSetIndexResponse {
uint32 latestGuardianSetIndex = 1;
}
// this line is used by starport scaffolding # 3

View File

@ -0,0 +1,12 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
message ReplayProtection {
string index = 1;
}

View File

@ -0,0 +1,12 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
message SequenceCounter {
string index = 1;
uint64 sequence = 2;
}

View File

@ -0,0 +1,33 @@
syntax = "proto3";
package certusone.wormholechain.wormhole;
// this line is used by starport scaffolding # proto/tx/import
import "wormhole/guardian_key.proto";
option go_package = "github.com/certusone/wormhole-chain/x/wormhole/types";
// Msg defines the Msg service.
service Msg {
rpc ExecuteGovernanceVAA(MsgExecuteGovernanceVAA) returns (MsgExecuteGovernanceVAAResponse);
rpc RegisterAccountAsGuardian(MsgRegisterAccountAsGuardian) returns (MsgRegisterAccountAsGuardianResponse);
// this line is used by starport scaffolding # proto/tx/rpc
}
message MsgExecuteGovernanceVAA {
bytes vaa = 1;
string signer = 2;
}
message MsgExecuteGovernanceVAAResponse {
}
message MsgRegisterAccountAsGuardian {
string signer = 1;
GuardianKey guardianPubkey = 2;
bytes signature = 3;
}
message MsgRegisterAccountAsGuardianResponse {
}
// this line is used by starport scaffolding # proto/tx/message

25
wormhole_chain/readme.md Normal file
View File

@ -0,0 +1,25 @@
# wormholechain
**wormholechain** is a blockchain built using Cosmos SDK and Tendermint and created with [Starport](https://github.com/tendermint/starport).
## Develop
See [development.md](./development.md)
## How to run the tests
run either "starport chain serve" or "tilt up"
cd ./ts-sdk
npm ci
npm run build
cd ../testing/js
npm ci
npm run test
## Learn more about Cosmos & Starport
- [Starport](https://github.com/tendermint/starport)
- [Starport Docs](https://docs.starport.network)
- [Cosmos SDK documentation](https://docs.cosmos.network)
- [Cosmos SDK Tutorials](https://tutorials.cosmos.network)
- [Discord](https://discord.gg/cosmosnetwork)

View File

@ -0,0 +1,12 @@
echo "entered CHAIN_REGISTRATION script"
cd ./cmd/wormhole-chaind
go build main.go
# Solana bridge registration
./main tx tokenbridge execute-governance-vaa 01000000000100c9f4230109e378f7efc0605fb40f0e1869f2d82fda5b1dfad8a5a2dafee85e033d155c18641165a77a2db6a7afbf2745b458616cb59347e89ae0c7aa3e7cc2d400000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f --from tiltGuardian --home ../../validators/first_validator --trace --node tcp://localhost:26657 --chain-id wormholechain --yes
# Eth bridge
./main tx tokenbridge execute-governance-vaa 01000000000100e2e1975d14734206e7a23d90db48a6b5b6696df72675443293c6057dcb936bf224b5df67d32967adeb220d4fe3cb28be515be5608c74aab6adb31099a478db5c01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e42726964676501000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16 --from tiltGuardian --home ../../validators/first_validator --trace --node tcp://localhost:26657 --chain-id wormholechain --yes
#Terra bridge
./main tx tokenbridge execute-governance-vaa 010000000001009a895e8b42444fdf60a71666121d7e84b3a49579ba3b84fff1dbdf9ec93360390c05a88f66c90df2034cb38427ba9b01632e780ce7b84df559a1bf44c316447d01000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000546f6b656e4272696467650100000003000000000000000000000000784999135aaa8a3ca5914468852fdddbddd8789d --from tiltGuardian --home ../../validators/first_validator --trace --node tcp://localhost:26657 --chain-id wormholechain --yes
#Bsc bridge
./main tx tokenbridge execute-governance-vaa 01000000000100719b4ada436f614489dbf87593c38ba9aea35aa7b997387f8ae09f819806f5654c8d45b6b751faa0e809ccbc294794885efa205bd8a046669464c7cbfb03d183010000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000002c8bb0600000000000000000000000000000000000000000000546f6b656e42726964676501000000040000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16 --from tiltGuardian --home ../../validators/first_validator --trace --node tcp://localhost:26657 --chain-id wormholechain --yes
exit 0

1
wormhole_chain/testing/js/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
lib/

View File

@ -0,0 +1,9 @@
{
"transform": {
"^.+\\.(t|j)sx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(tsx?)$",
"moduleFileExtensions": ["ts", "tsx", "js", "json", "node"],
"testTimeout": 60000
}

10912
wormhole_chain/testing/js/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
{
"name": "wormhole-chain-tests",
"version": "0.0.0",
"description": "testing project for wormhole chain",
"main": "index.js",
"type": "module",
"directories": {
"doc": "docs"
},
"scripts": {
"test": "jest --config jestconfig.json --verbose",
"bootstrap": "tsc && node lib/bootstrap.js",
"basicTransfer": "npm run test -- -t 'basicTransfer'",
"registerGuardianValidator": "npm run test -- -t 'registerGuardianValidator'"
},
"repository": {
"type": "git",
"url": "git+https://github.com/certusone/wormhole-chain.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/certusone/wormhole-chain/issues"
},
"homepage": "https://github.com/certusone/wormhole-chain#readme",
"dependencies": {
"@certusone/wormhole-sdk": "^0.2.0",
"@cosmjs/cosmwasm-stargate": "^0.27.1",
"@cosmjs/math": "^0.27.1",
"@cosmjs/proto-signing": "^0.27.1",
"@cosmjs/stargate": "^0.27.1",
"@cosmjs/tendermint-rpc": "^0.27.1",
"axios": "^0.26.0",
"bech32": "^2.0.0",
"elliptic": "^6.5.4",
"ethers": "^5.5.4",
"keccak256": "^1.0.6",
"ts-jest": "^27.1.3",
"ts-node": "^10.7.0",
"tslint": "^6.1.3",
"typescript": "^4.5.5",
"wormhole-chain-sdk": "file:../../ts-sdk"
},
"devDependencies": {
"jest": "^27.5.1"
}
}

View File

@ -0,0 +1,45 @@
import { expect, jest, test } from "@jest/globals";
import { getAddress, getWallet } from "wormhole-chain-sdk";
import { TEST_WALLET_MNEMONIC_1, TEST_WALLET_MNEMONIC_2 } from "../consts";
import { getBalance, sendTokens } from "../utils/walletHelpers";
jest.setTimeout(60000);
test("basicTransfer", async () => {
try {
const DENOM = "utest";
const wallet1 = await getWallet(TEST_WALLET_MNEMONIC_1);
console.log("wallet 1", wallet1);
const wallet2 = await getWallet(TEST_WALLET_MNEMONIC_2);
console.log("wallet 2", wallet2);
const wallet1Address = await getAddress(wallet1);
console.log("wallet 1 address", wallet1Address);
const wallet2Address = await getAddress(wallet2);
console.log("wallet 2 address", wallet2Address);
const wallet1InitialBalance = parseInt(
await getBalance(wallet1Address, DENOM)
);
console.log("wallet 1 init", wallet1InitialBalance);
const wallet2InitialBalance = parseInt(
await getBalance(wallet2Address, DENOM)
);
console.log("wallet 2 init", wallet2InitialBalance);
await sendTokens(wallet1, wallet2Address, "100", DENOM);
const wallet1BalanceAfterTransfer = parseInt(
await getBalance(wallet1Address, DENOM)
);
console.log("wallet 1 afer", wallet1BalanceAfterTransfer);
const wallet2BalanceAfterTransfer = parseInt(
await getBalance(wallet2Address, DENOM)
);
console.log("wallet 2 after", wallet2BalanceAfterTransfer);
expect(wallet1InitialBalance - wallet1BalanceAfterTransfer).toBe(100);
expect(wallet2BalanceAfterTransfer - wallet2InitialBalance).toBe(100);
} catch (e) {
console.error(e);
expect(true).toBe(false);
}
});

View File

@ -0,0 +1,77 @@
import { describe, jest, test, expect } from "@jest/globals";
import {
fromAccAddress,
fromBase64,
fromValAddress,
getAddress,
getOperatorWallet,
getWallet,
toAccAddress,
toBase64,
toValAddress,
} from "wormhole-chain-sdk";
import {
GUARDIAN_VALIDATOR_BASE64_VALADDR,
GUARDIAN_VALIDATOR_VALADDR,
TEST_WALLET_ADDRESS_1,
TEST_WALLET_MNEMONIC_1,
} from "../consts";
jest.setTimeout(60000);
describe("SDK tests", () => {
test("Address manipulation", (done) => {
const accountAddress = TEST_WALLET_ADDRESS_1;
const validatorAddress = GUARDIAN_VALIDATOR_VALADDR;
const validatorAddr64 = GUARDIAN_VALIDATOR_BASE64_VALADDR;
//checking invertibility
expect(
accountAddress === toAccAddress(fromAccAddress(accountAddress))
).toBe(true);
expect(
validatorAddress === toValAddress(fromValAddress(validatorAddress))
).toBe(true);
expect(validatorAddr64 === toBase64(fromBase64(validatorAddr64))).toBe(
true
);
//fromBase64
expect(accountAddress === toAccAddress(fromBase64(validatorAddr64))).toBe(
true
);
expect(validatorAddress === toValAddress(fromBase64(validatorAddr64))).toBe(
true
);
//fromAcc
//expect(something === toBase64(fromAccAddress(accountAddress))).toBe(true); //TODO don't have this string
expect(
validatorAddress === toValAddress(fromAccAddress(accountAddress))
).toBe(true);
//fromValAddr
expect(
accountAddress === toAccAddress(fromValAddress(validatorAddress))
).toBe(true);
expect(validatorAddr64 === toBase64(fromValAddress(validatorAddress))).toBe(
true
);
//todo conversion tests
done();
});
test("Wallet instantiation", (done) => {
(async () => {
const wallet = await getWallet(TEST_WALLET_MNEMONIC_1);
const operWallet = await getOperatorWallet(TEST_WALLET_MNEMONIC_1);
const address = await getAddress(wallet);
const valAddr = await getAddress(operWallet);
expect(address === TEST_WALLET_ADDRESS_1).toBe(true);
expect(valAddr === GUARDIAN_VALIDATOR_VALADDR).toBe(true);
done();
})();
});
});

View File

@ -0,0 +1,76 @@
import { describe, expect, jest, test } from "@jest/globals";
import {
getAddress,
getWallet,
getWormchainSigningClient,
} from "wormhole-chain-sdk";
import { WORM_DENOM, TENDERMINT_URL, TEST_WALLET_MNEMONIC_2 } from "../consts";
import { getBalance, getZeroFee } from "../utils/walletHelpers";
jest.setTimeout(60000);
describe("Token bridge tests", () => {
test("simple VAA redeem", async () => {
// try {
// const wallet1 = await getWallet(TEST_WALLET_MNEMONIC_1);
// const wallet1Address = await getAddress(wallet1);
// const wallet1InitialBalance = await getBalance(
// WORM_DENOM,
// wallet1Address
// );
// //VAA for 100 worm to this specific wallet
// const msg = redeemVaaMsg(TEST_TRANSFER_VAA);
// await signSendAndConfirm(wallet1, [msg]);
// const wallet1BalanceAfterTransfer = await getBalance(
// WORM_DENOM,
// wallet1Address
// );
// expect(wallet1BalanceAfterTransfer - wallet1InitialBalance).toBe(
// 100000000
// ); //100 worm = 100000000 uworm
// } catch (e) {
// expect(true).toBe(false);
// console.error(e);
// }
});
test("simple transfer out", async () => {
try {
const wallet2 = await getWallet(TEST_WALLET_MNEMONIC_2);
const wallet2Address = await getAddress(wallet2);
const wallet2InitialBalance = await getBalance(
wallet2Address,
WORM_DENOM
);
//VAA for 100 worm to this specific wallet
const client = await getWormchainSigningClient(TENDERMINT_URL, wallet2);
const msg = client.tokenbridge.msgTransfer({
creator: wallet2Address,
amount: { amount: "100", denom: WORM_DENOM },
toChain: 2,
toAddress: new Uint8Array(32),
fee: "0",
});
//@ts-ignore
const receipt = await client.signAndBroadcast(
wallet2Address,
[msg],
getZeroFee()
);
const wallet2BalanceAfterTransfer = await getBalance(
wallet2Address,
WORM_DENOM
);
console.log("balance before bridge ", wallet2InitialBalance);
console.log("balance after bridge ", wallet2BalanceAfterTransfer);
expect(
parseInt(wallet2InitialBalance) - parseInt(wallet2BalanceAfterTransfer)
).toBe(100);
} catch (e) {
console.error(e);
expect(true).toBe(false);
}
});
});

View File

@ -0,0 +1,51 @@
import { expect, jest, test } from "@jest/globals";
import {
fromAccAddress,
getWallet,
getWormchainSigningClient,
toValAddress,
} from "wormhole-chain-sdk";
import { getZeroFee } from "../bootstrap";
import {
DEVNET_GUARDIAN_PRIVATE_KEY,
DEVNET_GUARDIAN_PUBLIC_KEY,
TENDERMINT_URL,
TEST_WALLET_ADDRESS_2,
TEST_WALLET_MNEMONIC_2,
} from "../consts";
import { signValidatorAddress } from "../utils/walletHelpers";
jest.setTimeout(60000);
/*
This file tests to make sure that the network can start from genesis, and then change out the guardian set.
Prerequesites: Have two nodes running - the tilt guardian validator, and the 'second' wormhole chain node.
This test will register the the public ket of the second node, and then process a governance VAA to switch over the network.
*/
test("Verify guardian validator", async () => {});
test("Process guardian set upgrade", async () => {});
test("RegisterGuardianValidator", async () => {
const wallet = await getWallet(TEST_WALLET_MNEMONIC_2);
const signingClient = await getWormchainSigningClient(TENDERMINT_URL, wallet);
const registerMsg = signingClient.core.msgRegisterAccountAsGuardian({
guardianPubkey: { key: Buffer.from(DEVNET_GUARDIAN_PUBLIC_KEY, "hex") },
signer: TEST_WALLET_ADDRESS_2,
signature: signValidatorAddress(
toValAddress(fromAccAddress(TEST_WALLET_ADDRESS_2)),
DEVNET_GUARDIAN_PRIVATE_KEY
),
});
const registerMsgReceipe = await signingClient.signAndBroadcast(
TEST_WALLET_ADDRESS_2,
[registerMsg],
getZeroFee()
);
console.log("transaction hash: " + registerMsgReceipe.transactionHash);
expect(registerMsgReceipe.code === 0).toBe(true);
});

View File

@ -0,0 +1,316 @@
import { coins } from "@cosmjs/proto-signing";
import { DeliverTxResponse, StdFee } from "@cosmjs/stargate";
import axios from "axios";
import pkg from "protobufjs";
const { Field, Type } = pkg;
import * as sdk from "wormhole-chain-sdk";
import {
fromAccAddress,
fromValAddress,
toBase64,
toValAddress,
} from "wormhole-chain-sdk";
import {
DEVNET_GUARDIAN2_PRIVATE_KEY,
DEVNET_GUARDIAN2_PUBLIC_KEY,
GUARDIAN_VALIDATOR_VALADDR,
WORM_DENOM,
NODE_URL,
TENDERMINT_URL,
TEST_TRANSFER_VAA_1,
TEST_WALLET_ADDRESS_2,
TEST_WALLET_MNEMONIC_2,
TILTNET_GUARDIAN_PUBKEY,
UPGRADE_GUARDIAN_SET_VAA,
VALIDATOR2_TENDERMINT_KEY,
} from "./consts.js";
import { signValidatorAddress } from "./utils/walletHelpers.js";
import fs from 'fs';
const {
getAddress,
getWallet,
getWormchainSigningClient,
getWormholeQueryClient,
} = sdk;
let err: string | null = null;
//This test is split out into a global script file because it is not composeable with the other tests.
//This test requires a fresh tilt environment and cannot be repeated. It requires both the first & second validator to be running in tilt.
//TODO string encodings are all wrong, convert everything to base64
//TODO get a guardian set upgrade VAA for tiltnet that hands off to a new guardian key
//TODO figure out the valAddr of test wallet 2
async function fullBootstrapProcess() {
try {
console.log("Starting wormchain bootstrap test process");
//construct the clients we will use for the test
const queryClient = getWormholeQueryClient(NODE_URL, true);
const wallet2Signer = await getWallet(TEST_WALLET_MNEMONIC_2);
const wallet2Address = await getAddress(wallet2Signer);
const signingClient = await getWormchainSigningClient(
TENDERMINT_URL,
wallet2Signer
);
//verify that guardian 1 is the only bonded validator
const validators = await queryClient.staking.queryValidators({});
expectEqual("Initial bonded validators", validators.data.validators?.map((x) => x.operator_address), [GUARDIAN_VALIDATOR_VALADDR])
const Guardian1ValidatorAddress: string = getValidatorAddressBase64('../../validators/first_validator/config/priv_validator_key.json')
const Guardian2ValidatorAddress: string = getValidatorAddressBase64('../../validators/second_validator/config/priv_validator_key.json')
//verify that guardian 1 is producing blocks
let latestBlock = await getLatestBlock();
let validatorSet = latestBlock.block.last_commit.signatures;
expectEqual("Signers on first block", validatorSet.map((sig: any) => sig.validator_address), [Guardian1ValidatorAddress])
//verify that guardian 1 is registered to test wallet 1.
let response = await queryClient.core.queryGuardianValidatorAll();
const guardianValidators = response.data.guardianValidator || [];
const tiltnetGuardian = {guardianKey: TILTNET_GUARDIAN_PUBKEY, validatorAddr: toBase64(fromValAddress(GUARDIAN_VALIDATOR_VALADDR))}
expectEqual("Initial guardian validators", guardianValidators.map((x) => ({guardianKey: x.guardianKey, validatorAddr: x.validatorAddr})), [tiltnetGuardian] )
//verify that the latest guardian set is 1
const response2 = await queryClient.core.queryLatestGuardianSetIndex();
let index = response2.data.latestGuardianSetIndex;
expectEqual("Initial \"latest\" guardian set", index, 0)
//verify that the consensus guardian set is 1
const response3 = await queryClient.core.queryConsensusGuardianSetIndex();
index = response3.data.ConsensusGuardianSetIndex?.index;
expectEqual("Initial consensus guardian set", index, 0)
//verify that the only guardian public key is guardian public key 1.
const response4 = await queryClient.core.queryGuardianSet(0);
const guardianSet = response4.data || null;
expectEqual("Guardian set 0", guardianSet.GuardianSet?.keys, [TILTNET_GUARDIAN_PUBKEY])
//bridge in uworm tokens to wallet 2
const transferMsg1 = signingClient.tokenbridge.msgExecuteVAA({
creator: wallet2Address,
vaa: fromHex(TEST_TRANSFER_VAA_1),
});
const transferreceipt = await signingClient.signAndBroadcast(
wallet2Address,
[transferMsg1],
getZeroFee()
);
expectTxSuccess("initial bridge redeem VAA", transferreceipt)
//process upgrade VAA
const msg = signingClient.core.msgExecuteGovernanceVAA({
signer: await getAddress(wallet2Signer),
vaa: fromHex(UPGRADE_GUARDIAN_SET_VAA),
});
const receipt = await signingClient.signAndBroadcast(
wallet2Address,
[msg],
getZeroFee()
);
expectTxSuccess("guardian set upgrade VAA", receipt)
const guardianKey2base64 = Buffer.from(
DEVNET_GUARDIAN2_PUBLIC_KEY,
"hex"
).toString("base64");
//verify only guardian 2 is in guardian set 1.
const response7 = await queryClient.core.queryGuardianSet(1);
const guardianSet7 = response7.data || null;
expectEqual("Guardian set 1", guardianSet7.GuardianSet?.keys, [guardianKey2base64])
//verify latest guardian set is 1
const response5 = await queryClient.core.queryLatestGuardianSetIndex();
let index5 = response5.data.latestGuardianSetIndex || null;
expectEqual("Latest guardian set after upgrade", index5, 1)
//verify consensus guardian set is 0
const response6 = await queryClient.core.queryConsensusGuardianSetIndex();
let index6 = response6.data.ConsensusGuardianSetIndex?.index;
expectEqual("Consensus guardian set after upgrade", index6, 0)
//verify guardian 1 is still producing blocks
let latestBlock2 = await getLatestBlock();
let validatorSet2 = latestBlock2.block.last_commit.signatures;
expectEqual("Validators after upgrade", validatorSet2.map((sig: any) => sig.validator_address), [Guardian1ValidatorAddress])
//TODO attempt to register guardian2 to validator2, exception because validator2 is not bonded.
//protobuf quackery
//We should technically load the cosmos crypto ed15519 proto file here, but I'm going to spoof a type with the same field because our TS SDK doesn't have the proto files
let AwesomeMessage = new Type("AwesomeMessage").add(
new Field("key", 1, "bytes")
);
const pubkey = AwesomeMessage.encode({
key: Buffer.from(VALIDATOR2_TENDERMINT_KEY, "base64"),
}).finish();
//bond validator2
const bondMsg = signingClient.staking.msgCreateValidator({
commission: { rate: "0", max_change_rate: "0", max_rate: "0" },
description: {
moniker: "secondValidator",
details: "details",
identity: "identity",
security_contact: "contact",
website: "https://.com",
},
delegator_address: TEST_WALLET_ADDRESS_2,
min_self_delegation: "0",
pubkey: {
type_url: "/cosmos.crypto.ed25519.PubKey",
value: pubkey,
},
validator_address: toValAddress(fromAccAddress(TEST_WALLET_ADDRESS_2)),
value: { denom: "uworm", amount: "0" },
});
const createValidatorReceipt = await signingClient.signAndBroadcast(
wallet2Address,
[bondMsg],
getZeroFee()
);
expectTxSuccess("second validator registration", createValidatorReceipt)
//confirm validator2 is bonded
const validators2 = await queryClient.staking.queryValidators({});
expectEqual("Second bonded validators", validators2.data.validators?.map((x) => x.operator_address).sort(), [GUARDIAN_VALIDATOR_VALADDR, toValAddress(fromAccAddress(TEST_WALLET_ADDRESS_2))].sort())
let latestBlock3 = await getLatestBlock();
let validatorSet3 = latestBlock3.block.last_commit.signatures;
expectEqual("Signers after second validator bonded", validatorSet3.map((sig: any) => sig.validator_address), [Guardian1ValidatorAddress])
//attempt to register guardian2 to validator2
//TODO what encoding for the guardian key & how to sign the validator address?
const registerMsg = signingClient.core.msgRegisterAccountAsGuardian({
guardianPubkey: { key: Buffer.from(DEVNET_GUARDIAN2_PUBLIC_KEY, "hex") },
signer: TEST_WALLET_ADDRESS_2,
signature: signValidatorAddress(
toValAddress(fromAccAddress(TEST_WALLET_ADDRESS_2)),
DEVNET_GUARDIAN2_PRIVATE_KEY
),
});
const registerMsgReceipe = await signingClient.signAndBroadcast(
TEST_WALLET_ADDRESS_2,
[registerMsg],
getZeroFee()
);
expectTxSuccess("second guardian registration", registerMsgReceipe)
//confirm validator2 is also now registered as a guardian validator
let guardianValResponse =
await queryClient.core.queryGuardianValidatorAll();
const guardianValidators2 =
guardianValResponse.data.guardianValidator || [];
const secondGuardian = {guardianKey: Buffer.from(DEVNET_GUARDIAN2_PUBLIC_KEY, "hex").toString( "base64"), validatorAddr: toBase64(fromAccAddress(TEST_WALLET_ADDRESS_2))}
expectEqual("Updated guardian validators", guardianValidators2.map((x) => ({guardianKey: x.guardianKey, validatorAddr: x.validatorAddr})).sort(), [secondGuardian, tiltnetGuardian].sort())
//confirm consensus guardian set is now 2
const conResponse = await queryClient.core.queryConsensusGuardianSetIndex();
index = conResponse.data.ConsensusGuardianSetIndex?.index;
expectEqual("Updated consensus guardian set", index, 1)
//confirm blocks are only signed by validator2
console.log("Waiting 4 seconds for latest block...")
await new Promise((resolve) => setTimeout(resolve, 4000));
latestBlock = await getLatestBlock();
validatorSet = latestBlock.block.last_commit.signatures;
expectEqual("Signing validators on final block", validatorSet.map((sig: any) => sig.validator_address), [Guardian2ValidatorAddress])
console.log("Successfully completed bootstrap process.");
} catch (e) {
if (!err) {
// if err is set, it means we ejected, so it's a test failure, not an ordinary exception
console.error(e);
console.log("Hit a critical error, process will terminate.");
}
} finally {
if (err) {
console.log(red("ERROR: ") + err);
}
}
}
//TODO figure out how to best move these stock cosmos queries into the SDK
async function getLatestBlock() {
return await (
await axios.get(NODE_URL + "/cosmos/base/tendermint/v1beta1/blocks/latest")
).data;
}
function eject(error: string) {
err = error;
throw new Error();
}
function fromHex(hexString: string) {
return Buffer.from(hexString, "hex");
}
export function getZeroFee(): StdFee {
return {
amount: coins(0, WORM_DENOM),
gas: "180000", // 180k",
};
}
const wait = async () => {
await fullBootstrapProcess();
};
wait();
function getValidatorAddressBase64(file: string): string {
const validator_key_file = fs.readFileSync(file)
return Buffer.from(JSON.parse(validator_key_file.toString()).address, "hex").toString("base64")
}
function equal<T>(actual: T, expected: T): boolean {
if (Array.isArray(actual) && Array.isArray(expected)) {
return actual.length === expected.length && actual.every((val, index) => equal(val, expected[index]));
} else if (typeof actual === "object" && typeof expected === "object") {
return JSON.stringify(actual) === JSON.stringify(expected)
} else {
return actual === expected
}
}
function expectEqual<T>(msg: string, actual: T, expected: T): void {
if (!equal(actual, expected)) {
eject(msg + ":\nExpected: " + green(stringify(expected)) + ", got: " + red(stringify(actual)))
} else {
console.log(msg + ": " + green("PASS"))
}
}
function expectTxSuccess(msg: string, receipt: DeliverTxResponse): void {
if (receipt.code !== 0) {
eject("Transaction " + msg + " failed. Transaction hash: " + red(receipt.transactionHash))
}
console.log("Transaction " + msg + ": " + green("PASS") + " (" + receipt.transactionHash + ")")
}
function stringify<T>(x: T): string {
if (Array.isArray(x)) {
return "["+ x.map((x) => stringify(x)) + "]"
} else if (typeof x === "object") {
return JSON.stringify(x)
} else {
return "" + x
}
}
function red(str: string): string {
return '\x1b[31m' + str + '\x1b[0m'
}
function green(str: string): string {
return '\x1b[32m' + str + '\x1b[0m'
}
export default {};

View File

@ -0,0 +1,58 @@
export const TEST_WALLET_MNEMONIC_1 =
"notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius";
export const TEST_WALLET_MNEMONIC_2 =
"maple pudding enjoy pole real rabbit soft make square city wrestle area aisle dwarf spike voice over still post lend genius bitter exit shoot";
export const TEST_WALLET_ADDRESS_1 =
"wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq";
export const TEST_WALLET_ADDRESS_2 =
"wormhole1wqwywkce50mg6077huy4j9y8lt80943ks5udzr";
export const DEVNET_GUARDIAN_PUBLIC_KEY =
"beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe";
export const DEVNET_GUARDIAN_PRIVATE_KEY =
"cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
export const DEVNET_GUARDIAN2_PUBLIC_KEY =
"a75a14f140c22d691bb0b19b4a51fae5b77f9d89";
export const DEVNET_GUARDIAN2_PRIVATE_KEY =
"bfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0";
//This assume guardian 1 uses test wallet 1.
export const GUARDIAN_VALIDATOR_VALADDR =
"wormholevaloper1cyyzpxplxdzkeea7kwsydadg87357qna87hzv8";
// export const GUARDIAN_VALIDATOR2_VALADDR = "";
export const GUARDIAN_VALIDATOR_BASE64_VALADDR = "wQggmD8zRWznvrOgRvWoP6NPAn0=";
//This is a VAA in hex which is for guardian set 2, where Guardian 2 is the only active guardian.
export const NODE_URL = "http://0.0.0.0:1319";
export const TENDERMINT_URL = "http://localhost:26659";
//export const FAUCET_URL = "http://localhost:4500";
export const WORM_DENOM = "uworm";
export const ADDRESS_PREFIX = "wormhole";
export const OPERATOR_PREFIX = "wormholevaloper";
export const DEVNET_SOLT = "2WDq7wSs9zYrpx2kbHDA4RUTRch2CCTP6ZWaH4GNfnQQ";
//This is a transfer for 100 SOLT to Chain ID 2,
//And recipient address wormhole1cyyzpxplxdzkeea7kwsydadg87357qna3zg3tq, which should be TEST_WALLET_1
// Will need to update this with the real chain ID
export const TEST_TRANSFER_VAA_1 =
"01000000000100167fddaf3b94aa48975829abfa0f52b6f48ad97f67a6d62c928ad5159964471d3b3f465077aa08dc5311f3adbc92e76d6e7a2c114cad4a09297cd150336520b100000000006ea5bc5b0001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f1f428ee55b7e3c0d2001000000000000000000000000000000000000000000000000002386f26fc10000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000c10820983f33456ce7beb3a046f5a83fa34f027d0c200000000000000000000000000000000000000000000000000000000000000000";
export const TEST_TRANSFER_VAA_2 =
"0100000000010003319407d687b0e337905d85e6bb23ca3cb04167c49e6585e5c6f2d5da4b1d5739e865bcf38e3ae8ba5bc9c967b3477a33df0ce659e9879f488dc3ccf176fb5e0000000000166994180001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f0151c0cccf71c9ea200100000000000000000000000000000000000000000000000000470de4df820000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000701c475b19a3f68d3fdebf09591487facef2d6360c200000000000000000000000000000000000000000000000000000000000000000";
export const TEST_TRANSFER_VAA_3 =
"01000000010100938362116fc18edca1adec84515c7a62387cff995e65d0833696f911284a539e068a3097af551683bd07c92a5d5df53f8b7b2cce10a8ccf7fe136344815d995f010000000063a9016c0001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4fcaa15701f441c06620010000000000000000000000000000000000000000000000000027147114878000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000c10820983f33456ce7beb3a046f5a83fa34f027d0c200000000000000000000000000000000000000000000000000000000000000000";
export const TEST_TRANSFER_VAA_4 =
"01000000010100cf6d0dac8dd15eb86f185bf9ebf53f7a15424b35adbc6a50c352e2b91c15a298411f79f5a7ed9989db4bf79c50d5d278182b73789dbb825d2a7e4c0a4c15d81601000000008c3bd8230001c69a1b1a65dd336bf1df6a77afb501fc25db7fc0938cb08595a9ef473265cb4f19d8398119b1418e2001000000000000000000000000000000000000000000000000004a9b6384488000165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3010001000000000000000000000000701c475b19a3f68d3fdebf09591487facef2d6360c200000000000000000000000000000000000000000000000000000000000000000";
export const UPGRADE_GUARDIAN_SET_VAA =
"0100000000010035a5da3648df687185296528e404d101f5a20f4f8915d94046e0e4243f6b443d12d5899f50a8b83fe77c9970c08f458068f7f48555b6fb11269d959d3372a7fd000000000044e2ef4d000100000000000000000000000000000000000000000000000000000000000000044604178071f1a5962000000000000000000000000000000000000000000000000000000000436f72650200000000000101a75a14f140c22d691bb0b19b4a51fae5b77f9d89";
export const TILTNET_GUARDIAN_PUBKEY = "vvpCnVfNGLf4pNkaLamrSvBdD74=";
export const TILTNET_GUARDIAN_PRIVATE_KEY =
"cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"; //0x
export const VALIDATOR2_TENDERMINT_KEY =
"Zcujkt1sXRWWLfhgxLAm/Q+ioLn4wFim0OnGPLlCG0I=";

View File

@ -0,0 +1,46 @@
//code examples
//https://morioh.com/p/195b602b4350
const cosmosjs = require("@cosmostation/cosmosjs");
const chainId = "cosmoshub-2";
const cosmos = cosmosjs.network(lcdUrl, chainId);
const mnemonic = "...";
cosmos.setPath("m/44'/118'/0'/0/0");
const address = cosmos.getAddress(mnemonic);
const ecpairPriv = cosmos.getECPairPriv(mnemonic);
cosmos.getAccounts(address).then((data) => {
let stdSignMsg = cosmos.NewStdMsg({
type: "cosmos-sdk/MsgSend",
from_address: address,
to_address: "cosmos18vhdczjut44gpsy804crfhnd5nq003nz0nf20v",
amountDenom: "uatom",
amount: 100000,
feeDenom: "uatom",
fee: 5000,
gas: 200000,
memo: "",
account_number: data.value.account_number,
sequence: data.value.sequence,
});
});
const signedTx = cosmos.sign(stdSignMsg, ecpairPriv);
cosmos.broadcast(signedTx).then((response) => console.log(response));
let stdSignMsg = cosmos.NewStdMsg({
type: "cosmos-sdk/MsgSend",
from_address: address,
to_address: "cosmos18vhdczjut44gpsy804crfhnd5nq003nz0nf20v",
amountDenom: "uatom",
amount: 1000000,
feeDenom: "uatom",
fee: 5000,
gas: 200000,
memo: "",
account_number: data.value.account_number,
sequence: data.value.sequence,
});

View File

@ -0,0 +1,80 @@
import { coins } from "@cosmjs/proto-signing";
import { OfflineSigner } from "@cosmjs/proto-signing";
import { StdFee } from "@cosmjs/stargate";
import {
fromValAddress,
getAddress,
getWallet,
getWormchainSigningClient,
getWormholeQueryClient,
} from "wormhole-chain-sdk";
import {
WORM_DENOM,
NODE_URL,
TENDERMINT_URL,
TEST_WALLET_ADDRESS_1,
TEST_WALLET_MNEMONIC_1,
} from "../consts.js";
//@ts-ignore
import * as elliptic from "elliptic";
import keccak256 from "keccak256";
export async function getQueryClient() {
return getWormholeQueryClient(NODE_URL, true);
}
export async function getSigningClient() {
const testWallet1 = await getWallet(TEST_WALLET_MNEMONIC_1);
return await getWormchainSigningClient(TENDERMINT_URL, testWallet1);
}
export async function getBalance(address: string, denom: string) {
const client = await getQueryClient();
const response = await client.bank.queryBalance(address, denom);
return response.data.balance?.amount || "0";
}
export async function sendTokens(
wallet: OfflineSigner,
recipient: string,
amount: string,
denom: string
) {
const client = await getWormchainSigningClient(TENDERMINT_URL, wallet);
const fromAddress = await getAddress(wallet);
//TODO the autogenned protobuf code doesn't appear to be correct. This not working is a serious bug
// const msg = client.bank.msgSend({
// //@ts-ignore
// amount: [{ amount, denom }],
// //@ts-ignore
// from_address: fromAddress,
// to_address: recipient,
// });
return client.sendTokens(
fromAddress,
recipient,
[{ amount, denom }],
getZeroFee(),
"basicTransfer test"
);
}
export function getZeroFee(): StdFee {
return {
amount: coins(0, WORM_DENOM),
gas: "180000", // 180k",
};
}
export function signValidatorAddress(valAddr: string, privKey: string) {
const EC = elliptic.default.ec;
const ec = new EC("secp256k1");
const key = ec.keyFromPrivate(privKey);
const valAddrHash = keccak256(
Buffer.from(fromValAddress(valAddr).bytes)
).toString("hex");
const signature = key.sign(valAddrHash, { canonical: true });
const hexString = signature.r.toString("hex").padStart(64, "0") + signature.s.toString("hex").padStart(64, "0") + signature.recoveryParam.toString(16).padStart(2, "0");
return Buffer.from(hexString, "hex");
}

View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "es6",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"outDir": "lib",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"downlevelIteration": true,
"noEmit": false,
"jsx": "react-jsx"
},
"include": ["src"]
}

View File

@ -0,0 +1,6 @@
{
"extends": ["tslint:recommended", "tslint-config-prettier"],
"linterOptions": {
"exclude": ["src/proto/**"]
}
}

View File

@ -0,0 +1,41 @@
package keeper
import (
"testing"
"github.com/certusone/wormhole-chain/x/tokenbridge/keeper"
"github.com/certusone/wormhole-chain/x/tokenbridge/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
)
func TokenbridgeKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
storeKey := sdk.NewKVStoreKey(types.StoreKey)
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)
db := tmdb.NewMemDB()
stateStore := store.NewCommitMultiStore(db)
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil)
require.NoError(t, stateStore.LoadLatestVersion())
registry := codectypes.NewInterfaceRegistry()
k := keeper.NewKeeper(
codec.NewProtoCodec(registry),
storeKey,
memStoreKey,
nil,
nil,
nil,
)
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
return k, ctx
}

View File

@ -0,0 +1,40 @@
package keeper
import (
"testing"
"github.com/certusone/wormhole-chain/x/wormhole/keeper"
"github.com/certusone/wormhole-chain/x/wormhole/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
)
func WormholeKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
storeKey := sdk.NewKVStoreKey(types.StoreKey)
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)
db := tmdb.NewMemDB()
stateStore := store.NewCommitMultiStore(db)
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil)
require.NoError(t, stateStore.LoadLatestVersion())
registry := codectypes.NewInterfaceRegistry()
k := keeper.NewKeeper(
codec.NewProtoCodec(registry),
storeKey,
memStoreKey,
nil,
nil,
)
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
return k, ctx
}

View File

@ -0,0 +1,79 @@
package network
import (
"fmt"
"testing"
"time"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/tendermint/spm/cosmoscmd"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmdb "github.com/tendermint/tm-db"
"github.com/certusone/wormhole-chain/app"
)
type (
Network = network.Network
Config = network.Config
)
// New creates instance with fully configured cosmos network.
// Accepts optional config, that will be used in place of the DefaultConfig() if provided.
func New(t *testing.T, configs ...network.Config) *network.Network {
if len(configs) > 1 {
panic("at most one config should be provided")
}
var cfg network.Config
if len(configs) == 0 {
cfg = DefaultConfig()
} else {
cfg = configs[0]
}
net := network.New(t, cfg)
t.Cleanup(net.Cleanup)
return net
}
// DefaultConfig will initialize config for the network with custom application,
// genesis and single validator. All other parameters are inherited from cosmos-sdk/testutil/network.DefaultConfig
func DefaultConfig() network.Config {
encoding := cosmoscmd.MakeEncodingConfig(app.ModuleBasics)
return network.Config{
Codec: encoding.Marshaler,
TxConfig: encoding.TxConfig,
LegacyAmino: encoding.Amino,
InterfaceRegistry: encoding.InterfaceRegistry,
AccountRetriever: authtypes.AccountRetriever{},
AppConstructor: func(val network.Validator) servertypes.Application {
return app.New(
val.Ctx.Logger, tmdb.NewMemDB(), nil, true, map[int64]bool{}, val.Ctx.Config.RootDir, 0,
encoding,
simapp.EmptyAppOptions{},
baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)),
baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices),
)
},
GenesisState: app.ModuleBasics.DefaultGenesis(encoding.Marshaler),
TimeoutCommit: 2 * time.Second,
ChainID: "chain-" + tmrand.NewRand().Str(6),
NumValidators: 1,
BondDenom: sdk.DefaultBondDenom,
MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction),
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
PruningStrategy: storetypes.PruningOptionNothing,
CleanupDir: true,
SigningAlgo: string(hd.Secp256k1Type),
KeyringOptions: []keyring.Option{},
}
}

View File

@ -0,0 +1,57 @@
// Package nullify provides methods to init nil values structs for test assertion.
package nullify
import (
"reflect"
"unsafe"
sdk "github.com/cosmos/cosmos-sdk/types"
)
var (
coinType = reflect.TypeOf(sdk.Coin{})
coinsType = reflect.TypeOf(sdk.Coins{})
)
// Fill analyze all struct fields and slices with
// reflection and initialize the nil and empty slices,
// structs, and pointers.
func Fill(x interface{}) interface{} {
v := reflect.Indirect(reflect.ValueOf(x))
switch v.Kind() {
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
obj := v.Index(i)
objPt := reflect.NewAt(obj.Type(), unsafe.Pointer(obj.UnsafeAddr())).Interface()
objPt = Fill(objPt)
obj.Set(reflect.ValueOf(objPt))
}
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
f := reflect.Indirect(v.Field(i))
if !f.CanSet() {
continue
}
switch f.Kind() {
case reflect.Slice:
f.Set(reflect.MakeSlice(f.Type(), 0, 0))
case reflect.Struct:
switch f.Type() {
case coinType:
coin := reflect.New(coinType).Interface()
s := reflect.ValueOf(coin).Elem()
f.Set(s)
case coinsType:
coins := reflect.New(coinsType).Interface()
s := reflect.ValueOf(coins).Elem()
f.Set(s)
default:
objPt := reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Interface()
s := Fill(objPt)
f.Set(reflect.ValueOf(s))
}
}
}
}
return reflect.Indirect(v).Interface()
}

View File

@ -0,0 +1,13 @@
package sample
import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// AccAddress returns a sample account address
func AccAddress() string {
pk := ed25519.GenPrivKey().PubKey()
addr := pk.Address()
return sdk.AccAddress(addr).String()
}

View File

@ -0,0 +1,49 @@
package simapp
import (
"time"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/tendermint/spm/cosmoscmd"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
tmdb "github.com/tendermint/tm-db"
"github.com/certusone/wormhole-chain/app"
)
// New creates application instance with in-memory database and disabled logging.
func New(dir string) cosmoscmd.App {
db := tmdb.NewMemDB()
logger := log.NewNopLogger()
encoding := cosmoscmd.MakeEncodingConfig(app.ModuleBasics)
a := app.New(logger, db, nil, true, map[int64]bool{}, dir, 0, encoding,
simapp.EmptyAppOptions{})
// InitChain updates deliverState which is required when app.NewContext is called
a.InitChain(abci.RequestInitChain{
ConsensusParams: defaultConsensusParams,
AppStateBytes: []byte("{}"),
})
return a
}
var defaultConsensusParams = &abci.ConsensusParams{
Block: &abci.BlockParams{
MaxBytes: 200000,
MaxGas: 2000000,
},
Evidence: &tmproto.EvidenceParams{
MaxAgeNumBlocks: 302400,
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
MaxBytes: 10000,
},
Validator: &tmproto.ValidatorParams{
PubKeyTypes: []string{
tmtypes.ABCIPubKeyTypeEd25519,
},
},
}

10723
wormhole_chain/ts-sdk/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
{
"name": "wormhole-chain-sdk",
"version": "0.0.0",
"description": "Typescript SDK for interating with the Wormhole chain",
"main": "lib/index.js",
"scripts": {
"test": "jest --config jestconfig.json --verbose",
"build": "npm run genTypes && tsc",
"genTypes": "node src/buildHelper.cjs"
},
"repository": {
"type": "git",
"url": "git+https://github.com/certusone/wormhole-chain.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/certusone/wormhole-chain/issues"
},
"homepage": "https://github.com/certusone/wormhole-chain#readme",
"dependencies": {
"@certusone/wormhole-sdk": "^0.2.0",
"@cosmjs/cosmwasm-stargate": "^0.27.1",
"@cosmjs/launchpad": "^0.27.1",
"@cosmjs/math": "^0.27.1",
"@cosmjs/proto-signing": "^0.27.1",
"@cosmjs/stargate": "^0.27.1",
"@cosmjs/tendermint-rpc": "^0.27.1",
"axios": "^0.26.0",
"bech32": "^2.0.0",
"elliptic": "^6.5.4",
"ethers": "^5.5.4",
"keccak256": "^1.0.6",
"node-fetch": "^2.6.7",
"protobufjs": "^6.11.2",
"ts-jest": "^27.1.3",
"tslint": "^6.1.3",
"typescript": "^4.5.5"
},
"devDependencies": {
"jest": "^27.5.1"
}
}

View File

@ -0,0 +1,76 @@
//This file is meant to aggregate the relevant autogenerated files from starport
//and put them into a useable place inside the SDK.
//This file is meant to be run from the ts-sdk directory.
const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");
const CERTUS_DIRECTORY = "../vue/src/store/generated/certusone/wormhole-chain/";
const COSMOS_DIRECTORY = "../vue/src/store/generated/cosmos/cosmos-sdk/";
const MODULE_DIRECTORY = "../ts-sdk/src/modules/";
const VUE_DIRECTORY = "../vue";
function execWrapper(command) {
execSync(command, (error, stdout, stderr) => {
if (error) {
console.log(
`error while processing command - ${command}: ${error.message}`
);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
}
const certusFiles = fs.readdirSync(CERTUS_DIRECTORY, { withFileTypes: true }); //should only contain directories for the modules
const cosmosFiles = fs.readdirSync(COSMOS_DIRECTORY, { withFileTypes: true });
certusFiles.forEach((directory) => {
execWrapper(`mkdir -p ${MODULE_DIRECTORY + directory.name}/`);
execWrapper(
`cp -R ${CERTUS_DIRECTORY + directory.name}/module/* ${
MODULE_DIRECTORY + directory.name
}/`
); //move all the files from the vue module into the sdk
});
cosmosFiles.forEach((directory) => {
execWrapper(`mkdir -p ${MODULE_DIRECTORY + directory.name}/`);
execWrapper(
`cp -R ${COSMOS_DIRECTORY + directory.name}/module/* ${
MODULE_DIRECTORY + directory.name
}/`
); //move all the files from the vue module into the sdk
});
//As of 19.5 javascript isn't emitted
//execWrapper(`find ${MODULE_DIRECTORY} -name "*.js" | xargs rm `); //delete all javascript files, so they can be cleanly created based on our tsconfig
function getFilesRecursively(directory) {
const filesInDirectory = fs.readdirSync(directory);
return filesInDirectory.flatMap((file) => {
const absolute = path.join(directory, file);
if (fs.statSync(absolute).isDirectory()) {
return getFilesRecursively(absolute);
} else {
return [absolute];
}
});
}
const files = getFilesRecursively(MODULE_DIRECTORY);
files.forEach((path) => {
const fileContent = fs.readFileSync(path);
const fileString = fileContent.toString("UTF-8");
const fileStringModified = "//@ts-nocheck\n" + fileString;
fs.writeFileSync(path, fileStringModified);
});
console.log("Successfully copied all autogenerated typescript files");

View File

@ -0,0 +1,7 @@
export const ADDRESS_PREFIX = "wormhole";
export const OPERATOR_PREFIX = "wormholevaloper";
export const ZERO_FEE = {
amount: [{ amount: "0", denom: "uworm" }],
gas: "200000",
};

View File

@ -0,0 +1,32 @@
import { bech32 } from "bech32";
import { ADDRESS_PREFIX, OPERATOR_PREFIX } from "./consts";
export function fromAccAddress(address: string): BinaryAddress {
return { bytes: Buffer.from(bech32.fromWords(bech32.decode(address).words)) };
}
export function fromValAddress(valAddress: string): BinaryAddress {
return {
bytes: Buffer.from(bech32.fromWords(bech32.decode(valAddress).words)),
};
}
export function fromBase64(address: string): BinaryAddress {
return { bytes: Buffer.from(address, "base64") };
}
export function toAccAddress(address: BinaryAddress): string {
return bech32.encode(ADDRESS_PREFIX, bech32.toWords(address.bytes));
}
export function toValAddress(address: BinaryAddress): string {
return bech32.encode(OPERATOR_PREFIX, bech32.toWords(address.bytes));
}
export function toBase64(address: BinaryAddress): string {
return Buffer.from(address.bytes).toString("base64");
}
type BinaryAddress = {
bytes: Uint8Array;
};

View File

@ -0,0 +1,113 @@
import { GovernorCompatibilityBravo } from "@certusone/wormhole-sdk";
import {
QueryClient,
setupAuthExtension,
setupBankExtension,
setupGovExtension,
setupIbcExtension,
setupMintExtension,
setupStakingExtension,
setupTxExtension,
} from "@cosmjs/stargate";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import { Api as tokenbridgeApi } from "../modules/certusone.wormholechain.tokenbridge/rest";
import { Api as coreApi } from "../modules/certusone.wormholechain.wormhole/rest";
import { Api as authApi } from "../modules/cosmos.auth.v1beta1/rest";
import { Api as bankApi } from "../modules/cosmos.bank.v1beta1/rest";
import { Api as baseApi } from "../modules/cosmos.base.tendermint.v1beta1/rest";
import { Api as crisisApi } from "../modules/cosmos.crisis.v1beta1/rest";
import { Api as distributionApi } from "../modules/cosmos.distribution.v1beta1/rest";
import { Api as evidenceApi } from "../modules/cosmos.evidence.v1beta1/rest";
import { Api as feegrantApi } from "../modules/cosmos.feegrant.v1beta1/rest";
import { Api as govApi } from "../modules/cosmos.gov.v1beta1/rest";
import { Api as mintApi } from "../modules/cosmos.mint.v1beta1/rest";
import { Api as paramsApi } from "../modules/cosmos.params.v1beta1/rest";
import { Api as slashingApi } from "../modules/cosmos.slashing.v1beta1/rest";
import { Api as stakingApi } from "../modules/cosmos.staking.v1beta1/rest";
import { Api as txApi } from "../modules/cosmos.tx.v1beta1/rest";
import { Api as upgradeApi } from "../modules/cosmos.upgrade.v1beta1/rest";
import { Api as vestingApi } from "../modules/cosmos.vesting.v1beta1/rest";
export type WormchainQueryClient = {
core: coreApi<any>;
tokenbridge: tokenbridgeApi<any>;
auth: authApi<any>;
bank: bankApi<any>;
base: baseApi<any>;
crisis: crisisApi<any>;
distribution: distributionApi<any>;
evidence: evidenceApi<any>;
feegrant: feegrantApi<any>;
gov: govApi<any>;
mint: mintApi<any>;
params: paramsApi<any>;
slashing: slashingApi<any>;
staking: stakingApi<any>;
tx: txApi<any>;
upgrade: upgradeApi<any>;
vesting: vestingApi<any>;
};
export function getWormholeQueryClient(
lcdAddress: string,
nodejs?: boolean
): WormchainQueryClient {
if (nodejs) {
var fetch = require("node-fetch");
//@ts-ignore
globalThis.fetch = fetch;
}
const core = new coreApi({ baseUrl: lcdAddress });
const tokenbridge = new tokenbridgeApi({ baseUrl: lcdAddress });
const auth = new authApi({ baseUrl: lcdAddress });
const bank = new bankApi({ baseUrl: lcdAddress });
const base = new baseApi({ baseUrl: lcdAddress });
const crisis = new crisisApi({ baseUrl: lcdAddress });
const distribution = new distributionApi({ baseUrl: lcdAddress });
const evidence = new evidenceApi({ baseUrl: lcdAddress });
const feegrant = new feegrantApi({ baseUrl: lcdAddress });
const gov = new govApi({ baseUrl: lcdAddress });
const mint = new mintApi({ baseUrl: lcdAddress });
const params = new paramsApi({ baseUrl: lcdAddress });
const slashing = new slashingApi({ baseUrl: lcdAddress });
const staking = new stakingApi({ baseUrl: lcdAddress });
const tx = new txApi({ baseUrl: lcdAddress });
const upgrade = new upgradeApi({ baseUrl: lcdAddress });
const vesting = new vestingApi({ baseUrl: lcdAddress });
return {
core,
tokenbridge,
auth,
bank,
base,
crisis,
distribution,
evidence,
feegrant,
gov,
mint,
params,
slashing,
staking,
tx,
upgrade,
vesting,
};
}
// export async function getStargateQueryClient(tendermintAddress: string) {
// const tmClient = await Tendermint34Client.connect(tendermintAddress);
// const client = QueryClient.withExtensions(
// tmClient,
// setupTxExtension,
// setupGovExtension,
// setupIbcExtension,
// setupAuthExtension,
// setupBankExtension,
// setupMintExtension,
// setupStakingExtension
// );
// return client;
// }

View File

@ -0,0 +1,269 @@
var fetch = require("node-fetch");
//@ts-ignore
globalThis.fetch = fetch;
import { bech32 } from "bech32";
import {
coins,
DirectSecp256k1HdWallet,
EncodeObject,
OfflineSigner,
} from "@cosmjs/proto-signing";
import {
QueryClient,
setupAuthExtension,
setupBankExtension,
setupGovExtension,
setupIbcExtension,
setupMintExtension,
setupStakingExtension,
setupTxExtension,
SigningStargateClient,
StargateClient,
StdFee,
} from "@cosmjs/stargate";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import {
RpcStatus,
HttpResponse,
} from "../modules/certusone.wormholechain.tokenbridge/rest";
import {
txClient,
queryClient,
} from "../modules/certusone.wormholechain.wormhole";
import {
txClient as tokenBridgeClient,
} from "../modules/certusone.wormholechain.tokenbridge";
import { keccak256 } from "ethers/lib/utils";
import { MsgRegisterAccountAsGuardian } from "../modules/certusone.wormholechain.wormhole/types/wormhole/tx";
import { GuardianKey } from "../modules/certusone.wormholechain.wormhole/types/wormhole/guardian_key";
let elliptic = require("elliptic"); //No TS defs?
//https://tutorials.cosmos.network/academy/4-my-own-chain/cosmjs.html
const ADDRESS_PREFIX = "wormhole";
const OPERATOR_PREFIX = "wormholevaloper";
export const TENDERMINT_URL = "http://localhost:26658";
export const WORM_DENOM = "uworm";
export const LCD_URL = "http://localhost:1318";
export async function getStargateQueryClient() {
const tmClient = await Tendermint34Client.connect(TENDERMINT_URL);
const client = QueryClient.withExtensions(
tmClient,
setupTxExtension,
setupGovExtension,
setupIbcExtension,
setupAuthExtension,
setupBankExtension,
setupMintExtension,
setupStakingExtension
);
return client;
}
export async function getStargateClient() {
const client: StargateClient = await StargateClient.connect(TENDERMINT_URL);
return client;
}
export function getZeroFee(): StdFee {
return {
amount: coins(0, WORM_DENOM),
gas: "180000", // 180k",
};
}
export async function getWallet(
mnemonic: string
): Promise<DirectSecp256k1HdWallet> {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
prefix: ADDRESS_PREFIX,
});
return wallet;
}
export async function getAddress(
wallet: DirectSecp256k1HdWallet
): Promise<string> {
//There are actually up to 5 accounts in a cosmos wallet. I believe this returns the first wallet.
const [{ address }] = await wallet.getAccounts();
return address;
}
//TODO recipient chain should be chainID
export async function transferTokens(
wallet: DirectSecp256k1HdWallet,
denom: string,
amount: string,
recipientAddress: Uint8Array,
recipientChain: number,
fee: string
) {
const offline: OfflineSigner = wallet;
const client = await tokenBridgeClient(offline, { addr: TENDERMINT_URL });
const msg: EncodeObject = client.msgTransfer({
amount: { amount, denom },
toChain: recipientChain,
fee: fee,
toAddress: recipientAddress,
creator: await getAddress(wallet),
}); //TODO convert type
//const output = await client.signAndBroadcast([msg]);
const signingClient = await SigningStargateClient.connectWithSigner(
TENDERMINT_URL,
wallet
//{ gasPrice: { amount: Decimal.fromUserInput("0.0", 0), denom: "uworm" } }
);
//TODO investigate signing with the stargate client, as the module txClients can't do 100% of the operations
const output = signingClient.signAndBroadcast(
await getAddress(wallet),
[msg],
getZeroFee(),
"executing governance VAA"
);
return output;
}
export async function executeGovernanceVAA(
wallet: DirectSecp256k1HdWallet,
hexVaa: string
) {
const offline: OfflineSigner = wallet;
const client = await txClient(offline, { addr: TENDERMINT_URL });
const msg = client.msgExecuteGovernanceVAA({
vaa: new Uint8Array(),
signer: await getAddress(wallet),
}); //TODO convert type
const signingClient = await SigningStargateClient.connectWithSigner(
TENDERMINT_URL,
wallet
//{ gasPrice: { amount: Decimal.fromUserInput("0.0", 0), denom: "uworm" } }
);
//TODO investigate signing with the stargate client, as the module txClients can't do 100% of the operations
const output = signingClient.signAndBroadcast(
await getAddress(wallet),
[msg],
getZeroFee(),
"executing governance VAA"
);
//TODO the EncodingObjects from the txClient seem to be incompatible with the
//stargate client
// In order for all the encoding objects to be interoperable, we will have to either coerce the txClient msgs into the format of stargate,
// or we could just just txClients for everything. I am currently leaning towards the latter, as we can generate txClients for everything out of the cosmos-sdk,
// and we will likely need to generate txClients for our forked version of the cosmos SDK anyway.
//const output = await client.signAndBroadcast([msg]);
return output;
}
export async function getGuardianSets() {
const client = await queryClient({ addr: LCD_URL });
const response = client.queryGuardianSetAll();
return await unpackHttpReponse(response);
}
export async function getConsensusGuardianSet() {
const client = await queryClient({ addr: LCD_URL });
const response = client.queryConsensusGuardianSetIndex();
return await unpackHttpReponse(response);
}
export async function getValidators() {
const client = await getStargateQueryClient();
//TODO handle pagination here
const validators = await client.staking.validators("BOND_STATUS_BONDED");
return validators;
}
export async function getGuardianValidatorRegistrations() {
const client = await queryClient({ addr: LCD_URL });
const response = client.queryGuardianValidatorAll();
return await unpackHttpReponse(response);
}
export async function unpackHttpReponse<T>(
response: Promise<HttpResponse<T, RpcStatus>>
) {
const http = await response;
//TODO check rpc status
const content = http.data;
return content;
}
export async function registerGuardianValidator(
wallet: DirectSecp256k1HdWallet,
guardianPubkeyBase64: string,
guardianPrivkeyHex: string,
valAddress: string
) {
const ec = new elliptic.ec("secp256k1");
const key = ec.keyFromPrivate(guardianPrivkeyHex);
const binaryData = fromValAddress(valAddress);
const bytes = binaryData.bytes;
const hash = keccak256(bytes);
const signature = key.sign(hash, { canonical: true });
const args: MsgRegisterAccountAsGuardian = {
signer: await getAddress(wallet),
guardianPubkey: GuardianKey.fromJSON(guardianPubkeyBase64), //TODO fix this type, it's bad
signature: signature,
};
const offline: OfflineSigner = wallet;
const client = await txClient(offline, { addr: TENDERMINT_URL });
const msg = client.msgRegisterAccountAsGuardian(args);
const output = await client.signAndBroadcast([msg]);
return output;
}
export function fromAccAddress(address: string): BinaryAddress {
return { bytes: Buffer.from(bech32.fromWords(bech32.decode(address).words)) };
}
export function fromValAddress(valAddress: string): BinaryAddress {
return {
bytes: Buffer.from(bech32.fromWords(bech32.decode(valAddress).words)),
};
}
export function fromBase64(address: string): BinaryAddress {
return { bytes: Buffer.from(address, "base64") };
}
export function toAccAddress(address: BinaryAddress): string {
return bech32.encode(ADDRESS_PREFIX, bech32.toWords(address.bytes));
}
export function toValAddress(address: BinaryAddress): string {
return bech32.encode(OPERATOR_PREFIX, bech32.toWords(address.bytes));
}
export function toBase64(address: BinaryAddress): string {
return Buffer.from(address.bytes).toString("base64");
}
type BinaryAddress = {
bytes: Uint8Array;
};

View File

@ -0,0 +1,344 @@
import { OfflineSigner, Registry } from "@cosmjs/proto-signing";
import {
defaultRegistryTypes,
SigningStargateClient,
SigningStargateClientOptions,
StargateClient,
} from "@cosmjs/stargate";
import { getTypeParameterOwner } from "typescript";
import * as tokenBridgeModule from "../modules/certusone.wormholechain.tokenbridge";
import * as coreModule from "../modules/certusone.wormholechain.wormhole";
import * as authModule from "../modules/cosmos.auth.v1beta1";
import * as bankModule from "../modules/cosmos.bank.v1beta1";
import * as baseModule from "../modules/cosmos.base.tendermint.v1beta1";
import * as crisisModule from "../modules/cosmos.crisis.v1beta1";
import * as distributionModule from "../modules/cosmos.distribution.v1beta1";
import * as evidenceModule from "../modules/cosmos.evidence.v1beta1";
import * as feegrantModule from "../modules/cosmos.feegrant.v1beta1";
import * as govModule from "../modules/cosmos.gov.v1beta1";
import * as mintModule from "../modules/cosmos.mint.v1beta1";
import * as paramsModule from "../modules/cosmos.params.v1beta1";
import * as slashingModule from "../modules/cosmos.slashing.v1beta1";
import * as stakingModule from "../modules/cosmos.staking.v1beta1";
import * as txModule from "../modules/cosmos.tx.v1beta1";
import * as upgradeModule from "../modules/cosmos.upgrade.v1beta1";
import * as vestingModule from "../modules/cosmos.vesting.v1beta1";
//protobuf isn't guaranteed to have long support, which is used by the stargate signing client,
//so we're going to use an independent long module and shove it into the globals of protobuf
var Long = require("long");
var protobuf = require("protobufjs");
protobuf.util.Long = Long;
protobuf.configure();
//Rip the types out of their modules. These are private fields on the module.
//@ts-ignore
const coreTypes = coreModule.registry.types;
//@ts-ignore
const tokenBridgeTypes = tokenBridgeModule.registry.types;
//@ts-ignore
const authTypes = authModule.registry.types;
//@ts-ignore
const bankTypes = bankModule.registry.types;
//@ts-ignore
const baseTypes = baseModule.registry.types;
//@ts-ignore
const crisisTypes = crisisModule.registry.types;
//@ts-ignore
const distributionTypes = distributionModule.registry.types;
//@ts-ignore
const evidenceTypes = evidenceModule.registry.types;
//@ts-ignore
const feegrantTypes = feegrantModule.registry.types;
//@ts-ignore
const govTypes = govModule.registry.types;
//@ts-ignore
const mintTypes = mintModule.registry.types;
//@ts-ignore
const paramsTypes = paramsModule.registry.types;
//@ts-ignore
const slashingTypes = slashingModule.registry.types;
//@ts-ignore
const stakingTypes = stakingModule.registry.types;
//@ts-ignore
const txTypes = txModule.registry.types;
//@ts-ignore
const upgradeTypes = upgradeModule.registry.types;
//@ts-ignore
const vestingTypes = vestingModule.registry.types;
const aggregateTypes = [
...coreTypes,
...tokenBridgeTypes,
...authTypes,
...bankTypes,
...baseTypes,
...crisisTypes,
...distributionTypes,
...evidenceTypes,
...feegrantTypes,
...govTypes,
...mintTypes,
...paramsTypes,
...slashingTypes,
...stakingTypes,
...txTypes,
...upgradeTypes,
...vestingTypes,
];
export const MissingWalletError = new Error("wallet is required");
const registry = new Registry(<any>aggregateTypes);
export const getWormchainSigningClient = async (
tendermintAddress: string,
wallet: OfflineSigner,
options?: SigningStargateClientOptions
) => {
if (!wallet) throw MissingWalletError;
const coreClient = await coreModule.txClient(wallet, {
addr: tendermintAddress,
});
const tokenBridgeClient = await tokenBridgeModule.txClient(wallet, {
addr: tendermintAddress,
});
const authClient = await authModule.txClient(wallet, {
addr: tendermintAddress,
});
const bankClient = await bankModule.txClient(wallet, {
addr: tendermintAddress,
});
const baseClient = await baseModule.txClient(wallet, {
addr: tendermintAddress,
});
const crisisClient = await crisisModule.txClient(wallet, {
addr: tendermintAddress,
});
const distributionClient = await distributionModule.txClient(wallet, {
addr: tendermintAddress,
});
const evidenceClient = await evidenceModule.txClient(wallet, {
addr: tendermintAddress,
});
const feegrantClient = await feegrantModule.txClient(wallet, {
addr: tendermintAddress,
});
const govClient = await govModule.txClient(wallet, {
addr: tendermintAddress,
});
const mintClient = await mintModule.txClient(wallet, {
addr: tendermintAddress,
});
const paramsClient = await paramsModule.txClient(wallet, {
addr: tendermintAddress,
});
const slashingClient = await slashingModule.txClient(wallet, {
addr: tendermintAddress,
});
const stakingClient = await stakingModule.txClient(wallet, {
addr: tendermintAddress,
});
const txClient = await txModule.txClient(wallet, {
addr: tendermintAddress,
});
const upgradeClient = await upgradeModule.txClient(wallet, {
addr: tendermintAddress,
});
const vestingClient = await vestingModule.txClient(wallet, {
addr: tendermintAddress,
});
const client = await SigningStargateClient.connectWithSigner(
tendermintAddress,
wallet,
{
...options,
registry,
}
);
//This has some relevant info, but doesn't get us all the way there
//https://github.com/cosmos/cosmjs/pull/712/files
//The signAndBroadcast function needs to be undefined here because it uses and interface which can't be
//resolved by typescript.
const coreShell = {
...coreClient,
signAndBroadcast: undefined,
};
delete coreShell.signAndBroadcast;
const tokenBridgeShell = {
...tokenBridgeClient,
signAndBroadcast: undefined,
};
delete tokenBridgeShell.signAndBroadcast;
const authShell = {
...authClient,
signAndBroadcast: undefined,
};
delete authShell.signAndBroadcast;
const bankShell = {
...bankClient,
signAndBroadcast: undefined,
};
delete bankShell.signAndBroadcast;
const baseShell = {
...baseClient,
signAndBroadcast: undefined,
};
delete baseShell.signAndBroadcast;
const crisisShell = {
...crisisClient,
signAndBroadcast: undefined,
};
delete crisisShell.signAndBroadcast;
const distributionShell = {
...distributionClient,
signAndBroadcast: undefined,
};
delete distributionShell.signAndBroadcast;
const evidenceShell = {
...evidenceClient,
signAndBroadcast: undefined,
};
delete evidenceShell.signAndBroadcast;
const feegrantShell = {
...feegrantClient,
signAndBroadcast: undefined,
};
delete feegrantShell.signAndBroadcast;
const govShell = {
...govClient,
signAndBroadcast: undefined,
};
delete govShell.signAndBroadcast;
const mintShell = {
...mintClient,
signAndBroadcast: undefined,
};
delete mintShell.signAndBroadcast;
const paramsShell = {
...paramsClient,
signAndBroadcast: undefined,
};
delete paramsShell.signAndBroadcast;
const slashingShell = {
...slashingClient,
signAndBroadcast: undefined,
};
delete slashingShell.signAndBroadcast;
const stakingShell = {
...stakingClient,
signAndBroadcast: undefined,
};
delete stakingShell.signAndBroadcast;
const txShell = {
...txClient,
signAndBroadcast: undefined,
};
delete txShell.signAndBroadcast;
const upgradeShell = {
...upgradeClient,
signAndBroadcast: undefined,
};
delete upgradeShell.signAndBroadcast;
const vestingShell = {
...vestingClient,
signAndBroadcast: undefined,
};
delete vestingShell.signAndBroadcast;
type CoreType = Omit<typeof coreShell, "signAndBroadcast">;
type TokenBridgeType = Omit<typeof tokenBridgeShell, "signAndBroadcast">;
type AuthzType = Omit<typeof authShell, "signAndBroadcast">;
type BankType = Omit<typeof bankShell, "signAndBroadcast">;
type BaseType = Omit<typeof baseShell, "signAndBroadcast">;
type CrisisType = Omit<typeof crisisShell, "signAndBroadcast">;
type DistributionType = Omit<typeof distributionShell, "signAndBroadcast">;
type EvidenceType = Omit<typeof evidenceShell, "signAndBroadcast">;
type FeegrantType = Omit<typeof feegrantShell, "signAndBroadcast">;
type GovType = Omit<typeof govShell, "signAndBroadcast">;
type MintType = Omit<typeof mintShell, "signAndBroadcast">;
type ParamsType = Omit<typeof paramsShell, "signAndBroadcast">;
type SlashingType = Omit<typeof slashingShell, "signAndBroadcast">;
type StakingType = Omit<typeof stakingShell, "signAndBroadcast">;
type TxType = Omit<typeof txShell, "signAndBroadcast">;
type UpgradeType = Omit<typeof upgradeShell, "signAndBroadcast">;
type VestingType = Omit<typeof vestingShell, "signAndBroadcast">;
type WormholeFunctions = {
core: CoreType;
tokenbridge: TokenBridgeType;
auth: AuthzType;
bank: BankType;
base: BaseType;
crisis: CrisisType;
distribution: DistributionType;
evidence: EvidenceType;
feegrant: FeegrantType;
gov: GovType;
mint: MintType;
params: ParamsType;
slashing: SlashingType;
staking: StakingType;
tx: TxType;
upgrade: UpgradeType;
vesting: VestingType;
};
type WormholeSigningClient = SigningStargateClient & WormholeFunctions;
const output: WormholeSigningClient = client as WormholeSigningClient;
output.core = coreShell;
output.tokenbridge = tokenBridgeShell;
output.auth = authShell;
output.bank = bankShell;
output.base = baseShell;
output.crisis = crisisShell;
output.distribution = distributionShell;
output.evidence = evidenceShell;
output.feegrant = feegrantShell;
output.gov = govShell;
output.mint = mintShell;
output.params = paramsShell;
output.slashing = slashingShell;
output.staking = stakingShell;
output.tx = txShell;
output.upgrade = upgradeShell;
output.vesting = vestingShell;
return output;
};

View File

@ -0,0 +1,34 @@
import {
DirectSecp256k1HdWallet,
DirectSecp256k1HdWalletOptions,
OfflineSigner,
} from "@cosmjs/proto-signing";
import { ADDRESS_PREFIX, OPERATOR_PREFIX } from "./consts";
export async function getWallet(
mnemonic: string,
options?: DirectSecp256k1HdWalletOptions
): Promise<DirectSecp256k1HdWallet> {
console.log("wallet");
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
prefix: ADDRESS_PREFIX,
});
return wallet;
}
export async function getOperatorWallet(
mnemonic: string,
options?: DirectSecp256k1HdWalletOptions
): Promise<DirectSecp256k1HdWallet> {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
prefix: OPERATOR_PREFIX,
});
return wallet;
}
export async function getAddress(wallet: OfflineSigner): Promise<string> {
//There are actually up to 5 accounts in a cosmos wallet. I believe this returns the first wallet.
const [{ address }] = await wallet.getAccounts();
return address;
}

View File

@ -0,0 +1,9 @@
export * from "./core/helpers";
export * from "./core/queryClient";
export * from "./core/signingClient";
export * from "./core/wallet";
export * as helpers from "./core/helpers";
export * as queryClient from "./core/queryClient";
export * as signingClient from "./core/signingClient";
export * as wallet from "./core/wallet";

View File

@ -0,0 +1,70 @@
//@ts-nocheck
// THIS FILE IS GENERATED AUTOMATICALLY. DO NOT MODIFY.
import { StdFee } from "@cosmjs/launchpad";
import { SigningStargateClient } from "@cosmjs/stargate";
import { Registry, OfflineSigner, EncodeObject, DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { Api } from "./rest";
import { MsgExecuteVAA } from "./types/tokenbridge/tx";
import { MsgExecuteGovernanceVAA } from "./types/tokenbridge/tx";
import { MsgTransfer } from "./types/tokenbridge/tx";
import { MsgAttestToken } from "./types/tokenbridge/tx";
const types = [
["/certusone.wormholechain.tokenbridge.MsgExecuteVAA", MsgExecuteVAA],
["/certusone.wormholechain.tokenbridge.MsgExecuteGovernanceVAA", MsgExecuteGovernanceVAA],
["/certusone.wormholechain.tokenbridge.MsgTransfer", MsgTransfer],
["/certusone.wormholechain.tokenbridge.MsgAttestToken", MsgAttestToken],
];
export const MissingWalletError = new Error("wallet is required");
export const registry = new Registry(<any>types);
const defaultFee = {
amount: [],
gas: "200000",
};
interface TxClientOptions {
addr: string
}
interface SignAndBroadcastOptions {
fee: StdFee,
memo?: string
}
const txClient = async (wallet: OfflineSigner, { addr: addr }: TxClientOptions = { addr: "http://localhost:26657" }) => {
if (!wallet) throw MissingWalletError;
let client;
if (addr) {
client = await SigningStargateClient.connectWithSigner(addr, wallet, { registry });
}else{
client = await SigningStargateClient.offline( wallet, { registry });
}
const { address } = (await wallet.getAccounts())[0];
return {
signAndBroadcast: (msgs: EncodeObject[], { fee, memo }: SignAndBroadcastOptions = {fee: defaultFee, memo: ""}) => client.signAndBroadcast(address, msgs, fee,memo),
msgExecuteVAA: (data: MsgExecuteVAA): EncodeObject => ({ typeUrl: "/certusone.wormholechain.tokenbridge.MsgExecuteVAA", value: MsgExecuteVAA.fromPartial( data ) }),
msgExecuteGovernanceVAA: (data: MsgExecuteGovernanceVAA): EncodeObject => ({ typeUrl: "/certusone.wormholechain.tokenbridge.MsgExecuteGovernanceVAA", value: MsgExecuteGovernanceVAA.fromPartial( data ) }),
msgTransfer: (data: MsgTransfer): EncodeObject => ({ typeUrl: "/certusone.wormholechain.tokenbridge.MsgTransfer", value: MsgTransfer.fromPartial( data ) }),
msgAttestToken: (data: MsgAttestToken): EncodeObject => ({ typeUrl: "/certusone.wormholechain.tokenbridge.MsgAttestToken", value: MsgAttestToken.fromPartial( data ) }),
};
};
interface QueryClientOptions {
addr: string
}
const queryClient = async ({ addr: addr }: QueryClientOptions = { addr: "http://localhost:1317" }) => {
return new Api({ baseUrl: addr });
};
export {
txClient,
queryClient,
};

View File

@ -0,0 +1,521 @@
//@ts-nocheck
/* eslint-disable */
/* tslint:disable */
/*
* ---------------------------------------------------------------
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
* ## ##
* ## AUTHOR: acacode ##
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
* ---------------------------------------------------------------
*/
export interface ProtobufAny {
"@type"?: string;
}
export interface RpcStatus {
/** @format int32 */
code?: number;
message?: string;
details?: ProtobufAny[];
}
export interface TokenbridgeChainRegistration {
/** @format int64 */
chainID?: number;
/** @format byte */
emitterAddress?: string;
}
export interface TokenbridgeCoinMetaRollbackProtection {
index?: string;
/** @format uint64 */
lastUpdateSequence?: string;
}
export type TokenbridgeConfig = object;
export type TokenbridgeMsgAttestTokenResponse = object;
export type TokenbridgeMsgExecuteGovernanceVAAResponse = object;
export type TokenbridgeMsgExecuteVAAResponse = object;
export type TokenbridgeMsgTransferResponse = object;
export interface TokenbridgeQueryAllChainRegistrationResponse {
chainRegistration?: TokenbridgeChainRegistration[];
/**
* PageResponse is to be embedded in gRPC response messages where the
* corresponding request message has used PageRequest.
*
* message SomeResponse {
* repeated Bar results = 1;
* PageResponse page = 2;
* }
*/
pagination?: V1Beta1PageResponse;
}
export interface TokenbridgeQueryAllCoinMetaRollbackProtectionResponse {
coinMetaRollbackProtection?: TokenbridgeCoinMetaRollbackProtection[];
/**
* PageResponse is to be embedded in gRPC response messages where the
* corresponding request message has used PageRequest.
*
* message SomeResponse {
* repeated Bar results = 1;
* PageResponse page = 2;
* }
*/
pagination?: V1Beta1PageResponse;
}
export interface TokenbridgeQueryAllReplayProtectionResponse {
replayProtection?: TokenbridgeReplayProtection[];
/**
* PageResponse is to be embedded in gRPC response messages where the
* corresponding request message has used PageRequest.
*
* message SomeResponse {
* repeated Bar results = 1;
* PageResponse page = 2;
* }
*/
pagination?: V1Beta1PageResponse;
}
export interface TokenbridgeQueryGetChainRegistrationResponse {
chainRegistration?: TokenbridgeChainRegistration;
}
export interface TokenbridgeQueryGetCoinMetaRollbackProtectionResponse {
coinMetaRollbackProtection?: TokenbridgeCoinMetaRollbackProtection;
}
export interface TokenbridgeQueryGetConfigResponse {
Config?: TokenbridgeConfig;
}
export interface TokenbridgeQueryGetReplayProtectionResponse {
replayProtection?: TokenbridgeReplayProtection;
}
export interface TokenbridgeReplayProtection {
index?: string;
}
/**
* Coin defines a token with a denomination and an amount.
NOTE: The amount field is an Int which implements the custom method
signatures required by gogoproto.
*/
export interface V1Beta1Coin {
denom?: string;
amount?: string;
}
/**
* message SomeRequest {
Foo some_parameter = 1;
PageRequest pagination = 2;
}
*/
export interface V1Beta1PageRequest {
/**
* key is a value returned in PageResponse.next_key to begin
* querying the next page most efficiently. Only one of offset or key
* should be set.
* @format byte
*/
key?: string;
/**
* offset is a numeric offset that can be used when key is unavailable.
* It is less efficient than using key. Only one of offset or key should
* be set.
* @format uint64
*/
offset?: string;
/**
* limit is the total number of results to be returned in the result page.
* If left empty it will default to a value to be set by each app.
* @format uint64
*/
limit?: string;
/**
* count_total is set to true to indicate that the result set should include
* a count of the total number of items available for pagination in UIs.
* count_total is only respected when offset is used. It is ignored when key
* is set.
*/
count_total?: boolean;
/** reverse is set to true if results are to be returned in the descending order. */
reverse?: boolean;
}
/**
* PageResponse is to be embedded in gRPC response messages where the
corresponding request message has used PageRequest.
message SomeResponse {
repeated Bar results = 1;
PageResponse page = 2;
}
*/
export interface V1Beta1PageResponse {
/** @format byte */
next_key?: string;
/** @format uint64 */
total?: string;
}
export type QueryParamsType = Record<string | number, any>;
export type ResponseFormat = keyof Omit<Body, "body" | "bodyUsed">;
export interface FullRequestParams extends Omit<RequestInit, "body"> {
/** set parameter to `true` for call `securityWorker` for this request */
secure?: boolean;
/** request path */
path: string;
/** content type of request body */
type?: ContentType;
/** query params */
query?: QueryParamsType;
/** format of response (i.e. response.json() -> format: "json") */
format?: keyof Omit<Body, "body" | "bodyUsed">;
/** request body */
body?: unknown;
/** base url */
baseUrl?: string;
/** request cancellation token */
cancelToken?: CancelToken;
}
export type RequestParams = Omit<FullRequestParams, "body" | "method" | "query" | "path">;
export interface ApiConfig<SecurityDataType = unknown> {
baseUrl?: string;
baseApiParams?: Omit<RequestParams, "baseUrl" | "cancelToken" | "signal">;
securityWorker?: (securityData: SecurityDataType) => RequestParams | void;
}
export interface HttpResponse<D extends unknown, E extends unknown = unknown> extends Response {
data: D;
error: E;
}
type CancelToken = Symbol | string | number;
export enum ContentType {
Json = "application/json",
FormData = "multipart/form-data",
UrlEncoded = "application/x-www-form-urlencoded",
}
export class HttpClient<SecurityDataType = unknown> {
public baseUrl: string = "";
private securityData: SecurityDataType = null as any;
private securityWorker: null | ApiConfig<SecurityDataType>["securityWorker"] = null;
private abortControllers = new Map<CancelToken, AbortController>();
private baseApiParams: RequestParams = {
credentials: "same-origin",
headers: {},
redirect: "follow",
referrerPolicy: "no-referrer",
};
constructor(apiConfig: ApiConfig<SecurityDataType> = {}) {
Object.assign(this, apiConfig);
}
public setSecurityData = (data: SecurityDataType) => {
this.securityData = data;
};
private addQueryParam(query: QueryParamsType, key: string) {
const value = query[key];
return (
encodeURIComponent(key) +
"=" +
encodeURIComponent(Array.isArray(value) ? value.join(",") : typeof value === "number" ? value : `${value}`)
);
}
protected toQueryString(rawQuery?: QueryParamsType): string {
const query = rawQuery || {};
const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
return keys
.map((key) =>
typeof query[key] === "object" && !Array.isArray(query[key])
? this.toQueryString(query[key] as QueryParamsType)
: this.addQueryParam(query, key),
)
.join("&");
}
protected addQueryParams(rawQuery?: QueryParamsType): string {
const queryString = this.toQueryString(rawQuery);
return queryString ? `?${queryString}` : "";
}
private contentFormatters: Record<ContentType, (input: any) => any> = {
[ContentType.Json]: (input: any) =>
input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
[ContentType.FormData]: (input: any) =>
Object.keys(input || {}).reduce((data, key) => {
data.append(key, input[key]);
return data;
}, new FormData()),
[ContentType.UrlEncoded]: (input: any) => this.toQueryString(input),
};
private mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams {
return {
...this.baseApiParams,
...params1,
...(params2 || {}),
headers: {
...(this.baseApiParams.headers || {}),
...(params1.headers || {}),
...((params2 && params2.headers) || {}),
},
};
}
private createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => {
if (this.abortControllers.has(cancelToken)) {
const abortController = this.abortControllers.get(cancelToken);
if (abortController) {
return abortController.signal;
}
return void 0;
}
const abortController = new AbortController();
this.abortControllers.set(cancelToken, abortController);
return abortController.signal;
};
public abortRequest = (cancelToken: CancelToken) => {
const abortController = this.abortControllers.get(cancelToken);
if (abortController) {
abortController.abort();
this.abortControllers.delete(cancelToken);
}
};
public request = <T = any, E = any>({
body,
secure,
path,
type,
query,
format = "json",
baseUrl,
cancelToken,
...params
}: FullRequestParams): Promise<HttpResponse<T, E>> => {
const secureParams = (secure && this.securityWorker && this.securityWorker(this.securityData)) || {};
const requestParams = this.mergeRequestParams(params, secureParams);
const queryString = query && this.toQueryString(query);
const payloadFormatter = this.contentFormatters[type || ContentType.Json];
return fetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
...requestParams,
headers: {
...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
...(requestParams.headers || {}),
},
signal: cancelToken ? this.createAbortSignal(cancelToken) : void 0,
body: typeof body === "undefined" || body === null ? null : payloadFormatter(body),
}).then(async (response) => {
const r = response as HttpResponse<T, E>;
r.data = (null as unknown) as T;
r.error = (null as unknown) as E;
const data = await response[format]()
.then((data) => {
if (r.ok) {
r.data = data;
} else {
r.error = data;
}
return r;
})
.catch((e) => {
r.error = e;
return r;
});
if (cancelToken) {
this.abortControllers.delete(cancelToken);
}
if (!response.ok) throw data;
return data;
});
};
}
/**
* @title tokenbridge/chain_registration.proto
* @version version not set
*/
export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
/**
* No description
*
* @tags Query
* @name QueryChainRegistrationAll
* @summary Queries a list of chainRegistration items.
* @request GET:/certusone/wormholechain/tokenbridge/chainRegistration
*/
queryChainRegistrationAll = (
query?: {
"pagination.key"?: string;
"pagination.offset"?: string;
"pagination.limit"?: string;
"pagination.count_total"?: boolean;
"pagination.reverse"?: boolean;
},
params: RequestParams = {},
) =>
this.request<TokenbridgeQueryAllChainRegistrationResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/chainRegistration`,
method: "GET",
query: query,
format: "json",
...params,
});
/**
* No description
*
* @tags Query
* @name QueryChainRegistration
* @summary Queries a chainRegistration by index.
* @request GET:/certusone/wormholechain/tokenbridge/chainRegistration/{chainID}
*/
queryChainRegistration = (chainID: number, params: RequestParams = {}) =>
this.request<TokenbridgeQueryGetChainRegistrationResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/chainRegistration/${chainID}`,
method: "GET",
format: "json",
...params,
});
/**
* No description
*
* @tags Query
* @name QueryCoinMetaRollbackProtectionAll
* @summary Queries a list of coinMetaRollbackProtection items.
* @request GET:/certusone/wormholechain/tokenbridge/coinMetaRollbackProtection
*/
queryCoinMetaRollbackProtectionAll = (
query?: {
"pagination.key"?: string;
"pagination.offset"?: string;
"pagination.limit"?: string;
"pagination.count_total"?: boolean;
"pagination.reverse"?: boolean;
},
params: RequestParams = {},
) =>
this.request<TokenbridgeQueryAllCoinMetaRollbackProtectionResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/coinMetaRollbackProtection`,
method: "GET",
query: query,
format: "json",
...params,
});
/**
* No description
*
* @tags Query
* @name QueryCoinMetaRollbackProtection
* @summary Queries a coinMetaRollbackProtection by index.
* @request GET:/certusone/wormholechain/tokenbridge/coinMetaRollbackProtection/{index}
*/
queryCoinMetaRollbackProtection = (index: string, params: RequestParams = {}) =>
this.request<TokenbridgeQueryGetCoinMetaRollbackProtectionResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/coinMetaRollbackProtection/${index}`,
method: "GET",
format: "json",
...params,
});
/**
* No description
*
* @tags Query
* @name QueryConfig
* @summary Queries a config by index.
* @request GET:/certusone/wormholechain/tokenbridge/config
*/
queryConfig = (params: RequestParams = {}) =>
this.request<TokenbridgeQueryGetConfigResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/config`,
method: "GET",
format: "json",
...params,
});
/**
* No description
*
* @tags Query
* @name QueryReplayProtectionAll
* @summary Queries a list of replayProtection items.
* @request GET:/certusone/wormholechain/tokenbridge/replayProtection
*/
queryReplayProtectionAll = (
query?: {
"pagination.key"?: string;
"pagination.offset"?: string;
"pagination.limit"?: string;
"pagination.count_total"?: boolean;
"pagination.reverse"?: boolean;
},
params: RequestParams = {},
) =>
this.request<TokenbridgeQueryAllReplayProtectionResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/replayProtection`,
method: "GET",
query: query,
format: "json",
...params,
});
/**
* No description
*
* @tags Query
* @name QueryReplayProtection
* @summary Queries a replayProtection by index.
* @request GET:/certusone/wormholechain/tokenbridge/replayProtection/{index}
*/
queryReplayProtection = (index: string, params: RequestParams = {}) =>
this.request<TokenbridgeQueryGetReplayProtectionResponse, RpcStatus>({
path: `/certusone/wormholechain/tokenbridge/replayProtection/${index}`,
method: "GET",
format: "json",
...params,
});
}

View File

@ -0,0 +1,325 @@
//@ts-nocheck
/* eslint-disable */
import * as Long from "long";
import { util, configure, Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "cosmos.base.query.v1beta1";
/**
* PageRequest is to be embedded in gRPC request messages for efficient
* pagination. Ex:
*
* message SomeRequest {
* Foo some_parameter = 1;
* PageRequest pagination = 2;
* }
*/
export interface PageRequest {
/**
* key is a value returned in PageResponse.next_key to begin
* querying the next page most efficiently. Only one of offset or key
* should be set.
*/
key: Uint8Array;
/**
* offset is a numeric offset that can be used when key is unavailable.
* It is less efficient than using key. Only one of offset or key should
* be set.
*/
offset: number;
/**
* limit is the total number of results to be returned in the result page.
* If left empty it will default to a value to be set by each app.
*/
limit: number;
/**
* count_total is set to true to indicate that the result set should include
* a count of the total number of items available for pagination in UIs.
* count_total is only respected when offset is used. It is ignored when key
* is set.
*/
count_total: boolean;
/** reverse is set to true if results are to be returned in the descending order. */
reverse: boolean;
}
/**
* PageResponse is to be embedded in gRPC response messages where the
* corresponding request message has used PageRequest.
*
* message SomeResponse {
* repeated Bar results = 1;
* PageResponse page = 2;
* }
*/
export interface PageResponse {
/**
* next_key is the key to be passed to PageRequest.key to
* query the next page most efficiently
*/
next_key: Uint8Array;
/**
* total is total number of results available if PageRequest.count_total
* was set, its value is undefined otherwise
*/
total: number;
}
const basePageRequest: object = {
offset: 0,
limit: 0,
count_total: false,
reverse: false,
};
export const PageRequest = {
encode(message: PageRequest, writer: Writer = Writer.create()): Writer {
if (message.key.length !== 0) {
writer.uint32(10).bytes(message.key);
}
if (message.offset !== 0) {
writer.uint32(16).uint64(message.offset);
}
if (message.limit !== 0) {
writer.uint32(24).uint64(message.limit);
}
if (message.count_total === true) {
writer.uint32(32).bool(message.count_total);
}
if (message.reverse === true) {
writer.uint32(40).bool(message.reverse);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): PageRequest {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...basePageRequest } as PageRequest;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.key = reader.bytes();
break;
case 2:
message.offset = longToNumber(reader.uint64() as Long);
break;
case 3:
message.limit = longToNumber(reader.uint64() as Long);
break;
case 4:
message.count_total = reader.bool();
break;
case 5:
message.reverse = reader.bool();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): PageRequest {
const message = { ...basePageRequest } as PageRequest;
if (object.key !== undefined && object.key !== null) {
message.key = bytesFromBase64(object.key);
}
if (object.offset !== undefined && object.offset !== null) {
message.offset = Number(object.offset);
} else {
message.offset = 0;
}
if (object.limit !== undefined && object.limit !== null) {
message.limit = Number(object.limit);
} else {
message.limit = 0;
}
if (object.count_total !== undefined && object.count_total !== null) {
message.count_total = Boolean(object.count_total);
} else {
message.count_total = false;
}
if (object.reverse !== undefined && object.reverse !== null) {
message.reverse = Boolean(object.reverse);
} else {
message.reverse = false;
}
return message;
},
toJSON(message: PageRequest): unknown {
const obj: any = {};
message.key !== undefined &&
(obj.key = base64FromBytes(
message.key !== undefined ? message.key : new Uint8Array()
));
message.offset !== undefined && (obj.offset = message.offset);
message.limit !== undefined && (obj.limit = message.limit);
message.count_total !== undefined &&
(obj.count_total = message.count_total);
message.reverse !== undefined && (obj.reverse = message.reverse);
return obj;
},
fromPartial(object: DeepPartial<PageRequest>): PageRequest {
const message = { ...basePageRequest } as PageRequest;
if (object.key !== undefined && object.key !== null) {
message.key = object.key;
} else {
message.key = new Uint8Array();
}
if (object.offset !== undefined && object.offset !== null) {
message.offset = object.offset;
} else {
message.offset = 0;
}
if (object.limit !== undefined && object.limit !== null) {
message.limit = object.limit;
} else {
message.limit = 0;
}
if (object.count_total !== undefined && object.count_total !== null) {
message.count_total = object.count_total;
} else {
message.count_total = false;
}
if (object.reverse !== undefined && object.reverse !== null) {
message.reverse = object.reverse;
} else {
message.reverse = false;
}
return message;
},
};
const basePageResponse: object = { total: 0 };
export const PageResponse = {
encode(message: PageResponse, writer: Writer = Writer.create()): Writer {
if (message.next_key.length !== 0) {
writer.uint32(10).bytes(message.next_key);
}
if (message.total !== 0) {
writer.uint32(16).uint64(message.total);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): PageResponse {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...basePageResponse } as PageResponse;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.next_key = reader.bytes();
break;
case 2:
message.total = longToNumber(reader.uint64() as Long);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): PageResponse {
const message = { ...basePageResponse } as PageResponse;
if (object.next_key !== undefined && object.next_key !== null) {
message.next_key = bytesFromBase64(object.next_key);
}
if (object.total !== undefined && object.total !== null) {
message.total = Number(object.total);
} else {
message.total = 0;
}
return message;
},
toJSON(message: PageResponse): unknown {
const obj: any = {};
message.next_key !== undefined &&
(obj.next_key = base64FromBytes(
message.next_key !== undefined ? message.next_key : new Uint8Array()
));
message.total !== undefined && (obj.total = message.total);
return obj;
},
fromPartial(object: DeepPartial<PageResponse>): PageResponse {
const message = { ...basePageResponse } as PageResponse;
if (object.next_key !== undefined && object.next_key !== null) {
message.next_key = object.next_key;
} else {
message.next_key = new Uint8Array();
}
if (object.total !== undefined && object.total !== null) {
message.total = object.total;
} else {
message.total = 0;
}
return message;
},
};
declare var self: any | undefined;
declare var window: any | undefined;
var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw "Unable to locate global object";
})();
const atob: (b64: string) => string =
globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary"));
function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64);
const arr = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i);
}
return arr;
}
const btoa: (bin: string) => string =
globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64"));
function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = [];
for (let i = 0; i < arr.byteLength; ++i) {
bin.push(String.fromCharCode(arr[i]));
}
return btoa(bin.join(""));
}
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
function longToNumber(long: Long): number {
if (long.gt(Number.MAX_SAFE_INTEGER)) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
}
return long.toNumber();
}
if (util.Long !== Long) {
util.Long = Long as any;
configure();
}

View File

@ -0,0 +1,302 @@
//@ts-nocheck
/* eslint-disable */
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "cosmos.base.v1beta1";
/**
* Coin defines a token with a denomination and an amount.
*
* NOTE: The amount field is an Int which implements the custom method
* signatures required by gogoproto.
*/
export interface Coin {
denom: string;
amount: string;
}
/**
* DecCoin defines a token with a denomination and a decimal amount.
*
* NOTE: The amount field is an Dec which implements the custom method
* signatures required by gogoproto.
*/
export interface DecCoin {
denom: string;
amount: string;
}
/** IntProto defines a Protobuf wrapper around an Int object. */
export interface IntProto {
int: string;
}
/** DecProto defines a Protobuf wrapper around a Dec object. */
export interface DecProto {
dec: string;
}
const baseCoin: object = { denom: "", amount: "" };
export const Coin = {
encode(message: Coin, writer: Writer = Writer.create()): Writer {
if (message.denom !== "") {
writer.uint32(10).string(message.denom);
}
if (message.amount !== "") {
writer.uint32(18).string(message.amount);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): Coin {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseCoin } as Coin;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.denom = reader.string();
break;
case 2:
message.amount = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): Coin {
const message = { ...baseCoin } as Coin;
if (object.denom !== undefined && object.denom !== null) {
message.denom = String(object.denom);
} else {
message.denom = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = String(object.amount);
} else {
message.amount = "";
}
return message;
},
toJSON(message: Coin): unknown {
const obj: any = {};
message.denom !== undefined && (obj.denom = message.denom);
message.amount !== undefined && (obj.amount = message.amount);
return obj;
},
fromPartial(object: DeepPartial<Coin>): Coin {
const message = { ...baseCoin } as Coin;
if (object.denom !== undefined && object.denom !== null) {
message.denom = object.denom;
} else {
message.denom = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = object.amount;
} else {
message.amount = "";
}
return message;
},
};
const baseDecCoin: object = { denom: "", amount: "" };
export const DecCoin = {
encode(message: DecCoin, writer: Writer = Writer.create()): Writer {
if (message.denom !== "") {
writer.uint32(10).string(message.denom);
}
if (message.amount !== "") {
writer.uint32(18).string(message.amount);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): DecCoin {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseDecCoin } as DecCoin;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.denom = reader.string();
break;
case 2:
message.amount = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): DecCoin {
const message = { ...baseDecCoin } as DecCoin;
if (object.denom !== undefined && object.denom !== null) {
message.denom = String(object.denom);
} else {
message.denom = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = String(object.amount);
} else {
message.amount = "";
}
return message;
},
toJSON(message: DecCoin): unknown {
const obj: any = {};
message.denom !== undefined && (obj.denom = message.denom);
message.amount !== undefined && (obj.amount = message.amount);
return obj;
},
fromPartial(object: DeepPartial<DecCoin>): DecCoin {
const message = { ...baseDecCoin } as DecCoin;
if (object.denom !== undefined && object.denom !== null) {
message.denom = object.denom;
} else {
message.denom = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = object.amount;
} else {
message.amount = "";
}
return message;
},
};
const baseIntProto: object = { int: "" };
export const IntProto = {
encode(message: IntProto, writer: Writer = Writer.create()): Writer {
if (message.int !== "") {
writer.uint32(10).string(message.int);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): IntProto {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseIntProto } as IntProto;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.int = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): IntProto {
const message = { ...baseIntProto } as IntProto;
if (object.int !== undefined && object.int !== null) {
message.int = String(object.int);
} else {
message.int = "";
}
return message;
},
toJSON(message: IntProto): unknown {
const obj: any = {};
message.int !== undefined && (obj.int = message.int);
return obj;
},
fromPartial(object: DeepPartial<IntProto>): IntProto {
const message = { ...baseIntProto } as IntProto;
if (object.int !== undefined && object.int !== null) {
message.int = object.int;
} else {
message.int = "";
}
return message;
},
};
const baseDecProto: object = { dec: "" };
export const DecProto = {
encode(message: DecProto, writer: Writer = Writer.create()): Writer {
if (message.dec !== "") {
writer.uint32(10).string(message.dec);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): DecProto {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseDecProto } as DecProto;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.dec = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): DecProto {
const message = { ...baseDecProto } as DecProto;
if (object.dec !== undefined && object.dec !== null) {
message.dec = String(object.dec);
} else {
message.dec = "";
}
return message;
},
toJSON(message: DecProto): unknown {
const obj: any = {};
message.dec !== undefined && (obj.dec = message.dec);
return obj;
},
fromPartial(object: DeepPartial<DecProto>): DecProto {
const message = { ...baseDecProto } as DecProto;
if (object.dec !== undefined && object.dec !== null) {
message.dec = object.dec;
} else {
message.dec = "";
}
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,3 @@
//@ts-nocheck
/* eslint-disable */
export const protobufPackage = "gogoproto";

View File

@ -0,0 +1,3 @@
//@ts-nocheck
/* eslint-disable */
export const protobufPackage = "google.api";

View File

@ -0,0 +1,707 @@
//@ts-nocheck
/* eslint-disable */
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "google.api";
/**
* Defines the HTTP configuration for an API service. It contains a list of
* [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
* to one or more HTTP REST API methods.
*/
export interface Http {
/**
* A list of HTTP configuration rules that apply to individual API methods.
*
* **NOTE:** All service configuration rules follow "last one wins" order.
*/
rules: HttpRule[];
/**
* When set to true, URL path parmeters will be fully URI-decoded except in
* cases of single segment matches in reserved expansion, where "%2F" will be
* left encoded.
*
* The default behavior is to not decode RFC 6570 reserved characters in multi
* segment matches.
*/
fully_decode_reserved_expansion: boolean;
}
/**
* `HttpRule` defines the mapping of an RPC method to one or more HTTP
* REST API methods. The mapping specifies how different portions of the RPC
* request message are mapped to URL path, URL query parameters, and
* HTTP request body. The mapping is typically specified as an
* `google.api.http` annotation on the RPC method,
* see "google/api/annotations.proto" for details.
*
* The mapping consists of a field specifying the path template and
* method kind. The path template can refer to fields in the request
* message, as in the example below which describes a REST GET
* operation on a resource collection of messages:
*
*
* service Messaging {
* rpc GetMessage(GetMessageRequest) returns (Message) {
* option (google.api.http).get = "/v1/messages/{message_id}/{sub.subfield}";
* }
* }
* message GetMessageRequest {
* message SubMessage {
* string subfield = 1;
* }
* string message_id = 1; // mapped to the URL
* SubMessage sub = 2; // `sub.subfield` is url-mapped
* }
* message Message {
* string text = 1; // content of the resource
* }
*
* The same http annotation can alternatively be expressed inside the
* `GRPC API Configuration` YAML file.
*
* http:
* rules:
* - selector: <proto_package_name>.Messaging.GetMessage
* get: /v1/messages/{message_id}/{sub.subfield}
*
* This definition enables an automatic, bidrectional mapping of HTTP
* JSON to RPC. Example:
*
* HTTP | RPC
* -----|-----
* `GET /v1/messages/123456/foo` | `GetMessage(message_id: "123456" sub: SubMessage(subfield: "foo"))`
*
* In general, not only fields but also field paths can be referenced
* from a path pattern. Fields mapped to the path pattern cannot be
* repeated and must have a primitive (non-message) type.
*
* Any fields in the request message which are not bound by the path
* pattern automatically become (optional) HTTP query
* parameters. Assume the following definition of the request message:
*
*
* service Messaging {
* rpc GetMessage(GetMessageRequest) returns (Message) {
* option (google.api.http).get = "/v1/messages/{message_id}";
* }
* }
* message GetMessageRequest {
* message SubMessage {
* string subfield = 1;
* }
* string message_id = 1; // mapped to the URL
* int64 revision = 2; // becomes a parameter
* SubMessage sub = 3; // `sub.subfield` becomes a parameter
* }
*
*
* This enables a HTTP JSON to RPC mapping as below:
*
* HTTP | RPC
* -----|-----
* `GET /v1/messages/123456?revision=2&sub.subfield=foo` | `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo"))`
*
* Note that fields which are mapped to HTTP parameters must have a
* primitive type or a repeated primitive type. Message types are not
* allowed. In the case of a repeated type, the parameter can be
* repeated in the URL, as in `...?param=A&param=B`.
*
* For HTTP method kinds which allow a request body, the `body` field
* specifies the mapping. Consider a REST update method on the
* message resource collection:
*
*
* service Messaging {
* rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
* option (google.api.http) = {
* put: "/v1/messages/{message_id}"
* body: "message"
* };
* }
* }
* message UpdateMessageRequest {
* string message_id = 1; // mapped to the URL
* Message message = 2; // mapped to the body
* }
*
*
* The following HTTP JSON to RPC mapping is enabled, where the
* representation of the JSON in the request body is determined by
* protos JSON encoding:
*
* HTTP | RPC
* -----|-----
* `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
*
* The special name `*` can be used in the body mapping to define that
* every field not bound by the path template should be mapped to the
* request body. This enables the following alternative definition of
* the update method:
*
* service Messaging {
* rpc UpdateMessage(Message) returns (Message) {
* option (google.api.http) = {
* put: "/v1/messages/{message_id}"
* body: "*"
* };
* }
* }
* message Message {
* string message_id = 1;
* string text = 2;
* }
*
*
* The following HTTP JSON to RPC mapping is enabled:
*
* HTTP | RPC
* -----|-----
* `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")`
*
* Note that when using `*` in the body mapping, it is not possible to
* have HTTP parameters, as all fields not bound by the path end in
* the body. This makes this option more rarely used in practice of
* defining REST APIs. The common usage of `*` is in custom methods
* which don't use the URL at all for transferring data.
*
* It is possible to define multiple HTTP methods for one RPC by using
* the `additional_bindings` option. Example:
*
* service Messaging {
* rpc GetMessage(GetMessageRequest) returns (Message) {
* option (google.api.http) = {
* get: "/v1/messages/{message_id}"
* additional_bindings {
* get: "/v1/users/{user_id}/messages/{message_id}"
* }
* };
* }
* }
* message GetMessageRequest {
* string message_id = 1;
* string user_id = 2;
* }
*
*
* This enables the following two alternative HTTP JSON to RPC
* mappings:
*
* HTTP | RPC
* -----|-----
* `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
* `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")`
*
* # Rules for HTTP mapping
*
* The rules for mapping HTTP path, query parameters, and body fields
* to the request message are as follows:
*
* 1. The `body` field specifies either `*` or a field path, or is
* omitted. If omitted, it indicates there is no HTTP request body.
* 2. Leaf fields (recursive expansion of nested messages in the
* request) can be classified into three types:
* (a) Matched in the URL template.
* (b) Covered by body (if body is `*`, everything except (a) fields;
* else everything under the body field)
* (c) All other fields.
* 3. URL query parameters found in the HTTP request are mapped to (c) fields.
* 4. Any body sent with an HTTP request can contain only (b) fields.
*
* The syntax of the path template is as follows:
*
* Template = "/" Segments [ Verb ] ;
* Segments = Segment { "/" Segment } ;
* Segment = "*" | "**" | LITERAL | Variable ;
* Variable = "{" FieldPath [ "=" Segments ] "}" ;
* FieldPath = IDENT { "." IDENT } ;
* Verb = ":" LITERAL ;
*
* The syntax `*` matches a single path segment. The syntax `**` matches zero
* or more path segments, which must be the last part of the path except the
* `Verb`. The syntax `LITERAL` matches literal text in the path.
*
* The syntax `Variable` matches part of the URL path as specified by its
* template. A variable template must not contain other variables. If a variable
* matches a single path segment, its template may be omitted, e.g. `{var}`
* is equivalent to `{var=*}`.
*
* If a variable contains exactly one path segment, such as `"{var}"` or
* `"{var=*}"`, when such a variable is expanded into a URL path, all characters
* except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the
* Discovery Document as `{var}`.
*
* If a variable contains one or more path segments, such as `"{var=foo/*}"`
* or `"{var=**}"`, when such a variable is expanded into a URL path, all
* characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables
* show up in the Discovery Document as `{+var}`.
*
* NOTE: While the single segment variable matches the semantics of
* [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2
* Simple String Expansion, the multi segment variable **does not** match
* RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion
* does not expand special characters like `?` and `#`, which would lead
* to invalid URLs.
*
* NOTE: the field paths in variables and in the `body` must not refer to
* repeated fields or map fields.
*/
export interface HttpRule {
/**
* Selects methods to which this rule applies.
*
* Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
*/
selector: string;
/** Used for listing and getting information about resources. */
get: string | undefined;
/** Used for updating a resource. */
put: string | undefined;
/** Used for creating a resource. */
post: string | undefined;
/** Used for deleting a resource. */
delete: string | undefined;
/** Used for updating a resource. */
patch: string | undefined;
/**
* The custom pattern is used for specifying an HTTP method that is not
* included in the `pattern` field, such as HEAD, or "*" to leave the
* HTTP method unspecified for this rule. The wild-card rule is useful
* for services that provide content to Web (HTML) clients.
*/
custom: CustomHttpPattern | undefined;
/**
* The name of the request field whose value is mapped to the HTTP body, or
* `*` for mapping all fields not captured by the path pattern to the HTTP
* body. NOTE: the referred field must not be a repeated field and must be
* present at the top-level of request message type.
*/
body: string;
/**
* Optional. The name of the response field whose value is mapped to the HTTP
* body of response. Other response fields are ignored. When
* not set, the response message will be used as HTTP body of response.
*/
response_body: string;
/**
* Additional HTTP bindings for the selector. Nested bindings must
* not contain an `additional_bindings` field themselves (that is,
* the nesting may only be one level deep).
*/
additional_bindings: HttpRule[];
}
/** A custom pattern is used for defining custom HTTP verb. */
export interface CustomHttpPattern {
/** The name of this custom HTTP verb. */
kind: string;
/** The path matched by this custom verb. */
path: string;
}
const baseHttp: object = { fully_decode_reserved_expansion: false };
export const Http = {
encode(message: Http, writer: Writer = Writer.create()): Writer {
for (const v of message.rules) {
HttpRule.encode(v!, writer.uint32(10).fork()).ldelim();
}
if (message.fully_decode_reserved_expansion === true) {
writer.uint32(16).bool(message.fully_decode_reserved_expansion);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): Http {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseHttp } as Http;
message.rules = [];
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.rules.push(HttpRule.decode(reader, reader.uint32()));
break;
case 2:
message.fully_decode_reserved_expansion = reader.bool();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): Http {
const message = { ...baseHttp } as Http;
message.rules = [];
if (object.rules !== undefined && object.rules !== null) {
for (const e of object.rules) {
message.rules.push(HttpRule.fromJSON(e));
}
}
if (
object.fully_decode_reserved_expansion !== undefined &&
object.fully_decode_reserved_expansion !== null
) {
message.fully_decode_reserved_expansion = Boolean(
object.fully_decode_reserved_expansion
);
} else {
message.fully_decode_reserved_expansion = false;
}
return message;
},
toJSON(message: Http): unknown {
const obj: any = {};
if (message.rules) {
obj.rules = message.rules.map((e) =>
e ? HttpRule.toJSON(e) : undefined
);
} else {
obj.rules = [];
}
message.fully_decode_reserved_expansion !== undefined &&
(obj.fully_decode_reserved_expansion =
message.fully_decode_reserved_expansion);
return obj;
},
fromPartial(object: DeepPartial<Http>): Http {
const message = { ...baseHttp } as Http;
message.rules = [];
if (object.rules !== undefined && object.rules !== null) {
for (const e of object.rules) {
message.rules.push(HttpRule.fromPartial(e));
}
}
if (
object.fully_decode_reserved_expansion !== undefined &&
object.fully_decode_reserved_expansion !== null
) {
message.fully_decode_reserved_expansion =
object.fully_decode_reserved_expansion;
} else {
message.fully_decode_reserved_expansion = false;
}
return message;
},
};
const baseHttpRule: object = { selector: "", body: "", response_body: "" };
export const HttpRule = {
encode(message: HttpRule, writer: Writer = Writer.create()): Writer {
if (message.selector !== "") {
writer.uint32(10).string(message.selector);
}
if (message.get !== undefined) {
writer.uint32(18).string(message.get);
}
if (message.put !== undefined) {
writer.uint32(26).string(message.put);
}
if (message.post !== undefined) {
writer.uint32(34).string(message.post);
}
if (message.delete !== undefined) {
writer.uint32(42).string(message.delete);
}
if (message.patch !== undefined) {
writer.uint32(50).string(message.patch);
}
if (message.custom !== undefined) {
CustomHttpPattern.encode(
message.custom,
writer.uint32(66).fork()
).ldelim();
}
if (message.body !== "") {
writer.uint32(58).string(message.body);
}
if (message.response_body !== "") {
writer.uint32(98).string(message.response_body);
}
for (const v of message.additional_bindings) {
HttpRule.encode(v!, writer.uint32(90).fork()).ldelim();
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): HttpRule {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseHttpRule } as HttpRule;
message.additional_bindings = [];
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.selector = reader.string();
break;
case 2:
message.get = reader.string();
break;
case 3:
message.put = reader.string();
break;
case 4:
message.post = reader.string();
break;
case 5:
message.delete = reader.string();
break;
case 6:
message.patch = reader.string();
break;
case 8:
message.custom = CustomHttpPattern.decode(reader, reader.uint32());
break;
case 7:
message.body = reader.string();
break;
case 12:
message.response_body = reader.string();
break;
case 11:
message.additional_bindings.push(
HttpRule.decode(reader, reader.uint32())
);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): HttpRule {
const message = { ...baseHttpRule } as HttpRule;
message.additional_bindings = [];
if (object.selector !== undefined && object.selector !== null) {
message.selector = String(object.selector);
} else {
message.selector = "";
}
if (object.get !== undefined && object.get !== null) {
message.get = String(object.get);
} else {
message.get = undefined;
}
if (object.put !== undefined && object.put !== null) {
message.put = String(object.put);
} else {
message.put = undefined;
}
if (object.post !== undefined && object.post !== null) {
message.post = String(object.post);
} else {
message.post = undefined;
}
if (object.delete !== undefined && object.delete !== null) {
message.delete = String(object.delete);
} else {
message.delete = undefined;
}
if (object.patch !== undefined && object.patch !== null) {
message.patch = String(object.patch);
} else {
message.patch = undefined;
}
if (object.custom !== undefined && object.custom !== null) {
message.custom = CustomHttpPattern.fromJSON(object.custom);
} else {
message.custom = undefined;
}
if (object.body !== undefined && object.body !== null) {
message.body = String(object.body);
} else {
message.body = "";
}
if (object.response_body !== undefined && object.response_body !== null) {
message.response_body = String(object.response_body);
} else {
message.response_body = "";
}
if (
object.additional_bindings !== undefined &&
object.additional_bindings !== null
) {
for (const e of object.additional_bindings) {
message.additional_bindings.push(HttpRule.fromJSON(e));
}
}
return message;
},
toJSON(message: HttpRule): unknown {
const obj: any = {};
message.selector !== undefined && (obj.selector = message.selector);
message.get !== undefined && (obj.get = message.get);
message.put !== undefined && (obj.put = message.put);
message.post !== undefined && (obj.post = message.post);
message.delete !== undefined && (obj.delete = message.delete);
message.patch !== undefined && (obj.patch = message.patch);
message.custom !== undefined &&
(obj.custom = message.custom
? CustomHttpPattern.toJSON(message.custom)
: undefined);
message.body !== undefined && (obj.body = message.body);
message.response_body !== undefined &&
(obj.response_body = message.response_body);
if (message.additional_bindings) {
obj.additional_bindings = message.additional_bindings.map((e) =>
e ? HttpRule.toJSON(e) : undefined
);
} else {
obj.additional_bindings = [];
}
return obj;
},
fromPartial(object: DeepPartial<HttpRule>): HttpRule {
const message = { ...baseHttpRule } as HttpRule;
message.additional_bindings = [];
if (object.selector !== undefined && object.selector !== null) {
message.selector = object.selector;
} else {
message.selector = "";
}
if (object.get !== undefined && object.get !== null) {
message.get = object.get;
} else {
message.get = undefined;
}
if (object.put !== undefined && object.put !== null) {
message.put = object.put;
} else {
message.put = undefined;
}
if (object.post !== undefined && object.post !== null) {
message.post = object.post;
} else {
message.post = undefined;
}
if (object.delete !== undefined && object.delete !== null) {
message.delete = object.delete;
} else {
message.delete = undefined;
}
if (object.patch !== undefined && object.patch !== null) {
message.patch = object.patch;
} else {
message.patch = undefined;
}
if (object.custom !== undefined && object.custom !== null) {
message.custom = CustomHttpPattern.fromPartial(object.custom);
} else {
message.custom = undefined;
}
if (object.body !== undefined && object.body !== null) {
message.body = object.body;
} else {
message.body = "";
}
if (object.response_body !== undefined && object.response_body !== null) {
message.response_body = object.response_body;
} else {
message.response_body = "";
}
if (
object.additional_bindings !== undefined &&
object.additional_bindings !== null
) {
for (const e of object.additional_bindings) {
message.additional_bindings.push(HttpRule.fromPartial(e));
}
}
return message;
},
};
const baseCustomHttpPattern: object = { kind: "", path: "" };
export const CustomHttpPattern = {
encode(message: CustomHttpPattern, writer: Writer = Writer.create()): Writer {
if (message.kind !== "") {
writer.uint32(10).string(message.kind);
}
if (message.path !== "") {
writer.uint32(18).string(message.path);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): CustomHttpPattern {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseCustomHttpPattern } as CustomHttpPattern;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.kind = reader.string();
break;
case 2:
message.path = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): CustomHttpPattern {
const message = { ...baseCustomHttpPattern } as CustomHttpPattern;
if (object.kind !== undefined && object.kind !== null) {
message.kind = String(object.kind);
} else {
message.kind = "";
}
if (object.path !== undefined && object.path !== null) {
message.path = String(object.path);
} else {
message.path = "";
}
return message;
},
toJSON(message: CustomHttpPattern): unknown {
const obj: any = {};
message.kind !== undefined && (obj.kind = message.kind);
message.path !== undefined && (obj.path = message.path);
return obj;
},
fromPartial(object: DeepPartial<CustomHttpPattern>): CustomHttpPattern {
const message = { ...baseCustomHttpPattern } as CustomHttpPattern;
if (object.kind !== undefined && object.kind !== null) {
message.kind = object.kind;
} else {
message.kind = "";
}
if (object.path !== undefined && object.path !== null) {
message.path = object.path;
} else {
message.path = "";
}
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,129 @@
//@ts-nocheck
/* eslint-disable */
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
export interface ChainRegistration {
chainID: number;
emitterAddress: Uint8Array;
}
const baseChainRegistration: object = { chainID: 0 };
export const ChainRegistration = {
encode(message: ChainRegistration, writer: Writer = Writer.create()): Writer {
if (message.chainID !== 0) {
writer.uint32(8).uint32(message.chainID);
}
if (message.emitterAddress.length !== 0) {
writer.uint32(18).bytes(message.emitterAddress);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): ChainRegistration {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseChainRegistration } as ChainRegistration;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.chainID = reader.uint32();
break;
case 2:
message.emitterAddress = reader.bytes();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): ChainRegistration {
const message = { ...baseChainRegistration } as ChainRegistration;
if (object.chainID !== undefined && object.chainID !== null) {
message.chainID = Number(object.chainID);
} else {
message.chainID = 0;
}
if (object.emitterAddress !== undefined && object.emitterAddress !== null) {
message.emitterAddress = bytesFromBase64(object.emitterAddress);
}
return message;
},
toJSON(message: ChainRegistration): unknown {
const obj: any = {};
message.chainID !== undefined && (obj.chainID = message.chainID);
message.emitterAddress !== undefined &&
(obj.emitterAddress = base64FromBytes(
message.emitterAddress !== undefined
? message.emitterAddress
: new Uint8Array()
));
return obj;
},
fromPartial(object: DeepPartial<ChainRegistration>): ChainRegistration {
const message = { ...baseChainRegistration } as ChainRegistration;
if (object.chainID !== undefined && object.chainID !== null) {
message.chainID = object.chainID;
} else {
message.chainID = 0;
}
if (object.emitterAddress !== undefined && object.emitterAddress !== null) {
message.emitterAddress = object.emitterAddress;
} else {
message.emitterAddress = new Uint8Array();
}
return message;
},
};
declare var self: any | undefined;
declare var window: any | undefined;
var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw "Unable to locate global object";
})();
const atob: (b64: string) => string =
globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary"));
function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64);
const arr = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i);
}
return arr;
}
const btoa: (bin: string) => string =
globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64"));
function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = [];
for (let i = 0; i < arr.byteLength; ++i) {
bin.push(String.fromCharCode(arr[i]));
}
return btoa(bin.join(""));
}
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,140 @@
//@ts-nocheck
/* eslint-disable */
import * as Long from "long";
import { util, configure, Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
export interface CoinMetaRollbackProtection {
index: string;
lastUpdateSequence: number;
}
const baseCoinMetaRollbackProtection: object = {
index: "",
lastUpdateSequence: 0,
};
export const CoinMetaRollbackProtection = {
encode(
message: CoinMetaRollbackProtection,
writer: Writer = Writer.create()
): Writer {
if (message.index !== "") {
writer.uint32(10).string(message.index);
}
if (message.lastUpdateSequence !== 0) {
writer.uint32(16).uint64(message.lastUpdateSequence);
}
return writer;
},
decode(
input: Reader | Uint8Array,
length?: number
): CoinMetaRollbackProtection {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = {
...baseCoinMetaRollbackProtection,
} as CoinMetaRollbackProtection;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.index = reader.string();
break;
case 2:
message.lastUpdateSequence = longToNumber(reader.uint64() as Long);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): CoinMetaRollbackProtection {
const message = {
...baseCoinMetaRollbackProtection,
} as CoinMetaRollbackProtection;
if (object.index !== undefined && object.index !== null) {
message.index = String(object.index);
} else {
message.index = "";
}
if (
object.lastUpdateSequence !== undefined &&
object.lastUpdateSequence !== null
) {
message.lastUpdateSequence = Number(object.lastUpdateSequence);
} else {
message.lastUpdateSequence = 0;
}
return message;
},
toJSON(message: CoinMetaRollbackProtection): unknown {
const obj: any = {};
message.index !== undefined && (obj.index = message.index);
message.lastUpdateSequence !== undefined &&
(obj.lastUpdateSequence = message.lastUpdateSequence);
return obj;
},
fromPartial(
object: DeepPartial<CoinMetaRollbackProtection>
): CoinMetaRollbackProtection {
const message = {
...baseCoinMetaRollbackProtection,
} as CoinMetaRollbackProtection;
if (object.index !== undefined && object.index !== null) {
message.index = object.index;
} else {
message.index = "";
}
if (
object.lastUpdateSequence !== undefined &&
object.lastUpdateSequence !== null
) {
message.lastUpdateSequence = object.lastUpdateSequence;
} else {
message.lastUpdateSequence = 0;
}
return message;
},
};
declare var self: any | undefined;
declare var window: any | undefined;
var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw "Unable to locate global object";
})();
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;
function longToNumber(long: Long): number {
if (long.gt(Number.MAX_SAFE_INTEGER)) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
}
return long.toNumber();
}
if (util.Long !== Long) {
util.Long = Long as any;
configure();
}

View File

@ -0,0 +1,56 @@
//@ts-nocheck
/* eslint-disable */
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
export interface Config {}
const baseConfig: object = {};
export const Config = {
encode(_: Config, writer: Writer = Writer.create()): Writer {
return writer;
},
decode(input: Reader | Uint8Array, length?: number): Config {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseConfig } as Config;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(_: any): Config {
const message = { ...baseConfig } as Config;
return message;
},
toJSON(_: Config): unknown {
const obj: any = {};
return obj;
},
fromPartial(_: DeepPartial<Config>): Config {
const message = { ...baseConfig } as Config;
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,468 @@
//@ts-nocheck
/* eslint-disable */
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
export interface EventChainRegistered {
chainID: number;
emitterAddress: Uint8Array;
}
export interface EventAssetRegistrationUpdate {
tokenChain: number;
tokenAddress: Uint8Array;
name: string;
symbol: string;
decimals: number;
}
export interface EventTransferReceived {
tokenChain: number;
tokenAddress: Uint8Array;
to: string;
feeRecipient: string;
amount: string;
fee: string;
localDenom: string;
}
const baseEventChainRegistered: object = { chainID: 0 };
export const EventChainRegistered = {
encode(
message: EventChainRegistered,
writer: Writer = Writer.create()
): Writer {
if (message.chainID !== 0) {
writer.uint32(8).uint32(message.chainID);
}
if (message.emitterAddress.length !== 0) {
writer.uint32(18).bytes(message.emitterAddress);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): EventChainRegistered {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseEventChainRegistered } as EventChainRegistered;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.chainID = reader.uint32();
break;
case 2:
message.emitterAddress = reader.bytes();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): EventChainRegistered {
const message = { ...baseEventChainRegistered } as EventChainRegistered;
if (object.chainID !== undefined && object.chainID !== null) {
message.chainID = Number(object.chainID);
} else {
message.chainID = 0;
}
if (object.emitterAddress !== undefined && object.emitterAddress !== null) {
message.emitterAddress = bytesFromBase64(object.emitterAddress);
}
return message;
},
toJSON(message: EventChainRegistered): unknown {
const obj: any = {};
message.chainID !== undefined && (obj.chainID = message.chainID);
message.emitterAddress !== undefined &&
(obj.emitterAddress = base64FromBytes(
message.emitterAddress !== undefined
? message.emitterAddress
: new Uint8Array()
));
return obj;
},
fromPartial(object: DeepPartial<EventChainRegistered>): EventChainRegistered {
const message = { ...baseEventChainRegistered } as EventChainRegistered;
if (object.chainID !== undefined && object.chainID !== null) {
message.chainID = object.chainID;
} else {
message.chainID = 0;
}
if (object.emitterAddress !== undefined && object.emitterAddress !== null) {
message.emitterAddress = object.emitterAddress;
} else {
message.emitterAddress = new Uint8Array();
}
return message;
},
};
const baseEventAssetRegistrationUpdate: object = {
tokenChain: 0,
name: "",
symbol: "",
decimals: 0,
};
export const EventAssetRegistrationUpdate = {
encode(
message: EventAssetRegistrationUpdate,
writer: Writer = Writer.create()
): Writer {
if (message.tokenChain !== 0) {
writer.uint32(8).uint32(message.tokenChain);
}
if (message.tokenAddress.length !== 0) {
writer.uint32(18).bytes(message.tokenAddress);
}
if (message.name !== "") {
writer.uint32(26).string(message.name);
}
if (message.symbol !== "") {
writer.uint32(34).string(message.symbol);
}
if (message.decimals !== 0) {
writer.uint32(40).uint32(message.decimals);
}
return writer;
},
decode(
input: Reader | Uint8Array,
length?: number
): EventAssetRegistrationUpdate {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = {
...baseEventAssetRegistrationUpdate,
} as EventAssetRegistrationUpdate;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.tokenChain = reader.uint32();
break;
case 2:
message.tokenAddress = reader.bytes();
break;
case 3:
message.name = reader.string();
break;
case 4:
message.symbol = reader.string();
break;
case 5:
message.decimals = reader.uint32();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): EventAssetRegistrationUpdate {
const message = {
...baseEventAssetRegistrationUpdate,
} as EventAssetRegistrationUpdate;
if (object.tokenChain !== undefined && object.tokenChain !== null) {
message.tokenChain = Number(object.tokenChain);
} else {
message.tokenChain = 0;
}
if (object.tokenAddress !== undefined && object.tokenAddress !== null) {
message.tokenAddress = bytesFromBase64(object.tokenAddress);
}
if (object.name !== undefined && object.name !== null) {
message.name = String(object.name);
} else {
message.name = "";
}
if (object.symbol !== undefined && object.symbol !== null) {
message.symbol = String(object.symbol);
} else {
message.symbol = "";
}
if (object.decimals !== undefined && object.decimals !== null) {
message.decimals = Number(object.decimals);
} else {
message.decimals = 0;
}
return message;
},
toJSON(message: EventAssetRegistrationUpdate): unknown {
const obj: any = {};
message.tokenChain !== undefined && (obj.tokenChain = message.tokenChain);
message.tokenAddress !== undefined &&
(obj.tokenAddress = base64FromBytes(
message.tokenAddress !== undefined
? message.tokenAddress
: new Uint8Array()
));
message.name !== undefined && (obj.name = message.name);
message.symbol !== undefined && (obj.symbol = message.symbol);
message.decimals !== undefined && (obj.decimals = message.decimals);
return obj;
},
fromPartial(
object: DeepPartial<EventAssetRegistrationUpdate>
): EventAssetRegistrationUpdate {
const message = {
...baseEventAssetRegistrationUpdate,
} as EventAssetRegistrationUpdate;
if (object.tokenChain !== undefined && object.tokenChain !== null) {
message.tokenChain = object.tokenChain;
} else {
message.tokenChain = 0;
}
if (object.tokenAddress !== undefined && object.tokenAddress !== null) {
message.tokenAddress = object.tokenAddress;
} else {
message.tokenAddress = new Uint8Array();
}
if (object.name !== undefined && object.name !== null) {
message.name = object.name;
} else {
message.name = "";
}
if (object.symbol !== undefined && object.symbol !== null) {
message.symbol = object.symbol;
} else {
message.symbol = "";
}
if (object.decimals !== undefined && object.decimals !== null) {
message.decimals = object.decimals;
} else {
message.decimals = 0;
}
return message;
},
};
const baseEventTransferReceived: object = {
tokenChain: 0,
to: "",
feeRecipient: "",
amount: "",
fee: "",
localDenom: "",
};
export const EventTransferReceived = {
encode(
message: EventTransferReceived,
writer: Writer = Writer.create()
): Writer {
if (message.tokenChain !== 0) {
writer.uint32(8).uint32(message.tokenChain);
}
if (message.tokenAddress.length !== 0) {
writer.uint32(18).bytes(message.tokenAddress);
}
if (message.to !== "") {
writer.uint32(26).string(message.to);
}
if (message.feeRecipient !== "") {
writer.uint32(34).string(message.feeRecipient);
}
if (message.amount !== "") {
writer.uint32(42).string(message.amount);
}
if (message.fee !== "") {
writer.uint32(50).string(message.fee);
}
if (message.localDenom !== "") {
writer.uint32(58).string(message.localDenom);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): EventTransferReceived {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseEventTransferReceived } as EventTransferReceived;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.tokenChain = reader.uint32();
break;
case 2:
message.tokenAddress = reader.bytes();
break;
case 3:
message.to = reader.string();
break;
case 4:
message.feeRecipient = reader.string();
break;
case 5:
message.amount = reader.string();
break;
case 6:
message.fee = reader.string();
break;
case 7:
message.localDenom = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): EventTransferReceived {
const message = { ...baseEventTransferReceived } as EventTransferReceived;
if (object.tokenChain !== undefined && object.tokenChain !== null) {
message.tokenChain = Number(object.tokenChain);
} else {
message.tokenChain = 0;
}
if (object.tokenAddress !== undefined && object.tokenAddress !== null) {
message.tokenAddress = bytesFromBase64(object.tokenAddress);
}
if (object.to !== undefined && object.to !== null) {
message.to = String(object.to);
} else {
message.to = "";
}
if (object.feeRecipient !== undefined && object.feeRecipient !== null) {
message.feeRecipient = String(object.feeRecipient);
} else {
message.feeRecipient = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = String(object.amount);
} else {
message.amount = "";
}
if (object.fee !== undefined && object.fee !== null) {
message.fee = String(object.fee);
} else {
message.fee = "";
}
if (object.localDenom !== undefined && object.localDenom !== null) {
message.localDenom = String(object.localDenom);
} else {
message.localDenom = "";
}
return message;
},
toJSON(message: EventTransferReceived): unknown {
const obj: any = {};
message.tokenChain !== undefined && (obj.tokenChain = message.tokenChain);
message.tokenAddress !== undefined &&
(obj.tokenAddress = base64FromBytes(
message.tokenAddress !== undefined
? message.tokenAddress
: new Uint8Array()
));
message.to !== undefined && (obj.to = message.to);
message.feeRecipient !== undefined &&
(obj.feeRecipient = message.feeRecipient);
message.amount !== undefined && (obj.amount = message.amount);
message.fee !== undefined && (obj.fee = message.fee);
message.localDenom !== undefined && (obj.localDenom = message.localDenom);
return obj;
},
fromPartial(
object: DeepPartial<EventTransferReceived>
): EventTransferReceived {
const message = { ...baseEventTransferReceived } as EventTransferReceived;
if (object.tokenChain !== undefined && object.tokenChain !== null) {
message.tokenChain = object.tokenChain;
} else {
message.tokenChain = 0;
}
if (object.tokenAddress !== undefined && object.tokenAddress !== null) {
message.tokenAddress = object.tokenAddress;
} else {
message.tokenAddress = new Uint8Array();
}
if (object.to !== undefined && object.to !== null) {
message.to = object.to;
} else {
message.to = "";
}
if (object.feeRecipient !== undefined && object.feeRecipient !== null) {
message.feeRecipient = object.feeRecipient;
} else {
message.feeRecipient = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = object.amount;
} else {
message.amount = "";
}
if (object.fee !== undefined && object.fee !== null) {
message.fee = object.fee;
} else {
message.fee = "";
}
if (object.localDenom !== undefined && object.localDenom !== null) {
message.localDenom = object.localDenom;
} else {
message.localDenom = "";
}
return message;
},
};
declare var self: any | undefined;
declare var window: any | undefined;
var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw "Unable to locate global object";
})();
const atob: (b64: string) => string =
globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary"));
function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64);
const arr = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i);
}
return arr;
}
const btoa: (bin: string) => string =
globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64"));
function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = [];
for (let i = 0; i < arr.byteLength; ++i) {
bin.push(String.fromCharCode(arr[i]));
}
return btoa(bin.join(""));
}
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,191 @@
//@ts-nocheck
/* eslint-disable */
import { Config } from "../tokenbridge/config";
import { ReplayProtection } from "../tokenbridge/replay_protection";
import { ChainRegistration } from "../tokenbridge/chain_registration";
import { CoinMetaRollbackProtection } from "../tokenbridge/coin_meta_rollback_protection";
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
/** GenesisState defines the tokenbridge module's genesis state. */
export interface GenesisState {
config: Config | undefined;
replayProtectionList: ReplayProtection[];
chainRegistrationList: ChainRegistration[];
/** this line is used by starport scaffolding # genesis/proto/state */
coinMetaRollbackProtectionList: CoinMetaRollbackProtection[];
}
const baseGenesisState: object = {};
export const GenesisState = {
encode(message: GenesisState, writer: Writer = Writer.create()): Writer {
if (message.config !== undefined) {
Config.encode(message.config, writer.uint32(10).fork()).ldelim();
}
for (const v of message.replayProtectionList) {
ReplayProtection.encode(v!, writer.uint32(18).fork()).ldelim();
}
for (const v of message.chainRegistrationList) {
ChainRegistration.encode(v!, writer.uint32(26).fork()).ldelim();
}
for (const v of message.coinMetaRollbackProtectionList) {
CoinMetaRollbackProtection.encode(v!, writer.uint32(34).fork()).ldelim();
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): GenesisState {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseGenesisState } as GenesisState;
message.replayProtectionList = [];
message.chainRegistrationList = [];
message.coinMetaRollbackProtectionList = [];
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.config = Config.decode(reader, reader.uint32());
break;
case 2:
message.replayProtectionList.push(
ReplayProtection.decode(reader, reader.uint32())
);
break;
case 3:
message.chainRegistrationList.push(
ChainRegistration.decode(reader, reader.uint32())
);
break;
case 4:
message.coinMetaRollbackProtectionList.push(
CoinMetaRollbackProtection.decode(reader, reader.uint32())
);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): GenesisState {
const message = { ...baseGenesisState } as GenesisState;
message.replayProtectionList = [];
message.chainRegistrationList = [];
message.coinMetaRollbackProtectionList = [];
if (object.config !== undefined && object.config !== null) {
message.config = Config.fromJSON(object.config);
} else {
message.config = undefined;
}
if (
object.replayProtectionList !== undefined &&
object.replayProtectionList !== null
) {
for (const e of object.replayProtectionList) {
message.replayProtectionList.push(ReplayProtection.fromJSON(e));
}
}
if (
object.chainRegistrationList !== undefined &&
object.chainRegistrationList !== null
) {
for (const e of object.chainRegistrationList) {
message.chainRegistrationList.push(ChainRegistration.fromJSON(e));
}
}
if (
object.coinMetaRollbackProtectionList !== undefined &&
object.coinMetaRollbackProtectionList !== null
) {
for (const e of object.coinMetaRollbackProtectionList) {
message.coinMetaRollbackProtectionList.push(
CoinMetaRollbackProtection.fromJSON(e)
);
}
}
return message;
},
toJSON(message: GenesisState): unknown {
const obj: any = {};
message.config !== undefined &&
(obj.config = message.config ? Config.toJSON(message.config) : undefined);
if (message.replayProtectionList) {
obj.replayProtectionList = message.replayProtectionList.map((e) =>
e ? ReplayProtection.toJSON(e) : undefined
);
} else {
obj.replayProtectionList = [];
}
if (message.chainRegistrationList) {
obj.chainRegistrationList = message.chainRegistrationList.map((e) =>
e ? ChainRegistration.toJSON(e) : undefined
);
} else {
obj.chainRegistrationList = [];
}
if (message.coinMetaRollbackProtectionList) {
obj.coinMetaRollbackProtectionList = message.coinMetaRollbackProtectionList.map(
(e) => (e ? CoinMetaRollbackProtection.toJSON(e) : undefined)
);
} else {
obj.coinMetaRollbackProtectionList = [];
}
return obj;
},
fromPartial(object: DeepPartial<GenesisState>): GenesisState {
const message = { ...baseGenesisState } as GenesisState;
message.replayProtectionList = [];
message.chainRegistrationList = [];
message.coinMetaRollbackProtectionList = [];
if (object.config !== undefined && object.config !== null) {
message.config = Config.fromPartial(object.config);
} else {
message.config = undefined;
}
if (
object.replayProtectionList !== undefined &&
object.replayProtectionList !== null
) {
for (const e of object.replayProtectionList) {
message.replayProtectionList.push(ReplayProtection.fromPartial(e));
}
}
if (
object.chainRegistrationList !== undefined &&
object.chainRegistrationList !== null
) {
for (const e of object.chainRegistrationList) {
message.chainRegistrationList.push(ChainRegistration.fromPartial(e));
}
}
if (
object.coinMetaRollbackProtectionList !== undefined &&
object.coinMetaRollbackProtectionList !== null
) {
for (const e of object.coinMetaRollbackProtectionList) {
message.coinMetaRollbackProtectionList.push(
CoinMetaRollbackProtection.fromPartial(e)
);
}
}
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,75 @@
//@ts-nocheck
/* eslint-disable */
import { Writer, Reader } from "protobufjs/minimal";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
export interface ReplayProtection {
index: string;
}
const baseReplayProtection: object = { index: "" };
export const ReplayProtection = {
encode(message: ReplayProtection, writer: Writer = Writer.create()): Writer {
if (message.index !== "") {
writer.uint32(10).string(message.index);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): ReplayProtection {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseReplayProtection } as ReplayProtection;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.index = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): ReplayProtection {
const message = { ...baseReplayProtection } as ReplayProtection;
if (object.index !== undefined && object.index !== null) {
message.index = String(object.index);
} else {
message.index = "";
}
return message;
},
toJSON(message: ReplayProtection): unknown {
const obj: any = {};
message.index !== undefined && (obj.index = message.index);
return obj;
},
fromPartial(object: DeepPartial<ReplayProtection>): ReplayProtection {
const message = { ...baseReplayProtection } as ReplayProtection;
if (object.index !== undefined && object.index !== null) {
message.index = object.index;
} else {
message.index = "";
}
return message;
},
};
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

View File

@ -0,0 +1,674 @@
//@ts-nocheck
/* eslint-disable */
import { Reader, Writer } from "protobufjs/minimal";
import { Coin } from "../cosmos/base/v1beta1/coin";
export const protobufPackage = "certusone.wormholechain.tokenbridge";
export interface MsgExecuteGovernanceVAA {
creator: string;
vaa: Uint8Array;
}
export interface MsgExecuteGovernanceVAAResponse {}
export interface MsgExecuteVAA {
creator: string;
vaa: Uint8Array;
}
export interface MsgExecuteVAAResponse {}
export interface MsgAttestToken {
creator: string;
denom: string;
}
export interface MsgAttestTokenResponse {}
export interface MsgTransfer {
creator: string;
amount: Coin | undefined;
toChain: number;
toAddress: Uint8Array;
fee: string;
}
export interface MsgTransferResponse {}
const baseMsgExecuteGovernanceVAA: object = { creator: "" };
export const MsgExecuteGovernanceVAA = {
encode(
message: MsgExecuteGovernanceVAA,
writer: Writer = Writer.create()
): Writer {
if (message.creator !== "") {
writer.uint32(10).string(message.creator);
}
if (message.vaa.length !== 0) {
writer.uint32(18).bytes(message.vaa);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgExecuteGovernanceVAA {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = {
...baseMsgExecuteGovernanceVAA,
} as MsgExecuteGovernanceVAA;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.creator = reader.string();
break;
case 2:
message.vaa = reader.bytes();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): MsgExecuteGovernanceVAA {
const message = {
...baseMsgExecuteGovernanceVAA,
} as MsgExecuteGovernanceVAA;
if (object.creator !== undefined && object.creator !== null) {
message.creator = String(object.creator);
} else {
message.creator = "";
}
if (object.vaa !== undefined && object.vaa !== null) {
message.vaa = bytesFromBase64(object.vaa);
}
return message;
},
toJSON(message: MsgExecuteGovernanceVAA): unknown {
const obj: any = {};
message.creator !== undefined && (obj.creator = message.creator);
message.vaa !== undefined &&
(obj.vaa = base64FromBytes(
message.vaa !== undefined ? message.vaa : new Uint8Array()
));
return obj;
},
fromPartial(
object: DeepPartial<MsgExecuteGovernanceVAA>
): MsgExecuteGovernanceVAA {
const message = {
...baseMsgExecuteGovernanceVAA,
} as MsgExecuteGovernanceVAA;
if (object.creator !== undefined && object.creator !== null) {
message.creator = object.creator;
} else {
message.creator = "";
}
if (object.vaa !== undefined && object.vaa !== null) {
message.vaa = object.vaa;
} else {
message.vaa = new Uint8Array();
}
return message;
},
};
const baseMsgExecuteGovernanceVAAResponse: object = {};
export const MsgExecuteGovernanceVAAResponse = {
encode(
_: MsgExecuteGovernanceVAAResponse,
writer: Writer = Writer.create()
): Writer {
return writer;
},
decode(
input: Reader | Uint8Array,
length?: number
): MsgExecuteGovernanceVAAResponse {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = {
...baseMsgExecuteGovernanceVAAResponse,
} as MsgExecuteGovernanceVAAResponse;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(_: any): MsgExecuteGovernanceVAAResponse {
const message = {
...baseMsgExecuteGovernanceVAAResponse,
} as MsgExecuteGovernanceVAAResponse;
return message;
},
toJSON(_: MsgExecuteGovernanceVAAResponse): unknown {
const obj: any = {};
return obj;
},
fromPartial(
_: DeepPartial<MsgExecuteGovernanceVAAResponse>
): MsgExecuteGovernanceVAAResponse {
const message = {
...baseMsgExecuteGovernanceVAAResponse,
} as MsgExecuteGovernanceVAAResponse;
return message;
},
};
const baseMsgExecuteVAA: object = { creator: "" };
export const MsgExecuteVAA = {
encode(message: MsgExecuteVAA, writer: Writer = Writer.create()): Writer {
if (message.creator !== "") {
writer.uint32(10).string(message.creator);
}
if (message.vaa.length !== 0) {
writer.uint32(18).bytes(message.vaa);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgExecuteVAA {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseMsgExecuteVAA } as MsgExecuteVAA;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.creator = reader.string();
break;
case 2:
message.vaa = reader.bytes();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): MsgExecuteVAA {
const message = { ...baseMsgExecuteVAA } as MsgExecuteVAA;
if (object.creator !== undefined && object.creator !== null) {
message.creator = String(object.creator);
} else {
message.creator = "";
}
if (object.vaa !== undefined && object.vaa !== null) {
message.vaa = bytesFromBase64(object.vaa);
}
return message;
},
toJSON(message: MsgExecuteVAA): unknown {
const obj: any = {};
message.creator !== undefined && (obj.creator = message.creator);
message.vaa !== undefined &&
(obj.vaa = base64FromBytes(
message.vaa !== undefined ? message.vaa : new Uint8Array()
));
return obj;
},
fromPartial(object: DeepPartial<MsgExecuteVAA>): MsgExecuteVAA {
const message = { ...baseMsgExecuteVAA } as MsgExecuteVAA;
if (object.creator !== undefined && object.creator !== null) {
message.creator = object.creator;
} else {
message.creator = "";
}
if (object.vaa !== undefined && object.vaa !== null) {
message.vaa = object.vaa;
} else {
message.vaa = new Uint8Array();
}
return message;
},
};
const baseMsgExecuteVAAResponse: object = {};
export const MsgExecuteVAAResponse = {
encode(_: MsgExecuteVAAResponse, writer: Writer = Writer.create()): Writer {
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgExecuteVAAResponse {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseMsgExecuteVAAResponse } as MsgExecuteVAAResponse;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(_: any): MsgExecuteVAAResponse {
const message = { ...baseMsgExecuteVAAResponse } as MsgExecuteVAAResponse;
return message;
},
toJSON(_: MsgExecuteVAAResponse): unknown {
const obj: any = {};
return obj;
},
fromPartial(_: DeepPartial<MsgExecuteVAAResponse>): MsgExecuteVAAResponse {
const message = { ...baseMsgExecuteVAAResponse } as MsgExecuteVAAResponse;
return message;
},
};
const baseMsgAttestToken: object = { creator: "", denom: "" };
export const MsgAttestToken = {
encode(message: MsgAttestToken, writer: Writer = Writer.create()): Writer {
if (message.creator !== "") {
writer.uint32(10).string(message.creator);
}
if (message.denom !== "") {
writer.uint32(18).string(message.denom);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgAttestToken {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseMsgAttestToken } as MsgAttestToken;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.creator = reader.string();
break;
case 2:
message.denom = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): MsgAttestToken {
const message = { ...baseMsgAttestToken } as MsgAttestToken;
if (object.creator !== undefined && object.creator !== null) {
message.creator = String(object.creator);
} else {
message.creator = "";
}
if (object.denom !== undefined && object.denom !== null) {
message.denom = String(object.denom);
} else {
message.denom = "";
}
return message;
},
toJSON(message: MsgAttestToken): unknown {
const obj: any = {};
message.creator !== undefined && (obj.creator = message.creator);
message.denom !== undefined && (obj.denom = message.denom);
return obj;
},
fromPartial(object: DeepPartial<MsgAttestToken>): MsgAttestToken {
const message = { ...baseMsgAttestToken } as MsgAttestToken;
if (object.creator !== undefined && object.creator !== null) {
message.creator = object.creator;
} else {
message.creator = "";
}
if (object.denom !== undefined && object.denom !== null) {
message.denom = object.denom;
} else {
message.denom = "";
}
return message;
},
};
const baseMsgAttestTokenResponse: object = {};
export const MsgAttestTokenResponse = {
encode(_: MsgAttestTokenResponse, writer: Writer = Writer.create()): Writer {
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgAttestTokenResponse {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseMsgAttestTokenResponse } as MsgAttestTokenResponse;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(_: any): MsgAttestTokenResponse {
const message = { ...baseMsgAttestTokenResponse } as MsgAttestTokenResponse;
return message;
},
toJSON(_: MsgAttestTokenResponse): unknown {
const obj: any = {};
return obj;
},
fromPartial(_: DeepPartial<MsgAttestTokenResponse>): MsgAttestTokenResponse {
const message = { ...baseMsgAttestTokenResponse } as MsgAttestTokenResponse;
return message;
},
};
const baseMsgTransfer: object = { creator: "", toChain: 0, fee: "" };
export const MsgTransfer = {
encode(message: MsgTransfer, writer: Writer = Writer.create()): Writer {
if (message.creator !== "") {
writer.uint32(10).string(message.creator);
}
if (message.amount !== undefined) {
Coin.encode(message.amount, writer.uint32(18).fork()).ldelim();
}
if (message.toChain !== 0) {
writer.uint32(24).uint32(message.toChain);
}
if (message.toAddress.length !== 0) {
writer.uint32(34).bytes(message.toAddress);
}
if (message.fee !== "") {
writer.uint32(42).string(message.fee);
}
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgTransfer {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseMsgTransfer } as MsgTransfer;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.creator = reader.string();
break;
case 2:
message.amount = Coin.decode(reader, reader.uint32());
break;
case 3:
message.toChain = reader.uint32();
break;
case 4:
message.toAddress = reader.bytes();
break;
case 5:
message.fee = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(object: any): MsgTransfer {
const message = { ...baseMsgTransfer } as MsgTransfer;
if (object.creator !== undefined && object.creator !== null) {
message.creator = String(object.creator);
} else {
message.creator = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = Coin.fromJSON(object.amount);
} else {
message.amount = undefined;
}
if (object.toChain !== undefined && object.toChain !== null) {
message.toChain = Number(object.toChain);
} else {
message.toChain = 0;
}
if (object.toAddress !== undefined && object.toAddress !== null) {
message.toAddress = bytesFromBase64(object.toAddress);
}
if (object.fee !== undefined && object.fee !== null) {
message.fee = String(object.fee);
} else {
message.fee = "";
}
return message;
},
toJSON(message: MsgTransfer): unknown {
const obj: any = {};
message.creator !== undefined && (obj.creator = message.creator);
message.amount !== undefined &&
(obj.amount = message.amount ? Coin.toJSON(message.amount) : undefined);
message.toChain !== undefined && (obj.toChain = message.toChain);
message.toAddress !== undefined &&
(obj.toAddress = base64FromBytes(
message.toAddress !== undefined ? message.toAddress : new Uint8Array()
));
message.fee !== undefined && (obj.fee = message.fee);
return obj;
},
fromPartial(object: DeepPartial<MsgTransfer>): MsgTransfer {
const message = { ...baseMsgTransfer } as MsgTransfer;
if (object.creator !== undefined && object.creator !== null) {
message.creator = object.creator;
} else {
message.creator = "";
}
if (object.amount !== undefined && object.amount !== null) {
message.amount = Coin.fromPartial(object.amount);
} else {
message.amount = undefined;
}
if (object.toChain !== undefined && object.toChain !== null) {
message.toChain = object.toChain;
} else {
message.toChain = 0;
}
if (object.toAddress !== undefined && object.toAddress !== null) {
message.toAddress = object.toAddress;
} else {
message.toAddress = new Uint8Array();
}
if (object.fee !== undefined && object.fee !== null) {
message.fee = object.fee;
} else {
message.fee = "";
}
return message;
},
};
const baseMsgTransferResponse: object = {};
export const MsgTransferResponse = {
encode(_: MsgTransferResponse, writer: Writer = Writer.create()): Writer {
return writer;
},
decode(input: Reader | Uint8Array, length?: number): MsgTransferResponse {
const reader = input instanceof Uint8Array ? new Reader(input) : input;
let end = length === undefined ? reader.len : reader.pos + length;
const message = { ...baseMsgTransferResponse } as MsgTransferResponse;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
default:
reader.skipType(tag & 7);
break;
}
}
return message;
},
fromJSON(_: any): MsgTransferResponse {
const message = { ...baseMsgTransferResponse } as MsgTransferResponse;
return message;
},
toJSON(_: MsgTransferResponse): unknown {
const obj: any = {};
return obj;
},
fromPartial(_: DeepPartial<MsgTransferResponse>): MsgTransferResponse {
const message = { ...baseMsgTransferResponse } as MsgTransferResponse;
return message;
},
};
/** Msg defines the Msg service. */
export interface Msg {
ExecuteGovernanceVAA(
request: MsgExecuteGovernanceVAA
): Promise<MsgExecuteGovernanceVAAResponse>;
ExecuteVAA(request: MsgExecuteVAA): Promise<MsgExecuteVAAResponse>;
AttestToken(request: MsgAttestToken): Promise<MsgAttestTokenResponse>;
/** this line is used by starport scaffolding # proto/tx/rpc */
Transfer(request: MsgTransfer): Promise<MsgTransferResponse>;
}
export class MsgClientImpl implements Msg {
private readonly rpc: Rpc;
constructor(rpc: Rpc) {
this.rpc = rpc;
}
ExecuteGovernanceVAA(
request: MsgExecuteGovernanceVAA
): Promise<MsgExecuteGovernanceVAAResponse> {
const data = MsgExecuteGovernanceVAA.encode(request).finish();
const promise = this.rpc.request(
"certusone.wormholechain.tokenbridge.Msg",
"ExecuteGovernanceVAA",
data
);
return promise.then((data) =>
MsgExecuteGovernanceVAAResponse.decode(new Reader(data))
);
}
ExecuteVAA(request: MsgExecuteVAA): Promise<MsgExecuteVAAResponse> {
const data = MsgExecuteVAA.encode(request).finish();
const promise = this.rpc.request(
"certusone.wormholechain.tokenbridge.Msg",
"ExecuteVAA",
data
);
return promise.then((data) =>
MsgExecuteVAAResponse.decode(new Reader(data))
);
}
AttestToken(request: MsgAttestToken): Promise<MsgAttestTokenResponse> {
const data = MsgAttestToken.encode(request).finish();
const promise = this.rpc.request(
"certusone.wormholechain.tokenbridge.Msg",
"AttestToken",
data
);
return promise.then((data) =>
MsgAttestTokenResponse.decode(new Reader(data))
);
}
Transfer(request: MsgTransfer): Promise<MsgTransferResponse> {
const data = MsgTransfer.encode(request).finish();
const promise = this.rpc.request(
"certusone.wormholechain.tokenbridge.Msg",
"Transfer",
data
);
return promise.then((data) => MsgTransferResponse.decode(new Reader(data)));
}
}
interface Rpc {
request(
service: string,
method: string,
data: Uint8Array
): Promise<Uint8Array>;
}
declare var self: any | undefined;
declare var window: any | undefined;
var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
throw "Unable to locate global object";
})();
const atob: (b64: string) => string =
globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary"));
function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64);
const arr = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i);
}
return arr;
}
const btoa: (bin: string) => string =
globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64"));
function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = [];
for (let i = 0; i < arr.byteLength; ++i) {
bin.push(String.fromCharCode(arr[i]));
}
return btoa(bin.join(""));
}
type Builtin = Date | Function | Uint8Array | string | number | undefined;
export type DeepPartial<T> = T extends Builtin
? T
: T extends Array<infer U>
? Array<DeepPartial<U>>
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>;

Some files were not shown because too many files have changed in this diff Show More