-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/highway middleware #800
Conversation
… service proxies * refactor(auth.go): replace mdw.GetServiceRecord with serviceproxy.GetServiceRecord * refactor(auth.go): replace mdw.GetEmailRecordCreator with domainproxy.GetEmailRecordCreator * refactor(auth.go): replace mdw.GetControllerAccount with identityproxy.GetControllerAccount * chore(params.go): import domainproxy and serviceproxy packages * fix(params.go): update CheckAliasAvailable function call to use domainproxy.CheckAliasAvailable * fix(params.go): update GetServiceRecord function call to use serviceproxy.GetServiceRecord * fix(params.go): update CheckAliasUnavailable function call to use domainproxy.CheckAliasUnavailable * chore(broadcaster.go): remove unused imports and commented code * feat(broadcaster.go): remove PublishControllerAccount function * feat(broadcaster.go): remove CreateOrganizationRecord function * chore(checker.go): remove unused middleware package * chore(checker.go): remove unused imports * chore(checker.go): remove unused functions CheckAliasAvailable and CheckAliasUnavailable * chore(retriever.go): remove unused imports * chore(retriever.go): remove unused variables * chore(retriever.go): remove unused functions * chore(retriever.go): remove unused package * chore(verifier.go): import context package * chore(verifier.go): import domainproxy package * chore(verifier.go): import domaintypes package * chore(verifier.go): import identityproxy package * chore(verifier.go): import identitytypes package * refactor(verifier.go): remove unused import * refactor(verifier.go): remove unused code * refactor(verifier.go): replace GetEmailRecordCreator with domainproxy.GetEmailRecordCreator * refactor(verifier.go): replace GetControllerAccount with identityproxy.GetControllerAccount * refactor(verifier.go): replace GetControllerAccount with identityproxy.GetControllerAccount * refactor(verifier.go): replace VerifySessionJWTClaims with types.VerifySessionJWTClaims * feat(verifier.go): add PublishControllerAccount function to create and publish a new controller account to the blockchain * feat(verifier.go): add CreateOrganizationRecord function to create and publish a new organization record to the blockchain * feat(query.go): add GetEmailRecordCreator function to retrieve the DIDDocument of a given DID or Alias * feat(query.go): add CheckAliasAvailable function to check if an alias is available * feat(query.go): add CheckAliasUnavailable function to check if an alias is unavailable * feat(query.go): add GetControllerAccount function to retrieve the DIDDocument of a given DID or Alias * feat(query.go): add GetDIDByAlias function to retrieve the DIDDocument of a given DID or Alias * feat(query.go): add GetServiceRecord function to retrieve the DIDDocument of a given DID or Alias * feat(query.go): create a gRPC connection to the server using the provided address and insecure transport * feat(query.go): make a gRPC request to retrieve the ServiceRecord for the given origin
* chore(context.go): rename LocalContext to AppContext * chore(context.go): update function signature for Context * chore(context.go): update function signature for HomeDir
* chore(defaults.go): remove unused Masthead constant * chore(defaults.go): remove unused Init function * chore(defaults.go): remove unused initSDKConfig function * chore(defaults.go): remove unused initSonrConfig function * chore(defaults.go): remove unused default configuration values * refactor(root.go): remove unused import statement * feat(root.go): add import statement for sonrdconfig package * fix(root.go): update Long description to use sonrdconfig.Masthead * refactor(root.go): remove initSDKConfig and initSonrConfig function calls, replace with sonrdconfig.Init() call * fix(defaults.go): update default values for node.rpc.host and node.rpc.port
* fix(root.go): set MinGasPrices to "0.00usnr" to allow 0 gas transactions * fix(root.go): enable iavl fast node for upgraded nodes
* chore(.goreleaser.yaml): update release name template to include Sonr and version identifier
* feat(publish.yml): schedule the workflow to run daily at 9 AM PST * feat(publish.yml): add step to publish drafts created yesterday
SonarCloud Quality Gate failed. 0 Bugs 0.0% Coverage Catch issues before they fail your Quality Gate with our IDE extension SonarLint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feedback from Senior Dev Bot
package domainproxy | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
domaintypes "github.com/sonrhq/core/x/domain/types" | ||
"github.com/spf13/viper" | ||
"google.golang.org/grpc" | ||
) | ||
|
||
// GetEmailRecordCreator returns the DIDDocument of a given DID or Alias | ||
func GetEmailRecordCreator(ctx context.Context, index string) (string, error) { | ||
addr := fmt.Sprintf("%s:%d", viper.GetString("node.grpc.host"), viper.GetInt("node.grpc.port")) | ||
// Create a connection to the gRPC server. | ||
grpcConn, err := grpc.Dial( | ||
addr, | ||
grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. | ||
) | ||
if err != nil { | ||
return "", err | ||
} | ||
defer grpcConn.Close() | ||
qc := domaintypes.NewQueryClient(grpcConn) | ||
resp, err := qc.UsernameRecord(ctx, &domaintypes.QueryGetUsernameRecordsRequest{Index: index}) | ||
if err != nil { | ||
return "", err | ||
} | ||
return resp.UsernameRecords.Address, nil | ||
} | ||
|
||
// CheckAliasAvailable returns the DIDDocument of a given DID or Alias | ||
func CheckAliasAvailable(ctx context.Context, alias string) (bool, error) { | ||
addr, err := GetEmailRecordCreator(ctx, alias) | ||
if err != nil { | ||
return false, err | ||
} | ||
return addr == "", nil | ||
} | ||
|
||
// CheckAliasUnavailable returns the DIDDocument of a given DID or Alias | ||
func CheckAliasUnavailable(ctx context.Context, alias string) (bool, error) { | ||
addr, err := GetEmailRecordCreator(ctx, alias) | ||
if err != nil { | ||
return false, err | ||
} | ||
return addr != "", nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
The code changes look good. The new functions CheckAliasAvailable
and CheckAliasUnavailable
make use of the existing GetEmailRecordCreator
function to check if an alias is available or unavailable. The code follows the best practices of using context and handling errors properly.
package identityproxy | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
identitytypes "github.com/sonrhq/core/x/identity/types" | ||
"github.com/spf13/viper" | ||
"google.golang.org/grpc" | ||
) | ||
|
||
// GetControllerAccount returns the DIDDocument of a given DID or Alias | ||
func GetControllerAccount(ctx context.Context, address string) (*identitytypes.ControllerAccount, error) { | ||
addr := fmt.Sprintf("%s:%d", viper.GetString("node.grpc.host"), viper.GetInt("node.grpc.port")) | ||
// Create a connection to the gRPC server. | ||
grpcConn, err := grpc.Dial( | ||
addr, | ||
grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer grpcConn.Close() | ||
qc := identitytypes.NewQueryClient(grpcConn) | ||
resp, err := qc.ControllerAccount(ctx, &identitytypes.QueryGetControllerAccountRequest{Address: address}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &resp.ControllerAccount, nil | ||
} | ||
|
||
// GetDIDByAlias returns the DIDDocument of a given DID or Alias | ||
func GetDIDByAlias(ctx context.Context, alias string) (*identitytypes.DIDDocument, error) { | ||
addr := fmt.Sprintf("%s:%d", viper.GetString("node.grpc.host"), viper.GetInt("node.grpc.port")) | ||
// Create a connection to the gRPC server. | ||
grpcConn, err := grpc.Dial( | ||
addr, | ||
grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer grpcConn.Close() | ||
qc := identitytypes.NewQueryClient(grpcConn) | ||
resp, err := qc.DidByAlsoKnownAs(ctx, &identitytypes.QueryDidByAlsoKnownAsRequest{Alias: alias}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &resp.DidDocument, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good overall. Here are a few suggestions to improve the code:
- Import Grouping: Group import statements together for better readability. It is a best practice to have two separate groups for standard library packages and third-party packages.
import (
"context"
"fmt"
"google.golang.org/grpc"
"github.com/spf13/viper"
identitytypes "github.com/sonrhq/core/x/identity/types"
)
- Error Handling: The code should check for errors when dialing the gRPC server and closing the gRPC connection. It's a good practice to handle errors explicitly.
...
// Create a connection to the gRPC server.
grpcConn, err := grpc.Dial(
addr,
grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism.
)
if err != nil {
return nil, fmt.Errorf("unable to connect to gRPC server: %w", err)
}
defer func() {
if closeErr := grpcConn.Close(); closeErr != nil {
// Handle error while closing the gRPC connection, if required.
fmt.Printf("error closing gRPC connection: %v\n", closeErr)
}
}()
...
- Configuration: The code is using
viper
to retrieve the gRPC server address and port. Make sure that the necessary configuration values (node.grpc.host
andnode.grpc.port
) are set correctly before invoking these functions.
Overall, the code changes are good and follow best practices. However, it's always a good idea to add proper error handling and check the configuration values before using them.
|
||
mdw "github.com/sonrhq/core/internal/highway/middleware" | ||
"github.com/sonrhq/core/internal/highway/types" | ||
domainproxy "github.com/sonrhq/core/x/domain/client/proxy" | ||
identityproxy "github.com/sonrhq/core/x/identity/client/proxy" | ||
serviceproxy "github.com/sonrhq/core/x/service/client/proxy" | ||
) | ||
|
||
// RegisterEscrowIdentity returns the credential assertion options to start account login. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good. They add import statements for the domainproxy
, identityproxy
, and serviceproxy
packages. As long as these packages are being used correctly elsewhere in the code, these import statements are necessary for the code to compile and run correctly.
origin := c.Query("amount") | ||
alias := c.Query("email") | ||
|
||
record, err := mdw.GetServiceRecord(origin) | ||
record, err := serviceproxy.GetServiceRecord(c.Request.Context(), origin) | ||
if err != nil { | ||
c.JSON(500, gin.H{"error": err.Error(), "where": "GetServiceRecord"}) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good overall. However, there are a couple of improvements that can be made:
-
Error handling: When handling errors, it is best to follow the principle of "fail early, fail loud". In the original code, the error is simply logged and a generic 500 error response is returned. It would be more helpful to provide specific error messages based on the type of error encountered. For example, if the error is due to a service not being available, you can return a more specific error message indicating that the service is unavailable. This would help in troubleshooting and debugging.
-
Context propagation: The code change introduces passing the request context to the
GetServiceRecord
function. This is a good practice as it allows for proper context propagation and cancellation. However, it is important to ensure that the context passed is appropriately canceled when the request is aborted. This can be achieved by using methods likeWithCancel
orWithTimeout
on the context.
attestionResp := c.Query("attestation") | ||
challenge := c.Query("challenge") | ||
// Get the service record from the origin | ||
record, err := mdw.GetServiceRecord(origin) | ||
record, err := serviceproxy.GetServiceRecord(c.Request.Context(), origin) | ||
if err != nil { | ||
c.JSON(404, gin.H{"error": err.Error(), "where": "GetServiceRecord"}) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good overall. It seems that the GetServiceRecord
function has been moved to a new package called serviceproxy
and is now being called with an additional context parameter. This change ensures that the function can also work with a context, which is a good practice.
However, I have a few suggestions for improvement:
- Error handling: The code currently returns a JSON response with the error message when
GetServiceRecord
fails. It would be better to use appropriate HTTP status codes for different error scenarios (e.g., 500 for server errors, 404 for not found, etc.) and provide a consistent error response format. You may consider using a centralized error handling mechanism or middleware. - Documentation: Add comments or documentation for functions and important code blocks to improve code readability and maintainability.
- Input validation: It would be beneficial to validate the
attestation
andchallenge
query parameters before using them to avoid potential security vulnerabilities or issues. Consider adding input validation checks for proper data types and bounds.
Here's an updated version incorporating these suggestions:
attestation := c.Query("attestation")
challenge := c.Query("challenge")
// Validate input parameters
if attestation == "" || challenge == "" {
c.JSON(400, gin.H{"error": "Invalid request"})
return
}
// Get the service record from the origin
record, err := serviceproxy.GetServiceRecord(c.Request.Context(), origin)
if err != nil {
c.JSON(500, gin.H{"error": "Failed to retrieve service record"})
return
}
These updates improve error handling and input validation while maintaining the overall functionality of the code.
package middleware | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/gin-gonic/gin" | ||
"github.com/go-webauthn/webauthn/protocol" | ||
|
||
"github.com/sonrhq/core/internal/highway/types" | ||
"github.com/sonrhq/core/pkg/crypto" | ||
"github.com/sonrhq/core/pkg/did/controller" | ||
domainproxy "github.com/sonrhq/core/x/domain/client/proxy" | ||
domaintypes "github.com/sonrhq/core/x/domain/types" | ||
identityproxy "github.com/sonrhq/core/x/identity/client/proxy" | ||
identitytypes "github.com/sonrhq/core/x/identity/types" | ||
servicetypes "github.com/sonrhq/core/x/service/types" | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the code changes seem to be fine. They include importing relevant packages and adding context to the imports. However, there are a few suggestions that can be made to improve the code:
-
Order the import statements: It is best practice to order the import statements in a consistent manner. This can be done alphabetically or by grouping similar imports together.
-
Remove unused import: There is an empty import statement for
github.com/sonrhq/core/pkg/crypto
that can be removed. -
Use shorter import names: The imported packages
github.com/sonrhq/core/x/domain/*
andgithub.com/sonrhq/core/x/identity/*
are imported using longer names (domainproxy
,domaintypes
,identityproxy
,identitytypes
). It would be better to use shorter names that are easier to read and type.
Here's the updated code with the suggested changes:
package middleware
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-webauthn/webauthn/protocol"
"github.com/sonrhq/core/internal/highway/types"
"github.com/sonrhq/core/x/domain/client/proxy"
"github.com/sonrhq/core/x/domain/types"
"github.com/sonrhq/core/x/identity/client/proxy"
"github.com/sonrhq/core/x/identity/types"
servicetypes "github.com/sonrhq/core/x/service/types"
)
// code... (existing code)
Let me know if I can help you with anything else.
|
||
// IssueCredentialAssertionOptions takes a didDocument and serviceRecord in order to create a credential options. | ||
func IssueCredentialAssertionOptions(email string, record *servicetypes.ServiceRecord) (string, protocol.URLEncodedBase64, string, error) { | ||
addr, err := GetEmailRecordCreator(email) | ||
ctx := context.Background() | ||
addr, err := domainproxy.GetEmailRecordCreator(ctx, email) | ||
if err != nil { | ||
return "", nil, "", fmt.Errorf("failed to get email record creator: %w", err) | ||
} | ||
controllerAcc, err := GetControllerAccount(addr) | ||
controllerAcc, err := identityproxy.GetControllerAccount(ctx, addr) | ||
if err != nil { | ||
return "", nil, "", fmt.Errorf("failed to get controller account: %w", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes in this code appear to introduce the use of a context and replace the function calls GetEmailRecordCreator
and GetControllerAccount
with functions from different packages (GetEmailRecordCreator
with domainproxy.GetEmailRecordCreator
and GetControllerAccount
with identityproxy.GetControllerAccount
). However, the context is not being used in the new function calls, which can lead to potential issues.
Here are a few suggestions to improve the code:
- Make sure to pass the context to the new function calls
domainproxy.GetEmailRecordCreator
andidentityproxy.GetControllerAccount
. - Consider using more descriptive variable names for the context and the new function calls, to improve code readability.
- Add error handling for the new function calls, as they may also return errors that need to be handled properly.
Updated code:
func IssueCredentialAssertionOptions(email string, record *servicetypes.ServiceRecord) (string, protocol.URLEncodedBase64, string, error) {
ctx := context.Background()
emailRecordCreator, err := domainproxy.GetEmailRecordCreator(ctx, email)
if err != nil {
return "", nil, "", fmt.Errorf("failed to get email record creator: %w", err)
}
controllerAcc, err := identityproxy.GetControllerAccount(ctx, emailRecordCreator)
if err != nil {
return "", nil, "", fmt.Errorf("failed to get controller account: %w", err)
}
// ... rest of the code
}
The updated code now correctly passes the ctx
context to the new function calls and uses more meaningful variable names (emailRecordCreator
) to improve code clarity. Additionally, error handling is included for the new function calls.
|
||
// UseControllerAccount takes a jwt token and returns a controller account. | ||
func UseControllerAccount(token string) (*controller.SonrController, error) { | ||
ctx := context.Background() | ||
claims, err := types.VerifySessionJWTClaims(token) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to verify claims: %w", err) | ||
} | ||
acc, err := GetControllerAccount(claims.Address) | ||
acc, err := identityproxy.GetControllerAccount(ctx, claims.Address) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get controller account: %w", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good. Here are a few suggestions to further improve the code:
- It's a good practice to create a context with a timeout or deadline instead of using
context.Background()
directly. This can prevent potential resource leaks and help with controlling the execution time of operations.
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) // Add timeout of 5 seconds
defer cancel() // Cancel the context to release resources
- Ensure that the context is passed down the call stack to all the relevant functions that might need it. This ensures that the context's timeout or deadline is honored throughout the process.
Here's the modified code incorporating the changes:
func UseControllerAccount(token string) (*controller.SonrController, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) // Add timeout of 5 seconds
defer cancel() // Cancel the context to release resources
claims, err := types.VerifySessionJWTClaims(token)
if err != nil {
return nil, fmt.Errorf("failed to verify claims: %w", err)
}
acc, err := identityproxy.GetControllerAccount(ctx, claims.Address)
if err != nil {
return nil, fmt.Errorf("failed to get controller account: %w", err)
}
// rest of the code...
}
- If the
GetControllerAccount
function can also be modified to accept a context, it would be ideal to pass the existingctx
to it instead ofcontext.Background()
. This allows for better control and cancellation of the entire operation.
Overall, the code changes are good, but incorporating the suggestions above can further enhance the code.
} | ||
return controller, nil | ||
} | ||
|
||
// PublishControllerAccount creates a new controller account and publishes it to the blockchain | ||
func PublishControllerAccount(alias string, cred *servicetypes.WebauthnCredential, origin string) (*controller.SonrController, *types.TxResponse, error) { | ||
controller, err := controller.New(alias, cred, origin) | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("failed to create controller: %w", err) | ||
|
||
} | ||
acc := controller.Account() | ||
accMsg := identitytypes.NewMsgCreateControllerAccount(acc.Address, acc.PublicKey, acc.Authenticators...) | ||
usrMsg := domaintypes.NewMsgCreateEmailUsernameRecord(acc.Address, alias) | ||
resp, err := controller.GetPrimaryWallet().SendTx(accMsg, usrMsg) | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("failed to send tx: %w", err) | ||
} | ||
fmt.Println(resp) | ||
return controller, resp, nil | ||
} | ||
|
||
// CreateOrganizationRecord creates a new organization record and publishes it to the blockchain | ||
func CreateOrganizationRecord(name string, origin string, admin string, controller *controller.SonrController) error { | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good overall. However, the CreateOrganizationRecord
function is incomplete and does not have any logic. It currently returns nil
without performing any operations. Please ensure that the function performs the necessary actions to create and publish an organization record to the blockchain.
Also, it would be a good practice to handle the error returned by the CreateOrganizationRecord
function and provide meaningful error messages to the caller instead of returning nil
.
name: Publish Releases | ||
|
||
on: | ||
schedule: | ||
- cron: "0 17 * * *" # 9 AM PST is 17:00 UTC | ||
|
||
jobs: | ||
publish-drafts: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Publish Drafts | ||
run: | | ||
yesterday=$(date -u -d "yesterday" +"%Y-%m-%d") | ||
drafts=$(gh release list --json createdAt,draft -q "map(select(.draft==true and .createdAt >= '$yesterday')) | .[].name") | ||
for draft in $drafts; do | ||
gh release update $draft --draft false | ||
done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes look good overall. However, there are a few suggestions for improvement:
-
Add a description: It's good practice to add a brief description to the workflow file to explain what it does and provide context. This can be done by adding a
description
field under thename
field. -
Specify the timezone: The cron expression is using UTC time, but it's important to specify the timezone explicitly to avoid confusion. You can add a
timezone
field under theschedule
field and specify the timezone, for example:timezone: America/Los_Angeles
. -
Use double quotes: The
run
command is using single quotes for theyesterday
variable and inside thegh release list
command. It's generally recommended to use double quotes unless there is a specific reason to use single quotes. Double quotes allow for variable expansion and better readability. You can update the code to use double quotes instead. -
Handle date formatting: The
date
command used to calculate yesterday's date might not work on all systems. It would be better to use a more portable and reliable approach. You can use thedate
command with the-v
option, which is available on macOS and some Linux distributions. Alternatively, you can use a programming language like Python or Node.js to calculate the date. -
Error handling: Currently, there is no error handling in the code. If there are any errors while executing the
gh
command, it will fail silently. It would be beneficial to add error handling and logging to ensure that any issues are identified and addressed.
Here's an updated version of the code that incorporates these improvements:
name: Publish Releases
description: Automatically publishes draft releases
on:
schedule:
- cron: "0 17 * * *"
timezone: America/Los_Angeles
jobs:
publish-drafts:
runs-on: ubuntu-latest
steps:
- name: Publish Drafts
run: |
yesterday=$(date -u --date='-1 day' +"%Y-%m-%d")
drafts=$(gh release list --json createdAt,draft -q "map(select(.draft==true and .createdAt >= \"$yesterday\")) | .[].name")
for draft in $drafts; do
gh release update $draft --draft false || echo "Failed to update release: $draft"
done
Note: The exact method for handling dates may vary depending on the system and tools available. Please adjust the date calculation based on the platform you are using.
=== auto-pr-body ===
Summary
This Pull Request updates client query functions to use the newly added
domainproxy
,identityproxy
, andserviceproxy
packages. It adds functions to check alias availability, get a controller account with an address, get a DID document given an alias, and get a service record given an origin. Suggested refactorings are included.