refactor/internal (#1216)

* refactor: update import paths in gateway handlers

* refactor: remove obsolete devtools Makefile and README

* build: optimize build process for improved efficiency

* refactor: remove obsolete pkl files related to Matrix and Sonr network configurations

* refactor: move embed code to x/dwn/types
This commit is contained in:
Prad Nukala
2024-12-24 16:10:20 +00:00
committed by GitHub
parent 0ec2f7d86a
commit 47c3a53080
356 changed files with 402 additions and 1613 deletions
+80
View File
@@ -0,0 +1,80 @@
package common
import (
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
nodev1beta1 "github.com/cosmos/cosmos-sdk/client/grpc/node"
didv1 "github.com/onsonr/sonr/api/did/v1"
dwnv1 "github.com/onsonr/sonr/api/dwn/v1"
svcv1 "github.com/onsonr/sonr/api/svc/v1"
"google.golang.org/grpc"
)
type (
StatusResponse = nodev1beta1.StatusResponse // StatusResponse is the response type for the Service.Status RPC method.
StatusRequest = nodev1beta1.StatusRequest // StatusRequest is the request type for the Service.Status RPC method.
BalanceRequest = bankv1beta1.QueryBalanceRequest // BalanceRequest is the request type for the Bank.Balance RPC method.
BalanceResponse = bankv1beta1.QueryBalanceResponse // BalanceResponse is the response type for the Bank.Balance RPC method.
AllBalancesRequest = bankv1beta1.QueryAllBalancesRequest // AllBalancesRequest is the request type for the Bank.AllBalances RPC method.
AllBalancesResponse = bankv1beta1.QueryAllBalancesResponse // AllBalancesResponse is the response type for the Bank.AllBalances RPC method.
TotalSupplyRequest = bankv1beta1.QueryTotalSupplyRequest // TotalSupplyRequest is the request type for the Bank.TotalSupply RPC method.
TotalSupplyResponse = bankv1beta1.QueryTotalSupplyResponse // TotalSupplyResponse is the response type for the Bank.TotalSupply RPC method.
DenomMetadataRequest = bankv1beta1.QueryDenomMetadataRequest // DenomMetadataRequest is the request type for the Bank.DenomMetadata RPC method.
DenomMetadataResponse = bankv1beta1.QueryDenomMetadataResponse // DenomMetadataResponse is the response type for the Bank.DenomMetadata RPC method.
BankParamsRequest = bankv1beta1.QueryParamsRequest // BankParamsRequest is the request type for the Bank.Params RPC method.
BankParamsResponse = bankv1beta1.QueryParamsResponse // BankParamsResponse is the response type for the Bank.Params RPC method.
DIDParamsRequest = didv1.QueryRequest // DIDParamsRequest is the request type for the DID.Params RPC method.
DIDParamsResponse = didv1.QueryParamsResponse // DIDParamsResponse is the response type for the DID.Params RPC method.
DIDResolveResponse = didv1.QueryResolveResponse // DIDResolveResponse is the response type for the DID.Resolve RPC method.
DWNParamsRequest = dwnv1.QueryParamsRequest // DWNParamsRequest is the request type for the DWN.Params RPC method.
DWNParamsResponse = dwnv1.QueryParamsResponse // DWNParamsResponse is the response type for the DWN.Params RPC method.
SVCParamsRequest = svcv1.QueryParamsRequest // SVCParamsRequest is the request type for the SVC.Params RPC method.
SVCParamsResponse = svcv1.QueryParamsResponse // SVCParamsResponse is the response type for the SVC.Params RPC method.
)
func conn(addr string) (*grpc.ClientConn, error) {
grpcConn, err := grpc.NewClient(addr, grpc.WithInsecure())
if err != nil {
return nil, err
}
return grpcConn, nil
}
func NewBankClient(addr string) (bankv1beta1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return bankv1beta1.NewQueryClient(conn), nil
}
func NewDIDClient(addr string) (didv1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return didv1.NewQueryClient(conn), nil
}
func NewDWNClient(addr string) (dwnv1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return dwnv1.NewQueryClient(conn), nil
}
func NewNodeClient(addr string) (nodev1beta1.ServiceClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return nodev1beta1.NewServiceClient(conn), nil
}
func NewSVCClient(addr string) (svcv1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return svcv1.NewQueryClient(conn), nil
}
+124
View File
@@ -0,0 +1,124 @@
package common
import (
"encoding/base64"
"net/http"
"time"
"github.com/labstack/echo/v4"
)
// CookieKey is a type alias for string.
type CookieKey string
const (
// SessionID is the key for the session ID cookie.
SessionID CookieKey = "session.id"
// SessionChallenge is the key for the session challenge cookie.
SessionChallenge CookieKey = "session.challenge"
// SessionRole is the key for the session role cookie.
SessionRole CookieKey = "session.role"
// SonrAddress is the key for the Sonr address cookie.
SonrAddress CookieKey = "sonr.address"
// SonrDID is the key for the Sonr DID cookie.
SonrDID CookieKey = "sonr.did"
// UserAvatar is the key for the User Avatar cookie.
UserAvatar CookieKey = "user.avatar"
// UserHandle is the key for the User Handle cookie.
UserHandle CookieKey = "user.handle"
// UserName is the key for the User Name cookie.
UserName CookieKey = "user.full_name"
// VaultAddress is the key for the Vault address cookie.
VaultAddress CookieKey = "vault.address"
// VaultCID is the key for the Vault CID cookie.
VaultCID CookieKey = "vault.cid"
// VaultSchema is the key for the Vault schema cookie.
VaultSchema CookieKey = "vault.schema"
)
// String returns the string representation of the CookieKey.
func (c CookieKey) String() string {
return string(c)
}
// ╭───────────────────────────────────────────────────────────╮
// │ Utility Methods │
// ╰───────────────────────────────────────────────────────────╯
func CookieExists(c echo.Context, key CookieKey) bool {
ck, err := c.Cookie(key.String())
if err != nil {
return false
}
return ck != nil
}
func ReadCookie(c echo.Context, key CookieKey) (string, error) {
cookie, err := c.Cookie(key.String())
if err != nil {
// Cookie not found or other error
return "", err
}
if cookie == nil || cookie.Value == "" {
// Cookie is empty
return "", http.ErrNoCookie
}
return cookie.Value, nil
}
func ReadCookieBytes(c echo.Context, key CookieKey) ([]byte, error) {
cookie, err := c.Cookie(key.String())
if err != nil {
// Cookie not found or other error
return nil, err
}
if cookie == nil || cookie.Value == "" {
// Cookie is empty
return nil, http.ErrNoCookie
}
return base64.RawURLEncoding.DecodeString(cookie.Value)
}
func ReadCookieUnsafe(c echo.Context, key CookieKey) string {
ck, err := c.Cookie(key.String())
if err != nil {
return ""
}
return ck.Value
}
func WriteCookie(c echo.Context, key CookieKey, value string) error {
cookie := &http.Cookie{
Name: key.String(),
Value: value,
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Path: "/",
// Add Secure and SameSite attributes as needed
}
c.SetCookie(cookie)
return nil
}
func WriteCookieBytes(c echo.Context, key CookieKey, value []byte) error {
cookie := &http.Cookie{
Name: key.String(),
Value: base64.RawURLEncoding.EncodeToString(value),
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Path: "/",
// Add Secure and SameSite attributes as needed
}
c.SetCookie(cookie)
return nil
}
+52
View File
@@ -0,0 +1,52 @@
package common
import "github.com/labstack/echo/v4"
type HeaderKey string
const (
Authorization HeaderKey = "Authorization"
// User Agent
Architecture HeaderKey = "Sec-CH-UA-Arch"
Bitness HeaderKey = "Sec-CH-UA-Bitness"
FullVersionList HeaderKey = "Sec-CH-UA-Full-Version-List"
Mobile HeaderKey = "Sec-CH-UA-Mobile"
Model HeaderKey = "Sec-CH-UA-Model"
Platform HeaderKey = "Sec-CH-UA-Platform"
PlatformVersion HeaderKey = "Sec-CH-UA-Platform-Version"
UserAgent HeaderKey = "Sec-CH-UA"
// Sonr Injected
SonrAPIURL HeaderKey = "X-Sonr-API"
SonrgRPCURL HeaderKey = "X-Sonr-GRPC"
SonrRPCURL HeaderKey = "X-Sonr-RPC"
SonrWSURL HeaderKey = "X-Sonr-WS"
)
func (h HeaderKey) String() string {
return string(h)
}
// ╭───────────────────────────────────────────────────────────╮
// │ Utility Methods │
// ╰───────────────────────────────────────────────────────────╯
func HeaderEquals(c echo.Context, key HeaderKey, value string) bool {
return c.Response().Header().Get(key.String()) == value
}
// HeaderExists returns true if the request has the header Key.
func HeaderExists(c echo.Context, key HeaderKey) bool {
return c.Response().Header().Get(key.String()) != ""
}
// HeaderRead returns the header value for the Key.
func HeaderRead(c echo.Context, key HeaderKey) string {
return c.Response().Header().Get(key.String())
}
// HeaderWrite sets the header value for the Key.
func HeaderWrite(c echo.Context, key HeaderKey, value string) {
c.Response().Header().Set(key.String(), value)
}
+136
View File
@@ -0,0 +1,136 @@
package common
import (
"bytes"
"context"
"fmt"
"io"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/client/rpc"
"github.com/ipfs/kubo/core/coreiface/options"
)
// IPFS represents a wrapper interface abstracting the localhost api
type IPFS interface {
Add(data []byte) (string, error)
AddFile(file File) (string, error)
AddFolder(folder Folder) (string, error)
Exists(cid string) (bool, error)
Get(cid string) ([]byte, error)
IsPinned(ipns string) (bool, error)
Ls(cid string) ([]string, error)
Pin(cid string, name string) error
Unpin(cid string) error
}
type File interface {
files.File
Name() string
}
func NewFileMap(vs []File) map[string]files.Node {
m := make(map[string]files.Node)
for _, f := range vs {
m[f.Name()] = f
}
return m
}
type client struct {
api *rpc.HttpApi
}
func NewIPFS() (IPFS, error) {
api, err := rpc.NewLocalApi()
if err != nil {
return nil, err
}
return &client{api: api}, nil
}
func (c *client) Add(data []byte) (string, error) {
file := files.NewBytesFile(data)
cidFile, err := c.api.Unixfs().Add(context.Background(), file)
if err != nil {
return "", err
}
return cidFile.String(), nil
}
func (c *client) Get(cid string) ([]byte, error) {
p, err := path.NewPath(cid)
if err != nil {
return nil, err
}
node, err := c.api.Unixfs().Get(context.Background(), p)
if err != nil {
return nil, err
}
file, ok := node.(files.File)
if !ok {
return nil, fmt.Errorf("unexpected node type: %T", node)
}
buf := new(bytes.Buffer)
if _, err := io.Copy(buf, file); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (c *client) IsPinned(ipns string) (bool, error) {
_, err := c.api.Name().Resolve(context.Background(), ipns)
if err != nil {
return false, nil
}
return true, nil
}
func (c *client) Exists(cid string) (bool, error) {
p, err := path.NewPath(cid)
if err != nil {
return false, err
}
_, err = c.api.Block().Stat(context.Background(), p)
if err != nil {
return false, nil
}
return true, nil
}
func (c *client) Pin(cid string, name string) error {
p, err := path.NewPath(cid)
if err != nil {
return err
}
return c.api.Pin().Add(context.Background(), p, options.Pin.Name(name))
}
func (c *client) Unpin(cid string) error {
p, err := path.NewPath(cid)
if err != nil {
return err
}
return c.api.Pin().Rm(context.Background(), p)
}
func (c *client) Ls(cid string) ([]string, error) {
p, err := path.NewPath(cid)
if err != nil {
return nil, err
}
node, err := c.api.Unixfs().Ls(context.Background(), p)
if err != nil {
return nil, err
}
var files []string
for entry := range node {
files = append(files, entry.Name)
}
return files, nil
}
+28
View File
@@ -0,0 +1,28 @@
package common
import (
"context"
"github.com/ipfs/boxo/files"
)
type file struct {
files.File
name string
}
func (f *file) Name() string {
return f.name
}
func NewFile(name string, data []byte) File {
return &file{File: files.NewBytesFile(data), name: name}
}
func (c *client) AddFile(file File) (string, error) {
cidFile, err := c.api.Unixfs().Add(context.Background(), file)
if err != nil {
return "", err
}
return cidFile.String(), nil
}
+21
View File
@@ -0,0 +1,21 @@
package common
import (
"context"
"github.com/ipfs/boxo/files"
)
type Folder = files.Directory
func NewFolder(fs ...File) Folder {
return files.NewMapDirectory(NewFileMap(fs))
}
func (c *client) AddFolder(folder Folder) (string, error) {
cidFile, err := c.api.Unixfs().Add(context.Background(), folder)
if err != nil {
return "", err
}
return cidFile.String(), nil
}
+142
View File
@@ -0,0 +1,142 @@
package common
import (
"context"
"fmt"
"sort"
"sync"
"github.com/golang-jwt/jwt"
"github.com/ipfs/go-cid"
"github.com/onsonr/sonr/internal/crypto/keys"
"github.com/onsonr/sonr/internal/crypto/ucan"
)
type IPFSTokenStore interface {
ucan.TokenStore
ResolveCIDBytes(ctx context.Context, id cid.Cid) ([]byte, error)
ResolveDIDKey(ctx context.Context, did string) (keys.DID, error)
}
// ipfsUCANStore is a token store that uses IPFS to store tokens. It uses the memory store as a cache
// for CID strings to be used as keys for retrieving tokens.
type ipfsUCANStore struct {
sync.Mutex
ipfs IPFS
cache map[string]string
}
// NewUCANStore creates a new IPFS-backed token store
func NewUCANStore(ipfsClient IPFS) IPFSTokenStore {
return &ipfsUCANStore{
ipfs: ipfsClient,
cache: make(map[string]string),
}
}
func (st *ipfsUCANStore) PutToken(ctx context.Context, key string, raw string) error {
// Validate token format
p := &jwt.Parser{
UseJSONNumber: true,
SkipClaimsValidation: false,
}
if _, _, err := p.ParseUnverified(raw, jwt.MapClaims{}); err != nil {
return fmt.Errorf("%w: %s", ucan.ErrInvalidToken, err)
}
// Store token in IPFS
cid, err := st.ipfs.Add([]byte(raw))
if err != nil {
return fmt.Errorf("failed to store token in IPFS: %w", err)
}
// Update cache
st.Lock()
defer st.Unlock()
st.cache[key] = cid
return nil
}
func (st *ipfsUCANStore) RawToken(ctx context.Context, key string) (string, error) {
st.Lock()
cid, exists := st.cache[key]
st.Unlock()
if !exists {
return "", ucan.ErrTokenNotFound
}
// Retrieve token from IPFS
data, err := st.ipfs.Get(cid)
if err != nil {
return "", fmt.Errorf("failed to retrieve token from IPFS: %w", err)
}
return string(data), nil
}
func (st *ipfsUCANStore) DeleteToken(ctx context.Context, key string) error {
st.Lock()
defer st.Unlock()
cid, exists := st.cache[key]
if !exists {
return ucan.ErrTokenNotFound
}
// Unpin from IPFS
if err := st.ipfs.Unpin(cid); err != nil {
return fmt.Errorf("failed to unpin token from IPFS: %w", err)
}
delete(st.cache, key)
return nil
}
func (st *ipfsUCANStore) ListTokens(ctx context.Context, offset, limit int) ([]ucan.RawToken, error) {
st.Lock()
defer st.Unlock()
tokens := make(ucan.RawTokens, 0, len(st.cache))
for key, cid := range st.cache {
data, err := st.ipfs.Get(cid)
if err != nil {
continue // Skip invalid tokens
}
tokens = append(tokens, ucan.RawToken{
Key: key,
Raw: string(data),
})
}
// Sort tokens
sort.Sort(tokens)
// Apply pagination
if offset >= len(tokens) {
return []ucan.RawToken{}, nil
}
end := offset + limit
if end > len(tokens) || limit <= 0 {
end = len(tokens)
}
return tokens[offset:end], nil
}
func (st *ipfsUCANStore) ResolveCIDBytes(ctx context.Context, id cid.Cid) ([]byte, error) {
data, err := st.ipfs.Get(id.String())
if err != nil {
return nil, fmt.Errorf("failed to resolve CID bytes: %w", err)
}
return data, nil
}
func (st *ipfsUCANStore) ResolveDIDKey(ctx context.Context, did string) (keys.DID, error) {
id, err := keys.Parse(did)
if err != nil {
return keys.DID{}, fmt.Errorf("failed to parse DID: %w", err)
}
return id, nil
}