├── 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 | 
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 | 
4 |
5 | [](https://github.com/deweb-services/deweb/releases)
6 | 
7 | [](https://discord.gg/dws)
8 | [](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 |
--------------------------------------------------------------------------------