func ProfileExists(userID string, ctx provider) error {
	store, err := newProfileStore(ctx.StorageProvider())
	if err != nil {
		return fmt.Errorf("failed to get store to get VC wallet profile: %w", err)
	}
	_, err = store.get(userID)
	return err
}
ProfileExists checks if profile exists for given wallet user, returns error if not found.
package wallet
import (
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"time"
	"github.com/google/uuid"
	"github.com/piprate/json-gold/ld"
	"github.com/hyperledger/aries-framework-go/pkg/client/didexchange"
	"github.com/hyperledger/aries-framework-go/pkg/client/outofband"
	"github.com/hyperledger/aries-framework-go/pkg/client/presentproof"
	"github.com/hyperledger/aries-framework-go/pkg/common/log"
	"github.com/hyperledger/aries-framework-go/pkg/crypto"
	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model"
	"github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service"
	"github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator"
	didexchangeSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/didexchange"
	presentproofSvc "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/presentproof"
	"github.com/hyperledger/aries-framework-go/pkg/doc/did"
	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld"
	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/signer"
	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite"
	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/bbsblssignature2020"
	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/ed25519signature2018"
	"github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/jsonwebsignature2020"
	"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
	"github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr"
	"github.com/hyperledger/aries-framework-go/pkg/kms"
	"github.com/hyperledger/aries-framework-go/pkg/store/connection"
	"github.com/hyperledger/aries-framework-go/spi/storage"
)
const (
	Ed25519Signature2018 = "Ed25519Signature2018"
	JSONWebSignature2020 = "JsonWebSignature2020"
	BbsBlsSignature2020 = "BbsBlsSignature2020"
)
const (
	bbsContext           = "https://w3id.org/security/bbs/v1"
	emptyRawLength       = 4
	msgEventBufferSize   = 10
	presentProofMimeType = "application/ld+json"
	webRedirectStatusKey = "status"
	webRedirectURLKey    = "url"
	defaultDIDExchangeTimeOut                = 120 * time.Second
	defaultWaitForRequestPresentationTimeOut = 120 * time.Second
	defaultWaitForPresentProofDone           = 120 * time.Second
	retryDelay                               = 500 * time.Millisecond
)
var (
	defaultSignatureRepresentation = verifiable.SignatureJWS
	supportedRelationships         = map[did.VerificationRelationship]string{
		did.Authentication:  "authentication",
		did.AssertionMethod: "assertionMethod",
	}
)
var logger = log.New("aries-framework/wallet")
type provider interface {
	StorageProvider() storage.Provider
	VDRegistry() vdr.Registry
	Crypto() crypto.Crypto
	JSONLDDocumentLoader() ld.DocumentLoader
	MediaTypeProfiles() []string
	didCommProvider  
}
type didCommProvider interface {
	KMS() kms.KeyManager
	ServiceEndpoint() string
	ProtocolStateStorageProvider() storage.Provider
	Service(id string) (interface{}, error)
	KeyType() kms.KeyType
	KeyAgreementType() kms.KeyType
}
type provable interface {
	AddLinkedDataProof(context *verifiable.LinkedDataProofContext, jsonldOpts ...jsonld.ProcessorOpts) error
}
type Wallet struct {
	userID string
	profile *profile
	contents *contentStore
	walletCrypto crypto.Crypto
	storeProvider storage.Provider
	vdr vdr.Registry
	jsonldDocumentLoader ld.DocumentLoader
	presentProofClient *presentproof.Client
	oobClient *outofband.Client
	didexchangeClient *didexchange.Client
	connectionLookup *connection.Lookup
}
func New(userID string, ctx provider) (*Wallet, error) {
	store, err := newProfileStore(ctx.StorageProvider())
	if err != nil {
		return nil, fmt.Errorf("failed to get store to fetch VC wallet profile info: %w", err)
	}
	profile, err := store.get(userID)
	if err != nil {
		return nil, fmt.Errorf("failed to get VC wallet profile: %w", err)
	}
	presentProofClient, err := presentproof.New(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to initialize present proof client: %w", err)
	}
	oobClient, err := outofband.New(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to initialize out-of-band client: %w", err)
	}
	connectionLookup, err := connection.NewLookup(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to initialize connection lookup: %w", err)
	}
	didexchangeClient, err := didexchange.New(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to initialize didexchange client: %w", err)
	}
	return &Wallet{
		userID:               userID,
		profile:              profile,
		storeProvider:        ctx.StorageProvider(),
		walletCrypto:         ctx.Crypto(),
		contents:             newContentStore(ctx.StorageProvider(), profile),
		vdr:                  ctx.VDRegistry(),
		jsonldDocumentLoader: ctx.JSONLDDocumentLoader(),
		presentProofClient:   presentProofClient,
		oobClient:            oobClient,
		didexchangeClient:    didexchangeClient,
		connectionLookup:     connectionLookup,
	}, nil
}
func CreateProfile(userID string, ctx provider, options ...ProfileOptions) error {
	return createOrUpdate(userID, ctx, false, options...)
}
func UpdateProfile(userID string, ctx provider, options ...ProfileOptions) error {
	return createOrUpdate(userID, ctx, true, options...)
}
func CreateDataVaultKeyPairs(userID string, ctx provider, options ...UnlockOptions) error {
	store, err := newProfileStore(ctx.StorageProvider())
	if err != nil {
		return fmt.Errorf("failed to get wallet user profile: failed to get store: %w", err)
	}
	profile, err := store.get(userID)
	if err != nil {
		return fmt.Errorf("failed to get wallet user profile: %w", err)
	}
	if profile.EDVConf == nil {
		return fmt.Errorf("invalid operation, no edv configuration found in profile: %w", err)
	}
	opts := &unlockOpts{}
	for _, opt := range options {
		opt(opts)
	}
	token, err := keyManager().createKeyManager(profile, ctx.StorageProvider(), opts)
	if err != nil {
		return fmt.Errorf("failed to get key manager: %w", err)
	}
	defer keyManager().removeKeyManager(userID)
	err = updateProfile(token, profile)
	if err != nil {
		return fmt.Errorf("failed to create key pairs: %w", err)
	}
	err = store.save(profile, true)
	if err != nil {
		return fmt.Errorf("failed to update profile: %w", err)
	}
	return nil
}
func createOrUpdate(userID string, ctx provider, update bool, options ...ProfileOptions) error {
	opts := &profileOpts{}
	for _, opt := range options {
		opt(opts)
	}
	store, err := newProfileStore(ctx.StorageProvider())
	if err != nil {
		return fmt.Errorf("failed to get store to save VC wallet profile: %w", err)
	}
	var profile *profile
	if update {
		profile, err = store.get(userID)
		if err != nil {
			return fmt.Errorf("failed to update wallet user profile: %w", err)
		}
		err = profile.setKMSOptions(opts.passphrase, opts.secretLockSvc, opts.keyServerURL)
		if err != nil {
			return fmt.Errorf("failed to update wallet user profile KMS options: %w", err)
		}
		err = profile.setEDVOptions(opts.edvConf)
		if err != nil {
			return fmt.Errorf("failed to update EDV configuration")
		}
	} else {
		profile, err = createProfile(userID, opts)
		if err != nil {
			return fmt.Errorf("failed to create new  wallet user profile: %w", err)
		}
	}
	err = store.save(profile, update)
	if err != nil {
		return fmt.Errorf("failed to save VC wallet profile: %w", err)
	}
	return nil
}