├── docs ├── static │ ├── .nojekyll │ └── img │ │ ├── dws.png │ │ ├── banner.png │ │ └── favicon.ico ├── docs │ ├── support │ │ ├── _category_.json │ │ └── deployments │ │ │ └── _category_.json │ ├── fullnode │ │ ├── _category_.json │ │ └── 01-overview.md │ ├── domains │ │ ├── _category_.json │ │ ├── dws-dns-server.md │ │ └── dws-domains.md │ └── introduction.md ├── docs.go ├── babel.config.js ├── src │ ├── pages │ │ ├── index.js │ │ └── index.module.css │ └── css │ │ └── custom.css ├── sidebars.js ├── README.md ├── package.json └── docusaurus.config.js ├── x ├── deweb │ ├── types │ │ ├── types.go │ │ ├── errors.go │ │ ├── genesis.go │ │ ├── expected_keepers.go │ │ ├── message_save_user_test.go │ │ ├── message_delete_key_test.go │ │ ├── message_connect_chain_test.go │ │ ├── genesis_test.go │ │ ├── message_delete_chain_connect_test.go │ │ ├── params.go │ │ ├── keys.go │ │ ├── message_delete_key.go │ │ ├── message_save_user.go │ │ ├── message_connect_chain.go │ │ ├── message_delete_chain_connect.go │ │ └── codec.go │ ├── alias.go │ ├── keeper │ │ ├── msg_server.go │ │ ├── params.go │ │ ├── params_test.go │ │ ├── msg_server_test.go │ │ ├── grpc_query_params.go │ │ ├── grpc_query_params_test.go │ │ ├── msg_server_delete_wallet.go │ │ ├── msg_server_delete_chain_connect.go │ │ ├── keeper.go │ │ ├── grpc_query_filter_user_wallet_records.go │ │ ├── grpc_query_filter_chain_mappings_records.go │ │ ├── msg_server_connect_chain.go │ │ ├── grpc_query.go │ │ └── msg_server_save_wallet.go │ ├── simulation │ │ ├── simap.go │ │ ├── connect_chain.go │ │ └── delete_chain_connect.go │ ├── genesis.go │ ├── genesis_test.go │ ├── client │ │ └── cli │ │ │ ├── query_params.go │ │ │ ├── query.go │ │ │ ├── tx_delete_wallet.go │ │ │ ├── run_dns_server.go │ │ │ ├── tx_connect_chain.go │ │ │ ├── tx.go │ │ │ ├── tx_delete_chain_connect.go │ │ │ ├── tx_save_wallet.go │ │ │ ├── query_filter_user_key_records.go │ │ │ └── query_filter_chain_mappings_records.go │ ├── handler.go │ └── module_simulation.go ├── dns_module │ ├── metadata │ │ └── dns-metadata.json │ ├── types │ │ ├── events.go │ │ ├── querier.go │ │ ├── query.go │ │ ├── errors.go │ │ ├── denom.go │ │ ├── expected_keepers.go │ │ ├── collection.go │ │ ├── domain.go │ │ ├── genesis.go │ │ ├── owners.go │ │ ├── codec.go │ │ ├── validation.go │ │ ├── keys.go │ │ ├── params.go │ │ └── msgs.go │ ├── exported │ │ └── nft.go │ ├── genesis.go │ ├── handler.go │ ├── keeper │ │ ├── params.go │ │ ├── owners.go │ │ ├── dns_record.go │ │ ├── querier.go │ │ ├── denom.go │ │ ├── collection.go │ │ ├── domain.go │ │ ├── ownership_rules.go │ │ ├── msg_server.go │ │ ├── grpc_query.go │ │ └── val_state_change.go │ ├── client │ │ ├── rest │ │ │ ├── rest.go │ │ │ ├── query.go │ │ │ └── tx.go │ │ └── cli │ │ │ ├── flags.go │ │ │ └── query.go │ └── module.go └── dns_server │ ├── utils.go │ ├── dns_proxy.go │ ├── dns_from_chain.go │ └── dnsserver.go ├── assets └── banner.png ├── proto ├── deweb │ ├── params.proto │ ├── keyrec.proto │ ├── genesis.proto │ ├── tx.proto │ └── query.proto └── dns_module │ ├── genesis.proto │ ├── params.proto │ ├── domain.proto │ ├── tx.proto │ └── query.proto ├── testutil ├── sample │ └── sample.go ├── nullify │ └── nullify.go ├── keeper │ └── deweb.go └── network │ └── network.go ├── .gitignore ├── cmd └── dewebd │ └── main.go ├── app ├── genesis.go └── simulation_test.go ├── go.mod ├── .github └── workflows │ ├── docs.yml │ └── release.yml ├── config.yml ├── readme.md ├── Makefile └── contrib └── devtools └── Makefile /docs/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /x/deweb/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deweb-services/deweb/HEAD/assets/banner.png -------------------------------------------------------------------------------- /docs/docs/support/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Support", 3 | "position": 10 4 | } 5 | -------------------------------------------------------------------------------- /docs/docs.go: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import "embed" 4 | 5 | //go:embed static 6 | var Docs embed.FS 7 | -------------------------------------------------------------------------------- /docs/docs/fullnode/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Running a Fullnode", 3 | "position": 2 4 | } 5 | -------------------------------------------------------------------------------- /docs/static/img/dws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deweb-services/deweb/HEAD/docs/static/img/dws.png -------------------------------------------------------------------------------- /docs/docs/domains/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Decentralized Domains", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /docs/docs/support/deployments/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Deployments", 3 | "position": 1 4 | } 5 | -------------------------------------------------------------------------------- /docs/static/img/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deweb-services/deweb/HEAD/docs/static/img/banner.png -------------------------------------------------------------------------------- /docs/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deweb-services/deweb/HEAD/docs/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /x/deweb/alias.go: -------------------------------------------------------------------------------- 1 | package deweb 2 | 3 | import "github.com/deweb-services/deweb/x/deweb/types" 4 | 5 | const ModuleName = types.ModuleName 6 | -------------------------------------------------------------------------------- /x/dns_module/metadata/dns-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "records": [ 3 | { 4 | "type": "record type", 5 | "values": [] 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /x/dns_module/types/events.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // NFT module event types 4 | var ( 5 | AttributeValueCategory = ModuleName 6 | 7 | AttributeKeySender = "sender" 8 | ) 9 | -------------------------------------------------------------------------------- /docs/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Redirect } from "react-router-dom"; 3 | 4 | export default function Home() { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /x/deweb/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DONTCOVER 4 | 5 | import ( 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | ) 8 | 9 | // x/deweb module sentinel errors 10 | var ( 11 | ErrSample = sdkerrors.Register(ModuleName, 1100, "sample error") 12 | ) 13 | -------------------------------------------------------------------------------- /x/dns_module/exported/nft.go: -------------------------------------------------------------------------------- 1 | package exported 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // Domain non fungible token interface 8 | type Domain interface { 9 | GetID() string 10 | GetOwner() sdk.AccAddress 11 | GetData() string 12 | } 13 | -------------------------------------------------------------------------------- /proto/deweb/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.deweb.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/deweb-services/deweb/x/deweb/types"; 7 | 8 | // Params defines the parameters for the module. 9 | message Params { 10 | option (gogoproto.goproto_stringer) = false; 11 | 12 | } -------------------------------------------------------------------------------- /testutil/sample/sample.go: -------------------------------------------------------------------------------- 1 | package sample 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | ) 7 | 8 | // AccAddress returns a sample account address 9 | func AccAddress() string { 10 | pk := ed25519.GenPrivKey().PubKey() 11 | addr := pk.Address() 12 | return sdk.AccAddress(addr).String() 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /docs/node_modules 3 | 4 | # Production 5 | /docs/build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .idea/ 13 | .vscode/ 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | 24 | 25 | 26 | vue/node_modules 27 | vue/dist 28 | release/ -------------------------------------------------------------------------------- /x/deweb/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "github.com/deweb-services/deweb/x/deweb/types" 5 | ) 6 | 7 | type msgServer struct { 8 | Keeper 9 | } 10 | 11 | // NewMsgServerImpl returns an implementation of the MsgServer interface 12 | // for the provided Keeper. 13 | func NewMsgServerImpl(keeper Keeper) types.MsgServer { 14 | return &msgServer{Keeper: keeper} 15 | } 16 | 17 | var _ types.MsgServer = msgServer{} 18 | -------------------------------------------------------------------------------- /x/deweb/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/deweb-services/deweb/x/deweb/types" 6 | ) 7 | 8 | // GetParams get all parameters as types.Params 9 | func (k Keeper) GetParams(ctx sdk.Context) types.Params { 10 | return types.NewParams() 11 | } 12 | 13 | // SetParams set the params 14 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { 15 | k.paramstore.SetParamSet(ctx, ¶ms) 16 | } 17 | -------------------------------------------------------------------------------- /x/deweb/keeper/params_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | testkeeper "github.com/deweb-services/deweb/testutil/keeper" 7 | "github.com/deweb-services/deweb/x/deweb/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestGetParams(t *testing.T) { 12 | k, ctx := testkeeper.DewebKeeper(t) 13 | params := types.DefaultParams() 14 | 15 | k.SetParams(ctx, params) 16 | 17 | require.EqualValues(t, params, k.GetParams(ctx)) 18 | } 19 | -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /x/deweb/simulation/simap.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 6 | ) 7 | 8 | // FindAccount find a specific address from an account list 9 | func FindAccount(accs []simtypes.Account, address string) (simtypes.Account, bool) { 10 | creator, err := sdk.AccAddressFromBech32(address) 11 | if err != nil { 12 | panic(err) 13 | } 14 | return simtypes.FindAccount(accs, creator) 15 | } 16 | -------------------------------------------------------------------------------- /proto/deweb/keyrec.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.deweb.v1beta1; 3 | option go_package = "github.com/deweb-services/deweb/x/deweb/types"; 4 | 5 | message UserWalletRec { 6 | string address = 2; 7 | string encrypted_key = 3; 8 | string chain = 4; 9 | bool deleted = 5; 10 | } 11 | 12 | message RecordsToUser { 13 | repeated string records = 1; 14 | } 15 | 16 | message ChainAddressMapping { 17 | string ext_address = 1; 18 | string chain = 2; 19 | bool deleted = 3; 20 | } -------------------------------------------------------------------------------- /proto/dns_module/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.domain.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "dns_module/domain.proto"; 6 | import "dns_module/params.proto"; 7 | 8 | option go_package = "github.com/deweb-services/deweb/x/dns_module/types"; 9 | 10 | // GenesisState defines the NFT module's genesis state 11 | message GenesisState { 12 | repeated Collection collections = 1 [ (gogoproto.nullable) = false ]; 13 | Params params = 3 [(gogoproto.nullable) = false]; 14 | } 15 | -------------------------------------------------------------------------------- /x/deweb/keeper/msg_server_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | keepertest "github.com/deweb-services/deweb/testutil/keeper" 9 | "github.com/deweb-services/deweb/x/deweb/keeper" 10 | "github.com/deweb-services/deweb/x/deweb/types" 11 | ) 12 | 13 | func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) { 14 | k, ctx := keepertest.DewebKeeper(t) 15 | return keeper.NewMsgServerImpl(*k), sdk.WrapSDKContext(ctx) 16 | } 17 | -------------------------------------------------------------------------------- /x/dns_module/types/querier.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DONTCOVER 4 | 5 | // query endpoints supported by the NFT Querier 6 | const ( 7 | QueryParams = "params" 8 | QueryDomain = "domain" 9 | ) 10 | 11 | // QueryDomainParams params for query 'custom/nfts/nft' 12 | type QueryDomainParams struct { 13 | TokenID string 14 | } 15 | 16 | // NewQueryDomainsParams creates a new instance of QueryDomainParams 17 | func NewQueryDomainsParams(id string) QueryDomainParams { 18 | return QueryDomainParams{ 19 | TokenID: id, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /proto/deweb/genesis.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.deweb.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "deweb/params.proto"; 6 | // this line is used by starport scaffolding # genesis/proto/import 7 | 8 | option go_package = "github.com/deweb-services/deweb/x/deweb/types"; 9 | 10 | // GenesisState defines the deweb module's genesis state. 11 | message GenesisState { 12 | Params params = 1 [(gogoproto.nullable) = false]; 13 | // this line is used by starport scaffolding # genesis/proto/state 14 | } 15 | -------------------------------------------------------------------------------- /cmd/dewebd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" 7 | "github.com/deweb-services/deweb/app" 8 | ) 9 | 10 | func main() { 11 | rootCmd, _ := NewRootCmd( 12 | app.Name, 13 | app.AccountAddressPrefix, 14 | app.DefaultNodeHome, 15 | app.Name, 16 | app.ModuleBasics, 17 | app.New, 18 | // this line is used by starport scaffolding # root/arguments 19 | ) 20 | 21 | if err := svrcmd.Execute(rootCmd, app.DefaultNodeHome); err != nil { 22 | os.Exit(1) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /proto/dns_module/params.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.domain.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/deweb-services/deweb/x/dns_module/types"; 7 | 8 | // Params defines the parameters for the module. 9 | message Params { 10 | option (gogoproto.goproto_stringer) = false; 11 | uint64 domainPrice = 1; 12 | int64 domainExpirationHours = 2; 13 | int64 domainOwnerProlongationHours = 3; 14 | uint64 subDomainPrice = 4; 15 | repeated string blockTLDs = 5 [ (gogoproto.nullable) = false ]; 16 | } -------------------------------------------------------------------------------- /x/deweb/keeper/grpc_query_params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/deweb-services/deweb/x/deweb/types" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | func (k Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 13 | if req == nil { 14 | return nil, status.Error(codes.InvalidArgument, "invalid request") 15 | } 16 | ctx := sdk.UnwrapSDKContext(c) 17 | 18 | return &types.QueryParamsResponse{Params: k.GetParams(ctx)}, nil 19 | } 20 | -------------------------------------------------------------------------------- /x/deweb/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DefaultIndex is the default capability global index 4 | const DefaultIndex uint64 = 1 5 | 6 | // DefaultGenesis returns the default Capability genesis state 7 | func DefaultGenesis() *GenesisState { 8 | return &GenesisState{ 9 | // this line is used by starport scaffolding # genesis/types/default 10 | Params: DefaultParams(), 11 | } 12 | } 13 | 14 | // Validate performs basic genesis state validation returning an error upon any 15 | // failure. 16 | func (gs GenesisState) Validate() error { 17 | // this line is used by starport scaffolding # genesis/types/validate 18 | 19 | return gs.Params.Validate() 20 | } 21 | -------------------------------------------------------------------------------- /x/dns_module/types/query.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | func (m *TransferOffer) Equal(offer *TransferOffer) bool { 4 | if m.Price != offer.Price { 5 | return false 6 | } 7 | if m.ExpectedOwnerAddress != offer.ExpectedOwnerAddress { 8 | return false 9 | } 10 | return true 11 | } 12 | 13 | func (m *DNSRecords) Equal(dnsRec *DNSRecords) bool { 14 | if m.Type != dnsRec.Type { 15 | return false 16 | } 17 | for _, mVal := range m.Values { 18 | var recFound bool 19 | for _, tVal := range dnsRec.Values { 20 | if tVal == mVal { 21 | recFound = true 22 | break 23 | } 24 | } 25 | if !recFound { 26 | return false 27 | } 28 | } 29 | return true 30 | } 31 | -------------------------------------------------------------------------------- /x/deweb/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/cosmos/cosmos-sdk/x/auth/types" 6 | ) 7 | 8 | // AccountKeeper defines the expected account keeper used for simulations (noalias) 9 | type AccountKeeper interface { 10 | GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI 11 | // Methods imported from account should be defined here 12 | } 13 | 14 | // BankKeeper defines the expected interface needed to retrieve account balances. 15 | type BankKeeper interface { 16 | SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins 17 | // Methods imported from bank should be defined here 18 | } 19 | -------------------------------------------------------------------------------- /x/dns_module/types/errors.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 5 | ) 6 | 7 | var ( 8 | ErrDomainAlreadyExists = sdkerrors.Register(ModuleName, 5, "domain already exists") 9 | ErrUnknownDomain = sdkerrors.Register(ModuleName, 6, "unknown domain") 10 | ErrUnauthorized = sdkerrors.Register(ModuleName, 8, "unauthorized address") 11 | ErrInvalidDenom = sdkerrors.Register(ModuleName, 9, "invalid denom") 12 | ErrInvalidTokenID = sdkerrors.Register(ModuleName, 10, "invalid domain name") 13 | ErrDomainPermissionDenied = sdkerrors.Register(ModuleName, 12, "ownership check for domain failed") 14 | ) 15 | -------------------------------------------------------------------------------- /x/deweb/keeper/grpc_query_params_test.go: -------------------------------------------------------------------------------- 1 | package keeper_test 2 | 3 | import ( 4 | "testing" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | testkeeper "github.com/deweb-services/deweb/testutil/keeper" 8 | "github.com/deweb-services/deweb/x/deweb/types" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestParamsQuery(t *testing.T) { 13 | keeper, ctx := testkeeper.DewebKeeper(t) 14 | wctx := sdk.WrapSDKContext(ctx) 15 | params := types.DefaultParams() 16 | keeper.SetParams(ctx, params) 17 | 18 | response, err := keeper.Params(wctx, &types.QueryParamsRequest{}) 19 | require.NoError(t, err) 20 | require.Equal(t, &types.QueryParamsResponse{Params: params}, response) 21 | } 22 | -------------------------------------------------------------------------------- /x/dns_module/types/denom.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | ) 6 | 7 | // NewDenom return a new denom 8 | func NewDenom( 9 | id, name, schema, symbol, description, uri, uriHash, data string, 10 | creator sdk.AccAddress, 11 | mintRestricted, updateRestricted bool, 12 | ) Denom { 13 | return Denom{ 14 | Id: id, 15 | Name: name, 16 | Schema: schema, 17 | Creator: creator.String(), 18 | Symbol: symbol, 19 | MintRestricted: mintRestricted, 20 | UpdateRestricted: updateRestricted, 21 | Description: description, 22 | Uri: uri, 23 | UriHash: uriHash, 24 | Data: data, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /x/dns_module/types/expected_keepers.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 6 | ) 7 | 8 | // AccountKeeper defines the expected account keeper for query account 9 | type AccountKeeper interface { 10 | GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI 11 | } 12 | 13 | // BankKeeper defines the expected interface needed to retrieve account balances. 14 | type BankKeeper interface { 15 | GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins 16 | GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin 17 | LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins 18 | SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins 19 | } 20 | -------------------------------------------------------------------------------- /x/dns_module/types/collection.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/deweb-services/deweb/x/dns_module/exported" 5 | ) 6 | 7 | // NewCollection creates a new Domain Collection 8 | func NewCollection(denom Denom, domains []exported.Domain) (c Collection) { 9 | c.Denom = denom 10 | for _, nft := range domains { 11 | c = c.AddDomain(nft.(BaseDomain)) 12 | } 13 | return c 14 | } 15 | 16 | // AddDomain adds an Domain to the collection 17 | func (c Collection) AddDomain(nft BaseDomain) Collection { 18 | c.NFTs = append(c.NFTs, nft) 19 | return c 20 | } 21 | 22 | func (c Collection) Supply() int { 23 | return len(c.NFTs) 24 | } 25 | 26 | // NewCollection creates a new Domain Collection 27 | func NewCollections(c ...Collection) []Collection { 28 | return append([]Collection{}, c...) 29 | } 30 | -------------------------------------------------------------------------------- /app/genesis.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | ) 8 | 9 | // The genesis state of the blockchain is represented here as a map of raw json 10 | // messages key'd by a identifier string. 11 | // The identifier is used to determine which module genesis information belongs 12 | // to so it may be appropriately routed during init chain. 13 | // Within this application default genesis information is retrieved from 14 | // the ModuleBasicManager which populates json from each BasicModule 15 | // object provided to it during init. 16 | type GenesisState map[string]json.RawMessage 17 | 18 | // NewDefaultGenesisState generates the default state for the application. 19 | func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { 20 | return ModuleBasics.DefaultGenesis(cdc) 21 | } 22 | -------------------------------------------------------------------------------- /docs/docs/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Introduction 6 | 7 | ![Example banner](/img/banner.png) 8 | 9 | **Decentralized Web Services (DWS)** is a public Proof-of-Stake (PoS) blockchain application built with **[Cosmos SDK](https://docs.cosmos.network/)**. DWS offers reliable, scalable, secure and decentralized cloud computing services. 10 | 11 | ## Sirius Testnet 12 | 13 | Sirius Testnet is live! 14 | 15 | ## Block Explorers 16 | 17 | - **[DWS Explorer](https://explore.deweb.services/)** 18 | 19 | ## Wallets 20 | 21 | - **[Keplr Wallet](https://deweb.services/add-wallet)** 22 | 23 | ## Community 24 | 25 | - **[Discord](https://discord.gg/dws)** 26 | - **[Twitter](https://twitter.com/dewebservices)** 27 | - **[Telegram](https://t.me/deweb_services)** 28 | - **[Telegram Chat](https://t.me/dewebservices_chat)** 29 | -------------------------------------------------------------------------------- /x/deweb/genesis.go: -------------------------------------------------------------------------------- 1 | package deweb 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/deweb-services/deweb/x/deweb/keeper" 6 | "github.com/deweb-services/deweb/x/deweb/types" 7 | ) 8 | 9 | // InitGenesis initializes the capability module's state from a provided genesis 10 | // state. 11 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { 12 | // this line is used by starport scaffolding # genesis/module/init 13 | k.SetParams(ctx, genState.Params) 14 | } 15 | 16 | // ExportGenesis returns the capability module's exported genesis. 17 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 18 | genesis := types.DefaultGenesis() 19 | genesis.Params = k.GetParams(ctx) 20 | 21 | // this line is used by starport scaffolding # genesis/module/export 22 | 23 | return genesis 24 | } 25 | -------------------------------------------------------------------------------- /x/deweb/genesis_test.go: -------------------------------------------------------------------------------- 1 | package deweb_test 2 | 3 | import ( 4 | "testing" 5 | 6 | keepertest "github.com/deweb-services/deweb/testutil/keeper" 7 | "github.com/deweb-services/deweb/testutil/nullify" 8 | "github.com/deweb-services/deweb/x/deweb" 9 | "github.com/deweb-services/deweb/x/deweb/types" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestGenesis(t *testing.T) { 14 | genesisState := types.GenesisState{ 15 | Params: types.DefaultParams(), 16 | 17 | // this line is used by starport scaffolding # genesis/test/state 18 | } 19 | 20 | k, ctx := keepertest.DewebKeeper(t) 21 | deweb.InitGenesis(ctx, *k, genesisState) 22 | got := deweb.ExportGenesis(ctx, *k) 23 | require.NotNil(t, got) 24 | 25 | nullify.Fill(&genesisState) 26 | nullify.Fill(got) 27 | 28 | // this line is used by starport scaffolding # genesis/test/assert 29 | } 30 | -------------------------------------------------------------------------------- /docs/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | { 23 | type: 'category', 24 | label: 'Tutorial', 25 | items: ['hello'], 26 | }, 27 | ], 28 | */ 29 | }; 30 | 31 | module.exports = sidebars; 32 | -------------------------------------------------------------------------------- /x/dns_module/types/domain.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/deweb-services/deweb/x/dns_module/exported" 7 | ) 8 | 9 | var _ exported.Domain = BaseDomain{} 10 | 11 | // NewBaseNFT creates a new Domain instance 12 | func NewBaseNFT(id string, owner sdk.AccAddress, data string) BaseDomain { 13 | return BaseDomain{ 14 | Id: id, 15 | Owner: owner.String(), 16 | Data: data, 17 | } 18 | } 19 | 20 | // GetID return the id of BaseNFT 21 | func (bnft BaseDomain) GetID() string { 22 | return bnft.Id 23 | } 24 | 25 | // GetOwner return the owner of BaseNFT 26 | func (bnft BaseDomain) GetOwner() sdk.AccAddress { 27 | owner, _ := sdk.AccAddressFromBech32(bnft.Owner) 28 | return owner 29 | } 30 | 31 | // GetData return the Data of BaseNFT 32 | func (bnft BaseDomain) GetData() string { 33 | return bnft.Data 34 | } 35 | -------------------------------------------------------------------------------- /x/deweb/client/cli/query_params.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | "github.com/deweb-services/deweb/x/deweb/types" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | func CmdQueryParams() *cobra.Command { 13 | cmd := &cobra.Command{ 14 | Use: "params", 15 | Short: "shows the parameters of the module", 16 | Args: cobra.NoArgs, 17 | RunE: func(cmd *cobra.Command, args []string) error { 18 | clientCtx := client.GetClientContextFromCmd(cmd) 19 | 20 | queryClient := types.NewQueryClient(clientCtx) 21 | 22 | res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) 23 | if err != nil { 24 | return err 25 | } 26 | 27 | return clientCtx.PrintProto(res) 28 | }, 29 | } 30 | 31 | flags.AddQueryFlagsToCmd(cmd) 32 | 33 | return cmd 34 | } 35 | -------------------------------------------------------------------------------- /x/deweb/keeper/msg_server_delete_wallet.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/deweb-services/deweb/x/deweb/types" 9 | ) 10 | 11 | func (k msgServer) DeleteWallet(goCtx context.Context, msg *types.MsgDeleteWallet) (*types.MsgDeleteWalletResponse, error) { 12 | ctx := sdk.UnwrapSDKContext(goCtx) 13 | 14 | k.Logger(ctx).Error("[DeleteWallet] Starting") 15 | 16 | recordID := msg.Creator + "_" + msg.Address 17 | userRecord, err := k.getUserKeyRecord(ctx, recordID) 18 | if err != nil { 19 | return nil, fmt.Errorf("error chain mapping getting record by id: %w", err) 20 | } 21 | 22 | userRecord.Deleted = true 23 | err = k.writeUserKeyRecord(ctx, userRecord, recordID) 24 | if err != nil { 25 | return nil, fmt.Errorf("error updating chain mapping record by id: %w", err) 26 | } 27 | return &types.MsgDeleteWalletResponse{}, nil 28 | } 29 | -------------------------------------------------------------------------------- /x/deweb/types/message_save_user_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | "github.com/deweb-services/deweb/testutil/sample" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestMsgSaveUser_ValidateBasic(t *testing.T) { 12 | tests := []struct { 13 | name string 14 | msg MsgSaveWallet 15 | err error 16 | }{ 17 | { 18 | name: "invalid address", 19 | msg: MsgSaveWallet{ 20 | Creator: "invalid_address", 21 | }, 22 | err: sdkerrors.ErrInvalidAddress, 23 | }, { 24 | name: "valid address", 25 | msg: MsgSaveWallet{ 26 | Creator: sample.AccAddress(), 27 | }, 28 | }, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | err := tt.msg.ValidateBasic() 33 | if tt.err != nil { 34 | require.ErrorIs(t, err, tt.err) 35 | return 36 | } 37 | require.NoError(t, err) 38 | }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /x/deweb/types/message_delete_key_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | "github.com/deweb-services/deweb/testutil/sample" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestMsgDeleteKey_ValidateBasic(t *testing.T) { 12 | tests := []struct { 13 | name string 14 | msg MsgDeleteWallet 15 | err error 16 | }{ 17 | { 18 | name: "invalid address", 19 | msg: MsgDeleteWallet{ 20 | Creator: "invalid_address", 21 | }, 22 | err: sdkerrors.ErrInvalidAddress, 23 | }, { 24 | name: "valid address", 25 | msg: MsgDeleteWallet{ 26 | Creator: sample.AccAddress(), 27 | }, 28 | }, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | err := tt.msg.ValidateBasic() 33 | if tt.err != nil { 34 | require.ErrorIs(t, err, tt.err) 35 | return 36 | } 37 | require.NoError(t, err) 38 | }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /x/deweb/keeper/msg_server_delete_chain_connect.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/deweb-services/deweb/x/deweb/types" 9 | ) 10 | 11 | func (k msgServer) DeleteChainConnect(goCtx context.Context, msg *types.MsgDeleteChainConnect) (*types.MsgDeleteChainConnectResponse, error) { 12 | ctx := sdk.UnwrapSDKContext(goCtx) 13 | 14 | k.Logger(ctx).Error("[DeleteChainConnect] Starting") 15 | 16 | recordID := msg.Creator + "_" + msg.Chain + "_" + msg.Address 17 | chainRecord, err := k.getChainMappingRecord(ctx, recordID) 18 | if err != nil { 19 | return nil, fmt.Errorf("error getting record by id: %w", err) 20 | } 21 | 22 | chainRecord.Deleted = true 23 | err = k.writeChainMappingRecord(ctx, chainRecord, recordID) 24 | if err != nil { 25 | return nil, fmt.Errorf("error updating record by id: %w", err) 26 | } 27 | 28 | return &types.MsgDeleteChainConnectResponse{}, nil 29 | } 30 | -------------------------------------------------------------------------------- /x/deweb/types/message_connect_chain_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | "github.com/deweb-services/deweb/testutil/sample" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestMsgConnectChain_ValidateBasic(t *testing.T) { 12 | tests := []struct { 13 | name string 14 | msg MsgConnectChain 15 | err error 16 | }{ 17 | { 18 | name: "invalid address", 19 | msg: MsgConnectChain{ 20 | Creator: "invalid_address", 21 | }, 22 | err: sdkerrors.ErrInvalidAddress, 23 | }, { 24 | name: "valid address", 25 | msg: MsgConnectChain{ 26 | Creator: sample.AccAddress(), 27 | }, 28 | }, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | err := tt.msg.ValidateBasic() 33 | if tt.err != nil { 34 | require.ErrorIs(t, err, tt.err) 35 | return 36 | } 37 | require.NoError(t, err) 38 | }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /x/dns_module/types/genesis.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 5 | ) 6 | 7 | // NewGenesisState creates a new genesis state. 8 | func NewGenesisState(collections []Collection, params Params) *GenesisState { 9 | return &GenesisState{ 10 | Collections: collections, 11 | Params: params, 12 | } 13 | } 14 | 15 | // ValidateGenesis performs basic validation of nfts genesis data returning an 16 | // error for any failed validation criteria. 17 | func ValidateGenesis(data GenesisState) error { 18 | for _, c := range data.Collections { 19 | if err := ValidateDenomID(c.Denom.Name); err != nil { 20 | return err 21 | } 22 | 23 | for _, nft := range c.NFTs { 24 | if nft.GetOwner().Empty() { 25 | return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing owner") 26 | } 27 | 28 | if err := ValidateTokenID(nft.GetID()); err != nil { 29 | return err 30 | } 31 | } 32 | } 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /x/deweb/types/genesis_test.go: -------------------------------------------------------------------------------- 1 | package types_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/deweb-services/deweb/x/deweb/types" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestGenesisState_Validate(t *testing.T) { 11 | for _, tc := range []struct { 12 | desc string 13 | genState *types.GenesisState 14 | valid bool 15 | }{ 16 | { 17 | desc: "default is valid", 18 | genState: types.DefaultGenesis(), 19 | valid: true, 20 | }, 21 | { 22 | desc: "valid genesis state", 23 | genState: &types.GenesisState{ 24 | 25 | // this line is used by starport scaffolding # types/genesis/validField 26 | }, 27 | valid: true, 28 | }, 29 | // this line is used by starport scaffolding # types/genesis/testcase 30 | } { 31 | t.Run(tc.desc, func(t *testing.T) { 32 | err := tc.genState.Validate() 33 | if tc.valid { 34 | require.NoError(t, err) 35 | } else { 36 | require.Error(t, err) 37 | } 38 | }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /x/deweb/types/message_delete_chain_connect_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | "github.com/deweb-services/deweb/testutil/sample" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestMsgDeleteChainConnect_ValidateBasic(t *testing.T) { 12 | tests := []struct { 13 | name string 14 | msg MsgDeleteChainConnect 15 | err error 16 | }{ 17 | { 18 | name: "invalid address", 19 | msg: MsgDeleteChainConnect{ 20 | Creator: "invalid_address", 21 | }, 22 | err: sdkerrors.ErrInvalidAddress, 23 | }, { 24 | name: "valid address", 25 | msg: MsgDeleteChainConnect{ 26 | Creator: sample.AccAddress(), 27 | }, 28 | }, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | err := tt.msg.ValidateBasic() 33 | if tt.err != nil { 34 | require.ErrorIs(t, err, tt.err) 35 | return 36 | } 37 | require.NoError(t, err) 38 | }) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /x/deweb/simulation/connect_chain.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 9 | "github.com/deweb-services/deweb/x/deweb/keeper" 10 | "github.com/deweb-services/deweb/x/deweb/types" 11 | ) 12 | 13 | func SimulateMsgConnectChain( 14 | ak types.AccountKeeper, 15 | bk types.BankKeeper, 16 | k keeper.Keeper, 17 | ) simtypes.Operation { 18 | return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, 19 | ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 20 | simAccount, _ := simtypes.RandomAcc(r, accs) 21 | msg := &types.MsgConnectChain{ 22 | Creator: simAccount.Address.String(), 23 | } 24 | 25 | // TODO: Handling the ConnectChain simulation 26 | 27 | return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "ConnectChain simulation not implemented"), nil, nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /x/deweb/simulation/delete_chain_connect.go: -------------------------------------------------------------------------------- 1 | package simulation 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 9 | "github.com/deweb-services/deweb/x/deweb/keeper" 10 | "github.com/deweb-services/deweb/x/deweb/types" 11 | ) 12 | 13 | func SimulateMsgDeleteChainConnect( 14 | ak types.AccountKeeper, 15 | bk types.BankKeeper, 16 | k keeper.Keeper, 17 | ) simtypes.Operation { 18 | return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, 19 | ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { 20 | simAccount, _ := simtypes.RandomAcc(r, accs) 21 | msg := &types.MsgDeleteChainConnect{ 22 | Creator: simAccount.Address.String(), 23 | } 24 | 25 | // TODO: Handling the DeleteChainConnect simulation 26 | 27 | return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "DeleteChainConnect simulation not implemented"), nil, nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /x/deweb/types/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 5 | "gopkg.in/yaml.v2" 6 | ) 7 | 8 | var _ paramtypes.ParamSet = (*Params)(nil) 9 | 10 | // ParamKeyTable the param key table for launch module 11 | func ParamKeyTable() paramtypes.KeyTable { 12 | return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) 13 | } 14 | 15 | // NewParams creates a new Params instance 16 | func NewParams() Params { 17 | return Params{} 18 | } 19 | 20 | // DefaultParams returns a default set of parameters 21 | func DefaultParams() Params { 22 | return NewParams() 23 | } 24 | 25 | // ParamSetPairs get the params.ParamSet 26 | func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { 27 | return paramtypes.ParamSetPairs{} 28 | } 29 | 30 | // Validate validates the set of params 31 | func (p Params) Validate() error { 32 | return nil 33 | } 34 | 35 | // String implements the Stringer interface. 36 | func (p Params) String() string { 37 | out, _ := yaml.Marshal(p) 38 | return string(out) 39 | } 40 | -------------------------------------------------------------------------------- /docs/docs/domains/dws-dns-server.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # DWS DNS Server 6 | 7 | DNS Server starts with a node process. By default it listen for UDP/1053, this parameter can be changed in client.toml in config path (`~/.deweb/config/config.toml`). 8 | Parameter: `dns.lport` 9 | 10 | DNS server works in coroutine and making requests to main process via GRPC to port TCP/26657 (`rpc.laddr`). 11 | It has 10-seconds cache to prevent constant requests to GRPC server. 12 | 13 | :::danger To run public DNS Server 14 | 15 | To make any service working with your DNS Server, it should listen on port UDP/53. 16 | 17 | To listen on port UDP/53, node process must be executed as a root user. To prevent the whole node running by root user we have a special command which will run only DNS server: 18 | 19 | ``` 20 | sudo dewebd q deweb run-dns-server 53 1.1.1.1:53 21 | ``` 22 | 23 | `1.1.1.1` is a secondary DNS server, where all the requests will be rerouted if they would not be found on the DWS DNS. 24 | 25 | ::: 26 | 27 | Currently DNS Server supports only A and MX records. 28 | -------------------------------------------------------------------------------- /x/deweb/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | // "strings" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | // "github.com/cosmos/cosmos-sdk/client/flags" 11 | // sdk "github.com/cosmos/cosmos-sdk/types" 12 | 13 | "github.com/deweb-services/deweb/x/deweb/types" 14 | ) 15 | 16 | // GetQueryCmd returns the cli query commands for this module 17 | func GetQueryCmd(queryRoute string) *cobra.Command { 18 | // Group deweb queries under a subcommand 19 | cmd := &cobra.Command{ 20 | Use: types.ModuleName, 21 | Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), 22 | DisableFlagParsing: true, 23 | SuggestionsMinimumDistance: 2, 24 | RunE: client.ValidateCmd, 25 | } 26 | 27 | cmd.AddCommand(CmdQueryParams()) 28 | cmd.AddCommand(CmdFilterUserWalletRecords()) 29 | cmd.AddCommand(CmdFilterChainMappingsRecords()) 30 | cmd.AddCommand(CmdRunDNSServer()) 31 | 32 | // this line is used by starport scaffolding # 1 33 | 34 | return cmd 35 | } 36 | -------------------------------------------------------------------------------- /x/deweb/keeper/keeper.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/tendermint/tendermint/libs/log" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 11 | "github.com/deweb-services/deweb/x/deweb/types" 12 | ) 13 | 14 | type ( 15 | Keeper struct { 16 | cdc codec.BinaryCodec 17 | storeKey sdk.StoreKey 18 | memKey sdk.StoreKey 19 | paramstore paramtypes.Subspace 20 | } 21 | ) 22 | 23 | func NewKeeper( 24 | cdc codec.BinaryCodec, 25 | storeKey, 26 | memKey sdk.StoreKey, 27 | ps paramtypes.Subspace, 28 | 29 | ) *Keeper { 30 | // set KeyTable if it has not already been set 31 | if !ps.HasKeyTable() { 32 | ps = ps.WithKeyTable(types.ParamKeyTable()) 33 | } 34 | 35 | return &Keeper{ 36 | 37 | cdc: cdc, 38 | storeKey: storeKey, 39 | memKey: memKey, 40 | paramstore: ps, 41 | } 42 | } 43 | 44 | func (k Keeper) Logger(ctx sdk.Context) log.Logger { 45 | return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) 46 | } 47 | -------------------------------------------------------------------------------- /x/deweb/client/cli/tx_delete_wallet.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | "github.com/cosmos/cosmos-sdk/client/tx" 11 | "github.com/deweb-services/deweb/x/deweb/types" 12 | ) 13 | 14 | var _ = strconv.Itoa(0) 15 | 16 | func CmdDeleteWallet() *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: "delete-wallet [address]", 19 | Short: "Broadcast message delete_wallet", 20 | Args: cobra.ExactArgs(1), 21 | RunE: func(cmd *cobra.Command, args []string) (err error) { 22 | argAddress := args[0] 23 | 24 | clientCtx, err := client.GetClientTxContext(cmd) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | msg := types.NewMsgDeleteKey( 30 | clientCtx.GetFromAddress().String(), 31 | argAddress, 32 | ) 33 | if err := msg.ValidateBasic(); err != nil { 34 | return err 35 | } 36 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 37 | }, 38 | } 39 | 40 | flags.AddTxFlagsToCmd(cmd) 41 | 42 | return cmd 43 | } 44 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # DWS Docs 2 | 3 | This repo contains the documentation of Decentralized Web Services hosted on https://docs.deweb.services. 4 | Feel free to open issues/PRs to contribute! 5 | 6 | ### Installation 7 | 8 | ``` 9 | $ npm 10 | ``` 11 | 12 | ### Local Development 13 | 14 | ``` 15 | $ npm start 16 | ``` 17 | 18 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 19 | 20 | ### Build 21 | 22 | ``` 23 | $ npm run build 24 | ``` 25 | 26 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 27 | 28 | ### Deployment 29 | 30 | Using SSH: 31 | 32 | ``` 33 | $ USE_SSH=true npm run deploy 34 | ``` 35 | 36 | Not using SSH: 37 | 38 | ``` 39 | $ GIT_USER= npm run deploy 40 | ``` 41 | 42 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 43 | 44 | ### Credits 45 | 46 | > Docs powered by [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 47 | -------------------------------------------------------------------------------- /x/deweb/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ModuleName defines the module name 5 | ModuleName = "deweb" 6 | 7 | // StoreKey defines the primary module store key 8 | StoreKey = ModuleName 9 | 10 | // RouterKey is the message route for slashing 11 | RouterKey = ModuleName 12 | 13 | // QuerierRoute defines the module's query routing key 14 | QuerierRoute = ModuleName 15 | 16 | // MemStoreKey defines the in-memory store key 17 | MemStoreKey = "mem_deweb" 18 | 19 | // RecordsKey defines prefix for users storage. Here we get record by Address 20 | RecordsKey = "records-" 21 | 22 | // UsersRecords defines prefix for storage where we store mapping between user and list of records addresses 23 | UsersRecords = "users-" 24 | 25 | // ConnectChainRecords defines prefix to store mapping between user address in dws and other chains addresses 26 | ConnectChainRecords = "connections-" 27 | 28 | // UserConnectChainRecords defines prefix to store mapping between user address in dws and other chains addresses 29 | UserConnectChainRecords = "users_connections-" 30 | ) 31 | 32 | func KeyPrefix(p string) []byte { 33 | return []byte(p) 34 | } 35 | -------------------------------------------------------------------------------- /x/dns_server/utils.go: -------------------------------------------------------------------------------- 1 | package dns_server 2 | 3 | import ( 4 | "encoding/binary" 5 | "io" 6 | ) 7 | 8 | var recordTypesMapping = map[uint16]string{ 9 | 1: "A", 10 | 28: "AAAA", 11 | 18: "AFSDB", 12 | 42: "APL", 13 | 257: "CAA", 14 | 60: "CDNSKEY", 15 | 59: "CDS", 16 | 37: "CERT", 17 | 5: "CNAME", 18 | 62: "CSYNC", 19 | 49: "DHCID", 20 | 32769: "DLV", 21 | 39: "DNAME", 22 | 48: "DNSKEY", 23 | 43: "DS", 24 | 13: "HINFO", 25 | 55: "HIP", 26 | 65: "HTTPS", 27 | 45: "IPSECKEY", 28 | 25: "KEY", 29 | 36: "KX", 30 | 29: "LOC", 31 | 15: "MX", 32 | 35: "NAPTR", 33 | 2: "NS", 34 | 47: "NSEC", 35 | 61: "OPENPGPKEY", 36 | 12: "PTR", 37 | 46: "RRSIG", 38 | 17: "RP", 39 | 24: "SIG", 40 | 53: "SMIMEA", 41 | 6: "SOA", 42 | 33: "SRV", 43 | 44: "SSHFP", 44 | 64: "SVCB", 45 | 32768: "TA", 46 | 249: "TKEY", 47 | 52: "TLSA", 48 | 250: "TSIG", 49 | 16: "TXT", 50 | 256: "URI", 51 | 63: "ZONEMD", 52 | } 53 | 54 | func Write(w io.Writer, data interface{}) error { 55 | return binary.Write(w, binary.BigEndian, data) 56 | } 57 | -------------------------------------------------------------------------------- /x/deweb/client/cli/run_dns_server.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "github.com/cosmos/cosmos-sdk/client" 6 | "github.com/cosmos/cosmos-sdk/client/flags" 7 | "github.com/deweb-services/deweb/x/dns_server" 8 | "github.com/spf13/cobra" 9 | "strconv" 10 | ) 11 | 12 | func CmdRunDNSServer() *cobra.Command { 13 | cmd := &cobra.Command{ 14 | Use: "run-dns-server [port] [proxy_server:port]", 15 | Short: "Run DNS server for DNS NFT", 16 | Args: cobra.MinimumNArgs(1), 17 | RunE: func(cmd *cobra.Command, args []string) (err error) { 18 | reqPort, err := strconv.ParseInt(args[0], 10, 32) 19 | if err != nil { 20 | return fmt.Errorf("cannot parse parameter limit: %w", err) 21 | } 22 | var proxyServer string 23 | if len(args) > 1 { 24 | proxyServer = args[1] 25 | } 26 | 27 | clientCtx, err := client.GetClientTxContext(cmd) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | serverResolver := dns_server.NewDNSResolverService(clientCtx, proxyServer) 33 | serverResolver.RunServer(int(reqPort)) 34 | 35 | return nil 36 | }, 37 | } 38 | 39 | flags.AddQueryFlagsToCmd(cmd) 40 | 41 | return cmd 42 | } 43 | -------------------------------------------------------------------------------- /x/deweb/client/cli/tx_connect_chain.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | "github.com/cosmos/cosmos-sdk/client/tx" 9 | "github.com/deweb-services/deweb/x/deweb/types" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var _ = strconv.Itoa(0) 14 | 15 | func CmdConnectChain() *cobra.Command { 16 | cmd := &cobra.Command{ 17 | Use: "connect-chain [chain] [address]", 18 | Short: "Broadcast message connect_chain", 19 | Args: cobra.ExactArgs(2), 20 | RunE: func(cmd *cobra.Command, args []string) (err error) { 21 | argChain := args[0] 22 | argAddress := args[1] 23 | 24 | clientCtx, err := client.GetClientTxContext(cmd) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | msg := types.NewMsgConnectChain( 30 | clientCtx.GetFromAddress().String(), 31 | argChain, 32 | argAddress, 33 | ) 34 | if err := msg.ValidateBasic(); err != nil { 35 | return err 36 | } 37 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 38 | }, 39 | } 40 | 41 | flags.AddTxFlagsToCmd(cmd) 42 | 43 | return cmd 44 | } 45 | -------------------------------------------------------------------------------- /docs/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /x/deweb/client/cli/tx.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | // "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/deweb-services/deweb/x/deweb/types" 12 | ) 13 | 14 | var ( 15 | DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds()) 16 | ) 17 | 18 | const ( 19 | flagPacketTimeoutTimestamp = "packet-timeout-timestamp" 20 | listSeparator = "," 21 | ) 22 | 23 | // GetTxCmd returns the transaction commands for this module 24 | func GetTxCmd() *cobra.Command { 25 | cmd := &cobra.Command{ 26 | Use: types.ModuleName, 27 | Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), 28 | DisableFlagParsing: true, 29 | SuggestionsMinimumDistance: 2, 30 | RunE: client.ValidateCmd, 31 | } 32 | 33 | cmd.AddCommand(CmdSaveWallet()) 34 | cmd.AddCommand(CmdDeleteWallet()) 35 | cmd.AddCommand(CmdConnectChain()) 36 | cmd.AddCommand(CmdDeleteChainConnect()) 37 | // this line is used by starport scaffolding # 1 38 | 39 | return cmd 40 | } 41 | -------------------------------------------------------------------------------- /x/deweb/types/message_delete_key.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | ) 7 | 8 | var _ sdk.Msg = &MsgDeleteWallet{} 9 | 10 | func NewMsgDeleteKey(creator string, address string) *MsgDeleteWallet { 11 | return &MsgDeleteWallet{ 12 | Creator: creator, 13 | Address: address, 14 | } 15 | } 16 | 17 | func (msg *MsgDeleteWallet) Route() string { 18 | return RouterKey 19 | } 20 | 21 | func (msg *MsgDeleteWallet) Type() string { 22 | return "DeleteWallet" 23 | } 24 | 25 | func (msg *MsgDeleteWallet) GetSigners() []sdk.AccAddress { 26 | creator, err := sdk.AccAddressFromBech32(msg.Creator) 27 | if err != nil { 28 | panic(err) 29 | } 30 | return []sdk.AccAddress{creator} 31 | } 32 | 33 | func (msg *MsgDeleteWallet) GetSignBytes() []byte { 34 | bz := ModuleCdc.MustMarshalJSON(msg) 35 | return sdk.MustSortJSON(bz) 36 | } 37 | 38 | func (msg *MsgDeleteWallet) ValidateBasic() error { 39 | _, err := sdk.AccAddressFromBech32(msg.Creator) 40 | if err != nil { 41 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) 42 | } 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /x/deweb/client/cli/tx_delete_chain_connect.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/client/flags" 8 | "github.com/cosmos/cosmos-sdk/client/tx" 9 | "github.com/deweb-services/deweb/x/deweb/types" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var _ = strconv.Itoa(0) 14 | 15 | func CmdDeleteChainConnect() *cobra.Command { 16 | cmd := &cobra.Command{ 17 | Use: "delete-chain-connect [chain] [address]", 18 | Short: "Broadcast message delete_chain_connect", 19 | Args: cobra.ExactArgs(2), 20 | RunE: func(cmd *cobra.Command, args []string) (err error) { 21 | argChain := args[0] 22 | argAddress := args[1] 23 | 24 | clientCtx, err := client.GetClientTxContext(cmd) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | msg := types.NewMsgDeleteChainConnect( 30 | clientCtx.GetFromAddress().String(), 31 | argChain, 32 | argAddress, 33 | ) 34 | if err := msg.ValidateBasic(); err != nil { 35 | return err 36 | } 37 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 38 | }, 39 | } 40 | 41 | flags.AddTxFlagsToCmd(cmd) 42 | 43 | return cmd 44 | } 45 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/deweb-services/deweb 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/CosmWasm/wasmd v0.28.0 7 | github.com/cosmos/cosmos-sdk v0.45.10 8 | github.com/cosmos/ibc-go/v3 v3.3.1 9 | github.com/gogo/protobuf v1.3.3 10 | github.com/golang/protobuf v1.5.2 11 | github.com/gorilla/mux v1.8.0 12 | github.com/grpc-ecosystem/grpc-gateway v1.16.0 13 | github.com/miekg/dns v1.1.50 14 | github.com/spf13/cast v1.5.0 15 | github.com/spf13/cobra v1.5.0 16 | github.com/spf13/pflag v1.0.5 17 | github.com/stretchr/testify v1.8.0 18 | github.com/tendermint/starport v0.19.2 19 | github.com/tendermint/tendermint v0.34.22 20 | github.com/tendermint/tm-db v0.6.7 21 | golang.org/x/net v0.1.0 // indirect 22 | google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c 23 | google.golang.org/grpc v1.50.1 24 | gopkg.in/yaml.v2 v2.4.0 25 | ) 26 | 27 | replace ( 28 | github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 29 | github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 30 | github.com/keybase/go-keychain => github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 31 | google.golang.org/grpc => google.golang.org/grpc v1.33.2 32 | ) 33 | -------------------------------------------------------------------------------- /x/deweb/client/cli/tx_save_wallet.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/cosmos/cosmos-sdk/client" 9 | "github.com/cosmos/cosmos-sdk/client/flags" 10 | "github.com/cosmos/cosmos-sdk/client/tx" 11 | "github.com/deweb-services/deweb/x/deweb/types" 12 | ) 13 | 14 | var _ = strconv.Itoa(0) 15 | 16 | func CmdSaveWallet() *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: "save-wallet [address] [encrypted_key] [chain]", 19 | Short: "Broadcast message save_wallet", 20 | Args: cobra.ExactArgs(3), 21 | RunE: func(cmd *cobra.Command, args []string) (err error) { 22 | argAddress := args[0] 23 | argEncKey := args[1] 24 | argChain := args[2] 25 | 26 | clientCtx, err := client.GetClientTxContext(cmd) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | msg := types.NewMsgSaveUser( 32 | clientCtx.GetFromAddress().String(), 33 | argAddress, 34 | argEncKey, 35 | argChain, 36 | ) 37 | if err := msg.ValidateBasic(); err != nil { 38 | return err 39 | } 40 | return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) 41 | }, 42 | } 43 | 44 | flags.AddTxFlagsToCmd(cmd) 45 | 46 | return cmd 47 | } 48 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids" 15 | }, 16 | "dependencies": { 17 | "@docusaurus/core": "^2.1.0", 18 | "@docusaurus/preset-classic": "^2.1.0", 19 | "@mdx-js/react": "^1.6.22", 20 | "clsx": "^1.2.1", 21 | "prism-react-renderer": "^1.3.5", 22 | "react": "^17.0.2", 23 | "react-dom": "^17.0.2", 24 | "remarkable-embed": "^0.4.1" 25 | }, 26 | "devDependencies": { 27 | "@docusaurus/module-type-aliases": "^2.1.0" 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.5%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | }, 41 | "engines": { 42 | "node": ">=16.14" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /x/deweb/types/message_save_user.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | ) 7 | 8 | var _ sdk.Msg = &MsgSaveWallet{} 9 | 10 | func NewMsgSaveUser(creator string, address string, encKey string, chain string) *MsgSaveWallet { 11 | return &MsgSaveWallet{ 12 | Creator: creator, 13 | Address: address, 14 | EncryptedKey: encKey, 15 | Chain: chain, 16 | } 17 | } 18 | 19 | func (msg *MsgSaveWallet) Route() string { 20 | return RouterKey 21 | } 22 | 23 | func (msg *MsgSaveWallet) Type() string { 24 | return "SaveWallet" 25 | } 26 | 27 | func (msg *MsgSaveWallet) GetSigners() []sdk.AccAddress { 28 | creator, err := sdk.AccAddressFromBech32(msg.Creator) 29 | if err != nil { 30 | panic(err) 31 | } 32 | return []sdk.AccAddress{creator} 33 | } 34 | 35 | func (msg *MsgSaveWallet) GetSignBytes() []byte { 36 | bz := ModuleCdc.MustMarshalJSON(msg) 37 | return sdk.MustSortJSON(bz) 38 | } 39 | 40 | func (msg *MsgSaveWallet) ValidateBasic() error { 41 | _, err := sdk.AccAddressFromBech32(msg.Creator) 42 | if err != nil { 43 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) 44 | } 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /x/deweb/types/message_connect_chain.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | ) 7 | 8 | const TypeMsgConnectChain = "connect_chain" 9 | 10 | var _ sdk.Msg = &MsgConnectChain{} 11 | 12 | func NewMsgConnectChain(creator string, chain string, address string) *MsgConnectChain { 13 | return &MsgConnectChain{ 14 | Creator: creator, 15 | Chain: chain, 16 | Address: address, 17 | } 18 | } 19 | 20 | func (msg *MsgConnectChain) Route() string { 21 | return RouterKey 22 | } 23 | 24 | func (msg *MsgConnectChain) Type() string { 25 | return TypeMsgConnectChain 26 | } 27 | 28 | func (msg *MsgConnectChain) GetSigners() []sdk.AccAddress { 29 | creator, err := sdk.AccAddressFromBech32(msg.Creator) 30 | if err != nil { 31 | panic(err) 32 | } 33 | return []sdk.AccAddress{creator} 34 | } 35 | 36 | func (msg *MsgConnectChain) GetSignBytes() []byte { 37 | bz := ModuleCdc.MustMarshalJSON(msg) 38 | return sdk.MustSortJSON(bz) 39 | } 40 | 41 | func (msg *MsgConnectChain) ValidateBasic() error { 42 | _, err := sdk.AccAddressFromBech32(msg.Creator) 43 | if err != nil { 44 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) 45 | } 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | on: 3 | pull_request: 4 | branches: [main] 5 | types: [closed] 6 | 7 | # Allows you to run this workflow manually from the Actions tab 8 | workflow_dispatch: 9 | 10 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 11 | jobs: 12 | publish: 13 | name: Deploy Docs 14 | if: ${{ github.event.pull_request.merged }} 15 | runs-on: ubuntu-latest 16 | steps: 17 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 18 | - name: Check out repo 19 | uses: actions/checkout@v2 20 | # Node is required for npm 21 | - name: Set up Node 22 | uses: actions/setup-node@v2 23 | with: 24 | node-version: "16" 25 | # Install and build Docusaurus website 26 | - name: Build Docusaurus website 27 | run: | 28 | cd docs 29 | npm install 30 | npm run build 31 | - name: Deploy to GitHub Pages 32 | if: success() 33 | uses: crazy-max/ghaction-github-pages@v2 34 | with: 35 | target_branch: gh-pages 36 | build_dir: docs/build 37 | fqdn: docs.deweb.services 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | build: 3 | binary: dewebd 4 | proto: 5 | path: proto 6 | third_party_paths: 7 | - third_party/proto 8 | - proto_vendor 9 | accounts: 10 | - name: alice 11 | coins: 12 | - 100000000000000udws 13 | - name: bob 14 | coins: 15 | - 1000000000udws 16 | faucet: 17 | name: bob 18 | coins: 19 | - 100000udws 20 | host: 0.0.0.0:4500 21 | client: 22 | openapi: 23 | path: docs/static/openapi.yml 24 | genesis: 25 | app_state: 26 | gov: 27 | deposit_params: 28 | min_deposit: 29 | - amount: "10000000" 30 | denom: udws 31 | mint: 32 | minter: 33 | inflation: "0.000000000000000000" 34 | params: 35 | blocks_per_year: "5256000" 36 | inflation_max: "0.000000000000000000" 37 | inflation_min: "0.000000000000000000" 38 | inflation_rate_change: "0.000000000000000000" 39 | mint_denom: udws 40 | staking: 41 | params: 42 | bond_denom: udws 43 | token: 44 | params: 45 | issue_token_base_fee: 46 | amount: "1000" 47 | denom: dws 48 | mint_token_fee_ratio: "0.100000000000000000" 49 | token_tax_rate: "0.400000000000000000" 50 | chain_id: deweb-testnet-0 51 | validators: 52 | - name: bob 53 | bonded: 10000000udws 54 | -------------------------------------------------------------------------------- /x/dns_module/genesis.go: -------------------------------------------------------------------------------- 1 | package dns_module 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/deweb-services/deweb/x/dns_module/keeper" 7 | "github.com/deweb-services/deweb/x/dns_module/types" 8 | ) 9 | 10 | // InitGenesis stores the NFT genesis. 11 | func InitGenesis(ctx sdk.Context, k keeper.Keeper, data types.GenesisState) { 12 | if err := types.ValidateGenesis(data); err != nil { 13 | panic(err.Error()) 14 | } 15 | 16 | k.SetParams(ctx, data.Params) 17 | 18 | for _, c := range data.Collections { 19 | if err := k.SetDenom(ctx, c.Denom); err != nil { 20 | panic(err) 21 | } 22 | if err := k.SetCollection(ctx, c); err != nil { 23 | panic(err) 24 | } 25 | } 26 | } 27 | 28 | // ExportGenesis returns a GenesisState for a given context and keeper. 29 | func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { 30 | params := k.GetParams(ctx) 31 | return types.NewGenesisState(k.GetCollections(ctx), params) 32 | } 33 | 34 | // DefaultGenesisState returns a default genesis state 35 | func DefaultGenesisState() *types.GenesisState { 36 | dnsDenom := types.Denom{ 37 | Id: "domains", 38 | Name: "dnsregistry", 39 | Symbol: "DwDNS", 40 | } 41 | return types.NewGenesisState([]types.Collection{{ 42 | Denom: dnsDenom, 43 | }}, types.DefaultParams()) 44 | } 45 | -------------------------------------------------------------------------------- /x/deweb/types/message_delete_chain_connect.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | ) 7 | 8 | const TypeMsgDeleteChainConnect = "delete_chain_connect" 9 | 10 | var _ sdk.Msg = &MsgDeleteChainConnect{} 11 | 12 | func NewMsgDeleteChainConnect(creator string, chain string, address string) *MsgDeleteChainConnect { 13 | return &MsgDeleteChainConnect{ 14 | Creator: creator, 15 | Chain: chain, 16 | Address: address, 17 | } 18 | } 19 | 20 | func (msg *MsgDeleteChainConnect) Route() string { 21 | return RouterKey 22 | } 23 | 24 | func (msg *MsgDeleteChainConnect) Type() string { 25 | return TypeMsgDeleteChainConnect 26 | } 27 | 28 | func (msg *MsgDeleteChainConnect) GetSigners() []sdk.AccAddress { 29 | creator, err := sdk.AccAddressFromBech32(msg.Creator) 30 | if err != nil { 31 | panic(err) 32 | } 33 | return []sdk.AccAddress{creator} 34 | } 35 | 36 | func (msg *MsgDeleteChainConnect) GetSignBytes() []byte { 37 | bz := ModuleCdc.MustMarshalJSON(msg) 38 | return sdk.MustSortJSON(bz) 39 | } 40 | 41 | func (msg *MsgDeleteChainConnect) ValidateBasic() error { 42 | _, err := sdk.AccAddressFromBech32(msg.Creator) 43 | if err != nil { 44 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid creator address (%s)", err) 45 | } 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /x/dns_module/handler.go: -------------------------------------------------------------------------------- 1 | package dns_module 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | 7 | "github.com/deweb-services/deweb/x/dns_module/keeper" 8 | "github.com/deweb-services/deweb/x/dns_module/types" 9 | ) 10 | 11 | // NewHandler routes the messages to the handlers 12 | func NewHandler(k keeper.Keeper) sdk.Handler { 13 | msgServer := keeper.NewMsgServerImpl(k) 14 | 15 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 16 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 17 | 18 | switch msg := msg.(type) { 19 | case *types.MsgRegisterDomain: 20 | res, err := msgServer.RegisterDomain(sdk.WrapSDKContext(ctx), msg) 21 | return sdk.WrapServiceResult(ctx, res, err) 22 | 23 | case *types.MsgTransferDomain: 24 | res, err := msgServer.TransferDomain(sdk.WrapSDKContext(ctx), msg) 25 | return sdk.WrapServiceResult(ctx, res, err) 26 | 27 | case *types.MsgEditDomain: 28 | res, err := msgServer.EditDomain(sdk.WrapSDKContext(ctx), msg) 29 | return sdk.WrapServiceResult(ctx, res, err) 30 | 31 | case *types.MsgRemoveDomain: 32 | res, err := msgServer.RemoveDomain(sdk.WrapSDKContext(ctx), msg) 33 | return sdk.WrapServiceResult(ctx, res, err) 34 | 35 | default: 36 | return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized nft message type: %T", msg) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /x/deweb/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/cosmos/cosmos-sdk/codec" 5 | cdctypes "github.com/cosmos/cosmos-sdk/codec/types" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | 8 | // this line is used by starport scaffolding # 1 9 | "github.com/cosmos/cosmos-sdk/types/msgservice" 10 | ) 11 | 12 | func RegisterCodec(cdc *codec.LegacyAmino) { 13 | cdc.RegisterConcrete(&MsgSaveWallet{}, "deweb/SaveWallet", nil) 14 | cdc.RegisterConcrete(&MsgDeleteWallet{}, "deweb/DeleteWallet", nil) 15 | cdc.RegisterConcrete(&MsgConnectChain{}, "deweb/ConnectChain", nil) 16 | cdc.RegisterConcrete(&MsgDeleteChainConnect{}, "deweb/DeleteChainConnect", nil) 17 | // this line is used by starport scaffolding # 2 18 | } 19 | 20 | func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { 21 | registry.RegisterImplementations((*sdk.Msg)(nil), 22 | &MsgSaveWallet{}, 23 | ) 24 | registry.RegisterImplementations((*sdk.Msg)(nil), 25 | &MsgDeleteWallet{}, 26 | ) 27 | registry.RegisterImplementations((*sdk.Msg)(nil), 28 | &MsgConnectChain{}, 29 | ) 30 | registry.RegisterImplementations((*sdk.Msg)(nil), 31 | &MsgDeleteChainConnect{}, 32 | ) 33 | // this line is used by starport scaffolding # 3 34 | 35 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 36 | } 37 | 38 | var ( 39 | Amino = codec.NewLegacyAmino() 40 | ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) 41 | ) 42 | -------------------------------------------------------------------------------- /proto/deweb/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.deweb.v1beta1; 3 | 4 | // this line is used by starport scaffolding # proto/tx/import 5 | 6 | option go_package = "github.com/deweb-services/deweb/x/deweb/types"; 7 | 8 | // Msg defines the Msg service. 9 | service Msg { 10 | rpc SaveWallet(MsgSaveWallet) returns (MsgSaveWalletResponse); 11 | rpc DeleteWallet(MsgDeleteWallet) returns (MsgDeleteWalletResponse); 12 | rpc ConnectChain(MsgConnectChain) returns (MsgConnectChainResponse); 13 | rpc DeleteChainConnect(MsgDeleteChainConnect) returns (MsgDeleteChainConnectResponse); 14 | // this line is used by starport scaffolding # proto/tx/rpc 15 | } 16 | 17 | message MsgSaveWallet { 18 | string creator = 1; 19 | string address = 2; 20 | string encrypted_key = 3; 21 | string chain = 4; 22 | } 23 | 24 | message MsgSaveWalletResponse { 25 | } 26 | 27 | message MsgDeleteWallet { 28 | string creator = 1; 29 | string address = 2; 30 | } 31 | 32 | message MsgDeleteWalletResponse { 33 | } 34 | 35 | message MsgConnectChain { 36 | string creator = 1; 37 | string chain = 2; 38 | string address = 3; 39 | } 40 | 41 | message MsgConnectChainResponse { 42 | } 43 | 44 | message MsgDeleteChainConnect { 45 | string creator = 1; 46 | string chain = 2; 47 | string address = 3; 48 | } 49 | 50 | message MsgDeleteChainConnectResponse { 51 | } 52 | 53 | // this line is used by starport scaffolding # proto/tx/message -------------------------------------------------------------------------------- /x/dns_module/keeper/params.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | "github.com/deweb-services/deweb/x/dns_module/types" 6 | ) 7 | 8 | func (k Keeper) DomainPriceUDWS(ctx sdk.Context) (res uint64) { 9 | k.paramStore.Get(ctx, types.KeyDomainPrice, &res) 10 | return res 11 | } 12 | 13 | func (k Keeper) SubDomainPriceUDWS(ctx sdk.Context) (res uint64) { 14 | k.paramStore.Get(ctx, types.KeySubDomainPrice, &res) 15 | return res 16 | } 17 | 18 | func (k Keeper) DomainExpirationHours(ctx sdk.Context) (res int64) { 19 | k.paramStore.Get(ctx, types.KeyDomainExpirationHours, &res) 20 | return res 21 | } 22 | 23 | func (k Keeper) DomainOwnerProlongationHours(ctx sdk.Context) (res int64) { 24 | k.paramStore.Get(ctx, types.KeyDomainOwnerProlongationHours, &res) 25 | return res 26 | } 27 | 28 | func (k Keeper) BlockedTLDs(ctx sdk.Context) (res []string) { 29 | k.paramStore.Get(ctx, types.KeyBlockedTLDs, &res) 30 | return res 31 | } 32 | 33 | // GetParams get all parameters as types.Params 34 | func (k Keeper) GetParams(ctx sdk.Context) types.Params { 35 | return types.NewParams( 36 | k.DomainPriceUDWS(ctx), 37 | k.SubDomainPriceUDWS(ctx), 38 | k.DomainExpirationHours(ctx), 39 | k.DomainOwnerProlongationHours(ctx), 40 | k.BlockedTLDs(ctx), 41 | ) 42 | } 43 | 44 | // SetParams set the params 45 | func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { 46 | k.paramStore.SetParamSet(ctx, ¶ms) 47 | } 48 | -------------------------------------------------------------------------------- /x/deweb/handler.go: -------------------------------------------------------------------------------- 1 | package deweb 2 | 3 | import ( 4 | "fmt" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 8 | "github.com/deweb-services/deweb/x/deweb/keeper" 9 | "github.com/deweb-services/deweb/x/deweb/types" 10 | ) 11 | 12 | // NewHandler ... 13 | func NewHandler(k keeper.Keeper) sdk.Handler { 14 | msgServer := keeper.NewMsgServerImpl(k) 15 | 16 | return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 17 | ctx = ctx.WithEventManager(sdk.NewEventManager()) 18 | 19 | switch msg := msg.(type) { 20 | case *types.MsgSaveWallet: 21 | res, err := msgServer.SaveWallet(sdk.WrapSDKContext(ctx), msg) 22 | return sdk.WrapServiceResult(ctx, res, err) 23 | case *types.MsgDeleteWallet: 24 | res, err := msgServer.DeleteWallet(sdk.WrapSDKContext(ctx), msg) 25 | return sdk.WrapServiceResult(ctx, res, err) 26 | case *types.MsgConnectChain: 27 | res, err := msgServer.ConnectChain(sdk.WrapSDKContext(ctx), msg) 28 | return sdk.WrapServiceResult(ctx, res, err) 29 | case *types.MsgDeleteChainConnect: 30 | res, err := msgServer.DeleteChainConnect(sdk.WrapSDKContext(ctx), msg) 31 | return sdk.WrapServiceResult(ctx, res, err) 32 | // this line is used by starport scaffolding # 1 33 | default: 34 | errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg) 35 | return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /testutil/nullify/nullify.go: -------------------------------------------------------------------------------- 1 | // Package nullify provides methods to init nil values structs for test assertion. 2 | package nullify 3 | 4 | import ( 5 | "reflect" 6 | "unsafe" 7 | 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | ) 10 | 11 | var ( 12 | coinType = reflect.TypeOf(sdk.Coin{}) 13 | coinsType = reflect.TypeOf(sdk.Coins{}) 14 | ) 15 | 16 | // Fill analyze all struct fields and slices with 17 | // reflection and initialize the nil and empty slices, 18 | // structs, and pointers. 19 | func Fill(x interface{}) interface{} { 20 | v := reflect.Indirect(reflect.ValueOf(x)) 21 | switch v.Kind() { 22 | case reflect.Slice: 23 | for i := 0; i < v.Len(); i++ { 24 | obj := v.Index(i) 25 | objPt := reflect.NewAt(obj.Type(), unsafe.Pointer(obj.UnsafeAddr())).Interface() 26 | objPt = Fill(objPt) 27 | obj.Set(reflect.ValueOf(objPt)) 28 | } 29 | case reflect.Struct: 30 | for i := 0; i < v.NumField(); i++ { 31 | f := reflect.Indirect(v.Field(i)) 32 | if !f.CanSet() { 33 | continue 34 | } 35 | switch f.Kind() { 36 | case reflect.Slice: 37 | f.Set(reflect.MakeSlice(f.Type(), 0, 0)) 38 | case reflect.Struct: 39 | switch f.Type() { 40 | case coinType: 41 | coin := reflect.New(coinType).Interface() 42 | s := reflect.ValueOf(coin).Elem() 43 | f.Set(s) 44 | case coinsType: 45 | coins := reflect.New(coinsType).Interface() 46 | s := reflect.ValueOf(coins).Elem() 47 | f.Set(s) 48 | default: 49 | objPt := reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Interface() 50 | s := Fill(objPt) 51 | f.Set(reflect.ValueOf(s)) 52 | } 53 | } 54 | } 55 | } 56 | return reflect.Indirect(v).Interface() 57 | } 58 | -------------------------------------------------------------------------------- /testutil/keeper/deweb.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/cosmos/cosmos-sdk/codec" 7 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 8 | "github.com/cosmos/cosmos-sdk/store" 9 | storetypes "github.com/cosmos/cosmos-sdk/store/types" 10 | sdk "github.com/cosmos/cosmos-sdk/types" 11 | typesparams "github.com/cosmos/cosmos-sdk/x/params/types" 12 | "github.com/deweb-services/deweb/x/deweb/keeper" 13 | "github.com/deweb-services/deweb/x/deweb/types" 14 | "github.com/stretchr/testify/require" 15 | "github.com/tendermint/tendermint/libs/log" 16 | tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 17 | tmdb "github.com/tendermint/tm-db" 18 | ) 19 | 20 | func DewebKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { 21 | storeKey := sdk.NewKVStoreKey(types.StoreKey) 22 | memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) 23 | 24 | db := tmdb.NewMemDB() 25 | stateStore := store.NewCommitMultiStore(db) 26 | stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db) 27 | stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil) 28 | require.NoError(t, stateStore.LoadLatestVersion()) 29 | 30 | registry := codectypes.NewInterfaceRegistry() 31 | cdc := codec.NewProtoCodec(registry) 32 | 33 | paramsSubspace := typesparams.NewSubspace(cdc, 34 | types.Amino, 35 | storeKey, 36 | memStoreKey, 37 | "DewebParams", 38 | ) 39 | k := keeper.NewKeeper( 40 | cdc, 41 | storeKey, 42 | memStoreKey, 43 | paramsSubspace, 44 | ) 45 | 46 | ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) 47 | 48 | // Initialize params 49 | k.SetParams(ctx, types.DefaultParams()) 50 | 51 | return k, ctx 52 | } 53 | -------------------------------------------------------------------------------- /x/dns_module/keeper/owners.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | 6 | "github.com/deweb-services/deweb/x/dns_module/types" 7 | ) 8 | 9 | // GetByOwner gets all the domains owned by an address 10 | func (k Keeper) GetByOwner(ctx sdk.Context, address sdk.AccAddress) types.Owner { 11 | store := ctx.KVStore(k.storeKey) 12 | iterator := sdk.KVStorePrefixIterator(store, types.KeyOwner(address, "")) 13 | defer iterator.Close() 14 | 15 | owner := types.Owner{ 16 | Address: address.String(), 17 | IDCollections: types.IDCollections{}, 18 | } 19 | domainsCollections := types.IDCollections{} 20 | resDomains := make([]string, 0) 21 | 22 | for ; iterator.Valid(); iterator.Next() { 23 | key := iterator.Key() 24 | _, domainName, _ := types.SplitKeyOwner(key) 25 | resDomains = append(resDomains, domainName) 26 | domainsCollections = domainsCollections.Add(k.dnsDenomName, domainName) 27 | } 28 | 29 | owner.IDCollections = domainsCollections 30 | 31 | return owner 32 | } 33 | 34 | func (k Keeper) deleteOwner(ctx sdk.Context, tokenID string, owner sdk.AccAddress) { 35 | store := ctx.KVStore(k.storeKey) 36 | store.Delete(types.KeyOwner(owner, tokenID)) 37 | } 38 | 39 | func (k Keeper) setOwner(ctx sdk.Context, tokenID string, owner sdk.AccAddress) { 40 | store := ctx.KVStore(k.storeKey) 41 | 42 | bz := types.MustMarshalTokenID(k.cdc, tokenID) 43 | store.Set(types.KeyOwner(owner, tokenID), bz) 44 | } 45 | 46 | func (k Keeper) swapOwner(ctx sdk.Context, tokenID string, srcOwner, dstOwner sdk.AccAddress) { 47 | 48 | // delete old owner key 49 | k.deleteOwner(ctx, tokenID, srcOwner) 50 | 51 | // set new owner key 52 | k.setOwner(ctx, tokenID, dstOwner) 53 | } 54 | -------------------------------------------------------------------------------- /proto/dns_module/domain.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.domain.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/deweb-services/deweb/x/dns_module/types"; 7 | option (gogoproto.goproto_getters_all) = false; 8 | 9 | // BaseDomain defines a non-fungible domain token 10 | message BaseDomain { 11 | option (gogoproto.equal) = true; 12 | 13 | string id = 1; 14 | string data = 2; 15 | string owner = 3; 16 | } 17 | 18 | // Denom defines a type of NFT 19 | message Denom { 20 | option (gogoproto.equal) = true; 21 | 22 | string id = 1; 23 | string name = 2; 24 | string schema = 3; 25 | string creator = 4; 26 | string symbol = 5; 27 | bool mint_restricted = 6 ; 28 | bool update_restricted = 7 ; 29 | string description = 8; 30 | string uri = 9; 31 | string uri_hash = 10; 32 | string data = 11; 33 | } 34 | 35 | // IDCollection defines a type of collection with specified ID 36 | message IDCollection { 37 | option (gogoproto.equal) = true; 38 | 39 | string denom_id = 1 [ (gogoproto.moretags) = "yaml:\"denom_id\"" ]; 40 | repeated string token_ids = 2 [ (gogoproto.moretags) = "yaml:\"token_ids\"" ]; 41 | } 42 | 43 | // Owner defines a type of owner 44 | message Owner { 45 | option (gogoproto.equal) = true; 46 | 47 | string address = 1; 48 | repeated IDCollection id_collections = 2 [ (gogoproto.moretags) = "yaml:\"idcs\"", (gogoproto.customname) = "IDCollections", (gogoproto.nullable) = false ]; 49 | } 50 | 51 | // Collection defines a type of collection 52 | message Collection { 53 | option (gogoproto.equal) = true; 54 | 55 | Denom denom = 1 [ (gogoproto.nullable) = false ]; 56 | repeated BaseDomain nfts = 2 [ (gogoproto.customname) = "NFTs", (gogoproto.nullable) = false ]; 57 | } -------------------------------------------------------------------------------- /x/dns_module/keeper/dns_record.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/cosmos/cosmos-sdk/types/errors" 7 | "regexp" 8 | "time" 9 | ) 10 | 11 | type DNSTypeRecord struct { 12 | RecordType string `json:"type"` 13 | RecordValues []string `json:"values"` 14 | } 15 | 16 | type DNSTransferOffer struct { 17 | Price uint64 `json:"price"` // in udws 18 | ExpectedOwnerAddress string `json:"expected_owner_address"` 19 | } 20 | 21 | type DNSNameRecord struct { 22 | Issued time.Time `json:"issued"` 23 | ValidTill time.Time `json:"valid_till"` 24 | TransferOffer *DNSTransferOffer `json:"transfer_offer"` 25 | SubDomainsOnSale bool `json:"sub_domains_sale"` 26 | SubDomainsSalePrice uint64 `json:"sub_domains_sale_price"` 27 | DomainProlongationPrice uint64 `json:"domain_prolongation_price"` // price to pay parent domain owner on prolongation 28 | Records []DNSTypeRecord `json:"records"` 29 | } 30 | 31 | func ParseDomainData(data []byte) (DNSNameRecord, error) { 32 | resRecord := DNSNameRecord{} 33 | err := json.Unmarshal(data, &resRecord) 34 | if err != nil { 35 | return resRecord, errors.Wrap(err, "error parsing NFT DNS record") 36 | } 37 | return resRecord, nil 38 | } 39 | 40 | func validateARecord(values []string) error { 41 | ipRe := regexp.MustCompile(`^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$`) 42 | for _, val := range values { 43 | valid := ipRe.MatchString(val) 44 | if !valid { 45 | return fmt.Errorf("record %s is invalid IP address", val) 46 | } 47 | } 48 | return nil 49 | } 50 | 51 | func (d *DNSNameRecord) validateRecords() error { 52 | for _, rec := range d.Records { 53 | if rec.RecordType == "A" { 54 | err := validateARecord(rec.RecordValues) 55 | if err != nil { 56 | return fmt.Errorf("record type A is invalid: %w", err) 57 | } 58 | } 59 | } 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /x/dns_server/dns_proxy.go: -------------------------------------------------------------------------------- 1 | package dns_server 2 | 3 | import ( 4 | "fmt" 5 | "github.com/miekg/dns" 6 | ) 7 | 8 | func (srv *DNSResolverService) getResponse(requestMsg *dns.Msg) (*dns.Msg, error) { 9 | responseMsg := new(dns.Msg) 10 | if len(requestMsg.Question) > 0 { 11 | question := requestMsg.Question[0] 12 | _, ok := recordTypesMapping[question.Qtype] 13 | if !ok { 14 | fmt.Printf("unsupported type %d for domain %s \n", question.Qtype, question.Name) 15 | return responseMsg, nil 16 | } 17 | resAddresses, err := srv.resolveDNSRecord(question.Name, question.Qtype) 18 | if err == nil { 19 | storedVal := resAddresses[0] 20 | fmt.Printf("record for %s: %s found in chain\n", question.Name, storedVal.value) 21 | answer, err := dns.NewRR(fmt.Sprintf("%s %s %s", question.Name, storedVal.recType, storedVal.value)) 22 | if err != nil { 23 | return responseMsg, err 24 | } 25 | responseMsg.Answer = append(responseMsg.Answer, answer) 26 | } else { 27 | answer, err := srv.processOtherTypes(srv.proxyDNSServer, &question, requestMsg) 28 | if err != nil { 29 | return responseMsg, err 30 | } 31 | responseMsg.Answer = append(responseMsg.Answer, *answer) 32 | } 33 | } 34 | 35 | return responseMsg, nil 36 | } 37 | 38 | func (srv *DNSResolverService) processOtherTypes(dnsServer string, q *dns.Question, requestMsg *dns.Msg) (*dns.RR, error) { 39 | queryMsg := new(dns.Msg) 40 | requestMsg.CopyTo(queryMsg) 41 | queryMsg.Question = []dns.Question{*q} 42 | 43 | msg, err := lookup(dnsServer, queryMsg) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | if len(msg.Answer) > 0 { 49 | return &msg.Answer[0], nil 50 | } 51 | return nil, fmt.Errorf("not found") 52 | } 53 | 54 | func lookup(server string, m *dns.Msg) (*dns.Msg, error) { 55 | dnsClient := new(dns.Client) 56 | dnsClient.Net = "udp" 57 | response, _, err := dnsClient.Exchange(m, server) 58 | if err != nil { 59 | return nil, err 60 | } 61 | 62 | return response, nil 63 | } 64 | -------------------------------------------------------------------------------- /x/dns_module/keeper/querier.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "fmt" 5 | 6 | abci "github.com/tendermint/tendermint/abci/types" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 11 | 12 | "github.com/deweb-services/deweb/x/dns_module/types" 13 | ) 14 | 15 | // NewQuerier is the module level router for state queries 16 | func NewQuerier(k Keeper, legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { 17 | return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err error) { 18 | fmt.Printf("Query request to %s\n", path[0]) 19 | switch path[0] { 20 | case types.QueryParams: 21 | return queryParams(ctx, req, k, legacyQuerierCdc) 22 | case types.QueryDomain: 23 | return queryDomain(ctx, req, k, legacyQuerierCdc) 24 | default: 25 | return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown query path: %s", path[0]) 26 | } 27 | } 28 | } 29 | 30 | func queryParams(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { 31 | params := k.GetParams(ctx) 32 | 33 | bz, err := codec.MarshalJSONIndent(legacyQuerierCdc, params) 34 | if err != nil { 35 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 36 | } 37 | 38 | return bz, nil 39 | } 40 | 41 | func queryDomain(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQuerierCdc *codec.LegacyAmino) ([]byte, error) { 42 | var params types.QueryDomainParams 43 | 44 | if err := legacyQuerierCdc.UnmarshalJSON(req.Data, ¶ms); err != nil { 45 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) 46 | } 47 | 48 | domain, err := k.GetDomain(ctx, params.TokenID) 49 | if err != nil { 50 | return nil, sdkerrors.Wrapf(types.ErrUnknownDomain, "invalid domain NFT %s", params.TokenID) 51 | } 52 | 53 | bz, err := codec.MarshalJSONIndent(legacyQuerierCdc, domain) 54 | if err != nil { 55 | return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) 56 | } 57 | 58 | return bz, nil 59 | } 60 | -------------------------------------------------------------------------------- /x/dns_module/client/rest/rest.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "github.com/gorilla/mux" 5 | 6 | "github.com/cosmos/cosmos-sdk/client" 7 | "github.com/cosmos/cosmos-sdk/types/rest" 8 | ) 9 | 10 | // RegisterHandlers registers the NFT REST routes. 11 | func RegisterHandlers(cliCtx client.Context, r *mux.Router, queryRoute string) { 12 | registerQueryRoutes(cliCtx, r, queryRoute) 13 | registerTxRoutes(cliCtx, r, queryRoute) 14 | } 15 | 16 | const ( 17 | RestParamTokenID = "token-id" 18 | RestParamDomainName = "domainName" 19 | RestParamOwner = "owner" 20 | ) 21 | 22 | type issueDenomReq struct { 23 | BaseReq rest.BaseReq `json:"base_req"` 24 | Owner string `json:"owner"` 25 | ID string `json:"id"` 26 | Name string `json:"name"` 27 | Schema string `json:"schema"` 28 | Symbol string `json:"symbol"` 29 | MintRestricted bool `json:"mint_restricted"` 30 | UpdateRestricted bool `json:"update_restricted"` 31 | Description string `json:"description"` 32 | Uri string `json:"uri"` 33 | UriHash string `json:"uri_hash"` 34 | Data string `json:"data"` 35 | } 36 | 37 | type registerDomainReq struct { 38 | BaseReq rest.BaseReq `json:"base_req"` 39 | Owner string `json:"owner"` 40 | Recipient string `json:"recipient"` 41 | ID string `json:"id"` 42 | Data string `json:"data"` 43 | } 44 | 45 | type editDomainReq struct { 46 | BaseReq rest.BaseReq `json:"base_req"` 47 | Owner string `json:"owner"` 48 | Data string `json:"data"` 49 | } 50 | 51 | type transferDomainReq struct { 52 | BaseReq rest.BaseReq `json:"base_req"` 53 | Owner string `json:"owner"` 54 | Recipient string `json:"recipient"` 55 | Price uint64 `json:"price"` 56 | CancelOffer bool `json:"cancel_offer"` 57 | } 58 | 59 | type RemoveDomainReq struct { 60 | BaseReq rest.BaseReq `json:"base_req"` 61 | Owner string `json:"owner"` 62 | } 63 | -------------------------------------------------------------------------------- /x/deweb/keeper/grpc_query_filter_user_wallet_records.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/deweb-services/deweb/x/deweb/types" 9 | "google.golang.org/grpc/codes" 10 | "google.golang.org/grpc/status" 11 | ) 12 | 13 | func (k Keeper) FilterUserWalletRecords(goCtx context.Context, req *types.QueryFilterUserWalletRecordsRequest) (*types.QueryFilterUserWalletRecordsResponse, error) { 14 | if req == nil { 15 | return nil, status.Error(codes.InvalidArgument, "invalid request") 16 | } 17 | 18 | ctx := sdk.UnwrapSDKContext(goCtx) 19 | 20 | userRecordsIDs, err := k.getUserRecordsIDs(ctx, req.GetOwner()) 21 | if err != nil { 22 | return nil, fmt.Errorf("error getting user records list: %w", err) 23 | } 24 | 25 | resultedRecords := make([]*types.WalletRecordResponse, 0) 26 | processed := 0 27 | requestedOffset := int(req.Offset) 28 | requestedLimit := int(req.Limit) 29 | for _, recID := range userRecordsIDs { 30 | k.Logger(ctx).With("method", "FilterUserWalletRecords").Error( 31 | fmt.Sprintf("%s", recID)) 32 | record, err := k.getUserKeyRecord(ctx, recID) 33 | if err != nil { 34 | k.Logger(ctx).With("method", "FilterUserWalletRecords").Error( 35 | fmt.Sprintf("error getting record %s for address %s", record, req.GetAddress())) 36 | } 37 | if req.Address != "" && req.Address != record.Address { 38 | continue 39 | } 40 | if !req.Deleted && record.Deleted { 41 | continue 42 | } 43 | if req.Chain != "" && req.Chain != record.Chain { 44 | continue 45 | } 46 | processed += 1 47 | if processed <= requestedOffset { 48 | continue 49 | } 50 | resRecord := &types.WalletRecordResponse{ 51 | Owner: req.Owner, 52 | Address: record.Address, 53 | EncryptedKey: record.EncryptedKey, 54 | Chain: record.Chain, 55 | Deleted: record.Deleted, 56 | } 57 | resultedRecords = append(resultedRecords, resRecord) 58 | if len(resultedRecords) == requestedLimit { 59 | break 60 | } 61 | } 62 | 63 | return &types.QueryFilterUserWalletRecordsResponse{ 64 | Records: resultedRecords, 65 | }, nil 66 | } 67 | -------------------------------------------------------------------------------- /x/deweb/keeper/grpc_query_filter_chain_mappings_records.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/deweb-services/deweb/x/deweb/types" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | func (k Keeper) FilterChainMappingsRecords(goCtx context.Context, req *types.QueryFilterChainMappingsRecordsRequest) (*types.QueryFilterChainMappingsRecordsResponse, error) { 13 | if req == nil { 14 | return nil, status.Error(codes.InvalidArgument, "invalid request") 15 | } 16 | 17 | ctx := sdk.UnwrapSDKContext(goCtx) 18 | 19 | userRecordsIDs, err := k.getChainMappingRecordsIDs(ctx, req.GetOwner()) 20 | if err != nil { 21 | return nil, fmt.Errorf("error getting chain mappings records list: %w", err) 22 | } 23 | 24 | resultedRecords := make([]*types.ChainMappingRecordResponse, 0) 25 | processed := 0 26 | requestedOffset := int(req.Offset) 27 | requestedLimit := int(req.Limit) 28 | for _, recID := range userRecordsIDs { 29 | k.Logger(ctx).With("method", "FilterChainMappingsRecords").Error( 30 | fmt.Sprintf("%s", recID)) 31 | record, err := k.getChainMappingRecord(ctx, recID) 32 | if err != nil { 33 | k.Logger(ctx).With("method", "FilterChainMappingsRecords").Error( 34 | fmt.Sprintf("error getting record %s for address %s", record, req.GetAddress())) 35 | } 36 | if req.Address != "" && req.Address != record.ExtAddress { 37 | continue 38 | } 39 | if !req.Deleted && record.Deleted { 40 | continue 41 | } 42 | if req.Chain != "" && req.Chain != record.Chain { 43 | continue 44 | } 45 | processed += 1 46 | if processed <= requestedOffset { 47 | continue 48 | } 49 | resRecord := &types.ChainMappingRecordResponse{ 50 | Owner: req.Owner, 51 | ExtAddress: record.ExtAddress, 52 | Chain: record.Chain, 53 | Deleted: record.Deleted, 54 | } 55 | resultedRecords = append(resultedRecords, resRecord) 56 | if len(resultedRecords) == requestedLimit { 57 | break 58 | } 59 | } 60 | 61 | responseRecords := &types.QueryFilterChainMappingsRecordsResponse{ 62 | Records: resultedRecords, 63 | } 64 | return responseRecords, nil 65 | } 66 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This workflow is useful if you want to automate the process of: 2 | # 3 | # a) Creating a new prelease when you push a new tag with a "v" prefix (version). 4 | # 5 | # This type of prerelease is meant to be used for production: alpha, beta, rc, etc. types of releases. 6 | # After the prerelease is created, you need to make your changes on the release page at the relevant 7 | # Github page and publish your release. 8 | # 9 | # b) Creating/updating the "latest" prerelease when you push to your default branch. 10 | # 11 | # This type of prelease is useful to make your bleeding-edge binaries available to advanced users. 12 | # 13 | # The workflow will not run if there is no tag pushed with a "v" prefix and no change pushed to your 14 | # default branch. 15 | on: push 16 | 17 | jobs: 18 | might_release: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v2 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Prepare Release Variables 27 | id: vars 28 | uses: tendermint/starport/actions/release/vars@develop 29 | 30 | - name: Issue Release Assets 31 | uses: tendermint/starport/actions/cli@develop 32 | if: ${{ steps.vars.outputs.should_release == 'true' }} 33 | with: 34 | args: chain build --release --release.prefix ${{ steps.vars.outputs.tarball_prefix }} -t linux:amd64 -t darwin:amd64 35 | 36 | - name: Delete the "latest" Release 37 | uses: dev-drprasad/delete-tag-and-release@v0.2.0 38 | if: ${{ steps.vars.outputs.is_release_type_latest == 'true' }} 39 | with: 40 | tag_name: ${{ steps.vars.outputs.tag_name }} 41 | delete_release: true 42 | env: 43 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 44 | 45 | - name: Publish the Release 46 | uses: softprops/action-gh-release@v1 47 | if: ${{ steps.vars.outputs.should_release == 'true' }} 48 | with: 49 | tag_name: ${{ steps.vars.outputs.tag_name }} 50 | files: release/* 51 | prerelease: true 52 | env: 53 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | -------------------------------------------------------------------------------- /x/dns_module/keeper/denom.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | 7 | "github.com/deweb-services/deweb/x/dns_module/types" 8 | ) 9 | 10 | // HasDenom returns whether the specified denom ID exists 11 | func (k Keeper) HasDenomID(ctx sdk.Context, id string) bool { 12 | store := ctx.KVStore(k.storeKey) 13 | return store.Has(types.KeyDenomID(id)) 14 | } 15 | 16 | // SetDenom is responsible for saving the definition of denom 17 | func (k Keeper) SetDenom(ctx sdk.Context, denom types.Denom) error { 18 | if k.HasDenomID(ctx, denom.Id) { 19 | return sdkerrors.Wrapf(types.ErrInvalidDenom, "denomID %s has already exists", denom.Id) 20 | } 21 | 22 | store := ctx.KVStore(k.storeKey) 23 | bz := k.cdc.MustMarshal(&denom) 24 | store.Set(types.KeyDenomID(denom.Id), bz) 25 | store.Set(types.KeyDenomName(denom.Name), []byte(denom.Id)) 26 | return nil 27 | } 28 | 29 | // GetDenom returns the denom by id 30 | func (k Keeper) GetDenom(ctx sdk.Context, id string) (denom types.Denom, found bool) { 31 | store := ctx.KVStore(k.storeKey) 32 | storeKey := types.KeyDenomID(id) 33 | bz := store.Get(storeKey) 34 | if len(bz) == 0 { 35 | return denom, false 36 | } 37 | 38 | k.cdc.MustUnmarshal(bz, &denom) 39 | return denom, true 40 | } 41 | 42 | // GetDenoms returns all the denoms 43 | func (k Keeper) GetDenoms(ctx sdk.Context) (denoms []types.Denom) { 44 | store := ctx.KVStore(k.storeKey) 45 | iterator := sdk.KVStorePrefixIterator(store, types.KeyDenomID("")) 46 | defer iterator.Close() 47 | 48 | for ; iterator.Valid(); iterator.Next() { 49 | var denom types.Denom 50 | k.cdc.MustUnmarshal(iterator.Value(), &denom) 51 | denoms = append(denoms, denom) 52 | } 53 | return denoms 54 | } 55 | 56 | // UpdateDenom is responsible for updating the definition of denom 57 | func (k Keeper) UpdateDenom(ctx sdk.Context, denom types.Denom) error { 58 | if !k.HasDenomID(ctx, denom.Id) { 59 | return sdkerrors.Wrapf(types.ErrInvalidDenom, "denomID %s not exists", denom.Id) 60 | } 61 | 62 | store := ctx.KVStore(k.storeKey) 63 | bz := k.cdc.MustMarshal(&denom) 64 | store.Set(types.KeyDenomID(denom.Id), bz) 65 | return nil 66 | } 67 | -------------------------------------------------------------------------------- /x/deweb/client/cli/query_filter_user_key_records.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/deweb-services/deweb/x/deweb/types" 12 | ) 13 | 14 | var _ = strconv.Itoa(0) 15 | 16 | func CmdFilterUserWalletRecords() *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: "filter-user-wallet-records [owner] [address] [chain] [deleted] [limit] [offset]", 19 | Short: "Query filter_user_wallet_records", 20 | Args: cobra.MinimumNArgs(1), 21 | RunE: func(cmd *cobra.Command, args []string) (err error) { 22 | reqOwner := args[0] 23 | 24 | var reqAddress string 25 | if len(args) > 1 { 26 | reqAddress = args[1] 27 | } 28 | 29 | var reqChain string 30 | if len(args) > 2 { 31 | reqChain = args[2] 32 | } 33 | 34 | var reqDeleted bool 35 | if len(args) > 3 { 36 | reqDeleted, err = strconv.ParseBool(args[3]) 37 | if err != nil { 38 | return fmt.Errorf("cannot parse parameter deleted: %w", err) 39 | } 40 | } 41 | 42 | var reqLimit int64 43 | if len(args) > 4 { 44 | reqLimit, err = strconv.ParseInt(args[4], 10, 32) 45 | if err != nil { 46 | return fmt.Errorf("cannot parse parameter limit: %w", err) 47 | } 48 | } else { 49 | reqLimit = 10 50 | } 51 | 52 | var reqOffset int64 53 | if len(args) > 5 { 54 | reqOffset, err = strconv.ParseInt(args[5], 10, 32) 55 | if err != nil { 56 | return fmt.Errorf("cannot parse parameter offset: %w", err) 57 | } 58 | } 59 | 60 | clientCtx, err := client.GetClientTxContext(cmd) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | queryClient := types.NewQueryClient(clientCtx) 66 | 67 | params := &types.QueryFilterUserWalletRecordsRequest{ 68 | Owner: reqOwner, 69 | Address: reqAddress, 70 | Chain: reqChain, 71 | Deleted: reqDeleted, 72 | Limit: int32(reqLimit), 73 | Offset: int32(reqOffset), 74 | } 75 | 76 | res, err := queryClient.FilterUserWalletRecords(cmd.Context(), params) 77 | if err != nil { 78 | return err 79 | } 80 | 81 | return clientCtx.PrintProto(res) 82 | }, 83 | } 84 | 85 | flags.AddQueryFlagsToCmd(cmd) 86 | 87 | return cmd 88 | } 89 | -------------------------------------------------------------------------------- /proto/dns_module/tx.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.domain.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | 6 | option go_package = "github.com/deweb-services/deweb/x/dns_module/types"; 7 | option (gogoproto.goproto_getters_all) = false; 8 | 9 | // Msg defines the nft Msg service. 10 | service Msg { 11 | // MintNFT defines a method for mint a new nft 12 | rpc RegisterDomain(MsgRegisterDomain) returns (MsgRegisterDomainResponse); 13 | 14 | // RefundHTLC defines a method for editing a nft. 15 | rpc EditDomain(MsgEditDomain) returns (MsgEditdomainResponse); 16 | 17 | // TransferNFT defines a method for transferring a nft. 18 | rpc TransferDomain(MsgTransferDomain) returns (MsgTransferDomainResponse); 19 | 20 | // BurnNFT defines a method for burning a nft. 21 | rpc RemoveDomain(MsgRemoveDomain) returns (MsgRemoveDomainResponse); 22 | } 23 | 24 | // MsgTransferNFT defines an SDK message for transferring an NFT to recipient. 25 | message MsgTransferDomain { 26 | option (gogoproto.equal) = true; 27 | 28 | string id = 1; 29 | uint64 price= 2; 30 | bool cancel = 3; 31 | string sender = 4; 32 | string recipient = 5; 33 | } 34 | 35 | // MsgTransferNFTResponse defines the Msg/TransferNFT response type. 36 | message MsgTransferDomainResponse {} 37 | 38 | // MsgEditNFT defines an SDK message for editing a nft. 39 | message MsgEditDomain { 40 | option (gogoproto.equal) = true; 41 | 42 | string id = 1; 43 | string data = 2; 44 | string sender = 3; 45 | } 46 | 47 | // MsgEditNFTResponse defines the Msg/EditNFT response type. 48 | message MsgEditdomainResponse {} 49 | 50 | // MsgMintNFT defines an SDK message for creating a new NFT. 51 | message MsgRegisterDomain { 52 | option (gogoproto.equal) = true; 53 | 54 | string id = 1; 55 | string data = 2; 56 | string sender = 3; 57 | string recipient = 4; 58 | } 59 | 60 | // MsgMintNFTResponse defines the Msg/MintNFT response type. 61 | message MsgRegisterDomainResponse {} 62 | 63 | // MsgBurnNFT defines an SDK message for burning a NFT. 64 | message MsgRemoveDomain { 65 | option (gogoproto.equal) = true; 66 | 67 | string id = 1; 68 | string sender = 2; 69 | } 70 | 71 | // MsgBurnNFTResponse defines the Msg/BurnNFT response type. 72 | message MsgRemoveDomainResponse {} 73 | 74 | -------------------------------------------------------------------------------- /x/deweb/client/cli/query_filter_chain_mappings_records.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/cosmos/cosmos-sdk/client" 8 | "github.com/cosmos/cosmos-sdk/client/flags" 9 | "github.com/deweb-services/deweb/x/deweb/types" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var _ = strconv.Itoa(0) 14 | 15 | func CmdFilterChainMappingsRecords() *cobra.Command { 16 | cmd := &cobra.Command{ 17 | Use: "filter-chain-mappings-records [owner] [address] [chain] [deleted] [limit] [offset]", 18 | Short: "Query filter_chain_mappings_records", 19 | Args: cobra.ExactArgs(6), 20 | RunE: func(cmd *cobra.Command, args []string) (err error) { 21 | reqOwner := args[0] 22 | 23 | var reqAddress string 24 | if len(args) > 1 { 25 | reqAddress = args[1] 26 | } 27 | 28 | var reqChain string 29 | if len(args) > 2 { 30 | reqChain = args[2] 31 | } 32 | 33 | var reqDeleted bool 34 | if len(args) > 3 { 35 | reqDeleted, err = strconv.ParseBool(args[3]) 36 | if err != nil { 37 | return fmt.Errorf("cannot parse parameter deleted: %w", err) 38 | } 39 | } 40 | 41 | var reqLimit int64 42 | if len(args) > 4 { 43 | reqLimit, err = strconv.ParseInt(args[4], 10, 32) 44 | if err != nil { 45 | return fmt.Errorf("cannot parse parameter limit: %w", err) 46 | } 47 | } else { 48 | reqLimit = 10 49 | } 50 | 51 | var reqOffset int64 52 | if len(args) > 5 { 53 | reqOffset, err = strconv.ParseInt(args[5], 10, 32) 54 | if err != nil { 55 | return fmt.Errorf("cannot parse parameter offset: %w", err) 56 | } 57 | } 58 | 59 | clientCtx, err := client.GetClientTxContext(cmd) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | queryClient := types.NewQueryClient(clientCtx) 65 | 66 | params := &types.QueryFilterChainMappingsRecordsRequest{ 67 | Owner: reqOwner, 68 | Address: reqAddress, 69 | Chain: reqChain, 70 | Deleted: reqDeleted, 71 | Limit: int32(reqLimit), 72 | Offset: int32(reqOffset), 73 | } 74 | 75 | res, err := queryClient.FilterChainMappingsRecords(cmd.Context(), params) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | return clientCtx.PrintProto(res) 81 | }, 82 | } 83 | 84 | flags.AddQueryFlagsToCmd(cmd) 85 | 86 | return cmd 87 | } 88 | -------------------------------------------------------------------------------- /x/dns_server/dns_from_chain.go: -------------------------------------------------------------------------------- 1 | package dns_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/deweb-services/deweb/x/dns_module/types" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type resolvedRecord struct { 12 | recType string 13 | value string 14 | } 15 | 16 | func (srv *DNSResolverService) resolveDNSRecord(domain string, recordType uint16) ([]resolvedRecord, error) { 17 | if strings.HasSuffix(domain, ".") { 18 | domain = domain[:len(domain)-1] 19 | } 20 | queryClient := types.NewQueryClient(srv.cliCtx) 21 | resp, err := queryClient.Domain( 22 | context.Background(), 23 | &types.QueryDomainRequest{ 24 | DomainName: domain, 25 | }, 26 | ) 27 | if err != nil { 28 | return nil, fmt.Errorf("cannot perform domain search: %w", err) 29 | } 30 | 31 | var storedRecords []*types.DNSRecords 32 | recFromCache, ok := srv.cachedRecords[domain] 33 | if ok { 34 | cacheExpireTime := recFromCache.CreateTime.Add(10 * time.Second) 35 | if cacheExpireTime.After(time.Now()) { 36 | storedRecords = recFromCache.Values 37 | } else { 38 | delete(srv.cachedRecords, domain) 39 | } 40 | } 41 | if storedRecords == nil { 42 | srv.cachedRecords[domain] = CacheRecord{ 43 | Values: resp.Domain.Records, 44 | CreateTime: time.Now(), 45 | } 46 | storedRecords = resp.Domain.Records 47 | } 48 | 49 | recordTypeName, ok := recordTypesMapping[recordType] 50 | if !ok { 51 | return nil, fmt.Errorf("unsupported type %d", recordType) 52 | } 53 | var cnameRecords []string 54 | var resRecords []string 55 | for _, rec := range storedRecords { 56 | if rec.Type == recordTypeName { 57 | resRecords = rec.Values 58 | break 59 | } 60 | if rec.Type == "CNAME" { 61 | cnameRecords = rec.Values 62 | } 63 | } 64 | result := make([]resolvedRecord, 0) 65 | if resRecords != nil { 66 | for _, resRec := range resRecords { 67 | respItem := resolvedRecord{ 68 | recType: recordTypeName, 69 | value: resRec, 70 | } 71 | result = append(result, respItem) 72 | } 73 | return result, nil 74 | } 75 | if cnameRecords != nil { 76 | for _, resRec := range cnameRecords { 77 | respItem := resolvedRecord{ 78 | recType: "CNAME", 79 | value: resRec, 80 | } 81 | result = append(result, respItem) 82 | } 83 | return result, nil 84 | } 85 | return nil, fmt.Errorf("record for %s not found", domain) 86 | } 87 | -------------------------------------------------------------------------------- /x/dns_module/keeper/collection.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | "github.com/deweb-services/deweb/x/dns_module/types" 7 | ) 8 | 9 | // SetCollection saves all Domai and returns an error if there already exists 10 | func (k Keeper) SetCollection(ctx sdk.Context, collection types.Collection) error { 11 | for _, nft := range collection.NFTs { 12 | if err := k.RegisterDomain(ctx, nft.GetID(), nft.GetData(), nft.GetOwner(), nil); err != nil { 13 | return err 14 | } 15 | } 16 | return nil 17 | } 18 | 19 | // GetCollection returns the collection by the specified denom ID 20 | func (k Keeper) GetCollection(ctx sdk.Context, denomID string) (types.Collection, error) { 21 | denom, found := k.GetDenom(ctx, denomID) 22 | if !found { 23 | return types.Collection{}, sdkerrors.Wrapf(types.ErrInvalidDenom, "denomID %s not existed ", denomID) 24 | } 25 | 26 | nfts := k.GetDomains(ctx, denomID) 27 | return types.NewCollection(denom, nfts), nil 28 | } 29 | 30 | // GetCollections returns all the collections 31 | func (k Keeper) GetCollections(ctx sdk.Context) (cs []types.Collection) { 32 | for _, denom := range k.GetDenoms(ctx) { 33 | nfts := k.GetDomains(ctx, denom.Id) 34 | cs = append(cs, types.NewCollection(denom, nfts)) 35 | } 36 | return cs 37 | } 38 | 39 | // GetDenomSupply returns the number of Domains by the specified denom ID 40 | func (k Keeper) GetTotalSupply(ctx sdk.Context, denomID string) uint64 { 41 | store := ctx.KVStore(k.storeKey) 42 | bz := store.Get(types.KeyCollection(denomID)) 43 | if len(bz) == 0 { 44 | return 0 45 | } 46 | return types.MustUnMarshalSupply(k.cdc, bz) 47 | } 48 | 49 | func (k Keeper) increaseSupply(ctx sdk.Context, denomID string) { 50 | supply := k.GetTotalSupply(ctx, denomID) 51 | supply++ 52 | 53 | store := ctx.KVStore(k.storeKey) 54 | bz := types.MustMarshalSupply(k.cdc, supply) 55 | store.Set(types.KeyCollection(denomID), bz) 56 | } 57 | 58 | func (k Keeper) decreaseSupply(ctx sdk.Context, denomID string) { 59 | supply := k.GetTotalSupply(ctx, denomID) 60 | supply-- 61 | 62 | store := ctx.KVStore(k.storeKey) 63 | if supply == 0 { 64 | store.Delete(types.KeyCollection(denomID)) 65 | return 66 | } 67 | 68 | bz := types.MustMarshalSupply(k.cdc, supply) 69 | store.Set(types.KeyCollection(denomID), bz) 70 | } 71 | -------------------------------------------------------------------------------- /x/dns_module/client/rest/query.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/gorilla/mux" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/types/rest" 11 | 12 | "github.com/deweb-services/deweb/x/dns_module/types" 13 | ) 14 | 15 | func registerQueryRoutes(cliCtx client.Context, r *mux.Router, queryRoute string) { 16 | // Get the params of module 17 | r.HandleFunc(fmt.Sprintf("/%s/params", types.ModuleName), queryParams(cliCtx, queryRoute)).Methods("GET") 18 | // Query a single domain NFT 19 | r.HandleFunc(fmt.Sprintf("/deweb/domains/v1beta1/domain/{%s}", RestParamDomainName), queryDomain(cliCtx, queryRoute)).Methods("GET") 20 | } 21 | 22 | func queryParams(cliCtx client.Context, queryRoute string) http.HandlerFunc { 23 | return func(w http.ResponseWriter, r *http.Request) { 24 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 25 | if !ok { 26 | return 27 | } 28 | 29 | res, height, err := cliCtx.Query( 30 | fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryParams), 31 | ) 32 | if err != nil { 33 | rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) 34 | return 35 | } 36 | 37 | cliCtx = cliCtx.WithHeight(height) 38 | rest.PostProcessResponse(w, cliCtx, res) 39 | } 40 | } 41 | 42 | func queryDomain(cliCtx client.Context, queryRoute string) http.HandlerFunc { 43 | return func(w http.ResponseWriter, r *http.Request) { 44 | vars := mux.Vars(r) 45 | 46 | domainName := vars[RestParamDomainName] 47 | if err := types.ValidateTokenID(domainName); err != nil { 48 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 49 | } 50 | 51 | params := types.NewQueryDomainsParams(domainName) 52 | bz, err := cliCtx.LegacyAmino.MarshalJSON(params) 53 | if err != nil { 54 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 55 | return 56 | } 57 | 58 | cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r) 59 | if !ok { 60 | return 61 | } 62 | 63 | res, height, err := cliCtx.QueryWithData( 64 | fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryDomain), bz, 65 | ) 66 | if err != nil { 67 | rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) 68 | return 69 | } 70 | 71 | cliCtx = cliCtx.WithHeight(height) 72 | rest.PostProcessResponse(w, cliCtx, res) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Decentralized Web Services (DWS) Blockchain 2 | 3 | ![Banner!](assets/banner.png) 4 | 5 | [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/deweb-services/deweb)](https://github.com/deweb-services/deweb/releases) 6 | ![License](https://badgen.net/github/license/deweb-services/deweb) 7 | [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/dws) 8 | [![Discord](https://img.shields.io/discord/905830770441093150)](https://discord.gg/dws) 9 | 10 | ## Hardware Requirements 11 | 12 | Here are the minimal hardware configs required for running a validator/sentry node 13 | 14 | - 8GB RAM 15 | - 4vCPUs 16 | - 300GB Disk space 17 | 18 | ## Software Requirements 19 | 20 | Install deps 21 | 22 | ``` 23 | sudo apt-get install build-essential jq 24 | ``` 25 | 26 | ## Compile instructions: install GoLang 27 | 28 | Install Go 1.19.x 29 | The official instructions can be found here: https://golang.org/doc/install 30 | 31 | First remove any existing old Go installation as root 32 | 33 | ``` 34 | sudo rm -rf /usr/local/go 35 | ``` 36 | 37 | Download the software: 38 | 39 | ``` 40 | curl https://dl.google.com/go/go1.19.linux-amd64.tar.gz | sudo tar -C/usr/local -zxvf - 41 | ``` 42 | 43 | Update environment variables to include go (copy everything and paste) 44 | 45 | ``` 46 | cat <<'EOF' >>$HOME/.profile 47 | export GOROOT=/usr/local/go 48 | export GOPATH=$HOME/go 49 | export GO111MODULE=on 50 | export GOBIN=$HOME/go/bin 51 | export PATH=$PATH:/usr/local/go/bin:$GOBIN 52 | EOF 53 | source $HOME/.profile 54 | ``` 55 | 56 | To verify that Go is installed: 57 | 58 | ``` 59 | go version 60 | ``` 61 | 62 | Should return go version go1.19 linux/amd64 63 | 64 | ## Compile `dewebd` source code by yourself 65 | 66 | ### Download source code and compile 67 | 68 | ``` 69 | git clone https://github.com/deweb-services/deweb.git 70 | cd deweb 71 | git checkout v0.3.1 72 | make build #it build the binary in build/ folder 73 | ``` 74 | 75 | To know the version: 76 | 77 | ``` 78 | build/dewebd version 79 | ``` 80 | 81 | The output must be `0.3.1` 82 | 83 | Is the version match, now you have two options 84 | 85 | - Move the binary to the /usr/local/bin path with: `sudo mv build/dewebd /usr/local/bin/` 86 | - Compile and install the binary in the $GOPATH path: `make install` 87 | 88 | ## Join our Sirius Testnet 89 | 90 | Sirius testnet chainId: `deweb-testnet-sirius` 91 | 92 | - [Instructions](https://docs.deweb.services/fullnode/validator-setup) 93 | -------------------------------------------------------------------------------- /x/dns_module/types/owners.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "bytes" 5 | 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | ) 8 | 9 | // NewIDCollection creates a new IDCollection instance 10 | func NewIDCollection(denomID string, tokenIDs []string) IDCollection { 11 | return IDCollection{ 12 | DenomId: denomID, 13 | TokenIds: tokenIDs, 14 | } 15 | } 16 | 17 | // Supply return the amount of the denom 18 | func (idc IDCollection) Supply() int { 19 | return len(idc.TokenIds) 20 | } 21 | 22 | // AddID adds an tokenID to the idCollection 23 | func (idc IDCollection) AddID(tokenID string) IDCollection { 24 | idc.TokenIds = append(idc.TokenIds, tokenID) 25 | return idc 26 | } 27 | 28 | // ---------------------------------------------------------------------------- 29 | // IDCollections is an array of ID Collections 30 | type IDCollections []IDCollection 31 | 32 | // Add adds an ID to the idCollection 33 | func (idcs IDCollections) Add(denomID, tokenID string) IDCollections { 34 | for i, idc := range idcs { 35 | if idc.DenomId == denomID { 36 | idcs[i] = idc.AddID(tokenID) 37 | return idcs 38 | } 39 | } 40 | return append(idcs, IDCollection{ 41 | DenomId: denomID, 42 | TokenIds: []string{tokenID}, 43 | }) 44 | } 45 | 46 | // String follows stringer interface 47 | func (idcs IDCollections) String() string { 48 | if len(idcs) == 0 { 49 | return "" 50 | } 51 | 52 | var buf bytes.Buffer 53 | for _, idCollection := range idcs { 54 | if buf.Len() > 0 { 55 | buf.WriteString("\n") 56 | } 57 | buf.WriteString(idCollection.String()) 58 | } 59 | return buf.String() 60 | } 61 | 62 | // Owner of non fungible tokens 63 | //type Owner struct { 64 | // Address sdk.AccAddress `json:"address" yaml:"address"` 65 | // IDCollections IDCollections `json:"id_collections" yaml:"id_collections"` 66 | //} 67 | 68 | // NewOwner creates a new Owner 69 | func NewOwner(owner sdk.AccAddress, idCollections ...IDCollection) Owner { 70 | return Owner{ 71 | Address: owner.String(), 72 | IDCollections: idCollections, 73 | } 74 | } 75 | 76 | type Owners []Owner 77 | 78 | // NewOwner creates a new Owner 79 | func NewOwners(owner ...Owner) Owners { 80 | return append([]Owner{}, owner...) 81 | } 82 | 83 | // String follows stringer interface 84 | func (owners Owners) String() string { 85 | var buf bytes.Buffer 86 | for _, owner := range owners { 87 | if buf.Len() > 0 { 88 | buf.WriteString("\n") 89 | } 90 | buf.WriteString(owner.String()) 91 | } 92 | return buf.String() 93 | } 94 | -------------------------------------------------------------------------------- /x/dns_module/types/codec.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DONTCOVER 4 | 5 | import ( 6 | gogotypes "github.com/gogo/protobuf/types" 7 | 8 | "github.com/cosmos/cosmos-sdk/codec" 9 | "github.com/cosmos/cosmos-sdk/codec/types" 10 | cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | "github.com/cosmos/cosmos-sdk/types/msgservice" 13 | 14 | "github.com/deweb-services/deweb/x/dns_module/exported" 15 | ) 16 | 17 | var ( 18 | amino = codec.NewLegacyAmino() 19 | ModuleCdc = codec.NewAminoCodec(amino) 20 | ) 21 | 22 | func init() { 23 | RegisterLegacyAminoCodec(amino) 24 | cryptocodec.RegisterCrypto(amino) 25 | amino.Seal() 26 | } 27 | 28 | // RegisterLegacyAminoCodec concrete types on codec 29 | func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 30 | cdc.RegisterConcrete(&MsgTransferDomain{}, "deweb/dns/MsgTransferDomain", nil) 31 | cdc.RegisterConcrete(&MsgEditDomain{}, "deweb/dns/MsgEditDomain", nil) 32 | cdc.RegisterConcrete(&MsgRegisterDomain{}, "deweb/dns/MsgRegisterDomain", nil) 33 | cdc.RegisterConcrete(&MsgRemoveDomain{}, "deweb/dns/MsgRemoveDomain", nil) 34 | 35 | cdc.RegisterInterface((*exported.Domain)(nil), nil) 36 | cdc.RegisterConcrete(&BaseDomain{}, "deweb/dns/BaseNFT", nil) 37 | } 38 | 39 | func RegisterInterfaces(registry types.InterfaceRegistry) { 40 | registry.RegisterImplementations( 41 | (*sdk.Msg)(nil), 42 | &MsgTransferDomain{}, 43 | &MsgEditDomain{}, 44 | &MsgRegisterDomain{}, 45 | &MsgRemoveDomain{}, 46 | ) 47 | 48 | registry.RegisterImplementations( 49 | (*exported.Domain)(nil), 50 | &BaseDomain{}, 51 | ) 52 | 53 | msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) 54 | } 55 | 56 | // return supply protobuf code 57 | func MustMarshalSupply(cdc codec.Codec, supply uint64) []byte { 58 | supplyWrap := gogotypes.UInt64Value{Value: supply} 59 | return cdc.MustMarshal(&supplyWrap) 60 | } 61 | 62 | // return th supply 63 | func MustUnMarshalSupply(cdc codec.Codec, value []byte) uint64 { 64 | var supplyWrap gogotypes.UInt64Value 65 | cdc.MustUnmarshal(value, &supplyWrap) 66 | return supplyWrap.Value 67 | } 68 | 69 | // return the tokenID protobuf code 70 | func MustMarshalTokenID(cdc codec.Codec, tokenID string) []byte { 71 | tokenIDWrap := gogotypes.StringValue{Value: tokenID} 72 | return cdc.MustMarshal(&tokenIDWrap) 73 | } 74 | 75 | // return th tokenID 76 | func MustUnMarshalTokenID(cdc codec.Codec, value []byte) string { 77 | var tokenIDWrap gogotypes.StringValue 78 | cdc.MustUnmarshal(value, &tokenIDWrap) 79 | return tokenIDWrap.Value 80 | } 81 | -------------------------------------------------------------------------------- /x/deweb/keeper/msg_server_connect_chain.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/cosmos/cosmos-sdk/store/prefix" 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | "github.com/deweb-services/deweb/x/deweb/types" 9 | "strings" 10 | ) 11 | 12 | func (k msgServer) ConnectChain(goCtx context.Context, msg *types.MsgConnectChain) (*types.MsgConnectChainResponse, error) { 13 | ctx := sdk.UnwrapSDKContext(goCtx) 14 | 15 | externalAddress := msg.GetAddress() 16 | externalChain := msg.GetChain() 17 | creator := msg.GetCreator() 18 | 19 | itemToStore := types.ChainAddressMapping{ 20 | ExtAddress: externalAddress, 21 | Chain: externalChain, 22 | } 23 | 24 | idVal := creator + "_" + externalChain + "_" + externalAddress 25 | mappingWriteError := k.writeChainMappingRecord(ctx, itemToStore, idVal) 26 | if mappingWriteError != nil { 27 | return nil, fmt.Errorf("error writing message to store: %w", mappingWriteError) 28 | } 29 | 30 | toUserErr := k.appendMappingRecordToUser(ctx, creator, idVal) 31 | if toUserErr != nil { 32 | return nil, fmt.Errorf("error adding created record to user") 33 | } 34 | 35 | return &types.MsgConnectChainResponse{}, nil 36 | } 37 | 38 | func (k msgServer) writeChainMappingRecord(ctx sdk.Context, mappingRec types.ChainAddressMapping, idVal string) error { 39 | store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.ConnectChainRecords)) 40 | 41 | recordValue, err := k.cdc.Marshal(&mappingRec) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | store.Set([]byte(idVal), recordValue) 47 | return nil 48 | } 49 | 50 | func (k msgServer) appendMappingRecordToUser(ctx sdk.Context, address string, recordID string) error { 51 | k.Logger(ctx).Error(fmt.Sprintf("[appendUserRecordID] Process")) 52 | 53 | existRecords, err := k.getChainMappingRecordsIDs(ctx, address) 54 | if err != nil { 55 | return err 56 | } 57 | if existRecords == nil { 58 | existRecords = make([]string, 0, 1) 59 | } 60 | for _, recID := range existRecords { 61 | if recID == recordID { 62 | return nil 63 | } 64 | } 65 | existRecords = append(existRecords, recordID) 66 | k.Logger(ctx).Error(fmt.Sprintf("[appendUserRecordID] user records: %s", strings.Join(existRecords, ","))) 67 | store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.UserConnectChainRecords)) 68 | 69 | resRecords := types.RecordsToUser{Records: existRecords} 70 | recordValue, err := k.cdc.Marshal(&resRecords) 71 | if err != nil { 72 | return err 73 | } 74 | recKey := []byte(address) 75 | store.Set(recKey, recordValue) 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /proto/deweb/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.deweb.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "cosmos/base/query/v1beta1/pagination.proto"; 7 | import "deweb/params.proto"; 8 | // this line is used by starport scaffolding # 1 9 | 10 | option go_package = "github.com/deweb-services/deweb/x/deweb/types"; 11 | 12 | // Query defines the gRPC querier service. 13 | service Query { 14 | // Parameters queries the parameters of the module. 15 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 16 | option (google.api.http).get = "/dewebservices/deweb/deweb/params"; 17 | } 18 | rpc FilterUserWalletRecords(QueryFilterUserWalletRecordsRequest) returns (QueryFilterUserWalletRecordsResponse) { 19 | option (google.api.http).get = "/deweb/external_wallets/v1beta1/list"; 20 | } 21 | // Queries a list of FilterChainMappingsRecords items. 22 | rpc FilterChainMappingsRecords(QueryFilterChainMappingsRecordsRequest) returns (QueryFilterChainMappingsRecordsResponse) { 23 | option (google.api.http).get = "/deweb/filter_chain_mappings_records/v1beta1/list"; 24 | } 25 | 26 | // this line is used by starport scaffolding # 2 27 | } 28 | 29 | // QueryParamsRequest is request type for the Query/Params RPC method. 30 | message QueryParamsRequest {} 31 | 32 | // QueryParamsResponse is response type for the Query/Params RPC method. 33 | message QueryParamsResponse { 34 | // params holds all the parameters of this module. 35 | Params params = 1 [(gogoproto.nullable) = false]; 36 | } 37 | 38 | message WalletRecordResponse { 39 | string owner = 1; 40 | string address = 2; 41 | string encrypted_key = 3; 42 | string chain = 4; 43 | bool deleted = 5; 44 | } 45 | 46 | message QueryFilterUserWalletRecordsRequest { 47 | string owner = 1; 48 | string address = 2; 49 | string chain = 3; 50 | bool deleted = 4; 51 | int32 limit = 5; 52 | int32 offset = 6; 53 | } 54 | 55 | message QueryFilterUserWalletRecordsResponse { 56 | repeated WalletRecordResponse records = 1; 57 | } 58 | 59 | message ChainMappingRecordResponse { 60 | string owner = 1; 61 | string ext_address = 2; 62 | string chain = 3; 63 | bool deleted = 4; 64 | } 65 | 66 | message QueryFilterChainMappingsRecordsRequest { 67 | string owner = 1; 68 | string address = 2; 69 | string chain = 3; 70 | bool deleted = 4; 71 | int32 limit = 5; 72 | int32 offset = 6; 73 | } 74 | 75 | message QueryFilterChainMappingsRecordsResponse { 76 | repeated ChainMappingRecordResponse records = 1; 77 | } 78 | 79 | // this line is used by starport scaffolding # 3 80 | -------------------------------------------------------------------------------- /x/dns_server/dnsserver.go: -------------------------------------------------------------------------------- 1 | package dns_server 2 | 3 | import ( 4 | "fmt" 5 | "github.com/cosmos/cosmos-sdk/client" 6 | "github.com/deweb-services/deweb/x/dns_module/types" 7 | "github.com/miekg/dns" 8 | "net" 9 | "os" 10 | "regexp" 11 | "strings" 12 | "time" 13 | ) 14 | 15 | type CacheRecord struct { 16 | Values []*types.DNSRecords 17 | CreateTime time.Time 18 | } 19 | 20 | type DNSResolverService struct { 21 | cliCtx client.Context 22 | proxyDNSServer string 23 | cachedRecords map[string]CacheRecord 24 | } 25 | 26 | func NewDNSResolverService(cliCtx client.Context, proxyServer string) *DNSResolverService { 27 | if len(proxyServer) == 0 { 28 | proxyServer = "1.1.1.1:53" 29 | } 30 | return &DNSResolverService{ 31 | cliCtx: cliCtx, 32 | proxyDNSServer: proxyServer, 33 | cachedRecords: make(map[string]CacheRecord), 34 | } 35 | } 36 | 37 | func (srv *DNSResolverService) RunServer(port int) { 38 | serverAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", port)) 39 | 40 | if err != nil { 41 | fmt.Println("Error resolving UDP address: ", err.Error()) 42 | os.Exit(1) 43 | } 44 | 45 | dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) { 46 | switch r.Opcode { 47 | case dns.OpcodeQuery: 48 | qStrings := make([]string, 0, len(r.Question)) 49 | for _, q := range r.Question { 50 | qStr := strings.ReplaceAll(q.String(), "\t", " | ") 51 | qStrings = append(qStrings, qStr) 52 | } 53 | 54 | m, err := srv.getResponse(r) 55 | if err != nil { 56 | logStr := fmt.Sprintf("Failed lookup for [%s] with error: %s\n", strings.Join(qStrings, ";"), err.Error()) 57 | fmt.Printf(logStr) 58 | m.SetReply(r) 59 | w.WriteMsg(m) 60 | return 61 | } 62 | ipPattern := regexp.MustCompile(`(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}`) 63 | for _, answer := range m.Answer { 64 | ipAddress := ipPattern.FindAllString(m.Answer[0].String(), -1) 65 | if len(ipAddress) > 0 { 66 | fmt.Printf("Lookup for [%s] answer for %s with ip %s\n", strings.Join(qStrings, ";"), answer.Header().Name, ipAddress[0]) 67 | } else { 68 | fmt.Printf("Lookup for [%s] answer %s with response %s\n", strings.Join(qStrings, ";"), answer.Header().Name, answer.String()) 69 | } 70 | } 71 | m.SetReply(r) 72 | w.WriteMsg(m) 73 | } 74 | }) 75 | 76 | server := &dns.Server{Addr: serverAddr.String(), Net: "udp"} 77 | fmt.Printf("Starting at %s\n", serverAddr.String()) 78 | err = server.ListenAndServe() 79 | if err != nil { 80 | fmt.Printf("Failed to start server: %s\n ", err.Error()) 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /x/dns_module/keeper/domain.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | 7 | "github.com/deweb-services/deweb/x/dns_module/exported" 8 | "github.com/deweb-services/deweb/x/dns_module/types" 9 | ) 10 | 11 | // GetDomain gets the the specified Domain 12 | func (k Keeper) GetDomain(ctx sdk.Context, tokenID string) (nft exported.Domain, err error) { 13 | store := ctx.KVStore(k.storeKey) 14 | recKey := types.KeyDomain(k.dnsDenomName, tokenID) 15 | bz := store.Get(recKey) 16 | if bz == nil { 17 | return nil, sdkerrors.Wrapf(types.ErrUnknownDomain, "not found Domain: %s", tokenID) 18 | } 19 | 20 | var baseDomain types.BaseDomain 21 | k.cdc.MustUnmarshal(bz, &baseDomain) 22 | 23 | return baseDomain, nil 24 | } 25 | 26 | // GetDomains returns all Domains by the specified denom ID 27 | func (k Keeper) GetDomains(ctx sdk.Context, denom string) (nfts []exported.Domain) { 28 | store := ctx.KVStore(k.storeKey) 29 | 30 | iterator := sdk.KVStorePrefixIterator(store, types.KeyDomain(denom, "")) 31 | defer iterator.Close() 32 | for ; iterator.Valid(); iterator.Next() { 33 | var baseDomain types.BaseDomain 34 | k.cdc.MustUnmarshal(iterator.Value(), &baseDomain) 35 | nfts = append(nfts, baseDomain) 36 | } 37 | 38 | return nfts 39 | } 40 | 41 | // Authorize checks if the sender is the owner of the given Domain 42 | // Return the Domain if true, an error otherwise 43 | func (k Keeper) Authorize(ctx sdk.Context, tokenID string, owner sdk.AccAddress) (types.BaseDomain, error) { 44 | domain, err := k.GetDomain(ctx, tokenID) 45 | if err != nil { 46 | return types.BaseDomain{}, err 47 | } 48 | 49 | if !owner.Equals(domain.GetOwner()) { 50 | return types.BaseDomain{}, sdkerrors.Wrap(types.ErrUnauthorized, owner.String()) 51 | } 52 | 53 | return domain.(types.BaseDomain), nil 54 | } 55 | 56 | // HasDomain checks if the specified Domain exists 57 | func (k Keeper) HasDomain(ctx sdk.Context, denomID, tokenID string) bool { 58 | store := ctx.KVStore(k.storeKey) 59 | return store.Has(types.KeyDomain(denomID, tokenID)) 60 | } 61 | 62 | func (k Keeper) registerDomain(ctx sdk.Context, domain types.BaseDomain) { 63 | store := ctx.KVStore(k.storeKey) 64 | 65 | bz := k.cdc.MustMarshal(&domain) 66 | recKey := types.KeyDomain(k.dnsDenomName, domain.GetID()) 67 | store.Set(recKey, bz) 68 | } 69 | 70 | // deleteNFT deletes an existing Domain from store 71 | func (k Keeper) deleteNFT(ctx sdk.Context, denomID string, nft exported.Domain) { 72 | store := ctx.KVStore(k.storeKey) 73 | store.Delete(types.KeyDomain(denomID, nft.GetID())) 74 | } 75 | -------------------------------------------------------------------------------- /x/dns_module/client/cli/flags.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | flag "github.com/spf13/pflag" 5 | ) 6 | 7 | const ( 8 | FlagTokenName = "name" 9 | FlagTokenPrice = "price" 10 | FlagURI = "uri" 11 | FlagURIHash = "uri-hash" 12 | FlagDescription = "description" 13 | FlagRecipient = "recipient" 14 | FlagOwner = "owner" 15 | FlagData = "data" 16 | FlagCancel = "cancel" 17 | 18 | FlagDenomName = "name" 19 | FlagDenomID = "denom-id" 20 | FlagSchema = "schema" 21 | FlagSymbol = "symbol" 22 | FlagMintRestricted = "mint-restricted" 23 | FlagUpdateRestricted = "update-restricted" 24 | ) 25 | 26 | var ( 27 | FsIssueDenom = flag.NewFlagSet("", flag.ContinueOnError) 28 | FsRegisterDomain = flag.NewFlagSet("", flag.ContinueOnError) 29 | FsEditDomain = flag.NewFlagSet("", flag.ContinueOnError) 30 | FsTransferDomain = flag.NewFlagSet("", flag.ContinueOnError) 31 | FsQuerySupply = flag.NewFlagSet("", flag.ContinueOnError) 32 | FsQueryOwner = flag.NewFlagSet("", flag.ContinueOnError) 33 | ) 34 | 35 | func init() { 36 | FsIssueDenom.String(FlagSchema, "", "Denom data structure definition") 37 | FsIssueDenom.String(FlagURI, "", "The uri for the class metadata stored off chain. It can define schema for Class and NFT `Data` attributes. Optional") 38 | FsIssueDenom.String(FlagURIHash, "", "The uri-hash is a hash of the document pointed by uri. Optional") 39 | FsIssueDenom.String(FlagDescription, "", "The description is a brief description of nft classification. Optional") 40 | FsIssueDenom.String(FlagDenomName, "", "The name of the denom") 41 | FsIssueDenom.String(FlagSymbol, "", "The symbol of the denom") 42 | FsIssueDenom.String(FlagData, "", "The data is the app specific metadata of the NFT class. Optional") 43 | FsIssueDenom.Bool(FlagMintRestricted, false, "mint restricted of nft under denom") 44 | FsIssueDenom.Bool(FlagUpdateRestricted, false, "update restricted of nft under denom") 45 | 46 | FsRegisterDomain.String(FlagRecipient, "", "The receiver of the nft, if not filled, the default is the sender of the transaction") 47 | FsRegisterDomain.String(FlagData, "", "The origin data of the nft") 48 | 49 | FsEditDomain.String(FlagData, "[do-not-modify]", "The DNS record of domain") 50 | 51 | FsTransferDomain.String(FlagRecipient, "", "Domain NFT recipient") 52 | FsTransferDomain.String(FlagTokenPrice, "0", "Price for NFT in uDWS") 53 | FsTransferDomain.String(FlagCancel, "false", "Cancel created transfer for domain") 54 | 55 | FsQuerySupply.String(FlagOwner, "", "The owner of the nft") 56 | 57 | FsQueryOwner.String(FlagDenomID, "", "The name of the collection") 58 | } 59 | -------------------------------------------------------------------------------- /x/dns_module/keeper/ownership_rules.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "fmt" 5 | "github.com/cosmos/cosmos-sdk/types" 6 | "github.com/cosmos/cosmos-sdk/types/errors" 7 | "github.com/deweb-services/deweb/x/dns_module/exported" 8 | "strings" 9 | ) 10 | 11 | type DomainAlreadyCreated struct { 12 | domainName string 13 | } 14 | 15 | func (e DomainAlreadyCreated) Error() string { 16 | return fmt.Sprintf("domain %s already created", e.domainName) 17 | } 18 | 19 | type DomainNotOwned struct { 20 | domainName string 21 | } 22 | 23 | func (e DomainNotOwned) Error() string { 24 | return fmt.Sprintf("domain %s does not belong to this user", e.domainName) 25 | } 26 | 27 | type DomainDoesntExist struct { 28 | domainName string 29 | } 30 | 31 | func (e DomainDoesntExist) Error() string { 32 | return fmt.Sprintf("domain %s was not registered", e.domainName) 33 | } 34 | 35 | func (k Keeper) CheckDomainBlocked(ctx types.Context, domain string) bool { 36 | upperDomain := strings.ToUpper(domain) 37 | blockedDomains := k.BlockedTLDs(ctx) 38 | for _, blockedLD := range blockedDomains { 39 | if blockedLD == upperDomain { 40 | return true 41 | } 42 | } 43 | return false 44 | } 45 | 46 | func (k Keeper) CheckAllowedForAddress(ctx types.Context, dnsName string, creatorAddress types.AccAddress) error { 47 | domainParts := strings.Split(dnsName, ".") 48 | if len(domainParts) == 1 { 49 | _, err := k.GetDomain(ctx, domainParts[0]) 50 | if err == nil { 51 | return DomainAlreadyCreated{domainName: domainParts[0]} 52 | } 53 | return nil 54 | } 55 | parentDomainOwner, err := k.getParentDomainOwner(ctx, dnsName) 56 | if err != nil { 57 | return errors.Wrap(err, "cannot get parent domain") 58 | } 59 | if !parentDomainOwner.Equals(creatorAddress) { 60 | return &DomainNotOwned{domainName: dnsName} 61 | } 62 | return nil 63 | } 64 | 65 | func (k Keeper) getParentDomainOwner(ctx types.Context, dnsName string) (types.AccAddress, error) { 66 | domainRec, err := k.getParentDomain(ctx, dnsName) 67 | if err != nil { 68 | return nil, err 69 | } 70 | return domainRec.GetOwner(), nil 71 | } 72 | 73 | func (k Keeper) getParentDomain(ctx types.Context, dnsName string) (exported.Domain, error) { 74 | domainParts := strings.Split(dnsName, ".") 75 | if len(domainParts) == 1 { 76 | domainRec, err := k.GetDomain(ctx, domainParts[0]) 77 | if err != nil { 78 | return nil, &DomainDoesntExist{domainName: domainParts[0]} 79 | } 80 | return domainRec, nil 81 | } 82 | parentDomainParts := domainParts[1:] 83 | parentDomain := strings.Join(parentDomainParts, ".") 84 | domainRec, err := k.GetDomain(ctx, parentDomain) 85 | if err != nil { 86 | return nil, &DomainDoesntExist{domainName: dnsName} 87 | } 88 | return domainRec, nil 89 | } 90 | -------------------------------------------------------------------------------- /x/deweb/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "fmt" 5 | "github.com/cosmos/cosmos-sdk/store/prefix" 6 | sdk "github.com/cosmos/cosmos-sdk/types" 7 | "github.com/deweb-services/deweb/x/deweb/types" 8 | ) 9 | 10 | var _ types.QueryServer = Keeper{} 11 | 12 | func (k Keeper) getUserKeyRecord(ctx sdk.Context, recordID string) (userRecord types.UserWalletRec, err error) { 13 | store := ctx.KVStore(k.storeKey) 14 | postStore := prefix.NewStore(store, []byte(types.RecordsKey)) 15 | postKey := []byte(recordID) 16 | value := postStore.Get(postKey) 17 | if value == nil { 18 | return userRecord, fmt.Errorf("record not found") 19 | } 20 | 21 | err = k.cdc.Unmarshal(value, &userRecord) 22 | return 23 | } 24 | 25 | func (k Keeper) getUserRecordsIDs(ctx sdk.Context, address string) ([]string, error) { 26 | k.Logger(ctx).Error(fmt.Sprintf("[getUserRecordsIDs] Process")) 27 | 28 | // Get the key-value module store using the store key (in our case store key is "chain") 29 | records, err := k.readUserMappings(ctx, types.UsersRecords, address) 30 | 31 | return records, err 32 | } 33 | 34 | func (k Keeper) getChainMappingRecord(ctx sdk.Context, recordID string) (userRecord types.ChainAddressMapping, err error) { 35 | store := ctx.KVStore(k.storeKey) 36 | postStore := prefix.NewStore(store, []byte(types.ConnectChainRecords)) 37 | postKey := []byte(recordID) 38 | value := postStore.Get(postKey) 39 | if value == nil { 40 | return userRecord, fmt.Errorf("record not found") 41 | } 42 | 43 | err = k.cdc.Unmarshal(value, &userRecord) 44 | return 45 | } 46 | 47 | func (k Keeper) getChainMappingRecordsIDs(ctx sdk.Context, address string) ([]string, error) { 48 | k.Logger(ctx).Error(fmt.Sprintf("[getChainMappingRecordsIDs] Process")) 49 | 50 | // Get the key-value module store using the store key (in our case store key is "chain") 51 | records, err := k.readUserMappings(ctx, types.UserConnectChainRecords, address) 52 | 53 | return records, err 54 | } 55 | 56 | // readUserMappings - retrieve address-to-ids mappings from storage 57 | func (k Keeper) readUserMappings(ctx sdk.Context, storePrefix string, address string) ([]string, error) { 58 | // Get the key-value module store using the store key (in our case store key is "chain") 59 | store := ctx.KVStore(k.storeKey) 60 | // Get the part of the store that keeps posts (using post key, which is "Post-value-") 61 | storedRecordsMapStore := prefix.NewStore(store, []byte(storePrefix)) 62 | recKey := []byte(address) 63 | value := storedRecordsMapStore.Get(recKey) 64 | if value == nil { 65 | return nil, nil 66 | } 67 | var storedRecordsIDs types.RecordsToUser 68 | if err := k.cdc.Unmarshal(value, &storedRecordsIDs); err != nil { 69 | return nil, err 70 | } 71 | return storedRecordsIDs.Records, nil 72 | } 73 | -------------------------------------------------------------------------------- /proto/dns_module/query.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package dewebservices.domain.v1beta1; 3 | 4 | import "gogoproto/gogo.proto"; 5 | import "google/api/annotations.proto"; 6 | import "dns_module/domain.proto"; 7 | import "dns_module/params.proto"; 8 | 9 | option go_package = "github.com/deweb-services/deweb/x/dns_module/types"; 10 | 11 | // Query defines the gRPC querier service for NFT module 12 | service Query { 13 | // Parameters queries the parameters of the module. 14 | rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { 15 | option (google.api.http).get = "/deweb/domains/v1beta1/params"; 16 | } 17 | 18 | // Query domain info by domain name 19 | rpc Domain(QueryDomainRequest) returns (QueryDomainResponse) { 20 | option (google.api.http).get = "/deweb/domains/v1beta1/domain/{domain_name}"; 21 | } 22 | // Query domains owned by user 23 | rpc OwnedDomains(QueryOwnedDomainsRequest) returns (QueryOwnedDomainsResponse) { 24 | option (google.api.http).get = "/deweb/domains/v1beta1/address/{address}"; 25 | } 26 | } 27 | 28 | message TransferOffer { 29 | uint64 price = 1; 30 | string ExpectedOwnerAddress = 2; 31 | } 32 | 33 | message DNSRecords { 34 | string type = 1; 35 | repeated string values = 2; 36 | } 37 | 38 | message ResponseDomain { 39 | option (gogoproto.equal) = true; 40 | 41 | string id = 1; 42 | string issued = 2; 43 | string validTill = 3; 44 | TransferOffer transfer_offer = 4; 45 | repeated DNSRecords records = 5; 46 | bool subDomainsOnSale = 6; 47 | uint64 subDomainsSalePrice = 7; 48 | string owner = 8; 49 | } 50 | 51 | // QueryParamsRequest is request type for the Query/Params RPC method. 52 | message QueryParamsRequest {} 53 | 54 | // QueryParamsResponse is response type for the Query/Params RPC method. 55 | message QueryParamsResponse { 56 | // params holds all the parameters of this module. 57 | Params params = 1 [(gogoproto.nullable) = false]; 58 | } 59 | 60 | // QueryNFTRequest is the request type for the Query/NFT RPC method 61 | message QueryDomainRequest { 62 | string domain_name = 1 [ (gogoproto.moretags) = "yaml:\"domain_name\"" ]; 63 | } 64 | 65 | // QueryNFTResponse is the response type for the Query/NFT RPC method 66 | message QueryDomainResponse { 67 | ResponseDomain domain = 1 [ (gogoproto.customname) = "Domain" ]; 68 | } 69 | 70 | // QueryNFTRequest is the request type for the Query/NFT RPC method 71 | message QueryOwnedDomainsRequest { 72 | string address = 1; 73 | int64 offset = 2; 74 | int64 count = 3; 75 | } 76 | 77 | // QueryNFTResponse is the response type for the Query/NFT RPC method 78 | message QueryOwnedDomainsResponse { 79 | int64 total = 1; 80 | repeated ResponseDomain domains = 2 [ (gogoproto.customname) = "Domains" ]; 81 | } -------------------------------------------------------------------------------- /x/deweb/keeper/msg_server_save_wallet.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/cosmos/cosmos-sdk/store/prefix" 7 | "strings" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | "github.com/deweb-services/deweb/x/deweb/types" 11 | ) 12 | 13 | const MaxMessageLength = 1000 14 | 15 | func (k msgServer) SaveWallet(goCtx context.Context, msg *types.MsgSaveWallet) (*types.MsgSaveWalletResponse, error) { 16 | ctx := sdk.UnwrapSDKContext(goCtx) 17 | encryptedKey := msg.GetEncryptedKey() 18 | if len(encryptedKey) > MaxMessageLength { 19 | return nil, fmt.Errorf("received mesage greater then maximum lengtx %d", MaxMessageLength) 20 | } 21 | creator := msg.GetCreator() 22 | if msg.Chain == "" { 23 | // Maybe create a list of allowed chains 24 | return nil, fmt.Errorf("parameter chain required") 25 | } 26 | userRec := types.UserWalletRec{ 27 | Address: msg.Address, 28 | EncryptedKey: encryptedKey, 29 | Chain: msg.Chain, 30 | } 31 | recordID := creator + "_" + userRec.Address 32 | err := k.writeUserKeyRecord(ctx, userRec, recordID) 33 | if err != nil { 34 | return nil, fmt.Errorf("error writing message to store: %w", err) 35 | } 36 | err = k.appendUserRecordID(ctx, creator, recordID) 37 | if err != nil { 38 | return nil, fmt.Errorf("error appending created record to user records list: %w", err) 39 | } 40 | k.Logger(ctx).Error(fmt.Sprintf("[SaveWallet] Saved encrypted key with id: %s: %s", recordID, encryptedKey)) 41 | // Update the post count 42 | return &types.MsgSaveWalletResponse{}, nil 43 | } 44 | 45 | func (k msgServer) writeUserKeyRecord(ctx sdk.Context, userRec types.UserWalletRec, idVal string) error { 46 | store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.RecordsKey)) 47 | 48 | recordValue, err := k.cdc.Marshal(&userRec) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | store.Set([]byte(idVal), recordValue) 54 | return nil 55 | } 56 | 57 | func (k msgServer) appendUserRecordID(ctx sdk.Context, address string, recordID string) error { 58 | k.Logger(ctx).Error(fmt.Sprintf("[appendUserRecordID] Process")) 59 | 60 | existRecords, err := k.getUserRecordsIDs(ctx, address) 61 | if err != nil { 62 | return err 63 | } 64 | if existRecords == nil { 65 | existRecords = make([]string, 0, 1) 66 | } 67 | for _, recID := range existRecords { 68 | if recID == recordID { 69 | return nil 70 | } 71 | } 72 | existRecords = append(existRecords, recordID) 73 | k.Logger(ctx).Error(fmt.Sprintf("[appendUserRecordID] user records: %s", strings.Join(existRecords, ","))) 74 | store := prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.UsersRecords)) 75 | 76 | resRecords := types.RecordsToUser{Records: existRecords} 77 | recordValue, err := k.cdc.Marshal(&resRecords) 78 | if err != nil { 79 | return err 80 | } 81 | recKey := []byte(address) 82 | store.Set(recKey, recordValue) 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /x/dns_module/keeper/msg_server.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | sdk "github.com/cosmos/cosmos-sdk/types" 6 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 7 | "github.com/deweb-services/deweb/x/dns_module/types" 8 | ) 9 | 10 | type msgServer struct { 11 | Keeper 12 | dnsDenomName string 13 | } 14 | 15 | var _ types.MsgServer = msgServer{} 16 | 17 | // NewMsgServerImpl returns an implementation of the NFT MsgServer interface 18 | // for the provided Keeper. 19 | func NewMsgServerImpl(keeper Keeper) types.MsgServer { 20 | return &msgServer{ 21 | Keeper: keeper, 22 | dnsDenomName: DNSDenomName, 23 | } 24 | } 25 | 26 | func (m msgServer) RegisterDomain(goCtx context.Context, msg *types.MsgRegisterDomain) (*types.MsgRegisterDomainResponse, error) { 27 | recipient, err := sdk.AccAddressFromBech32(msg.Recipient) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | sender, err := sdk.AccAddressFromBech32(msg.Sender) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | ctx := sdk.UnwrapSDKContext(goCtx) 38 | 39 | if err := m.Keeper.RegisterDomain(ctx, msg.Id, msg.Data, sender, recipient); err != nil { 40 | return nil, err 41 | } 42 | 43 | return &types.MsgRegisterDomainResponse{}, nil 44 | } 45 | 46 | func (m msgServer) EditDomain(goCtx context.Context, msg *types.MsgEditDomain) (*types.MsgEditdomainResponse, error) { 47 | sender, err := sdk.AccAddressFromBech32(msg.Sender) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | _, err = ParseDomainData([]byte(msg.Data)) 53 | if err != nil { 54 | return nil, sdkerrors.Wrapf(sdkerrors.ErrJSONUnmarshal, "invalid data") 55 | } 56 | 57 | ctx := sdk.UnwrapSDKContext(goCtx) 58 | if err := m.Keeper.EditDomain(ctx, msg.Id, msg.Data, sender); err != nil { 59 | return nil, err 60 | } 61 | 62 | return &types.MsgEditdomainResponse{}, nil 63 | } 64 | 65 | func (m msgServer) TransferDomain(goCtx context.Context, msg *types.MsgTransferDomain) (*types.MsgTransferDomainResponse, error) { 66 | sender, err := sdk.AccAddressFromBech32(msg.Sender) 67 | if err != nil { 68 | return nil, err 69 | } 70 | 71 | if len(msg.Recipient) > 0 { 72 | _, err = sdk.AccAddressFromBech32(msg.Recipient) 73 | if err != nil { 74 | return nil, err 75 | } 76 | } 77 | 78 | ctx := sdk.UnwrapSDKContext(goCtx) 79 | if err := m.Keeper.TransferDomainOwner(ctx, msg.Id, msg.Cancel, msg.Price, sender, msg.Recipient); err != nil { 80 | return nil, err 81 | } 82 | 83 | return &types.MsgTransferDomainResponse{}, nil 84 | } 85 | 86 | func (m msgServer) RemoveDomain(goCtx context.Context, msg *types.MsgRemoveDomain) (*types.MsgRemoveDomainResponse, error) { 87 | sender, err := sdk.AccAddressFromBech32(msg.Sender) 88 | if err != nil { 89 | return nil, err 90 | } 91 | 92 | ctx := sdk.UnwrapSDKContext(goCtx) 93 | if err := m.Keeper.RemoveDomain(ctx, msg.Id, sender); err != nil { 94 | return nil, err 95 | } 96 | 97 | return &types.MsgRemoveDomainResponse{}, nil 98 | } 99 | -------------------------------------------------------------------------------- /testutil/network/network.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | 8 | "github.com/cosmos/cosmos-sdk/baseapp" 9 | "github.com/cosmos/cosmos-sdk/crypto/hd" 10 | "github.com/cosmos/cosmos-sdk/crypto/keyring" 11 | servertypes "github.com/cosmos/cosmos-sdk/server/types" 12 | "github.com/cosmos/cosmos-sdk/simapp" 13 | storetypes "github.com/cosmos/cosmos-sdk/store/types" 14 | "github.com/cosmos/cosmos-sdk/testutil/network" 15 | sdk "github.com/cosmos/cosmos-sdk/types" 16 | authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 17 | "github.com/tendermint/starport/starport/pkg/cosmoscmd" 18 | tmrand "github.com/tendermint/tendermint/libs/rand" 19 | tmdb "github.com/tendermint/tm-db" 20 | 21 | "github.com/deweb-services/deweb/app" 22 | ) 23 | 24 | type ( 25 | Network = network.Network 26 | Config = network.Config 27 | ) 28 | 29 | // New creates instance with fully configured cosmos network. 30 | // Accepts optional config, that will be used in place of the DefaultConfig() if provided. 31 | func New(t *testing.T, configs ...network.Config) *network.Network { 32 | if len(configs) > 1 { 33 | panic("at most one config should be provided") 34 | } 35 | var cfg network.Config 36 | if len(configs) == 0 { 37 | cfg = DefaultConfig() 38 | } else { 39 | cfg = configs[0] 40 | } 41 | net := network.New(t, cfg) 42 | t.Cleanup(net.Cleanup) 43 | return net 44 | } 45 | 46 | // DefaultConfig will initialize config for the network with custom application, 47 | // genesis and single validator. All other parameters are inherited from cosmos-sdk/testutil/network.DefaultConfig 48 | func DefaultConfig() network.Config { 49 | encoding := cosmoscmd.MakeEncodingConfig(app.ModuleBasics) 50 | return network.Config{ 51 | Codec: encoding.Marshaler, 52 | TxConfig: encoding.TxConfig, 53 | LegacyAmino: encoding.Amino, 54 | InterfaceRegistry: encoding.InterfaceRegistry, 55 | AccountRetriever: authtypes.AccountRetriever{}, 56 | AppConstructor: func(val network.Validator) servertypes.Application { 57 | return app.New( 58 | val.Ctx.Logger, tmdb.NewMemDB(), nil, true, map[int64]bool{}, val.Ctx.Config.RootDir, 0, 59 | encoding, 60 | simapp.EmptyAppOptions{}, 61 | baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), 62 | baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), 63 | ) 64 | }, 65 | GenesisState: app.ModuleBasics.DefaultGenesis(encoding.Marshaler), 66 | TimeoutCommit: 2 * time.Second, 67 | ChainID: "chain-" + tmrand.NewRand().Str(6), 68 | NumValidators: 1, 69 | BondDenom: sdk.DefaultBondDenom, 70 | MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), 71 | AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction), 72 | StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction), 73 | BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), 74 | PruningStrategy: storetypes.PruningOptionNothing, 75 | CleanupDir: true, 76 | SigningAlgo: string(hd.Secp256k1Type), 77 | KeyringOptions: []keyring.Option{}, 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /x/dns_module/types/validation.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strings" 7 | 8 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 9 | ) 10 | 11 | const ( 12 | DoNotModify = "[do-not-modify]" 13 | MinDenomLen = 3 14 | MaxDenomLen = 128 15 | MinDomainLen = 1 16 | MaxDomainLen = 255 17 | MaxDomainPartLen = 63 18 | 19 | MaxTokenURILen = 256 20 | 21 | ReservedPeg = "peg" 22 | ReservedIBC = "ibc" 23 | ReservedHTLT = "htlt" 24 | ReservedTIBC = "tibc" 25 | ) 26 | 27 | var ( 28 | // IsAlphaNumeric only accepts [a-z0-9] 29 | IsAlphaNumeric = regexp.MustCompile(`^[a-z0-9]+$`).MatchString 30 | // IsDomainValidChars only accepts [a-z0-9\.] 31 | IsDomainValidChars = regexp.MustCompile(`^[a-z0-9\.-]+$`).MatchString 32 | // IsBeginWithAlpha only begin with [a-z] 33 | IsBeginWithAlpha = regexp.MustCompile(`^[a-z].*`).MatchString 34 | 35 | keywords = strings.Join([]string{ReservedPeg, ReservedIBC, ReservedHTLT, ReservedTIBC}, "|") 36 | regexpKeywordsFmt = fmt.Sprintf("^(%s).*", keywords) 37 | regexpKeyword = regexp.MustCompile(regexpKeywordsFmt).MatchString 38 | ) 39 | 40 | // ValidateDenomID verifies whether the parameters are legal 41 | func ValidateDenomID(denomID string) error { 42 | if len(denomID) < MinDenomLen || len(denomID) > MaxDenomLen { 43 | return sdkerrors.Wrapf(ErrInvalidDenom, "the length of denom(%s) only accepts value [%d, %d]", denomID, MinDenomLen, MaxDenomLen) 44 | } 45 | boolPrifix := strings.HasPrefix(denomID, "tibc-") 46 | if !IsBeginWithAlpha(denomID) || !IsAlphaNumeric(denomID) && !boolPrifix { 47 | return sdkerrors.Wrapf(ErrInvalidDenom, "the denom(%s) only accepts alphanumeric characters, and begin with an english letter", denomID) 48 | } 49 | return nil 50 | } 51 | 52 | // ValidateTokenID verify that the tokenID is legal 53 | func ValidateTokenID(tokenID string) error { 54 | if len(tokenID) < MinDomainLen || len(tokenID) > MaxDomainLen { 55 | return sdkerrors.Wrapf(ErrInvalidTokenID, "the length of domain name (%s) only accepts value [%d, %d]", tokenID, MinDomainLen, MaxDomainLen) 56 | } 57 | if !IsBeginWithAlpha(tokenID) || !IsDomainValidChars(tokenID) { 58 | return sdkerrors.Wrapf(ErrInvalidTokenID, "nft domain name (%s) only accepts alphanumeric characters, dots, dashes, and begin with an english letter", tokenID) 59 | } 60 | domainParts := strings.Split(tokenID, ".") 61 | for _, partVal := range domainParts { 62 | if len(partVal) < MinDomainLen || len(partVal) > MaxDomainPartLen { 63 | return sdkerrors.Wrapf(ErrInvalidTokenID, "the length of domain part (%s) only accepts value [%d, %d]", partVal, MinDomainLen, MaxDomainPartLen) 64 | } 65 | } 66 | return nil 67 | } 68 | 69 | // Modified returns whether the field is modified 70 | func Modified(target string) bool { 71 | return target != DoNotModify 72 | } 73 | 74 | // ValidateKeywords checks if the given denomId begins with `DenomKeywords` 75 | func ValidateKeywords(denomId string) error { 76 | if regexpKeyword(denomId) { 77 | return sdkerrors.Wrapf(ErrInvalidDenom, "invalid denomId: %s, can not begin with keyword: (%s)", denomId, keywords) 78 | } 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /x/dns_module/types/keys.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | 7 | sdk "github.com/cosmos/cosmos-sdk/types" 8 | ) 9 | 10 | const ( 11 | // ModuleName is the name of the module 12 | ModuleName = "domain" 13 | 14 | // StoreKey is the default store key for NFT 15 | StoreKey = ModuleName 16 | 17 | // QuerierRoute is the querier route for the NFT store. 18 | QuerierRoute = ModuleName 19 | 20 | // RouterKey is the message route for the NFT module 21 | RouterKey = ModuleName 22 | ) 23 | 24 | var ( 25 | PrefixDomain = []byte{0x01} 26 | PrefixOwners = []byte{0x02} // key for a owner 27 | PrefixCollection = []byte{0x03} // key for balance of Domains held by the denom 28 | PrefixDenom = []byte{0x04} // key for denom of the nft 29 | PrefixDenomName = []byte{0x05} // key for denom name of the nft 30 | 31 | delimiter = []byte("/") 32 | ) 33 | 34 | // SplitKeyOwner return the address,denom,id from the key of stored owner 35 | func SplitKeyOwner(key []byte) (address sdk.AccAddress, domainName string, err error) { 36 | key = key[len(PrefixOwners)+len(delimiter):] 37 | keys := bytes.Split(key, delimiter) 38 | if len(keys) != 2 { 39 | return address, domainName, errors.New("wrong KeyBalance") 40 | } 41 | 42 | address, _ = sdk.AccAddressFromBech32(string(keys[0])) 43 | domainName = string(keys[1]) 44 | return 45 | } 46 | 47 | func SplitKeyDenom(key []byte) (denomID, tokenID string, err error) { 48 | keys := bytes.Split(key, delimiter) 49 | if len(keys) != 2 { 50 | return denomID, tokenID, errors.New("wrong KeyBalance") 51 | } 52 | 53 | denomID = string(keys[0]) 54 | tokenID = string(keys[1]) 55 | return 56 | } 57 | 58 | // KeyOwner gets the key of a collection owned by an account address 59 | func KeyOwner(address sdk.AccAddress, tokenID string) []byte { 60 | key := append(PrefixOwners, delimiter...) 61 | if address != nil { 62 | key = append(key, []byte(address.String())...) 63 | key = append(key, delimiter...) 64 | } 65 | 66 | if address != nil && len(tokenID) > 0 { 67 | key = append(key, []byte(tokenID)...) 68 | } 69 | return key 70 | } 71 | 72 | // KeyDomain gets the key of nft stored by an denom and id 73 | func KeyDomain(denomID, tokenID string) []byte { 74 | key := append(PrefixDomain, delimiter...) 75 | if len(denomID) > 0 { 76 | key = append(key, []byte(denomID)...) 77 | key = append(key, delimiter...) 78 | } 79 | 80 | if len(denomID) > 0 && len(tokenID) > 0 { 81 | key = append(key, []byte(tokenID)...) 82 | } 83 | return key 84 | } 85 | 86 | // KeyCollection gets the storeKey by the collection 87 | func KeyCollection(denomID string) []byte { 88 | key := append(PrefixCollection, delimiter...) 89 | return append(key, []byte(denomID)...) 90 | } 91 | 92 | // KeyDenom gets the storeKey by the denom id 93 | func KeyDenomID(id string) []byte { 94 | key := append(PrefixDenom, delimiter...) 95 | return append(key, []byte(id)...) 96 | } 97 | 98 | // KeyDenomName gets the storeKey by the denom name 99 | func KeyDenomName(name string) []byte { 100 | key := append(PrefixDenomName, delimiter...) 101 | return append(key, []byte(name)...) 102 | } 103 | -------------------------------------------------------------------------------- /x/deweb/module_simulation.go: -------------------------------------------------------------------------------- 1 | package deweb 2 | 3 | import ( 4 | "math/rand" 5 | 6 | "github.com/cosmos/cosmos-sdk/baseapp" 7 | simappparams "github.com/cosmos/cosmos-sdk/simapp/params" 8 | sdk "github.com/cosmos/cosmos-sdk/types" 9 | "github.com/cosmos/cosmos-sdk/types/module" 10 | simtypes "github.com/cosmos/cosmos-sdk/types/simulation" 11 | "github.com/cosmos/cosmos-sdk/x/simulation" 12 | "github.com/deweb-services/deweb/testutil/sample" 13 | dewebsimulation "github.com/deweb-services/deweb/x/deweb/simulation" 14 | "github.com/deweb-services/deweb/x/deweb/types" 15 | ) 16 | 17 | // avoid unused import issue 18 | var ( 19 | _ = sample.AccAddress 20 | _ = dewebsimulation.FindAccount 21 | _ = simappparams.StakePerAccount 22 | _ = simulation.MsgEntryKind 23 | _ = baseapp.Paramspace 24 | ) 25 | 26 | const ( 27 | opWeightMsgConnectChain = "op_weight_msg_create_chain" 28 | // TODO: Determine the simulation weight value 29 | defaultWeightMsgConnectChain int = 100 30 | 31 | opWeightMsgDeleteChainConnect = "op_weight_msg_create_chain" 32 | // TODO: Determine the simulation weight value 33 | defaultWeightMsgDeleteChainConnect int = 100 34 | 35 | // this line is used by starport scaffolding # simapp/module/const 36 | ) 37 | 38 | // GenerateGenesisState creates a randomized GenState of the module 39 | func (AppModule) GenerateGenesisState(simState *module.SimulationState) { 40 | accs := make([]string, len(simState.Accounts)) 41 | for i, acc := range simState.Accounts { 42 | accs[i] = acc.Address.String() 43 | } 44 | dewebGenesis := types.GenesisState{ 45 | // this line is used by starport scaffolding # simapp/module/genesisState 46 | } 47 | simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&dewebGenesis) 48 | } 49 | 50 | // ProposalContents doesn't return any content functions for governance proposals 51 | func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { 52 | return nil 53 | } 54 | 55 | // RandomizedParams creates randomized param changes for the simulator 56 | func (am AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { 57 | 58 | return []simtypes.ParamChange{} 59 | } 60 | 61 | // RegisterStoreDecoder registers a decoder 62 | func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {} 63 | 64 | // WeightedOperations returns the all the gov module operations with their respective weights. 65 | func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { 66 | operations := make([]simtypes.WeightedOperation, 0) 67 | 68 | var weightMsgConnectChain int 69 | simState.AppParams.GetOrGenerate(simState.Cdc, opWeightMsgConnectChain, &weightMsgConnectChain, nil, 70 | func(_ *rand.Rand) { 71 | weightMsgConnectChain = defaultWeightMsgConnectChain 72 | }, 73 | ) 74 | operations = append(operations, simulation.NewWeightedOperation( 75 | weightMsgConnectChain, 76 | dewebsimulation.SimulateMsgConnectChain(am.accountKeeper, am.bankKeeper, am.keeper), 77 | )) 78 | 79 | var weightMsgDeleteChainConnect int 80 | simState.AppParams.GetOrGenerate(simState.Cdc, opWeightMsgDeleteChainConnect, &weightMsgDeleteChainConnect, nil, 81 | func(_ *rand.Rand) { 82 | weightMsgDeleteChainConnect = defaultWeightMsgDeleteChainConnect 83 | }, 84 | ) 85 | operations = append(operations, simulation.NewWeightedOperation( 86 | weightMsgDeleteChainConnect, 87 | dewebsimulation.SimulateMsgDeleteChainConnect(am.accountKeeper, am.bankKeeper, am.keeper), 88 | )) 89 | 90 | // this line is used by starport scaffolding # simapp/module/operation 91 | 92 | return operations 93 | } 94 | -------------------------------------------------------------------------------- /app/simulation_test.go: -------------------------------------------------------------------------------- 1 | package app_test 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | "time" 7 | 8 | "github.com/cosmos/cosmos-sdk/baseapp" 9 | "github.com/cosmos/cosmos-sdk/codec" 10 | "github.com/cosmos/cosmos-sdk/simapp" 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | "github.com/cosmos/cosmos-sdk/types/module" 13 | simulationtypes "github.com/cosmos/cosmos-sdk/types/simulation" 14 | "github.com/cosmos/cosmos-sdk/x/simulation" 15 | "github.com/deweb-services/deweb/app" 16 | "github.com/stretchr/testify/require" 17 | "github.com/tendermint/starport/starport/pkg/cosmoscmd" 18 | abci "github.com/tendermint/tendermint/abci/types" 19 | tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 20 | tmtypes "github.com/tendermint/tendermint/types" 21 | ) 22 | 23 | func init() { 24 | simapp.GetSimulatorFlags() 25 | } 26 | 27 | type SimApp interface { 28 | cosmoscmd.App 29 | GetBaseApp() *baseapp.BaseApp 30 | AppCodec() codec.Codec 31 | SimulationManager() *module.SimulationManager 32 | ModuleAccountAddrs() map[string]bool 33 | Name() string 34 | LegacyAmino() *codec.LegacyAmino 35 | BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock 36 | EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock 37 | InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain 38 | } 39 | 40 | var defaultConsensusParams = &abci.ConsensusParams{ 41 | Block: &abci.BlockParams{ 42 | MaxBytes: 200000, 43 | MaxGas: 2000000, 44 | }, 45 | Evidence: &tmproto.EvidenceParams{ 46 | MaxAgeNumBlocks: 302400, 47 | MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration 48 | MaxBytes: 10000, 49 | }, 50 | Validator: &tmproto.ValidatorParams{ 51 | PubKeyTypes: []string{ 52 | tmtypes.ABCIPubKeyTypeEd25519, 53 | }, 54 | }, 55 | } 56 | 57 | // BenchmarkSimulation run the chain simulation 58 | // Running using starport command: 59 | // `starport chain simulate -v --numBlocks 200 --blockSize 50` 60 | // Running as go benchmark test: 61 | // `go test -benchmem -run=^$ -bench ^BenchmarkSimulation ./app -NumBlocks=200 -BlockSize 50 -Commit=true -Verbose=true -Enabled=true` 62 | func BenchmarkSimulation(b *testing.B) { 63 | simapp.FlagEnabledValue = true 64 | simapp.FlagCommitValue = true 65 | 66 | config, db, dir, logger, _, err := simapp.SetupSimulation("goleveldb-app-sim", "Simulation") 67 | require.NoError(b, err, "simulation setup failed") 68 | 69 | b.Cleanup(func() { 70 | db.Close() 71 | err = os.RemoveAll(dir) 72 | require.NoError(b, err) 73 | }) 74 | 75 | encoding := cosmoscmd.MakeEncodingConfig(app.ModuleBasics) 76 | 77 | app := app.New( 78 | logger, 79 | db, 80 | nil, 81 | true, 82 | map[int64]bool{}, 83 | app.DefaultNodeHome, 84 | 0, 85 | encoding, 86 | simapp.EmptyAppOptions{}, 87 | ) 88 | 89 | simApp, ok := app.(SimApp) 90 | require.True(b, ok, "can't use simapp") 91 | 92 | // Run randomized simulations 93 | _, simParams, simErr := simulation.SimulateFromSeed( 94 | b, 95 | os.Stdout, 96 | simApp.GetBaseApp(), 97 | simapp.AppStateFn(simApp.AppCodec(), simApp.SimulationManager()), 98 | simulationtypes.RandomAccounts, 99 | simapp.SimulationOperations(simApp, simApp.AppCodec(), config), 100 | simApp.ModuleAccountAddrs(), 101 | config, 102 | simApp.AppCodec(), 103 | ) 104 | 105 | // export state and simParams before the simulation error is checked 106 | err = simapp.CheckExportSimulation(simApp, config, simParams) 107 | require.NoError(b, err) 108 | require.NoError(b, simErr) 109 | 110 | if config.Commit { 111 | simapp.PrintStats(db) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /docs/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Note: type annotations allow type checking and IDEs autocompletion 3 | 4 | const lightCodeTheme = require("prism-react-renderer/themes/github"); 5 | const darkCodeTheme = require("prism-react-renderer/themes/dracula"); 6 | 7 | /** @type {import('@docusaurus/types').Config} */ 8 | const config = { 9 | title: "Decentralized Web Services (DWS)", 10 | tagline: "Web3.0 starts here", 11 | url: "https://docs.deweb.services", 12 | baseUrl: "/", 13 | onBrokenLinks: "throw", 14 | onBrokenMarkdownLinks: "warn", 15 | favicon: "img/favicon.ico", 16 | organizationName: "deweb-services", // Usually your GitHub org/user name. 17 | projectName: "deweb", // Usually your repo name. 18 | 19 | presets: [ 20 | [ 21 | "classic", 22 | /** @type {import('@docusaurus/preset-classic').Options} */ 23 | ({ 24 | docs: { 25 | routeBasePath: "/", 26 | }, 27 | blog: false, 28 | theme: { 29 | customCss: require.resolve("./src/css/custom.css"), 30 | }, 31 | }), 32 | ], 33 | ], 34 | 35 | themeConfig: 36 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 37 | ({ 38 | navbar: { 39 | title: "Decentralized Web Services (DWS)", 40 | logo: { 41 | alt: "Decentralized Web Services (DWS)", 42 | src: "img/dws.png", 43 | }, 44 | items: [ 45 | { 46 | href: "https://github.com/deweb-services/deweb", 47 | label: "GitHub", 48 | position: "right", 49 | }, 50 | ], 51 | }, 52 | footer: { 53 | style: "dark", 54 | links: [ 55 | { 56 | title: "Docs", 57 | items: [ 58 | { 59 | label: "Introduction", 60 | to: "/introduction", 61 | }, 62 | { 63 | label: "Validator Setup Guide", 64 | to: "/fullnode/validator-setup", 65 | }, 66 | ], 67 | }, 68 | { 69 | title: "Community", 70 | items: [ 71 | { 72 | label: "Discord", 73 | href: "https://discord.gg/NENJeq58Tc", 74 | }, 75 | { 76 | label: "Twitter", 77 | href: "https://twitter.com/dewebservices", 78 | }, 79 | { 80 | label: "Telegram Chat", 81 | href: "https://t.me/dewebservices_chat", 82 | }, 83 | ], 84 | }, 85 | { 86 | title: "More", 87 | items: [ 88 | { 89 | label: "Medium", 90 | href: "https://blog.deweb.services/", 91 | }, 92 | { 93 | label: "Mastodon", 94 | href: "https://mastodon.social/@dewebservices", 95 | }, 96 | { 97 | label: "GitHub", 98 | href: "https://github.com/deweb-services", 99 | }, 100 | { 101 | label: "Explorer", 102 | href: "https://explore.deweb.services/", 103 | }, 104 | { 105 | label: "Telegram", 106 | href: "https://t.me/deweb_services", 107 | }, 108 | ], 109 | }, 110 | ], 111 | copyright: `Copyright © ${new Date().getFullYear()} Decentralized Web Services.`, 112 | }, 113 | prism: { 114 | theme: lightCodeTheme, 115 | darkTheme: darkCodeTheme, 116 | }, 117 | }), 118 | }; 119 | 120 | module.exports = config; 121 | -------------------------------------------------------------------------------- /x/dns_module/client/cli/query.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/spf13/cobra" 7 | "strconv" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/flags" 11 | "github.com/cosmos/cosmos-sdk/version" 12 | 13 | "github.com/deweb-services/deweb/x/dns_module/types" 14 | ) 15 | 16 | // GetQueryCmd returns the cli query commands for this module 17 | func GetQueryCmd() *cobra.Command { 18 | queryCmd := &cobra.Command{ 19 | Use: types.ModuleName, 20 | Short: "Querying commands for the domains module", 21 | DisableFlagParsing: true, 22 | } 23 | 24 | queryCmd.AddCommand( 25 | GetCmdQueryParams(), 26 | GetCmdQueryDomain(), 27 | GetCmdQueryOwnersDomain(), 28 | ) 29 | 30 | return queryCmd 31 | } 32 | 33 | // GetCmdQueryDomain queries a single Domains from a collection 34 | func GetCmdQueryDomain() *cobra.Command { 35 | cmd := &cobra.Command{ 36 | Use: "domain [domain]", 37 | Long: "Query a single domain NFT ", 38 | Example: fmt.Sprintf("$ %s query domain ", version.AppName), 39 | Args: cobra.ExactArgs(1), 40 | RunE: func(cmd *cobra.Command, args []string) error { 41 | clientCtx, err := client.GetClientTxContext(cmd) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | if err := types.ValidateTokenID(args[0]); err != nil { 47 | return err 48 | } 49 | 50 | queryClient := types.NewQueryClient(clientCtx) 51 | resp, err := queryClient.Domain(context.Background(), &types.QueryDomainRequest{ 52 | DomainName: args[0], 53 | }) 54 | if err != nil { 55 | return err 56 | } 57 | return clientCtx.PrintProto(resp.Domain) 58 | }, 59 | } 60 | flags.AddQueryFlagsToCmd(cmd) 61 | 62 | return cmd 63 | } 64 | 65 | // GetCmdQueryOwnersDomain queries a list of domains owned by iser 66 | func GetCmdQueryOwnersDomain() *cobra.Command { 67 | cmd := &cobra.Command{ 68 | Use: "address [address] [offset] [limit]", 69 | Long: "Query a list of domains owned by user ", 70 | Example: fmt.Sprintf("$ %s query address ", version.AppName), 71 | Args: cobra.ExactArgs(3), 72 | RunE: func(cmd *cobra.Command, args []string) error { 73 | clientCtx, err := client.GetClientTxContext(cmd) 74 | if err != nil { 75 | return err 76 | } 77 | var offset int 78 | if len(args) > 1 { 79 | offset, err = strconv.Atoi(args[1]) 80 | if err != nil { 81 | return fmt.Errorf("invalid offset value: %s: %w", args[1], err) 82 | } 83 | } 84 | 85 | count := 10 86 | if len(args) > 2 { 87 | count, err = strconv.Atoi(args[2]) 88 | if err != nil { 89 | return fmt.Errorf("invalid count value: %s: %w", args[1], err) 90 | } 91 | } 92 | 93 | queryClient := types.NewQueryClient(clientCtx) 94 | resp, err := queryClient.OwnedDomains(context.Background(), &types.QueryOwnedDomainsRequest{ 95 | Address: args[0], 96 | Offset: int64(offset), 97 | Count: int64(count), 98 | }) 99 | if err != nil { 100 | return err 101 | } 102 | return clientCtx.PrintProto(resp) 103 | }, 104 | } 105 | flags.AddQueryFlagsToCmd(cmd) 106 | 107 | return cmd 108 | } 109 | 110 | func GetCmdQueryParams() *cobra.Command { 111 | cmd := &cobra.Command{ 112 | Use: "params", 113 | Long: "Query module parameters ", 114 | Example: fmt.Sprintf("$ %s query nft params", version.AppName), 115 | Args: cobra.ExactArgs(0), 116 | RunE: func(cmd *cobra.Command, args []string) error { 117 | clientCtx, err := client.GetClientTxContext(cmd) 118 | if err != nil { 119 | return err 120 | } 121 | resMsg := &types.Params{} 122 | return clientCtx.PrintProto(resMsg) 123 | }, 124 | } 125 | flags.AddQueryFlagsToCmd(cmd) 126 | 127 | return cmd 128 | } 129 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | BRANCH := $(shell git rev-parse --abbrev-ref HEAD) 4 | COMMIT := $(shell git log -1 --format='%H') 5 | 6 | # don't override user values 7 | ifeq (,$(VERSION)) 8 | VERSION := $(shell git describe --tags | sed 's/^v//') 9 | # if VERSION is empty, then populate it with branch's name and raw commit hash 10 | ifeq (,$(VERSION)) 11 | VERSION := $(BRANCH)-$(COMMIT) 12 | endif 13 | endif 14 | PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation') 15 | LEDGER_ENABLED ?= true 16 | SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') 17 | TM_VERSION := $(shell go list -m github.com/tendermint/tendermint | sed 's:.* ::') # grab everything after the space in "github.com/tendermint/tendermint v0.34.7" 18 | DOCKER := $(shell which docker) 19 | BUILDDIR ?= $(CURDIR)/build 20 | TEST_DOCKER_REPO=jackzampolin/gaiatest 21 | 22 | export GO111MODULE = on 23 | 24 | # process build tags 25 | 26 | build_tags = netgo 27 | ifeq ($(LEDGER_ENABLED),true) 28 | ifeq ($(OS),Windows_NT) 29 | GCCEXE = $(shell where gcc.exe 2> NUL) 30 | ifeq ($(GCCEXE),) 31 | $(error gcc.exe not installed for ledger support, please install or set LEDGER_ENABLED=false) 32 | else 33 | build_tags += ledger 34 | endif 35 | else 36 | UNAME_S = $(shell uname -s) 37 | ifeq ($(UNAME_S),OpenBSD) 38 | $(warning OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988)) 39 | else 40 | GCC = $(shell command -v gcc 2> /dev/null) 41 | ifeq ($(GCC),) 42 | $(error gcc not installed for ledger support, please install or set LEDGER_ENABLED=false) 43 | else 44 | build_tags += ledger 45 | endif 46 | endif 47 | endif 48 | endif 49 | 50 | ifeq (cleveldb,$(findstring cleveldb,$(GAIA_BUILD_OPTIONS))) 51 | build_tags += gcc cleveldb 52 | endif 53 | build_tags += $(BUILD_TAGS) 54 | build_tags := $(strip $(build_tags)) 55 | 56 | whitespace := 57 | whitespace += $(whitespace) 58 | comma := , 59 | build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags)) 60 | 61 | # process linker flags 62 | 63 | ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=deweb \ 64 | -X github.com/cosmos/cosmos-sdk/version.AppName=dewebd \ 65 | -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ 66 | -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \ 67 | -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \ 68 | -X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TM_VERSION) 69 | 70 | ifeq (cleveldb,$(findstring cleveldb,$(GAIA_BUILD_OPTIONS))) 71 | ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=cleveldb 72 | endif 73 | ifeq (,$(findstring nostrip,$(GAIA_BUILD_OPTIONS))) 74 | ldflags += -w -s 75 | endif 76 | ldflags += $(LDFLAGS) 77 | ldflags := $(strip $(ldflags)) 78 | 79 | BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)' 80 | # check for nostrip option 81 | ifeq (,$(findstring nostrip,$(GAIA_BUILD_OPTIONS))) 82 | BUILD_FLAGS += -trimpath 83 | endif 84 | 85 | #$(info $$BUILD_FLAGS is [$(BUILD_FLAGS)]) 86 | 87 | # The below include contains the tools target. 88 | include contrib/devtools/Makefile 89 | 90 | ############################################################################### 91 | ### Documentation ### 92 | ############################################################################### 93 | all: install lint test 94 | 95 | BUILD_TARGETS := build install 96 | 97 | build: BUILD_ARGS=-o $(BUILDDIR)/ 98 | 99 | $(BUILD_TARGETS): go.sum $(BUILDDIR)/ 100 | #go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... Don't overwrite go.sum 101 | go $@ $(BUILD_FLAGS) $(BUILD_ARGS) ./... 102 | 103 | $(BUILDDIR)/: 104 | mkdir -p $(BUILDDIR)/ -------------------------------------------------------------------------------- /x/dns_module/types/params.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" 6 | "gopkg.in/yaml.v2" 7 | ) 8 | 9 | const ( 10 | domainBasePriceDWS = 100000000 //100 DWS = 100 * 10^6 uDWS 11 | subDomainBasePriceDWS = 50000000 //50 DWS = 50 * 10^6 uDWS 12 | domainDefaultValidityHours = 17520 13 | domainOwnerProlongationHours = 1440 14 | ) 15 | 16 | var ( 17 | KeyDomainPrice = []byte("DomainPrice") 18 | KeySubDomainPrice = []byte("SubDomainPrice") 19 | KeyDomainExpirationHours = []byte("DomainExpiration") 20 | KeyDomainOwnerProlongationHours = []byte("DomainOwnerProlongation") 21 | KeyBlockedTLDs = []byte("BlockedTLDs") 22 | _ paramtypes.ParamSet = (*Params)(nil) 23 | ) 24 | 25 | // ParamKeyTable the param key table for launch module 26 | func ParamKeyTable() paramtypes.KeyTable { 27 | return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) 28 | } 29 | 30 | // NewParams creates a new Params instance 31 | func NewParams(domainPrice uint64, subDomainPrice uint64, domainExpirationHours int64, domainOwnerProlong int64, blockTLDs []string) Params { 32 | return Params{ 33 | DomainPrice: domainPrice, 34 | DomainExpirationHours: domainExpirationHours, 35 | DomainOwnerProlongationHours: domainOwnerProlong, 36 | SubDomainPrice: subDomainPrice, 37 | BlockTLDs: blockTLDs, 38 | } 39 | } 40 | 41 | // DefaultParams returns a default set of parameters 42 | func DefaultParams() Params { 43 | return NewParams(domainBasePriceDWS, subDomainBasePriceDWS, domainDefaultValidityHours, domainOwnerProlongationHours, DefaultDomainsBlockList) 44 | } 45 | 46 | // ParamSetPairs get the params.ParamSet 47 | func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { 48 | return paramtypes.ParamSetPairs{ 49 | paramtypes.NewParamSetPair(KeyDomainPrice, &p.DomainPrice, validateDomainPrice), 50 | paramtypes.NewParamSetPair(KeyDomainExpirationHours, &p.DomainExpirationHours, validateDomainExpirationHours), 51 | paramtypes.NewParamSetPair(KeySubDomainPrice, &p.SubDomainPrice, validateDomainPrice), 52 | paramtypes.NewParamSetPair(KeyDomainOwnerProlongationHours, &p.DomainOwnerProlongationHours, validateDomainOwnerProlongationHours), 53 | paramtypes.NewParamSetPair(KeyBlockedTLDs, &p.BlockTLDs, validateBlockedTLDs), 54 | } 55 | } 56 | 57 | // Validate validates the set of params 58 | func (p Params) Validate() error { 59 | return nil 60 | } 61 | 62 | // String implements the Stringer interface. 63 | func (p Params) String() string { 64 | out, _ := yaml.Marshal(p) 65 | return string(out) 66 | } 67 | 68 | func validateDomainPrice(i interface{}) error { 69 | v, ok := i.(uint64) 70 | if !ok { 71 | return fmt.Errorf("invalid parameter type: %T", i) 72 | } 73 | 74 | if v <= 0 { 75 | return fmt.Errorf("domain price must be positive: %d", v) 76 | } 77 | 78 | return nil 79 | } 80 | 81 | func validateDomainExpirationHours(i interface{}) error { 82 | v, ok := i.(int64) 83 | if !ok { 84 | return fmt.Errorf("invalid parameter type: %T", i) 85 | } 86 | 87 | if v <= 0 { 88 | return fmt.Errorf("domain expiration period hours must be positive: %d", v) 89 | } 90 | 91 | return nil 92 | } 93 | 94 | func validateDomainOwnerProlongationHours(i interface{}) error { 95 | v, ok := i.(int64) 96 | if !ok { 97 | return fmt.Errorf("invalid parameter type: %T", i) 98 | } 99 | 100 | if v <= 0 { 101 | return fmt.Errorf("domain owner prolongation before expiration hours must be positive: %d", v) 102 | } 103 | 104 | return nil 105 | } 106 | 107 | func validateBlockedTLDs(i interface{}) error { 108 | _, ok := i.([]string) 109 | if !ok { 110 | return fmt.Errorf("invalid parameter type: %T", i) 111 | } 112 | 113 | return nil 114 | } 115 | -------------------------------------------------------------------------------- /contrib/devtools/Makefile: -------------------------------------------------------------------------------- 1 | ### 2 | # Find OS and Go environment 3 | # GO contains the Go binary 4 | # FS contains the OS file separator 5 | ### 6 | ifeq ($(OS),Windows_NT) 7 | GO := $(shell where go.exe 2> NUL) 8 | FS := \\ 9 | else 10 | GO := $(shell command -v go 2> /dev/null) 11 | FS := / 12 | endif 13 | 14 | ifeq ($(GO),) 15 | $(error could not find go. Is it in PATH? $(GO)) 16 | endif 17 | 18 | GOPATH ?= $(shell $(GO) env GOPATH) 19 | GITHUBDIR := $(GOPATH)$(FS)src$(FS)github.com 20 | 21 | ### 22 | # Functions 23 | ### 24 | 25 | go_get = $(if $(findstring Windows_NT,$(OS)),\ 26 | IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS) ( mkdir $(GITHUBDIR)$(FS)$(1) ) else (cd .) &\ 27 | IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS)$(2)$(FS) ( cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2) ) else (cd .) &\ 28 | ,\ 29 | mkdir -p $(GITHUBDIR)$(FS)$(1) &&\ 30 | (test ! -d $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2)) || true &&\ 31 | )\ 32 | cd $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && git fetch origin && git checkout -q $(3) 33 | 34 | go_install = $(call go_get,$(1),$(2),$(3)) && cd $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && $(GO) install 35 | 36 | mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) 37 | mkfile_dir := $(shell cd $(shell dirname $(mkfile_path)); pwd) 38 | 39 | ############################################################################### 40 | ### Tools ### 41 | ############################################################################### 42 | 43 | BIN ?= /usr/local/bin 44 | UNAME_S ?= $(shell uname -s) 45 | UNAME_M ?= $(shell uname -m) 46 | 47 | TOOLS_DESTDIR ?= $(GOPATH)/bin 48 | RUNSIM = $(TOOLS_DESTDIR)/runsim 49 | 50 | BUF_VERSION ?= 0.7.0 51 | PROTOC_VERSION ?= 3.11.2 52 | 53 | ifeq ($(UNAME_S),Linux) 54 | PROTOC_ZIP ?= protoc-3.11.2-linux-x86_64.zip 55 | endif 56 | ifeq ($(UNAME_S),Darwin) 57 | PROTOC_ZIP ?= protoc-3.11.2-osx-x86_64.zip 58 | endif 59 | 60 | all: tools 61 | 62 | tools: tools-stamp 63 | 64 | tools-stamp: $(RUNSIM) 65 | touch $@ 66 | 67 | # Install the runsim binary with a temporary workaround of entering an outside 68 | # directory as the "go get" command ignores the -mod option and will polute the 69 | # go.{mod, sum} files. 70 | # 71 | # ref: https://github.com/golang/go/issues/30515 72 | runsim: $(RUNSIM) 73 | $(RUNSIM): 74 | @echo "Installing runsim..." 75 | @(cd /tmp && go get github.com/cosmos/tools/cmd/runsim@v1.0.0) 76 | 77 | protoc: 78 | @echo "Installing protoc compiler..." 79 | @(cd /tmp; \ 80 | curl -sSOL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/${PROTOC_ZIP}"; \ 81 | unzip -o ${PROTOC_ZIP} -d /usr/local bin/protoc; \ 82 | unzip -o ${PROTOC_ZIP} -d /usr/local 'include/*'; \ 83 | rm -f ${PROTOC_ZIP}) 84 | 85 | protoc-gen-gocosmos: 86 | @echo "Installing protoc-gen-gocosmos..." 87 | @go install github.com/regen-network/cosmos-proto/protoc-gen-gocosmos 88 | 89 | buf: protoc-gen-buf-check-breaking protoc-gen-buf-check-lint 90 | @echo "Installing buf..." 91 | @(cd /tmp; \ 92 | curl -sSOL "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/buf-${UNAME_S}-${UNAME_M}"; \ 93 | mv buf-${UNAME_S}-${UNAME_M} "${BIN}/buf"; \ 94 | chmod +x "${BIN}/buf") 95 | 96 | protoc-gen-buf-check-breaking: 97 | @echo "Installing protoc-gen-buf-check-breaking..." 98 | @(cd /tmp; \ 99 | curl -sSOL "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/protoc-gen-buf-check-breaking-${UNAME_S}-${UNAME_M}"; \ 100 | mv protoc-gen-buf-check-breaking-${UNAME_S}-${UNAME_M} "${BIN}/protoc-gen-buf-check-breaking"; \ 101 | chmod +x "${BIN}/protoc-gen-buf-check-breaking") 102 | 103 | protoc-gen-buf-check-lint: 104 | @echo "Installing protoc-gen-buf-check-lint..." 105 | @(cd /tmp; \ 106 | curl -sSOL "https://github.com/bufbuild/buf/releases/download/v${BUF_VERSION}/protoc-gen-buf-check-lint-${UNAME_S}-${UNAME_M}"; \ 107 | mv protoc-gen-buf-check-lint-${UNAME_S}-${UNAME_M} "${BIN}/protoc-gen-buf-check-lint"; \ 108 | chmod +x "${BIN}/protoc-gen-buf-check-lint") 109 | 110 | tools-clean: 111 | rm -f $(RUNSIM) 112 | rm -f tools-stamp 113 | 114 | .PHONY: all tools tools-clean protoc buf protoc-gen-buf-check-breaking protoc-gen-buf-check-lint protoc-gen-gocosmos -------------------------------------------------------------------------------- /x/dns_module/keeper/grpc_query.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "sort" 7 | "time" 8 | 9 | sdk "github.com/cosmos/cosmos-sdk/types" 10 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 11 | "github.com/deweb-services/deweb/x/dns_module/types" 12 | ) 13 | 14 | type queryServer struct { 15 | Keeper 16 | dnsDenomName string 17 | } 18 | 19 | var _ types.QueryServer = queryServer{} 20 | 21 | const ( 22 | DefaultDomainsCount = 10 23 | ) 24 | 25 | // NewQueryServerImpl returns an implementation of the NFT QueryServer interface 26 | // for the provided Keeper. 27 | func NewQueryServerImpl(keeper Keeper) types.QueryServer { 28 | return &queryServer{ 29 | Keeper: keeper, 30 | dnsDenomName: DNSDenomName, 31 | } 32 | } 33 | 34 | func (q queryServer) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { 35 | ctx := sdk.UnwrapSDKContext(c) 36 | 37 | params := q.GetParams(ctx) 38 | 39 | return &types.QueryParamsResponse{ 40 | Params: params, 41 | }, nil 42 | } 43 | 44 | func (q queryServer) Domain(c context.Context, request *types.QueryDomainRequest) (*types.QueryDomainResponse, error) { 45 | ctx := sdk.UnwrapSDKContext(c) 46 | 47 | nft, err := q.GetDomain(ctx, request.DomainName) 48 | if err != nil { 49 | return nil, sdkerrors.Wrapf(types.ErrUnknownDomain, "invalid domains name %s ", request.DomainName) 50 | } 51 | 52 | baseDomainNFT, ok := nft.(types.BaseDomain) 53 | if !ok { 54 | return nil, sdkerrors.Wrapf(types.ErrUnknownDomain, "invalid type of domain NFT %s", request.DomainName) 55 | } 56 | domainRecordData, err := ParseDomainData([]byte(baseDomainNFT.GetData())) 57 | if err != nil { 58 | return nil, sdkerrors.Wrapf(sdkerrors.ErrJSONUnmarshal, 59 | fmt.Sprintf("cannot process record for domain %s", baseDomainNFT.GetID()), err) 60 | } 61 | var domainTransferOffer *types.TransferOffer 62 | if domainRecordData.TransferOffer != nil { 63 | domainTransferOffer = &types.TransferOffer{ 64 | Price: domainRecordData.TransferOffer.Price, 65 | ExpectedOwnerAddress: domainRecordData.TransferOffer.ExpectedOwnerAddress, 66 | } 67 | } 68 | resRecords := make([]*types.DNSRecords, 0, len(domainRecordData.Records)) 69 | for _, rec := range domainRecordData.Records { 70 | resRecord := &types.DNSRecords{ 71 | Type: rec.RecordType, 72 | Values: rec.RecordValues, 73 | } 74 | resRecords = append(resRecords, resRecord) 75 | } 76 | respDomain := &types.ResponseDomain{ 77 | Id: baseDomainNFT.Id, 78 | Issued: domainRecordData.Issued.Format(time.RFC3339), 79 | ValidTill: domainRecordData.ValidTill.Format(time.RFC3339), 80 | TransferOffer: domainTransferOffer, 81 | Records: resRecords, 82 | SubDomainsOnSale: domainRecordData.SubDomainsOnSale, 83 | SubDomainsSalePrice: domainRecordData.SubDomainsSalePrice, 84 | Owner: baseDomainNFT.Owner, 85 | } 86 | return &types.QueryDomainResponse{Domain: respDomain}, nil 87 | } 88 | 89 | func (q queryServer) OwnedDomains(c context.Context, request *types.QueryOwnedDomainsRequest) (*types.QueryOwnedDomainsResponse, error) { 90 | ctx := sdk.UnwrapSDKContext(c) 91 | address, err := sdk.AccAddressFromBech32(request.Address) 92 | if err != nil { 93 | return nil, err 94 | } 95 | ownedCollections := q.GetByOwner(ctx, address) 96 | 97 | var domains []string 98 | for _, collection := range ownedCollections.IDCollections { 99 | if collection.DenomId != q.dnsDenomName { 100 | continue 101 | } 102 | domains = collection.TokenIds 103 | } 104 | if domains == nil || len(domains) == 0 { 105 | return &types.QueryOwnedDomainsResponse{}, nil 106 | } 107 | res := &types.QueryOwnedDomainsResponse{ 108 | Total: int64(len(domains)), 109 | Domains: make([]*types.ResponseDomain, 0, request.Count), 110 | } 111 | sort.Strings(domains) 112 | count := int(request.Count) 113 | if count == 0 { 114 | count = DefaultDomainsCount 115 | } 116 | offset := int(request.Offset) 117 | for i, domainName := range domains { 118 | if i < offset { 119 | continue 120 | } 121 | req := &types.QueryDomainRequest{DomainName: domainName} 122 | domainResp, err := q.Domain(c, req) 123 | if err != nil { 124 | return nil, sdkerrors.Wrapf(err, "cannot get info for domain %s", domainName) 125 | } 126 | res.Domains = append(res.Domains, domainResp.Domain) 127 | if len(res.Domains) == count { 128 | break 129 | } 130 | } 131 | return res, nil 132 | } 133 | -------------------------------------------------------------------------------- /x/dns_module/client/rest/tx.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/gorilla/mux" 8 | 9 | "github.com/cosmos/cosmos-sdk/client" 10 | "github.com/cosmos/cosmos-sdk/client/tx" 11 | sdk "github.com/cosmos/cosmos-sdk/types" 12 | "github.com/cosmos/cosmos-sdk/types/rest" 13 | 14 | "github.com/deweb-services/deweb/x/dns_module/types" 15 | ) 16 | 17 | func registerTxRoutes(cliCtx client.Context, r *mux.Router, queryRoute string) { 18 | // Mint an NFT 19 | r.HandleFunc("/deweb/domains/v1beta1/domain/register", registerDomainHandlerFn(cliCtx)).Methods("POST") 20 | // Update an NFT 21 | r.HandleFunc(fmt.Sprintf("/deweb/domains/v1beta1/domain/{%s}", RestParamDomainName), editDomainHandlerFn(cliCtx)).Methods("PUT") 22 | // Transfer an NFT to an address 23 | r.HandleFunc(fmt.Sprintf("/deweb/domains/v1beta1/domain/{%s}/transfer", RestParamDomainName), transferDomainHandlerFn(cliCtx)).Methods("POST") 24 | // Burn an NFT 25 | r.HandleFunc(fmt.Sprintf("/deweb/domains/v1beta1/domain/{%s}/burn", RestParamDomainName), burnDomainHandlerFn(cliCtx)).Methods("POST") 26 | } 27 | 28 | func registerDomainHandlerFn(cliCtx client.Context) http.HandlerFunc { 29 | return func(w http.ResponseWriter, r *http.Request) { 30 | var req registerDomainReq 31 | if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) { 32 | rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") 33 | return 34 | } 35 | baseReq := req.BaseReq.Sanitize() 36 | if !baseReq.ValidateBasic(w) { 37 | return 38 | } 39 | 40 | if req.Recipient == "" { 41 | req.Recipient = req.Owner 42 | } 43 | // create the message 44 | msg := types.NewMsgRegisterDomain( 45 | req.ID, 46 | req.Data, 47 | req.Owner, 48 | req.Recipient, 49 | ) 50 | if err := msg.ValidateBasic(); err != nil { 51 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 52 | return 53 | } 54 | tx.WriteGeneratedTxResponse(cliCtx, w, req.BaseReq, msg) 55 | } 56 | } 57 | 58 | func editDomainHandlerFn(cliCtx client.Context) http.HandlerFunc { 59 | return func(w http.ResponseWriter, r *http.Request) { 60 | var req editDomainReq 61 | if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) { 62 | rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") 63 | return 64 | } 65 | baseReq := req.BaseReq.Sanitize() 66 | if !baseReq.ValidateBasic(w) { 67 | return 68 | } 69 | 70 | vars := mux.Vars(r) 71 | // create the message 72 | msg := types.NewMsgEditDomain(vars[RestParamTokenID], req.Data, req.Owner) 73 | if err := msg.ValidateBasic(); err != nil { 74 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 75 | return 76 | } 77 | tx.WriteGeneratedTxResponse(cliCtx, w, req.BaseReq, msg) 78 | } 79 | } 80 | 81 | func transferDomainHandlerFn(cliCtx client.Context) http.HandlerFunc { 82 | return func(w http.ResponseWriter, r *http.Request) { 83 | var req transferDomainReq 84 | if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) { 85 | rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") 86 | return 87 | } 88 | baseReq := req.BaseReq.Sanitize() 89 | if !baseReq.ValidateBasic(w) { 90 | return 91 | } 92 | if _, err := sdk.AccAddressFromBech32(req.Recipient); err != nil { 93 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 94 | return 95 | } 96 | 97 | vars := mux.Vars(r) 98 | // create the message 99 | msg := types.NewMsgTransferDomain( 100 | vars[RestParamTokenID], 101 | req.Price, 102 | req.CancelOffer, 103 | req.Owner, 104 | req.Recipient, 105 | ) 106 | if err := msg.ValidateBasic(); err != nil { 107 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 108 | return 109 | } 110 | tx.WriteGeneratedTxResponse(cliCtx, w, req.BaseReq, msg) 111 | } 112 | } 113 | 114 | func burnDomainHandlerFn(cliCtx client.Context) http.HandlerFunc { 115 | return func(w http.ResponseWriter, r *http.Request) { 116 | var req RemoveDomainReq 117 | if !rest.ReadRESTReq(w, r, cliCtx.LegacyAmino, &req) { 118 | rest.WriteErrorResponse(w, http.StatusBadRequest, "failed to parse request") 119 | return 120 | } 121 | baseReq := req.BaseReq.Sanitize() 122 | if !baseReq.ValidateBasic(w) { 123 | return 124 | } 125 | 126 | vars := mux.Vars(r) 127 | 128 | // create the message 129 | msg := types.NewMsgRemoveDomain(req.Owner, vars[RestParamDomainName]) 130 | if err := msg.ValidateBasic(); err != nil { 131 | rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) 132 | return 133 | } 134 | tx.WriteGeneratedTxResponse(cliCtx, w, req.BaseReq, msg) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /x/dns_module/keeper/val_state_change.go: -------------------------------------------------------------------------------- 1 | package keeper 2 | 3 | //import ( 4 | // "bytes" 5 | // sdk "github.com/cosmos/cosmos-sdk/types" 6 | // gogotypes "github.com/gogo/protobuf/types" 7 | // abci "github.com/tendermint/tendermint/abci/types" 8 | //) 9 | // 10 | //// ApplyAndReturnValidatorSetUpdates applies and return accumulated updates to the bonded validator set. Also, 11 | //// * Updates the active valset as keyed by LastValidatorPowerKey. 12 | //// * Updates the total power as keyed by LastTotalPowerKey. 13 | //// * Updates validator status' according to updated powers. 14 | //// * Updates the fee pool bonded vs not-bonded tokens. 15 | //// * Updates relevant indices. 16 | //// It gets called once after genesis, another time maybe after genesis transactions, 17 | //// then once at every EndBlock. 18 | //// 19 | //// CONTRACT: Only validators with non-zero power or zero-power that were bonded 20 | //// at the previous block height or were removed from the validator set entirely 21 | //// are returned to Tendermint. 22 | //func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []abci.ValidatorUpdate, err error) { 23 | // params := k.GetParams(ctx) 24 | // maxValidators := params.MaxValidators 25 | // powerReduction := k.PowerReduction(ctx) 26 | // totalPower := sdk.ZeroInt() 27 | // amtFromBondedToNotBonded, amtFromNotBondedToBonded := sdk.ZeroInt(), sdk.ZeroInt() 28 | // 29 | // // Retrieve the last validator set. 30 | // // The persistent set is updated later in this function. 31 | // // (see LastValidatorPowerKey). 32 | // last, err := k.getLastValidatorsByAddr(ctx) 33 | // if err != nil { 34 | // return nil, err 35 | // } 36 | // 37 | // // Iterate over validators, highest power to lowest. 38 | // iterator := k.ValidatorsPowerStoreIterator(ctx) 39 | // defer iterator.Close() 40 | // 41 | // for count := 0; iterator.Valid() && count < int(maxValidators); iterator.Next() { 42 | // // everything that is iterated in this loop is becoming or already a 43 | // // part of the bonded validator set 44 | // valAddr := sdk.ValAddress(iterator.Value()) 45 | // validator := k.mustGetValidator(ctx, valAddr) 46 | // 47 | // if validator.Jailed { 48 | // panic("should never retrieve a jailed validator from the power store") 49 | // } 50 | // 51 | // // if we get to a zero-power validator (which we don't bond), 52 | // // there are no more possible bonded validators 53 | // if validator.PotentialConsensusPower(k.PowerReduction(ctx)) == 0 { 54 | // break 55 | // } 56 | // 57 | // // apply the appropriate state change if necessary 58 | // switch { 59 | // case validator.IsUnbonded(): 60 | // validator, err = k.unbondedToBonded(ctx, validator) 61 | // if err != nil { 62 | // return 63 | // } 64 | // amtFromNotBondedToBonded = amtFromNotBondedToBonded.Add(validator.GetTokens()) 65 | // case validator.IsUnbonding(): 66 | // validator, err = k.unbondingToBonded(ctx, validator) 67 | // if err != nil { 68 | // return 69 | // } 70 | // amtFromNotBondedToBonded = amtFromNotBondedToBonded.Add(validator.GetTokens()) 71 | // case validator.IsBonded(): 72 | // // no state change 73 | // default: 74 | // panic("unexpected validator status") 75 | // } 76 | // 77 | // // fetch the old power bytes 78 | // valAddrStr, err := sdk.Bech32ifyAddressBytes(sdk.GetConfig().GetBech32ValidatorAddrPrefix(), valAddr) 79 | // if err != nil { 80 | // return nil, err 81 | // } 82 | // oldPowerBytes, found := last[valAddrStr] 83 | // newPower := validator.ConsensusPower(powerReduction) 84 | // newPowerBytes := k.cdc.MustMarshal(&gogotypes.Int64Value{Value: newPower}) 85 | // 86 | // // update the validator set if power has changed 87 | // if !found || !bytes.Equal(oldPowerBytes, newPowerBytes) { 88 | // updates = append(updates, validator.ABCIValidatorUpdate(powerReduction)) 89 | // 90 | // k.SetLastValidatorPower(ctx, valAddr, newPower) 91 | // } 92 | // 93 | // delete(last, valAddrStr) 94 | // count++ 95 | // 96 | // totalPower = totalPower.Add(sdk.NewInt(newPower)) 97 | // } 98 | // 99 | // noLongerBonded, err := sortNoLongerBonded(last) 100 | // if err != nil { 101 | // return nil, err 102 | // } 103 | // 104 | // for _, valAddrBytes := range noLongerBonded { 105 | // validator := k.mustGetValidator(ctx, sdk.ValAddress(valAddrBytes)) 106 | // validator, err = k.bondedToUnbonding(ctx, validator) 107 | // if err != nil { 108 | // return 109 | // } 110 | // amtFromBondedToNotBonded = amtFromBondedToNotBonded.Add(validator.GetTokens()) 111 | // k.DeleteLastValidatorPower(ctx, validator.GetOperator()) 112 | // updates = append(updates, validator.ABCIValidatorUpdateZero()) 113 | // } 114 | // 115 | // // Update the pools based on the recent updates in the validator set: 116 | // // - The tokens from the non-bonded candidates that enter the new validator set need to be transferred 117 | // // to the Bonded pool. 118 | // // - The tokens from the bonded validators that are being kicked out from the validator set 119 | // // need to be transferred to the NotBonded pool. 120 | // switch { 121 | // // Compare and subtract the respective amounts to only perform one transfer. 122 | // // This is done in order to avoid doing multiple updates inside each iterator/loop. 123 | // case amtFromNotBondedToBonded.GT(amtFromBondedToNotBonded): 124 | // k.notBondedTokensToBonded(ctx, amtFromNotBondedToBonded.Sub(amtFromBondedToNotBonded)) 125 | // case amtFromNotBondedToBonded.LT(amtFromBondedToNotBonded): 126 | // k.bondedTokensToNotBonded(ctx, amtFromBondedToNotBonded.Sub(amtFromNotBondedToBonded)) 127 | // default: // equal amounts of tokens; no update required 128 | // } 129 | // 130 | // // set total power on lookup index if there are any updates 131 | // if len(updates) > 0 { 132 | // k.SetLastTotalPower(ctx, totalPower) 133 | // } 134 | // 135 | // return updates, err 136 | //} 137 | -------------------------------------------------------------------------------- /x/dns_module/types/msgs.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | sdk "github.com/cosmos/cosmos-sdk/types" 5 | sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 6 | ) 7 | 8 | // constant used to indicate that some field should not be updated 9 | const ( 10 | TypeMsgTransferDomain = "transfer_domain" 11 | TypeMsgEditDomain = "edit_domain" 12 | TypeMsgRegisterDomain = "register_domain" 13 | TypeMsgRemoveDomain = "remove_domain" 14 | ) 15 | 16 | var ( 17 | _ sdk.Msg = &MsgTransferDomain{} 18 | _ sdk.Msg = &MsgEditDomain{} 19 | _ sdk.Msg = &MsgRegisterDomain{} 20 | _ sdk.Msg = &MsgRemoveDomain{} 21 | ) 22 | 23 | // NewMsgTransferDomain is a constructor function for MsgSetName 24 | func NewMsgTransferDomain( 25 | tokenID string, transferPrice uint64, cancelTransfer bool, sender, recipient string, 26 | ) *MsgTransferDomain { 27 | return &MsgTransferDomain{ 28 | Id: tokenID, 29 | Price: transferPrice, 30 | Cancel: cancelTransfer, 31 | Sender: sender, 32 | Recipient: recipient, 33 | } 34 | } 35 | 36 | // Route Implements Msg 37 | func (msg MsgTransferDomain) Route() string { return RouterKey } 38 | 39 | // Type Implements Msg 40 | func (msg MsgTransferDomain) Type() string { return TypeMsgTransferDomain } 41 | 42 | // ValidateBasic Implements Msg. 43 | func (msg MsgTransferDomain) ValidateBasic() error { 44 | if _, err := sdk.AccAddressFromBech32(msg.Sender); err != nil { 45 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err) 46 | } 47 | return ValidateTokenID(msg.Id) 48 | } 49 | 50 | // GetSignBytes Implements Msg. 51 | func (msg MsgTransferDomain) GetSignBytes() []byte { 52 | bz := ModuleCdc.MustMarshalJSON(&msg) 53 | return sdk.MustSortJSON(bz) 54 | } 55 | 56 | // GetSigners Implements Msg. 57 | func (msg MsgTransferDomain) GetSigners() []sdk.AccAddress { 58 | from, err := sdk.AccAddressFromBech32(msg.Sender) 59 | if err != nil { 60 | panic(err) 61 | } 62 | return []sdk.AccAddress{from} 63 | } 64 | 65 | // NewMsgEditDomain is a constructor function for MsgSetName 66 | func NewMsgEditDomain(tokenID, tokenData, sender string) *MsgEditDomain { 67 | return &MsgEditDomain{ 68 | Id: tokenID, 69 | Data: tokenData, 70 | Sender: sender, 71 | } 72 | } 73 | 74 | // Route Implements Msg 75 | func (msg MsgEditDomain) Route() string { return RouterKey } 76 | 77 | // Type Implements Msg 78 | func (msg MsgEditDomain) Type() string { return TypeMsgEditDomain } 79 | 80 | // ValidateBasic Implements Msg. 81 | func (msg MsgEditDomain) ValidateBasic() error { 82 | if _, err := sdk.AccAddressFromBech32(msg.Sender); err != nil { 83 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err) 84 | } 85 | return ValidateTokenID(msg.Id) 86 | } 87 | 88 | // GetSignBytes Implements Msg. 89 | func (msg MsgEditDomain) GetSignBytes() []byte { 90 | bz := ModuleCdc.MustMarshalJSON(&msg) 91 | return sdk.MustSortJSON(bz) 92 | } 93 | 94 | // GetSigners Implements Msg. 95 | func (msg MsgEditDomain) GetSigners() []sdk.AccAddress { 96 | from, err := sdk.AccAddressFromBech32(msg.Sender) 97 | if err != nil { 98 | panic(err) 99 | } 100 | return []sdk.AccAddress{from} 101 | } 102 | 103 | // NewMsgRegisterDomain is a constructor function for MsgMintNFT 104 | func NewMsgRegisterDomain(tokenID, tokenData, sender, recipient string) *MsgRegisterDomain { 105 | return &MsgRegisterDomain{ 106 | Id: tokenID, 107 | Data: tokenData, 108 | Sender: sender, 109 | Recipient: recipient, 110 | } 111 | } 112 | 113 | // Route Implements Msg 114 | func (msg MsgRegisterDomain) Route() string { return RouterKey } 115 | 116 | // Type Implements Msg 117 | func (msg MsgRegisterDomain) Type() string { return TypeMsgRegisterDomain } 118 | 119 | // ValidateBasic Implements Msg. 120 | func (msg MsgRegisterDomain) ValidateBasic() error { 121 | if _, err := sdk.AccAddressFromBech32(msg.Sender); err != nil { 122 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err) 123 | } 124 | if _, err := sdk.AccAddressFromBech32(msg.Recipient); err != nil { 125 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid receipt address (%s)", err) 126 | } 127 | return ValidateTokenID(msg.Id) 128 | } 129 | 130 | // GetSignBytes Implements Msg. 131 | func (msg MsgRegisterDomain) GetSignBytes() []byte { 132 | bz := ModuleCdc.MustMarshalJSON(&msg) 133 | return sdk.MustSortJSON(bz) 134 | } 135 | 136 | // GetSigners Implements Msg. 137 | func (msg MsgRegisterDomain) GetSigners() []sdk.AccAddress { 138 | from, err := sdk.AccAddressFromBech32(msg.Sender) 139 | if err != nil { 140 | panic(err) 141 | } 142 | return []sdk.AccAddress{from} 143 | } 144 | 145 | // NewMsgRemoveDomain is a constructor function for MsgBurnNFT 146 | func NewMsgRemoveDomain(sender, tokenID string) *MsgRemoveDomain { 147 | return &MsgRemoveDomain{ 148 | Sender: sender, 149 | Id: tokenID, 150 | } 151 | } 152 | 153 | // Route Implements Msg 154 | func (msg MsgRemoveDomain) Route() string { return RouterKey } 155 | 156 | // Type Implements Msg 157 | func (msg MsgRemoveDomain) Type() string { return TypeMsgRemoveDomain } 158 | 159 | // ValidateBasic Implements Msg. 160 | func (msg MsgRemoveDomain) ValidateBasic() error { 161 | if _, err := sdk.AccAddressFromBech32(msg.Sender); err != nil { 162 | return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address (%s)", err) 163 | } 164 | return ValidateTokenID(msg.Id) 165 | } 166 | 167 | // GetSignBytes Implements Msg. 168 | func (msg MsgRemoveDomain) GetSignBytes() []byte { 169 | bz := ModuleCdc.MustMarshalJSON(&msg) 170 | return sdk.MustSortJSON(bz) 171 | } 172 | 173 | // GetSigners Implements Msg. 174 | func (msg MsgRemoveDomain) GetSigners() []sdk.AccAddress { 175 | from, err := sdk.AccAddressFromBech32(msg.Sender) 176 | if err != nil { 177 | panic(err) 178 | } 179 | return []sdk.AccAddress{from} 180 | } 181 | -------------------------------------------------------------------------------- /x/dns_module/module.go: -------------------------------------------------------------------------------- 1 | package dns_module 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "github.com/gorilla/mux" 8 | "github.com/grpc-ecosystem/grpc-gateway/runtime" 9 | "github.com/spf13/cobra" 10 | 11 | abci "github.com/tendermint/tendermint/abci/types" 12 | 13 | "github.com/cosmos/cosmos-sdk/client" 14 | "github.com/cosmos/cosmos-sdk/codec" 15 | codectypes "github.com/cosmos/cosmos-sdk/codec/types" 16 | sdk "github.com/cosmos/cosmos-sdk/types" 17 | "github.com/cosmos/cosmos-sdk/types/module" 18 | "github.com/deweb-services/deweb/x/dns_module/client/cli" 19 | "github.com/deweb-services/deweb/x/dns_module/keeper" 20 | "github.com/deweb-services/deweb/x/dns_module/types" 21 | ) 22 | 23 | var ( 24 | _ module.AppModule = AppModule{} 25 | _ module.AppModuleBasic = AppModuleBasic{} 26 | ) 27 | 28 | // AppModuleBasic defines the basic application module used by the NFT module. 29 | type AppModuleBasic struct { 30 | cdc codec.Codec 31 | } 32 | 33 | // Name returns the NFT module's name. 34 | func (AppModuleBasic) Name() string { return types.ModuleName } 35 | 36 | // RegisterLegacyAminoCodec registers the NFT module's types on the LegacyAmino codec. 37 | func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { 38 | types.RegisterLegacyAminoCodec(cdc) 39 | } 40 | 41 | // DefaultGenesis returns default genesis state as raw bytes for the NFT module. 42 | func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { 43 | return cdc.MustMarshalJSON(DefaultGenesisState()) 44 | } 45 | 46 | // ValidateGenesis performs genesis state validation for the NFT module. 47 | func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { 48 | var data types.GenesisState 49 | if err := cdc.UnmarshalJSON(bz, &data); err != nil { 50 | return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) 51 | } 52 | 53 | return types.ValidateGenesis(data) 54 | } 55 | 56 | // RegisterRESTRoutes registers the REST routes for the NFT module. 57 | func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { 58 | } 59 | 60 | // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the NFT module. 61 | func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { 62 | _ = types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) 63 | } 64 | 65 | // GetTxCmd returns the root tx command for the NFT module. 66 | func (AppModuleBasic) GetTxCmd() *cobra.Command { 67 | return cli.NewTxCmd() 68 | } 69 | 70 | // GetQueryCmd returns no root query command for the NFT module. 71 | func (AppModuleBasic) GetQueryCmd() *cobra.Command { 72 | return cli.GetQueryCmd() 73 | } 74 | 75 | // RegisterInterfaces registers interfaces and implementations of the NFT module. 76 | func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { 77 | types.RegisterInterfaces(registry) 78 | } 79 | 80 | // ____________________________________________________________________________ 81 | 82 | // AppModule implements an application module for the NFT module. 83 | type AppModule struct { 84 | AppModuleBasic 85 | 86 | keeper keeper.Keeper 87 | accountKeeper types.AccountKeeper 88 | bankKeeper types.BankKeeper 89 | } 90 | 91 | // NewAppModule creates a new AppModule object 92 | func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper) AppModule { 93 | return AppModule{ 94 | AppModuleBasic: AppModuleBasic{cdc: cdc}, 95 | keeper: keeper, 96 | accountKeeper: accountKeeper, 97 | bankKeeper: bankKeeper, 98 | } 99 | } 100 | 101 | // Name returns the NFT module's name. 102 | func (AppModule) Name() string { return types.ModuleName } 103 | 104 | // RegisterServices registers module services. 105 | func (am AppModule) RegisterServices(cfg module.Configurator) { 106 | types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) 107 | types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper)) 108 | } 109 | 110 | // RegisterInvariants registers the NFT module invariants. 111 | func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} 112 | 113 | // Route returns the message routing key for the NFT module. 114 | func (am AppModule) Route() sdk.Route { 115 | return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper)) 116 | } 117 | 118 | // QuerierRoute returns the NFT module's querier route name. 119 | func (AppModule) QuerierRoute() string { return types.RouterKey } 120 | 121 | // LegacyQuerierHandler returns the NFT module sdk.Querier. 122 | func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { 123 | return keeper.NewQuerier(am.keeper, legacyQuerierCdc) 124 | } 125 | 126 | // InitGenesis performs genesis initialization for the NFT module. It returns 127 | // no validator updates. 128 | func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { 129 | var genesisState types.GenesisState 130 | 131 | cdc.MustUnmarshalJSON(data, &genesisState) 132 | 133 | InitGenesis(ctx, am.keeper, genesisState) 134 | return []abci.ValidatorUpdate{} 135 | } 136 | 137 | // ExportGenesis returns the exported genesis state as raw bytes for the NFT module. 138 | func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { 139 | gs := ExportGenesis(ctx, am.keeper) 140 | return cdc.MustMarshalJSON(gs) 141 | } 142 | 143 | // ConsensusVersion implements AppModule/ConsensusVersion. 144 | func (AppModule) ConsensusVersion() uint64 { return 1 } 145 | 146 | // BeginBlock performs a no-op. 147 | func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { 148 | am.keeper.ProcessDomainsExpiration(ctx) 149 | } 150 | 151 | // EndBlock returns the end blocker for the NFT module. It returns no validator updates. 152 | func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { 153 | return []abci.ValidatorUpdate{} 154 | } 155 | -------------------------------------------------------------------------------- /docs/docs/fullnode/01-overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: overview 3 | title: Overview 4 | sidebar_label: Overview 5 | slug: overview 6 | --- 7 | 8 | import Tabs from '@theme/Tabs'; 9 | import TabItem from '@theme/TabItem'; 10 | 11 | # DWS fullnode overview 12 | 13 | A full-node is a program that fully validates transactions and blocks of a blockchain. It is distinct from a light-node 14 | that only processes block headers and a small subset of transactions. Running a full-node requires more resources than a 15 | light-node but is necessary in order to be a validator. In practice, running a full-node only implies running a 16 | non-compromised and up-to-date version of the software with low network latency and without downtime. 17 | 18 | Of course, it is possible and encouraged for users to run full-nodes even if they do not plan to be validators. 19 | 20 | ## Requirements 21 | 22 | ### Understanding pruning 23 | 24 | In order to run a full node, different hardware requirements should be met based on the pruning strategy you would like 25 | to use. 26 | 27 | _Pruning_ is the term used to identify the periodic action that can be taken in order to free some disk space on your 28 | full node. This is done by removing old blocks data from the disk, freeing up space. 29 | 30 | Inside DWS, there are various types of pruning strategies that can be applied. The main ones are: 31 | 32 | - `default`: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals; 33 | 34 | - `nothing`: all historic states will be saved, nothing will be deleted (i.e. archiving node); 35 | 36 | - `everything`: all saved states will be deleted, storing only the current state; pruning at 10 block intervals 37 | (At the moment this option is not recommended as it can easily corrupt the database and the node will halt); 38 | 39 | - `custom`: allow pruning options to be manually specified through `pruning-keep-recent`, `pruning-keep-every`, and `pruning-interval`. 40 | 41 | ### Hardware requirements 42 | 43 | You can easily understand how using a pruning strategy of `nothing` will use more disk space than `everything`. 44 | For this reason, there are different disk space that we recommend based on the pruning strategy you choose: 45 | 46 | | Pruning strategy | Minimum disk space | Recommended disk space | 47 | | :--------------: | :----------------: | :--------------------: | 48 | | `everything` | 20 GB | 60 GB | 49 | | `default` | 80 GB | 160 GB | 50 | | `nothing` | 120 GB | \> 300 GB | 51 | 52 | Apart from disk space, the following requirements should be met. 53 | 54 | | Minimum CPU cores | Recommended CPU cores | 55 | | :---------------: | :-------------------: | 56 | | 2 | 4 | 57 | 58 | | Minimum RAM | Recommended RAM | 59 | | :---------: | :-------------: | 60 | | 4 GB | 8 GB | 61 | 62 | ## 1. Setup your environment 63 | 64 | In order to run a fullnode, you need to build `dewebd` which requires `Go`, `git`, `gcc` and `make` installed. 65 | 66 | This process depends on your working environment. 67 | 68 | 76 | 77 | 78 | The following example is based on **Ubuntu (Debian)** and assumes you are using a terminal environment by default. 79 | Please run the equivalent commands if you are running other Linux distributions. 80 | 81 | ```bash 82 | # Update the system 83 | sudo apt update 84 | sudo apt upgrade 85 | 86 | # Install git, gcc and make 87 | sudo apt install git build-essential ufw curl jq snapd --yes 88 | 89 | # Install Go with Snap 90 | sudo snap install go --classic 91 | 92 | # Export environment variables 93 | echo 'export GOPATH="$HOME/go"' >> ~/.profile 94 | echo 'export GOBIN="$GOPATH/bin"' >> ~/.profile 95 | echo 'export PATH="$GOBIN:$PATH"' >> ~/.profile 96 | source ~/.profile 97 | ``` 98 | 99 | 100 | 101 | 102 | 103 | To install the required build tools, 104 | simple [install Xcode from the Mac App Store](https://apps.apple.com/hk/app/xcode/id497799835?l=en&mt=12). 105 | 106 | To install `Go` on **MacOS**, the best option is to install with [**Homebrew**](https://brew.sh/). To do so, open 107 | the `Terminal` application and run the following command: 108 | 109 | ```bash 110 | # Install Homebrew 111 | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 112 | ``` 113 | 114 | > If you don't know how to open a `Terminal`, you can search it by typing `terminal` in `Spotlight`(to access spotlight press cmd + spacebar simultaneously). 115 | 116 | After **Homebrew** is installed, run 117 | 118 | ```bash 119 | # Install software using Homebrew 120 | brew install go git curl jq 121 | 122 | # Export environment variables 123 | echo 'export GOPATH="$HOME/go"' >> ~/.profile 124 | echo 'export GOBIN="$GOPATH/bin"' >> ~/.profile 125 | echo 'export PATH="$GOBIN:$PATH"' >> ~/.profile 126 | source ~/.profile 127 | ``` 128 | 129 | 130 | 131 | 132 | 133 | The software has not been tested on **Windows** If you are currently running a **Windows** PC, the following options 134 | should be considered: 135 | 136 | 1. Switch to a **Mac** 👨‍💻. 137 | 2. Wipe your hard drive and install a **Linux** system on your PC. 138 | 3. Install a separate **Linux** system using [VirtualBox](https://www.virtualbox.org/wiki/Downloads) 139 | 4. Run a **Linux** instance on a cloud provider. 140 | 141 | Note that is still possible to build and run the software on **Windows** but it may give you unexpected results and it 142 | may require additional setup to be done. If you insist to build and run the software on **Windows**, the best bet would 143 | be installing the [Chocolatey](https://chocolatey.org/) package manager. 144 | 145 | 146 | 147 | 148 | 149 | ## 2. Install the software 150 | 151 | Once you have set up your environment correctly, you are now ready to install the DWS software and start your full 152 | node. 153 | 154 | In order to do so, you can follow our [setup guide](02-validator-setup.md). 155 | -------------------------------------------------------------------------------- /docs/docs/domains/dws-domains.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # DWS Domains 6 | 7 | Decentralized Web Services Blockchain has a DWS Domains module. User can buy domain of any level. 8 | 9 | Initial Top-level domain (TLD) price is defined in genesis as 100 DWS and can be changed via the governance proposal. 10 | 11 | Each domain ownership is 2 years from buy time. After 2 years the domain owner has the 2 weeks window to extend the ownership by pay the full price (100 DWS). 12 | 13 | For example Alice can buy domain `hello/` for 100 DWS. Then Alice can say that anyone can buy a subdomain `*.hello/` for 10 DWS. Any subdomain which Alice will sell will belong to the buyer for 2 years. 14 | 15 | For example Bob will buy domain `bob.hello` for 10 DWS. 10 DWS will be transfered to Alice and Bob will get `bob.hello` domain ownership for 2 years. Alice will not have any permission to get this domain back from Bob. After 2 years Bob will have a 2 weeks window to extend the ownership for 10 DWS, which will be transfered to Alice. If Alice changed the price of subdomains to 20 DWS, Bob will still pay 10 DWS per 2 years, as it was the initial price. 16 | 17 | ## Buy domain 18 | 19 | If we want to buy a domain, we can set DNS records: 20 | 21 | ``` 22 | BasicDataEmpty='{}' 23 | BasicData='{"records": [{"type": "A","values": ["192.168.1.10"]}]}' 24 | BasicDataWithSubPrice='{"records":[{"type": "A","values":["192.168.1.10"]}],"sub_domains_sale": true,"sub_domains_sale_price": 10000}' 25 | BasicDataWithMX='{"records": [{"type": "A","values": ["192.168.1.10"]},{"type": "MX","values": ["10 mx.bob.alice.deweb."]}]}' 26 | BasicDataWithCNAME='{"records": [{"type": "CNAME","values": ["test.deweb.com."]}]}' 27 | ``` 28 | 29 | If we want to start selling the subdomains, we should set `"sub_domains_sale": true` and `"sub_domains_sale_price": 10000`, where `sub_domains_sale_price` is in `udws` denom. 30 | 31 | First we can mint a TLD `deweb`: 32 | 33 | ``` 34 | # how to: 35 | # dewebd tx domain register --data="$BasicData" --from bob --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 36 | dewebd tx domain register deweb --data="$BasicData" --from bob --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 37 | ``` 38 | 39 | ## Extend domain ownership (Prolongation) 40 | 41 | Prolongation request is sent via the register command. It is allowed only for the domain owner. Other users will receive the message that 42 | the domain is already registered. 43 | 44 | Let's create a domain `test.deweb`: 45 | 46 | ``` 47 | dewebd tx domain register test.deweb --data="$BasicData" --from bob --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 48 | ``` 49 | 50 | If Alice will try to register domain in Bob's zone she will receive an error `parent domain check error: domain deweb does not belong to this user`: 51 | 52 | ``` 53 | dewebd tx domain register alice.deweb --data="$BasicData" --from alice --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 54 | ``` 55 | 56 | ## Edit domain settings 57 | 58 | Bob can edit domain and allow anyone to buy subdomains of the domain he own. He will receive payments for these domains: 59 | 60 | ``` 61 | BasicDataWithSubPrice='{"records":[{"type": "A","values":["192.168.1.10"]}],"sub_domains_sale": true,"sub_domains_sale_price": 10000}' 62 | dewebd tx domain edit deweb --data="BasicDataWithSubPrice" --from bob --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 63 | ``` 64 | 65 | ## Subdomain ownership examples 66 | 67 | Then Alice can register subdomain and pay the fee to Bob: 68 | 69 | ``` 70 | BasicData='{"records": [{"type": "A","values": ["192.168.1.10"]}]}' 71 | dewebd tx domain register newalice.deweb --data="$BasicData" --from alice --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 72 | ``` 73 | 74 | But Bob also can register subdomain for Alice (her address `deweb1x6s67chad4p2rznmclskw7xr3qfppfhjkqs3ee`): 75 | 76 | ``` 77 | dewebd tx domain register alice.deweb --data="$BasicData" --recipient=deweb1x6s67chad4p2rznmclskw7xr3qfppfhjkqs3ee --from bob --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 78 | ``` 79 | 80 | Then Alice can register domain `www.alice.deweb` because she is the owner of `alice.deweb`: 81 | 82 | ``` 83 | dewebd tx domain register www.aliced.deweb --data="$BasicData" --from alice --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 84 | ``` 85 | 86 | Alice can register domain for Bob in her zone and then transfer this Domain to Bob, so he will become an owner of `bob.alice.deweb`: 87 | 88 | ``` 89 | dewebd tx domain register bob.aliced.deweb --data="$BasicData" --from alice --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 90 | ``` 91 | 92 | ## 2-step transfer 93 | 94 | This is used to sell the domain to exact deweb address for exact price. 95 | 96 | Firstly the domain owner Alice sends the transaction with expected domain receiver and price. Only selected receiver Bob (his address is `deweb138sq5w8yxsdzgvs7lse5j3dtr3e2t5z08cw8aj`) can buy the domain. If no receiver determined, anyone can buy this domain. 97 | 98 | ``` 99 | dewebd tx domain transfer bob.aliced.deweb --recipient=deweb138sq5w8yxsdzgvs7lse5j3dtr3e2t5z08cw8aj --price=10000 --from alice --chain-id deweb-2 --gas 2000000 --output json -b block 100 | dewebd tx domain transfer bob.aliced.deweb --from bob --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 101 | ``` 102 | 103 | To cancel created transfer: 104 | 105 | ``` 106 | dewebd tx domain transfer bob.aliced.deweb --cancel=true --from alice --chain-id deweb-testnet-sirius --gas 2000000 --output json -b block 107 | ``` 108 | 109 | ## Module parameters 110 | 111 | Parameters that can be changed via Government proposal: 112 | 113 | - DomainPrice 114 | - DomainExpiration 115 | - DomainOwnerProlongation 116 | - BlockedTLDs 117 | 118 | ```json title="dns_proposal.json" 119 | { 120 | "title": "Increase the lease time for domains", 121 | "description": "Set lease time to 60 minutes for domains", 122 | "changes": [ 123 | { 124 | "subspace": "nft", 125 | "key": "DomainExpiration", 126 | "value": "60" 127 | } 128 | ], 129 | "deposit": "10000000udws" 130 | } 131 | ``` 132 | 133 | Submit proposal: 134 | 135 | ``` 136 | dewebd tx gov submit-proposal param-change dns_proposal.json --from alice --chain-id deweb-testnet-sirius --gas 2000000 137 | ``` 138 | --------------------------------------------------------------------------------