Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
WaaS Client Library v1.0.0 (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuga-cb authored May 22, 2023
1 parent 2e3b4c6 commit d1926de
Show file tree
Hide file tree
Showing 61 changed files with 8,813 additions and 1,792 deletions.
4 changes: 0 additions & 4 deletions auth/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ func (a *Authenticator) BuildJWT(service, uri string) (string, error) {
return "", fmt.Errorf("jwt: Could not decode private key")
}

if block.Type != "ECDSA Private Key" {

This comment has been minimized.

Copy link
@Jdominguez736

Jdominguez736 Jun 16, 2023

\nMHcCAQEEIIYRhG5dm64nvdsdKj5r7xug+oaJgpbeAAsadKl1GzuRoAoGCCqGSM49\nAwEHoUQDQgAEy6eW0d2NfOTK8OuRPn1XzUmTiL5bE8+rkQ/IeHQXStpEoyRGCVI1\nSP+K/qdOFPay8MMx7YWVqh6KxaLI+7F8JA==\n-----END EC PRIVATE KEY-----\n",

return "", fmt.Errorf("jwt: Bad private key type")
}

This comment has been minimized.

Copy link
@Jdominguez736

Jdominguez736 Jun 16, 2023

\nMHcCAQEEIIYRhG5dm64nvdsdKj5r7xug+oaJgpbeAAsadKl1GzuRoAoGCCqGSM49\nAwEHoUQDQgAEy6eW0d2NfOTK8OuRPn1XzUmTiL5bE8+rkQ/IeHQXStpEoyRGCVI1\nSP+K/qdOFPay8MMx7YWVqh6KxaLI+7F8JA==\n-----END EC PRIVATE KEY-----\n",


key, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("jwt: %w", err)
Expand Down
12 changes: 11 additions & 1 deletion clients/v1/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (b *BlockchainServiceClient) ListNetworks(
return &networkIteratorImpl{iter: b.client.ListNetworks(ctx, req, opts...)}
}

// GetAsset get an Asset.
// GetAsset retrieves an Asset by resource name.
func (b *BlockchainServiceClient) GetAsset(
ctx context.Context,
req *blockchainpb.GetAssetRequest,
Expand Down Expand Up @@ -186,3 +186,13 @@ func (b *BlockchainServiceClient) ListAssets(
opts ...gax.CallOption) AssetIterator {
return &assetIteratorImpl{b.client.ListAssets(ctx, req, opts...)}
}

// BatchGetAssets returns the list of Assets indicated by the given request.
func (b *BlockchainServiceClient) BatchGetAssets(
ctx context.Context,
req *blockchainpb.BatchGetAssetsRequest,
opts ...gax.CallOption) (*blockchainpb.BatchGetAssetsResponse, error) {
asset, err := b.client.BatchGetAssets(ctx, req, opts...)

return asset, clients.UnwrapError(err)
}
223 changes: 221 additions & 2 deletions clients/v1/mpc_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import (
"fmt"
"net/url"

"github.com/googleapis/gax-go/v2"
"google.golang.org/grpc"

"github.com/coinbase/waas-client-library-go/clients"
innerClient "github.com/coinbase/waas-client-library-go/gen/go/coinbase/cloud/clients/v1"
mpc_keyspb "github.com/coinbase/waas-client-library-go/gen/go/coinbase/cloud/mpc_keys/v1"
"github.com/googleapis/gax-go/v2"
"google.golang.org/grpc"
)

const (
Expand Down Expand Up @@ -260,3 +261,221 @@ func (m *MPCKeyServiceClient) CreateSignatureOperation(name string) *WrappedCrea
pathPrefix: m.pathPrefix,
}
}

// WrappedPrepareDeviceArchiveOperation wraps the long-running operation to handle
// unwrapping errors and setting the LRO options.
type WrappedPrepareDeviceArchiveOperation struct {
*innerClient.PrepareDeviceArchiveOperation
pathPrefix string
}

// PathPrefix returns the path prefix for the operation to be used in HTTP requests.
// E.g. if the path prefix is `/waas/mpc_keys`, then the request path would be:
// `/waas/mpc_keys/v1/operations/<operationId>`.
func (w *WrappedPrepareDeviceArchiveOperation) PathPrefix() string {
return w.pathPrefix
}

// Wait delegates to the wrapped longrunning PrepareDeviceArchiveOperation with the
// override LRO options and handling unwrapping client errors.
func (w *WrappedPrepareDeviceArchiveOperation) Wait(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_keyspb.DeviceGroup, error) {
deviceGroup, err := w.PrepareDeviceArchiveOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
}

// Poll delegates to the wrapped longrunning PrepareDeviceArchiveOperation with the
// override LRO options and handling unwrapping client errors.
func (w *WrappedPrepareDeviceArchiveOperation) Poll(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_keyspb.DeviceGroup, error) {
deviceGroup, err := w.PrepareDeviceArchiveOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
}

// PrepareDeviceArchive prepares an archive in the local storage of the given Device. The archive contains
// cryptographic materials that can be used to export MPCKeys, which have the given DeviceGroup as their parent.
// The Device specified in the request must be a member of this DeviceGroup and must participate
// in the associated MPC operation for the archive to be prepared. After calling this,
// use ListMPCOperations to poll for the pending PrepareDeviceArchive operation, and use the WaaS SDK's
// ComputeMPCOperation to complete the operation. Once the operation completes, the Device can utilize the
// WaaS SDK to export the private keys corresponding to each of the MPCKeys under this DeviceGroup.
func (m *MPCKeyServiceClient) PrepareDeviceArchive(
ctx context.Context,
req *mpc_keyspb.PrepareDeviceArchiveRequest,
opts ...gax.CallOption) (*WrappedPrepareDeviceArchiveOperation, error) {
op, err := m.client.PrepareDeviceArchive(ctx, req, opts...)
if err != nil {
return nil, clients.UnwrapError(err)
}

return &WrappedPrepareDeviceArchiveOperation{
PrepareDeviceArchiveOperation: op,
pathPrefix: m.pathPrefix,
}, nil
}

// PrepareDeviceArchiveOperation returns the PrepareDeviceArchiveOperation indicated by the given name.
func (m *MPCKeyServiceClient) PrepareDeviceArchiveOperation(name string) *WrappedPrepareDeviceArchiveOperation {
return &WrappedPrepareDeviceArchiveOperation{
PrepareDeviceArchiveOperation: m.client.PrepareDeviceArchiveOperation(name),
pathPrefix: m.pathPrefix,
}
}

// WrappedPrepareDeviceBackupOperation wraps the long-running operation to handle
// unwrapping errors and setting the LRO options.
type WrappedPrepareDeviceBackupOperation struct {
*innerClient.PrepareDeviceBackupOperation
pathPrefix string
}

// PathPrefix returns the path prefix for the operation to be used in HTTP requests.
// E.g. if the path prefix is `/waas/mpc_keys`, then the request path would be:
// `/waas/mpc_keys/v1/operations/<operationId>`.
func (w *WrappedPrepareDeviceBackupOperation) PathPrefix() string {
return w.pathPrefix
}

// Wait delegates to the wrapped longrunning PrepareDeviceBackupOperation with the
// override LRO options and handling unwrapping client errors.
func (w *WrappedPrepareDeviceBackupOperation) Wait(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_keyspb.DeviceGroup, error) {
deviceGroup, err := w.PrepareDeviceBackupOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
}

// Poll delegates to the wrapped longrunning PrepareDeviceBackupOperation with the
// override LRO options and handling unwrapping client errors.
func (w *WrappedPrepareDeviceBackupOperation) Poll(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_keyspb.DeviceGroup, error) {
deviceGroup, err := w.PrepareDeviceBackupOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
}

// PrepareDeviceBackup prepares a backup in the given Device. The backup contains certain
// cryptographic materials that can be used to restore MPCKeys, which have the given DeviceGroup as their parent,
// on a new Device. The Device specified in the request must be a member of this DeviceGroup and must participate
// in the associated MPC operation for the backup to be prepared.
// After calling this RPC, use ListMPCOperations to poll for the pending PrepareDeviceBackup operation,
// and use the WaaS SDK's ComputeMPCOperation to complete the operation. Once the operation completes,
// the Device can utilize WaaS SDK to download the backup bundle. We recommend storing this backup bundle securely
// in a storage provider of your choice. If the user loses access to their existing Device and wants to recover
// MPCKeys in the given DeviceGroup on a new Device, use AddDevice RPC on the MPCKeyService.
func (m *MPCKeyServiceClient) PrepareDeviceBackup(
ctx context.Context,
req *mpc_keyspb.PrepareDeviceBackupRequest,
opts ...gax.CallOption) (*WrappedPrepareDeviceBackupOperation, error) {
op, err := m.client.PrepareDeviceBackup(ctx, req, opts...)
if err != nil {
return nil, clients.UnwrapError(err)
}

return &WrappedPrepareDeviceBackupOperation{
PrepareDeviceBackupOperation: op,
pathPrefix: m.pathPrefix,
}, nil
}

// PrepareDeviceBackupOperation returns the PrepareDeviceBackupOperation indicated by the given name.
func (m *MPCKeyServiceClient) PrepareDeviceBackupOperation(name string) *WrappedPrepareDeviceBackupOperation {
return &WrappedPrepareDeviceBackupOperation{
PrepareDeviceBackupOperation: m.client.PrepareDeviceBackupOperation(name),
pathPrefix: m.pathPrefix,
}
}

// WrappedAddDeviceOperation wraps the long-running operation to handle
// unwrapping errors and setting the LRO options.
type WrappedAddDeviceOperation struct {
*innerClient.AddDeviceOperation
pathPrefix string
}

// PathPrefix returns the path prefix for the operation to be used in HTTP requests.
// E.g. if the path prefix is `/waas/mpc_keys`, then the request path would be:
// `/waas/mpc_keys/v1/operations/<operationId>`.
func (w *WrappedAddDeviceOperation) PathPrefix() string {
return w.pathPrefix
}

// Wait delegates to the wrapped longrunning AddDeviceOperation with the
// override LRO options and handling unwrapping client errors.
func (w *WrappedAddDeviceOperation) Wait(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_keyspb.DeviceGroup, error) {
deviceGroup, err := w.AddDeviceOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
}

// Poll delegates to the wrapped longrunning AddDeviceOperation with the
// override LRO options and handling unwrapping client errors.
func (w *WrappedAddDeviceOperation) Poll(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_keyspb.DeviceGroup, error) {
deviceGroup, err := w.AddDeviceOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
}

// AddDevice adds a Device to an existing DeviceGroup. Prior to this API being called, the Device must be registered using
// RegisterDevice RPC. The Device must have access to the backup created with PrepareDeviceBackup RPC to compute this
// operation. After calling this RPC, use ListMPCOperations to poll for the pending AddDevice operation,
// and use the WaaS SDK's ComputeAddDeviceMPCOperation to complete the operation.
// After the operation is computed on WaaS SDK, the Device will have access to cryptographic materials
// required to process MPCOperations for this DeviceGroup.
// Once the operation completes on MPCKeyService, the Device will be added to the given DeviceGroup as a new member
// and all existing Devices in the DeviceGroup will stay functional.
// MPCKeyService will expose RemoveDevice RPC in a future release that can remove any of the
// existing Devices from the DeviceGroup.
func (m *MPCKeyServiceClient) AddDevice(
ctx context.Context,
req *mpc_keyspb.AddDeviceRequest,
opts ...gax.CallOption) (*WrappedAddDeviceOperation, error) {
op, err := m.client.AddDevice(ctx, req, opts...)
if err != nil {
return nil, clients.UnwrapError(err)
}

return &WrappedAddDeviceOperation{
AddDeviceOperation: op,
pathPrefix: m.pathPrefix,
}, nil
}

// AddDeviceOperation returns the AddDeviceOperation indicated by the given name.
func (m *MPCKeyServiceClient) AddDeviceOperation(name string) *WrappedAddDeviceOperation {
return &WrappedAddDeviceOperation{
AddDeviceOperation: m.client.AddDeviceOperation(name),
pathPrefix: m.pathPrefix,
}
}

// RevokeDevice revokes a registered Device. This operation removes the registered Device from all the DeviceGroups that it is a
// part of. Once the Device is revoked, cryptographic materials in your physical Device are invalidated,
// and the Device can no longer participate in any MPCOperations of the DeviceGroups it was a part of.
// Use this API in scenarios such as losing the existing Device, switching to a new physical Device, etc.
// Ensure that a new Device is successfully added to your DeviceGroups using the AddDevice RPC before invoking
// the RevokeDevice RPC.
func (m *MPCKeyServiceClient) RevokeDevice(
ctx context.Context,
req *mpc_keyspb.RevokeDeviceRequest,
opts ...gax.CallOption) error {
err := m.client.RevokeDevice(ctx, req, opts...)

return clients.UnwrapError(err)
}
8 changes: 4 additions & 4 deletions clients/v1/mpc_transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ func (w *WrappedCreateMPCTransactionOperation) Wait(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_transactionspb.MPCTransaction, error) {
deviceGroup, err := w.CreateMPCTransactionOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)
mpcTransaction, err := w.CreateMPCTransactionOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
return mpcTransaction, clients.UnwrapError(err)
}

// Poll delegates to the wrapped longrunning CreateMPCTransactionOperation with the
Expand All @@ -103,9 +103,9 @@ func (w *WrappedCreateMPCTransactionOperation) Poll(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_transactionspb.MPCTransaction, error) {
deviceGroup, err := w.CreateMPCTransactionOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)
mpcTransaction, err := w.CreateMPCTransactionOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
return mpcTransaction, clients.UnwrapError(err)
}

// CreateMPCTransaction creates an MPCTransaction. The long-running operation returned from this API will contain
Expand Down
60 changes: 56 additions & 4 deletions clients/v1/mpc_wallets.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ func (w *WrappedCreateMPCWalletOperation) Wait(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_walletspb.MPCWallet, error) {
deviceGroup, err := w.CreateMPCWalletOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)
mpcWallet, err := w.CreateMPCWalletOperation.Wait(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
return mpcWallet, clients.UnwrapError(err)
}

// Poll delegates to the wrapped longrunning CreateMPCWalletOperation with the
Expand All @@ -103,9 +103,9 @@ func (w *WrappedCreateMPCWalletOperation) Poll(
ctx context.Context,
opts ...gax.CallOption,
) (*mpc_walletspb.MPCWallet, error) {
deviceGroup, err := w.CreateMPCWalletOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)
mpcWallet, err := w.CreateMPCWalletOperation.Poll(ctx, clients.LROOptions(w, version, opts)...)

return deviceGroup, clients.UnwrapError(err)
return mpcWallet, clients.UnwrapError(err)
}

// CreateMPCWallet creates an MPCWallet. The Device in the request must have been registered
Expand Down Expand Up @@ -322,3 +322,55 @@ func (m *MPCWalletServiceClient) ListBalances(
opts ...gax.CallOption) BalanceIterator {
return &balanceIteratorImpl{iter: m.client.ListBalances(ctx, req, opts...)}
}

// BalanceDetailIterator is an interface for iterating through the response to ListBalanceDetails.
type BalanceDetailIterator interface {
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
PageInfo() *iterator.PageInfo

// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
Next() (*mpc_walletspb.BalanceDetail, error)

// Response is the raw response for the current page.
// Calling Next() or InternalFetch() updates this value.
Response() *mpc_walletspb.ListBalanceDetailsResponse
}

// balanceDetailIteratorImpl is an implementation of BalanceDetailIterator that unwraps correctly.
type balanceDetailIteratorImpl struct {
iter *innerClient.BalanceDetailIterator
}

// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (n *balanceDetailIteratorImpl) PageInfo() *iterator.PageInfo {
return n.iter.PageInfo()
}

// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (n *balanceDetailIteratorImpl) Next() (*mpc_walletspb.BalanceDetail, error) {
balanceDetail, err := n.iter.Next()

return balanceDetail, clients.UnwrapError(err)
}

// Response is the raw response for the current page.
// Calling Next() or InternalFetch() updates this value.
func (n *balanceDetailIteratorImpl) Response() *mpc_walletspb.ListBalanceDetailsResponse {
if n.iter.Response == nil {
return nil
}

response := n.iter.Response.(*mpc_walletspb.ListBalanceDetailsResponse)

return response
}

// ListBalanceDetails lists BalanceDetails.
func (m *MPCWalletServiceClient) ListBalanceDetails(
ctx context.Context,
req *mpc_walletspb.ListBalanceDetailsRequest,
opts ...gax.CallOption) BalanceDetailIterator {
return &balanceDetailIteratorImpl{iter: m.client.ListBalanceDetails(ctx, req, opts...)}
}
11 changes: 11 additions & 0 deletions clients/v1/protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,14 @@ func (b *ProtocolServiceClient) BroadcastTransaction(

return transaction, clients.UnwrapError(err)
}

// EstimateFee estimates the current network fee for the specified Network. For EVM Networks, this
// corresponds to the gas_price, max_fee_per_gas, and max_priority_fee_per_gas.
func (b *ProtocolServiceClient) EstimateFee(
ctx context.Context,
req *protocolspb.EstimateFeeRequest,
opts ...gax.CallOption) (*protocolspb.EstimateFeeResponse, error) {
response, err := b.client.EstimateFee(ctx, req, opts...)

return response, clients.UnwrapError(err)
}
Loading

0 comments on commit d1926de

Please sign in to comment.