示例#1
0
        /// <summary>
        /// Creates a new AgentListener that listens for incoming connections on the specified endpoint.
        /// </summary>
        /// <remarks>
        /// The endpoint specified must be in the format <c>address:port</c> where <c>address</c> is
        /// an IP address or host address and <c>port</c> is a numeric port number.
        /// </remarks>
        /// <param name="endpoint">The endpoint on which the incoming connections will listened for.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to an AgentListener instance
        /// once the listener has been created.</returns>
        public static Task <AgentListener> ListenAsync(string endpoint)
        {
            var listener = new AgentListener();

            var taskCompletionSource = new TaskCompletionSource <AgentListener>(listener);
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_agent_listen(
                commandHandle,
                endpoint,
                _listenerCreatedCallback,
                listener.ConnectionEstablishedCallback,
                listener.MessageReceivedCallback);

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#2
0
        /// <summary>
        /// Adds an identity to the listener.
        /// </summary>
        /// <remarks>
        /// <para>Although an AgentListner instance can listen for incoming connections on a specified
        /// endpoint, any incoming connection to an identity not associated with the listener will be
        /// automatically rejected.  This method adds an identity to the listener that will be authorized
        /// to accept connections.
        /// </para>
        /// <para>This method will perform a <see cref="Wallet"/> lookup to find the identity information
        /// for the DID to add and consequently the DID must have already been saved in the wallet using
        /// the <see cref="Hyperledger.Indy.SignusApi.CreateAndStoreMyDidResult"/> method prior to attempting to
        /// add it to the listener.
        /// </para>
        /// <para>Authorization to accept incoming connections to a DID on a listener can be removed using
        /// the <see cref="RemoveIdentityAsync(Wallet, string)"/> method.
        /// </para>
        /// </remarks>
        /// <seealso cref="Signus"/>
        /// <param name="pool">The node pool that will be used to verify the identity.</param>
        /// <param name="wallet">The Wallet that contains the identity.</param>
        /// <param name="did">The DID of the identity to authorize connections to.</param>
        /// <returns>An asynchronous <see cref="Task"/> completes once the operation completes.</returns>
        public Task AddIdentityAsync(Pool pool, Wallet wallet, string did)
        {
            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_agent_add_identity(
                commandHandle,
                Handle,
                pool.Handle,
                wallet.Handle,
                did,
                CallbackHelper.TaskCompletingNoValueCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#3
0
        /// <summary>
        /// Decrypts the provided message using the public key associated with the specified DID using the anonymous-encryption scheme.
        /// </summary>
        /// <param name="wallet">The wallet containing the DID and associated secret key to use for decryption.</param>
        /// <param name="did">The DID of the encrypting party to use for verification.</param>
        /// <param name="encryptedMsg">The message to decrypt.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a byte array containing the decrypted message.</returns>
        public static Task <byte[]> DecryptSealedAsync(Wallet wallet, string did, byte[] encryptedMsg)
        {
            var taskCompletionSource = new TaskCompletionSource <byte[]>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_decrypt_sealed(
                commandHandle,
                wallet.Handle,
                did,
                encryptedMsg,
                encryptedMsg.Length,
                _decryptSealedCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#4
0
        /// <summary>
        /// Sends a message to the connection.
        /// </summary>
        /// <remarks>
        /// <note type="note">Messages sent to a connection are automatically encrypted for the receiver
        /// prior to sending.
        /// </note>
        /// </remarks>
        /// <param name="message">The message to send.</param>
        /// <returns>An asynchronous <see cref="Task"/> completes once the operation completes.</returns>
        public Task SendAsync(string message)
        {
            ParamGuard.NotNull(message, "message");

            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_agent_send(
                commandHandle,
                Handle,
                message,
                CallbackHelper.TaskCompletingNoValueCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#5
0
        /// <summary>
        /// Submits a request to the ledger.
        /// </summary>
        /// <remarks>
        /// This method publishes a message to the validator pool as-is and assumes that the message was
        /// previously prepared for submission.  Requests can be signed prior to using this method with a
        /// call to the <see cref="SignRequestAsync(Wallet, string, string)"/> method, or messages can be
        /// both signed and submitted using the <see cref="SignAndSubmitRequestAsync(Pool, Wallet, string, string)"/>
        /// method.
        /// </remarks>
        /// <param name="pool">The validator pool to submit the request to.</param>
        /// <param name="requestJson">The request to submit.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a JSON <see cref="string"/>
        /// containing the results when the operation completes.</returns>
        public static Task <string> SubmitRequestAsync(Pool pool, string requestJson)
        {
            ParamGuard.NotNull(pool, "pool");
            ParamGuard.NotNullOrWhiteSpace(requestJson, "requestJson");

            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_submit_request(
                commandHandle,
                pool.Handle,
                requestJson,
                _submitRequestCallback);

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#6
0
        /// <summary>
        /// Builds a ledger request to get a DDO.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This message builds a request message that is suitable for requesting a DDO from the ledger.
        /// </para>
        /// <para>
        /// The resulting message can be submitted to the ledger using the <see cref="SignAndSubmitRequestAsync(Pool, Wallet, string, string)"/>
        /// method or can be signed first using the <see cref="SignRequestAsync(Wallet, string, string)"/>
        /// method then submitted later using the <see cref="SubmitRequestAsync(Pool, string)"/> method.
        /// </para>
        /// </remarks>
        /// <param name="submitterDid">The DID of the party who will submit the request to the ledger.</param>
        /// <param name="targetDid">The DID of the DDO to get from the ledger.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a <see cref="string"/>
        /// containing the request JSON.</returns>
        public static Task <string> BuildGetDdoRequestAsync(string submitterDid, string targetDid)
        {
            ParamGuard.NotNullOrWhiteSpace(submitterDid, "submitterDid");
            ParamGuard.NotNullOrWhiteSpace(targetDid, "targetDid");

            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_build_get_ddo_request(
                commandHandle,
                submitterDid,
                targetDid,
                _buildRequestCallback);

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#7
0
        /// <summary>
        /// Signs the provided claim for using the key provided in the specified claim request.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The <paramref name="claimReqJson"/> parameter must be passed a claim request that was previously
        /// created using the <see cref="ProverCreateAndStoreClaimReqAsync(Wallet, string, string, string, string)"/>
        /// method.  Usually the claim request will be received from another party that has performed this
        /// action.
        /// </para>
        /// <para>
        /// The claim to be signed is provided in the <paramref name="claimJson"/> parameter
        /// and the structure of the claim must conform to the schema from claim request provided in
        /// the <paramref name="claimReqJson"/> parameter.  Claims must be structured as a series of
        /// attributes, each of which has two values; a human readable value and a hex encoded value.
        /// <code>
        /// {
        ///      "attr1" : ["value1", "value1_as_int"],
        ///      "attr2" : ["value2", "value2_as_int"]
        /// }
        /// </code>
        /// For example:
        /// <code>
        /// {
        ///     'name': ['Alex', '1139481716457488690172217916278103335'],
        ///     'height': ['175', '175']
        /// }
        /// </code>
        /// </para>
        /// <para>
        /// This method results a revocation registry update JSON and a newly issued claim JSON.  The
        /// claim JSON contains the issued claim, the DID of the issuer (<c>issuer_did</c>),
        /// schema sequence number (<c>schema_seq_no</c>) and revocation registry sequence number (<c>
        /// revoc_reg_seq_no</c>) used for issuance:
        /// <code>
        /// {
        ///     "claim": &lt;see claim_json above&gt;,
        ///     "signature": &lt;signature&gt;,
        ///     "revoc_reg_seq_no", string,
        ///     "issuer_did", string,
        ///     "schema_seq_no", string,
        /// }
        /// </code>
        /// </para>
        /// </remarks>
        /// <param name="wallet">The wallet containing the keys to use for signing the claim.</param>
        /// <param name="claimReqJson">A claim request with a blinded secret.</param>
        /// <param name="claimJson">A claim containing attribute values for each of requested attribute names.</param>
        /// <param name="userRevocIndex">The index of a new user in the revocation registry or -1 if absentee.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves to
        /// an <see cref="IssuerCreateClaimResult"/>.</returns>
        public static Task <IssuerCreateClaimResult> IssuerCreateClaimAsync(Wallet wallet, string claimReqJson, string claimJson, int userRevocIndex)
        {
            var taskCompletionSource = new TaskCompletionSource <IssuerCreateClaimResult>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_issuer_create_claim(
                commandHandle,
                wallet.Handle,
                claimReqJson,
                claimJson,
                userRevocIndex,
                _issuerCreateClaimCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#8
0
        /// <summary>
        /// Revokes a user identified by a revoc_id in a given revoc-registry.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The corresponding claim definition and revocation registry must be already
        /// have been created and stored in the wallet.
        /// </para>
        /// </remarks>
        /// <param name="wallet">The target wallet.</param>
        /// <param name="issuerDid">The DID of the issuer.</param>
        /// <param name="schemaSequenceNumber">The sequence number of the schema.</param>
        /// <param name="userRevocIndex">index of the user in the revocation registry</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves
        /// to a revocation registry update JSON with a revoked claim.</returns>
        public static Task <string> IssuerRevokeClaimAsync(Wallet wallet, string issuerDid, int schemaSequenceNumber, int userRevocIndex)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_issuer_revoke_claim(
                commandHandle,
                wallet.Handle,
                issuerDid,
                schemaSequenceNumber,
                userRevocIndex,
                IssuerRevokeClaimCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#9
0
        /// <summary>
        /// Creates a new revocation registry for the provided claim definition.
        /// </summary>
        /// <remarks>
        /// The revocation registry is stored in the provided <see cref="Wallet"/> and is identified by
        /// a unique key which is returned in the revocation registry JSON string returned by the method.
        /// </remarks>
        /// <param name="wallet">The wallet to store the revocation registry in.</param>
        /// <param name="issuerDid">The DID of the issuer that signed the revoc_reg transaction to the ledger.</param>
        /// <param name="schemaSeqNo">The sequence number of a schema transaction in the ledger.</param>
        /// <param name="maxClaimNum">The maximum number of claims the new registry can process.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves
        /// to a JSON string containing the revocation registry.</returns>
        public static Task <string> IssuerCreateAndStoreRevocRegAsync(Wallet wallet, string issuerDid, int schemaSeqNo, int maxClaimNum)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_issuer_create_and_store_revoc_reg(
                commandHandle,
                wallet.Handle,
                issuerDid,
                schemaSeqNo,
                maxClaimNum,
                _issuerCreateAndStoreClaimRevocRegCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#10
0
        /// <summary>
        /// Opens a pool and connects to the ledger nodes.
        /// </summary>
        /// <remarks>
        /// A Pool cannot be opened unless the a pool configuration with the specified name was previously
        /// configured using the <see cref="CreatePoolLedgerConfigAsync(string, string)"/> method.
        ///
        /// When opening a pool the runtime configuration can be specified using the <paramref name="config"/>
        /// parameter, which expects a JSON string with the following format:
        ///
        /// <code>
        /// {
        ///     "refresh_on_open": bool (optional), Forces pool ledger to be refreshed immediately after opening.
        ///                      Defaults to true.
        ///     "auto_refresh_time": int (optional), After this time in minutes pool ledger will be automatically refreshed.
        ///                        Use 0 to disable automatic refresh. Defaults to 24*60.
        ///     "network_timeout": int (optional), Network timeout for communication with nodes in milliseconds.
        ///                       Defaults to 20000.
        /// }
        /// </code>
        ///
        /// If the <paramref name="config"/> parameter is null then the default configuration will be used.
        ///
        /// <note type="note">Attempting to open a pool with the same name more than once will result in an error.</note>
        /// </remarks>
        /// <param name="configName">The name of the pool configuration to use.</param>
        /// <param name="config">The runtime configuration to use.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a Pool instance once the pool is opened.</returns>
        public static Task <Pool> OpenPoolLedgerAsync(string configName, string config)
        {
            ParamGuard.NotNullOrWhiteSpace(configName, "configName");

            var taskCompletionSource = new TaskCompletionSource <Pool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_open_pool_ledger(
                commandHandle,
                configName,
                config,
                _openPoolLedgerCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#11
0
        /// <summary>
        /// Gets claims matching the provided filter from the specified wallet.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Claims can be filtered by Issuer, claim_def and/or Schema. To filter the results set the
        /// <paramref name="filterJson"/> parameter with a JSON string that conforms to the following
        /// format:
        /// <code>
        /// {
        ///     "issuer_did": string,
        ///     "schema_seq_no": string
        /// }
        /// </code>
        /// If <paramref name="filterJson"/> is null then all claims will be returned.
        /// </para>
        /// <para>
        /// Upon successful completion this method will return a JSON string containing an array of
        /// claims:
        /// <code>
        /// [
        ///     {
        ///         "claim_uuid": string,
        ///         "attrs": [{"attr_name" : "attr_value"}, ...],
        ///         "schema_seq_no": string,
        ///         "issuer_did": string,
        ///         "revoc_reg_seq_no": string,
        ///     },
        ///     ...
        /// ]
        /// </code>
        /// </para>
        /// </remarks>
        /// <param name="wallet">The target wallet.</param>
        /// <param name="filterJson">The filter JSON.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves
        /// to a JSON string containing the claim request.</returns>
        public static Task <string> ProverGetClaimsAsync(Wallet wallet, string filterJson)
        {
            ParamGuard.NotNull(wallet, "wallet");

            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_prover_get_claims(
                commandHandle,
                wallet.Handle,
                filterJson,
                _proverGetClaimsCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#12
0
        /// <summary>
        /// Adds an identity to an agent listener.
        /// </summary>
        /// <param name="listener">The listener to add the identity to.</param>
        /// <param name="pool">The pool.</param>
        /// <param name="wallet">The wallet.</param>
        /// <param name="did">The DID of the identity to add.</param>
        /// <returns>An asynchronous task that returns no value.</returns>
        private static Task AgentAddIdentityAsync(Listener listener, Pool pool, Wallet wallet, string did)
        {
            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            var result = IndyNativeMethods.indy_agent_add_identity(
                commandHandle,
                listener.Handle,
                pool.Handle,
                wallet.Handle,
                did,
                _noValueCallback
                );

            CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#13
0
文件: Pool.cs 项目: fsreyes/indy-sdk
        /// <summary>
        /// Closes the pool.
        /// </summary>
        /// <remarks>
        /// <note type="note">Once a Pool instance is closed it cannot be opened again.  Instead call the
        /// <see cref="OpenPoolLedgerAsync(string, string)"/> method to open a new Pool instance.</note>
        /// </remarks>
        /// <returns>An asynchronous <see cref="Task"/> that completes when the operation completes.</returns>
        public Task CloseAsync()
        {
            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_close_pool_ledger(
                commandHandle,
                Handle,
                CallbackHelper.TaskCompletingNoValueCallback
                );

            CallbackHelper.CheckResult(result);

            _closeRequested = true;
            GC.SuppressFinalize(this);

            return(taskCompletionSource.Task);
        }
示例#14
0
        /// <summary>
        /// Creates a listener than can be connected to by other agents.
        /// </summary>
        /// <param name="endpoint">The endpoint the agent is to be exposed on.</param>
        /// <param name="connectionOpenedHandler">The observer that will receive connection events from the listener.</param>
        /// <returns>An asynchronous task that returns a Listener result.</returns>
        public static Task <Listener> AgentListenAsync(string endpoint, ConnectionOpenedHandler connectionOpenedHandler)
        {
            var taskCompletionSource = new TaskCompletionSource <Listener>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            AddConnectionOpenedHandler(commandHandle, connectionOpenedHandler);

            var result = IndyNativeMethods.indy_agent_listen(
                commandHandle,
                endpoint,
                _listenerCreatedCallback,
                _listenerConnectionEstablishedCallback,
                _agentListenerMessageReceivedCallback);

            CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#15
0
        /// <summary>
        /// Signs the specified message using the specified DID.
        /// </summary>
        /// <param name="wallet">The wallet that contains the DID.</param>
        /// <param name="did">The did to sign with.</param>
        /// <param name="msg">The message to sign.</param>
        /// <returns>An asynchronous task that returns the signed message.</returns>
        public static Task <byte[]> SignAsync(Wallet wallet, string did, byte[] msg)
        {
            var taskCompletionSource = new TaskCompletionSource <byte[]>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_sign(
                commandHandle,
                wallet.Handle,
                did,
                msg,
                msg.Length,
                _signCallback
                );

            CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#16
0
        /// <summary>
        /// Builds a GET_CLAIM_DEF ledger request.
        /// </summary>
        /// <param name="submitterDid">The DID of the submitter.</param>
        /// <param name="xref">Seq. number of schema</param>
        /// <param name="signatureType">signature type (only CL supported now)</param>
        /// <param name="origin">The issuer DID.</param>
        /// <returns>An asynchonous Task that returns the request.</returns>
        public static Task <string> BuildGetClaimDefTxnAsync(string submitterDid, int xref, string signatureType, string origin)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            var result = IndyNativeMethods.indy_build_get_claim_def_txn(
                commandHandle,
                submitterDid,
                xref,
                signatureType,
                origin,
                _buildRequestCallback
                );

            CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#17
0
        /// <summary>
        /// Signs and submits a request to the ledger.
        /// </summary>
        /// <param name="pool">The ledger pool to submit to.</param>
        /// <param name="wallet">The wallet containing the keys to sign with.</param>
        /// <param name="submitterDid">The DID of the submitter.</param>
        /// <param name="requstJson">The request to sign and submit.</param>
        /// <returns>An asynchronous Task that returns the submit result.</returns>
        public static Task <string> SignAndSubmitRequestAsync(Pool pool, Wallet wallet, string submitterDid, string requstJson)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            var result = IndyNativeMethods.indy_sign_and_submit_request(
                commandHandle,
                pool.Handle,
                wallet.Handle,
                submitterDid,
                requstJson,
                _submitRequestCallback
                );

            CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#18
0
        /// <summary>
        /// Creates a new local pool configuration that can be used later to open a connection to pool nodes.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the configuration specified in the <paramref name="config"/> parameter is null then the
        /// default configuration will be used, however if specified the value should adhere to the following
        /// JSON format:
        /// <code>
        /// {
        ///     "genesis_txn": "path/to/genesis/transaction/file"
        /// }
        /// </code>
        /// If the value of the <c>genesis_txn</c> key in the JSON is null then a default file will be
        /// used.  If the file specified does not exist it will be created.
        /// </para>
        /// </remarks>
        /// <seealso cref="OpenPoolLedgerAsync(string, string)"/>
        /// <seealso cref="DeletePoolLedgerConfigAsync(string)"/>
        /// <param name="configName">The name for the configuration.</param>
        /// <param name="config">The configuration JSON.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> with no return value that completes when
        /// the configuration is created.</returns>
        public static Task CreatePoolLedgerConfigAsync(string configName, string config)
        {
            ParamGuard.NotNullOrWhiteSpace(configName, "configName");

            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_create_pool_ledger_config(
                commandHandle,
                configName,
                config,
                CallbackHelper.TaskCompletingNoValueCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#19
0
        /// <summary>
        /// Creates a new wallet.
        /// </summary>
        /// <param name="poolName">The name of the pool the wallet is associated with.</param>
        /// <param name="name">The name of the wallet.</param>
        /// <param name="type">The type of the wallet.  Use null to indicate the 'default' type.</param>
        /// <param name="config">The wallet configuration JSON.  Use null to indicate the default config.</param>
        /// <param name="credentials">The wallet credentials JSON or null to use the default credentials.</param>
        /// <returns>An asynchronous Task with no return value.</returns>
        public static Task CreateWalletAsync(string poolName, string name, string type, string config, string credentials)
        {
            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            var result = IndyNativeMethods.indy_create_wallet(
                commandHandle,
                poolName,
                name,
                type,
                config,
                credentials,
                _noValueCallback);

            CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#20
0
        /// <summary>
        /// Stores a remote party's DID for a pairwise connection in the specified wallet.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The DID and optional associated parameters must be provided in the <paramref name="identityJson"/>
        /// parameter as a JSON string:
        /// </para>
        /// <code>
        /// {
        ///        "did": string,
        ///        "verkey": string,
        ///        "crypto_type": string
        /// }
        /// </code>
        /// <para>The <c>did</c> member specifies the DID to store.  This value is required.</para>
        /// <para>The <c>verkey</c> member specifies the verification key and is optional.</para>
        /// <para>The <c>crypto_type</c> member specifies the type of cryptographic algorithm will be
        /// used to generate they keys.  If not provided then ed22519 curve will be used.
        /// <note type="note">The only value currently supported for this member is 'ed25519'.</note>
        /// </para>
        /// </remarks>
        /// <param name="wallet">The wallet to store the DID in.</param>
        /// <param name="identityJson">The identity JSON.</param>
        /// <returns>An asynchronous <see cref="Task"/> that  with no return value the completes when the operation completes.</returns>
        public static Task StoreTheirDidAsync(Wallet wallet, string identityJson)
        {
            ParamGuard.NotNull(wallet, "wallet");
            ParamGuard.NotNullOrWhiteSpace(identityJson, "identityJson");

            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_store_their_did(
                commandHandle,
                wallet.Handle,
                identityJson,
                CallbackHelper.TaskCompletingNoValueCallback);

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#21
0
        /// <summary>
        /// Creates signing and encryption keys in specified wallet for a new DID owned by the caller.
        /// </summary>
        /// <remarks>
        /// <para>Saves the identity DID with keys in a wallet so that it can be used to sign
        /// and encrypt transactions.  Control over the created DID is provided through the
        /// <paramref name="didJson"/> parameter which accepts a JSON string with the following
        /// optional parameters:
        /// </para>
        /// <code>
        /// {
        ///     "did": string,
        ///     "seed": string,
        ///     "crypto_type": string,
        ///     "cid": bool
        /// }
        /// </code>
        /// <para>The <c>did</c> member specifies the DID of the new entry.  If not
        /// provided and the <c>cid</c> member is <c>false</c> then the first 16 bits of the VerKey value
        /// generated will be used as a new DID.  If not provided and the <c>cid</c> member is <c>true</c> then the full
        /// VerKey value will be used as a new DID.  If the <c>did</c> member is provided then the keys will be
        /// replaced - this is normally used in the case of key rotation.</para>
        /// <para>The <c>seed</c> member specifies the seed to use when generating keys.  If not provided
        /// then a random seed value will be created.</para>
        /// <para>The <c>crypto_type</c> member specifies the cryptographic algorithm used for generating
        /// keys.  If not provided then ed25519 curve is used.
        /// <note type="note">The only value currently supported for this member is 'ed25519'.</note>
        /// </para>
        /// <para>The <c>cid</c> member indicates whether the DID should be used in creating the DID.
        /// If not provided then the value defaults to false.</para>
        /// </remarks>
        /// <param name="wallet">The wallet to store the DID in.</param>
        /// <param name="didJson">The DID JSON.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a <see cref="CreateAndStoreMyDidResult"/> when the operation completes.</returns>
        public static Task <CreateAndStoreMyDidResult> CreateAndStoreMyDidAsync(Wallet wallet, string didJson)
        {
            ParamGuard.NotNull(wallet, "wallet");
            ParamGuard.NotNullOrWhiteSpace(didJson, "didJson");

            var taskCompletionSource = new TaskCompletionSource <CreateAndStoreMyDidResult>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_create_and_store_my_did(
                commandHandle,
                wallet.Handle,
                didJson,
                _createAndStoreMyDidCallback);

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#22
0
        /// <summary>
        /// Builds a ledger request for storing an ATTRIB.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Builds a request message that is suitable for setting an attribute on the ledger.
        /// </para>
        /// <para>
        /// The <paramref name="submitterDid"/>, <paramref name="targetDid"/> are mandatory and
        /// any one of the <paramref name="hash"/>, <paramref name="raw"/> or <paramref name="enc"/>
        /// parameters must also be provided, depending on what type of data should be stored.
        /// </para>
        /// </remarks>
        /// <param name="submitterDid">The DID of the party that will submit the request to the ledger.</param>
        /// <param name="targetDid">The DID the ATTRIB will belong to.</param>
        /// <param name="hash">The hash of the ATTRIB data.</param>
        /// <param name="raw">The raw JSON attribute data.</param>
        /// <param name="enc">The encrypted attribute data.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a <see cref="string"/>
        /// containing the request JSON. </returns>
        public static Task <string> BuildAttribRequestAsync(string submitterDid, string targetDid, string hash, string raw, string enc)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_build_attrib_request(
                commandHandle,
                submitterDid,
                targetDid,
                hash,
                raw,
                enc,
                _buildRequestCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#23
0
        /// <summary>
        /// Encrypts the specified message for the specified DID.
        /// </summary>
        /// <param name="wallet">The wallet containing the DID to use for encyption.</param>
        /// <param name="pool">The pool</param>
        /// <param name="my_did">My DID</param>
        /// <param name="did">The did to encrypt for.</param>
        /// <param name="msg">The message to encrypt.</param>
        /// <returns>An asynchronous task that returns an EncryptResult.</returns>
        public static Task <EncryptResult> EncryptAsync(Wallet wallet, Pool pool, string my_did, string did, byte[] msg)
        {
            var taskCompletionSource = new TaskCompletionSource <EncryptResult>();
            var commandHandle        = AddTaskCompletionSource(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_encrypt(
                commandHandle,
                wallet.Handle,
                pool.Handle,
                my_did,
                did,
                msg,
                msg.Length,
                _encryptCallback);

            CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#24
0
        /// <summary>
        /// Creates keys for the given schema and signature type.
        /// </summary>
        /// <remarks>
        /// <para>This method creates both primary and revocation keys for the given
        /// signature type and schema and stores them in the provided <see cref="Wallet"/>.
        /// The generated claim definition is returned as a JSON string containing information about the
        /// signature type, schema, the issuer's public key and the unique identifier of the public key
        /// in the wallet.
        /// </para>
        /// <note type="note">Currently the only signature type that is supported is 'CL'.</note>
        /// </remarks>
        /// <param name="wallet">The wallet into which the claim definition will be stored.</param>
        /// <param name="issuerDid">The DID of the issuer of the claim definition.</param>
        /// <param name="schemaJson">The JSON schema of the claim definition.</param>
        /// <param name="signatureType">The type of signature to use.</param>
        /// <param name="createNonRevoc">Whether to request non-revocation claim.</param>
        /// <returns>
        /// An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves to a
        /// JSON string containing the claim definition.</returns>
        public static Task <string> IssuerCreateAndStoreClaimDefAsync(Wallet wallet, string issuerDid, string schemaJson, string signatureType, bool createNonRevoc)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_issuer_create_and_store_claim_def(
                commandHandle,
                wallet.Handle,
                issuerDid,
                schemaJson,
                signatureType,
                createNonRevoc,
                _issuerCreateAndStoreClaimDefCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#25
0
        /// <summary>
        /// Verifies whether or not a proof is valid.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method verifies a proof that can be made up of multiple claims.
        /// All required schema, public keys and revocation registries must be provided.
        /// </para>
        /// <para>
        /// The <paramref name="proofRequestJson"/> parameter expects the initial proof request sent
        /// by the verifier.
        /// <code>
        /// {
        ///     "nonce": string,
        ///     "requested_attr1_uuid": &lt;attr_info&gt;,
        ///     "requested_attr2_uuid": &lt;attr_info&gt;,
        ///     "requested_attr3_uuid": &lt;attr_info&gt;,
        ///     "requested_predicate_1_uuid": &lt;predicate_info&gt;,
        ///     "requested_predicate_2_uuid": &lt;predicate_info&gt;,
        /// }
        /// </code>
        /// </para>
        /// <para>
        /// The <paramref name="proofJson"/> parameter expects a JSON string containing,
        /// for each requested attribute,  either a proof (with optionally revealed attribute value) or
        /// self-attested attribute value.  Each proof is associated with a claim and corresponding
        /// schema_seq_no, issuer_did and revoc_reg_seq_no. There is also aggregated proof part
        /// common for all claim proofs.
        /// <code>
        /// {
        ///     "requested": {
        ///         "requested_attr1_id": [claim_proof1_uuid, revealed_attr1, revealed_attr1_as_int],
        ///         "requested_attr2_id": [self_attested_attribute],
        ///         "requested_attr3_id": [claim_proof2_uuid]
        ///         "requested_attr4_id": [claim_proof2_uuid, revealed_attr4, revealed_attr4_as_int],
        ///         "requested_predicate_1_uuid": [claim_proof2_uuid],
        ///         "requested_predicate_2_uuid": [claim_proof3_uuid],
        ///     },
        ///     "claim_proofs": {
        ///         "claim_proof1_uuid": [&lt;claim_proof&gt;, issuer_did, schema_seq_no, revoc_reg_seq_no],
        ///         "claim_proof2_uuid": [&lt;claim_proof&gt;, issuer_did, schema_seq_no, revoc_reg_seq_no],
        ///         "claim_proof3_uuid": [&lt;claim_proof&gt;, issuer_did, schema_seq_no, revoc_reg_seq_no]
        ///     },
        ///     "aggregated_proof": &lt;aggregated_proof&gt;
        /// }
        /// </code>
        /// </para>
        /// <para>
        /// The <paramref name="schemasJson"/> parameter expects a JSON string containing all schema
        /// participating in the proof.
        /// <code>
        /// {
        ///     "claim_proof1_uuid": &lt;schema&gt;,
        ///     "claim_proof2_uuid": &lt;schema&gt;,
        ///     "claim_proof3_uuid": &lt;schema&gt;
        /// }
        /// </code>
        /// </para>
        /// <para>
        /// The <paramref name="claimDefsJson"/> parameter expects a JSON string containing all claim
        /// definitions participating in the proof.
        /// <code>
        /// {
        ///     "claim_proof1_uuid": &lt;claim_def&gt;,
        ///     "claim_proof2_uuid": &lt;claim_def&gt;,
        ///     "claim_proof3_uuid": &lt;claim_def&gt;
        /// }
        /// </code>
        /// </para>
        /// <para>
        /// The <paramref name="revocRegsJson"/> parameter expects a JSON string containing all revocation
        /// registries participating in the proof.
        /// <code>
        /// {
        ///     "claim_proof1_uuid": &lt;revoc_reg&gt;,
        ///     "claim_proof2_uuid": &lt;revoc_reg&gt;,
        ///     "claim_proof3_uuid": &lt;revoc_reg&gt;
        /// }
        /// </code>
        /// </para>
        /// </remarks>
        /// <param name="proofRequestJson">The proof request JSON.</param>
        /// <param name="proofJson">The proof JSON.</param>
        /// <param name="schemasJson">The schemas JSON.</param>
        /// <param name="claimDefsJson">The claim definitions JSON.</param>
        /// <param name="revocRegsJson">The revocation registries JSON.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves
        /// to true if the proof is valid, otherwise false.</returns>
        public static Task <bool> VerifierVerifyProofAsync(string proofRequestJson, string proofJson, string schemasJson, string claimDefsJson, string revocRegsJson)
        {
            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_verifier_verify_proof(
                commandHandle,
                proofRequestJson,
                proofJson,
                schemasJson,
                claimDefsJson,
                revocRegsJson,
                _verifierVerifyProofCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#26
0
        /// <summary>
        /// Creates a claim request for the specified claim offer and stores it in the provided wallet.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The JSON of a claim definition that is associated with the issuer_did and schema_seq_no in the
        /// claim_offer must be provided in the <paramref name="claimDefJson"/> parameter.  Claim
        /// definitions can be retrieved from the ledger using the
        /// <see cref="Ledger.BuildGetClaimDefTxnAsync(string, int, string, string)"/>method.
        /// </para>
        /// <para>
        /// The JSON in the <paramref name="claimOfferJson"/> parameter contains information about the
        /// issuer of the claim offer:
        /// <code>
        /// {
        ///     "issuer_did": string,
        ///     "schema_seq_no": string
        /// }
        /// </code>
        /// This method gets the public key and schema the <c>issuer_did</c> from the ledger for and
        /// stores them in the provided wallet. Once this is complete a blinded master secret is for the
        /// master secret specified by the <paramref name="masterSecretName"/> parameter.
        /// <note type="note">
        /// The master secret identified by the name must be already stored in the secure wallet using the
        /// <see cref="ProverCreateMasterSecretAsync(Wallet, string)"/> method.
        /// </note>
        /// The blinded master secret becomes a part of the claim request.
        /// </para>
        /// </remarks>
        /// <param name="wallet">The target wallet.</param>
        /// <param name="proverDid">The DID of the prover.</param>
        /// <param name="claimOfferJson">The claim offer JSON to generate a claim request for.</param>
        /// <param name="claimDefJson">The claim definition JSON.</param>
        /// <param name="masterSecretName">The name of the master secret in the wallet to use for generating the blinded secret.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves
        /// to a JSON string containing the claim request.</returns>
        public static Task <string> ProverCreateAndStoreClaimReqAsync(Wallet wallet, string proverDid, string claimOfferJson, string claimDefJson, string masterSecretName)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_prover_create_and_store_claim_req(
                commandHandle,
                wallet.Handle,
                proverDid,
                claimOfferJson,
                claimDefJson,
                masterSecretName,
                _proverCreateAndStoreClaimReqCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#27
0
        /// <summary>
        /// Builds a ledger request to store a NYM.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Builds a request message that is suitable for storing a NYM for the <paramref name="targetDid"/>
        /// on the ledger.
        /// </para>
        /// <para>
        /// Only the <paramref name="submitterDid"/> and <paramref name="targetDid"/> parameters
        /// are required, however the other parameters provide greater control over the process.  Normally
        /// the <paramref name="targetDid"/> and <paramref name="verKey"/> parameters would be from values
        /// generated by a prior call to <see cref="Signus.CreateAndStoreMyDidAsync(Wallet, string)"/>.
        /// </para>
        /// <para>
        /// The <paramref name="role"/> parameter dictates what permissions the NYM will have - valid values
        /// are 'STEWARD' and 'TRUSTEE' and 'TRUST_ANCHOR'.
        /// </para>
        /// </remarks>
        /// <param name="submitterDid">The DID of the party who will submit the request to the ledger.</param>
        /// <param name="targetDid">The DID the NYM belongs to.</param>
        /// <param name="verKey">The verification key for the NYM.</param>
        /// <param name="alias">The alias for the NYM.</param>
        /// <param name="role">The role of the NYM.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a <see cref="string"/>
        /// containing the request JSON. </returns>
        public static Task <string> BuildNymRequestAsync(string submitterDid, string targetDid, string verKey, string alias, string role)
        {
            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_build_nym_request(
                commandHandle,
                submitterDid,
                targetDid,
                verKey,
                alias,
                role,
                _buildRequestCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#28
0
        /// <summary>
        /// Gets claims matching the provided proof request from the specified wallet.
        /// </summary>
        /// <remarks>
        /// The proof request provided in the <paramref name="proofRequestJson"/> parameter must conform
        /// to the format:
        /// <code>
        /// {
        ///     "name": string,
        ///     "version": string,
        ///     "nonce": string,
        ///     "requested_attr1_uuid": &lt;attr_info&gt;,
        ///     "requested_attr2_uuid": &lt;attr_info&gt;,
        ///     "requested_attr3_uuid": &lt;attr_info&gt;,
        ///     "requested_predicate_1_uuid": &lt;predicate_info&gt;,
        ///     "requested_predicate_2_uuid": &lt;predicate_info&gt;,
        /// }
        /// </code>
        /// The method will return a JSON string with claims matching the given proof request in the following format:
        /// <code>
        /// {
        ///     "requested_attr1_uuid": [claim1, claim2],
        ///     "requested_attr2_uuid": [],
        ///     "requested_attr3_uuid": [claim3],
        ///     "requested_predicate_1_uuid": [claim1, claim3],
        ///     "requested_predicate_2_uuid": [claim2],
        /// }
        /// </code>
        /// Each claim in the result consists of a uuid (<c>claim_uuid</c>), human-readable attributes as
        /// a key-value map (<c>attrs</c>), a schema sequence number (<c>schema_seq_no</c>) an issuer DID
        /// (<c>issuer_did</c>) and a revocation registry sequence number (<c>revoc_reg_seq_no</c>):
        /// <code>
        /// {
        ///     "claim_uuid": string,
        ///     "attrs": [{"attr_name" : "attr_value"}],
        ///     "schema_seq_no": string,
        ///     "issuer_did": string,
        ///     "revoc_reg_seq_no": string,
        /// }
        /// </code>
        /// </remarks>
        /// <param name="wallet">The target wallet.</param>
        /// <param name="proofRequestJson">The proof request JSON.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that, when the operation completes, resolves
        /// to a JSON string containing the claims for the proof request.</returns>
        public static Task <string> ProverGetClaimsForProofReqAsync(Wallet wallet, string proofRequestJson)
        {
            ParamGuard.NotNull(wallet, "wallet");
            ParamGuard.NotNullOrWhiteSpace(proofRequestJson, "proofRequestJson");

            var taskCompletionSource = new TaskCompletionSource <string>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_prover_get_claims_for_proof_req(
                commandHandle,
                wallet.Handle,
                proofRequestJson,
                _proverGetClaimsForProofCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }
示例#29
0
        /// <summary>
        /// Opens a Wallet.
        /// </summary>
        /// <remarks>
        /// <para>Opens a wallet by name using the name of a wallet created earlier using the
        /// <see cref="CreateWalletAsync(string, string, string, string, string)"/> method.
        /// </para>
        /// <note type="note">Attempting to open the same wallet more than once will result in an error.</note>
        /// <para>
        /// The <paramref name="runtimeConfig"/> parameter allows the default configuration of the wallet
        /// to be overridden while opening the wallet; this does not replace the configuration registered
        /// when the wallet was created but instead overrides it for the duration of this opening only.
        /// See the <see cref="CreateWalletAsync(string, string, string, string, string)"/> method for
        /// details on the configuration string supported by the default wallet type; custom wallet
        /// types will can support their own format.
        /// </para>
        /// <para>The <paramref name="credentials"/> parameter is unused in the default wallet at present,
        /// however the value can be used by custom wallet implementations; it is up to the custom wallet
        /// type implementer to interpret the value.
        /// </para>
        /// </remarks>
        /// <param name="name">The name of the Wallet to open.</param>
        /// <param name="runtimeConfig">The runtime configuration to override the configuration the wallet was created with.</param>
        /// <param name="credentials">The wallet credentials.</param>
        /// <returns>An asynchronous <see cref="Task{T}"/> that resolves to a <see cref="Wallet"/> instance when the operation completes.</returns>
        public static Task <Wallet> OpenWalletAsync(string name, string runtimeConfig, string credentials)
        {
            ParamGuard.NotNullOrWhiteSpace(name, "name");

            var taskCompletionSource = new TaskCompletionSource <Wallet>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var result = IndyNativeMethods.indy_open_wallet(
                commandHandle,
                name,
                runtimeConfig,
                credentials,
                _openWalletCallback
                );

            CallbackHelper.CheckResult(result);

            return(taskCompletionSource.Task);
        }
示例#30
0
        /// <summary>
        /// Updates and stores the provided claim in the specified wallet.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method updates the claim provided in the <paramref name="claimsJson"/> parameter
        /// with a blinded master secret and stores it in the wallet specified in the
        /// <paramref name="wallet"/> parameter.
        /// </para>
        /// <para>
        /// The claim JSON is typically structured as follows:
        /// <code>
        /// {
        ///     "claim": {attr1:[value, value_as_int]}
        ///     "signature": &lt;signature&gt;,
        ///     "schema_seq_no": string,
        ///     "revoc_reg_seq_no", string
        ///     "issuer_did", string
        /// }
        /// </code>
        /// It contains the information about the <c>schema_seq_no</c>, <c>issuer_did</c>
        /// and <c>revoc_reg_seq_no</c> - see the <see cref="IssuerCreateClaimAsync(Wallet, string, string, int)"/>
        /// method for details.
        /// </para>
        /// Seq_no is a sequence number of the corresponding transaction in the ledger.
        /// </remarks>
        /// <param name="wallet">The target wallet.</param>
        /// <param name="claimsJson">The claims JSON.</param>
        /// <returns>An asynchronous <see cref="Task"/> that completes when the operation has completed.</returns>
        public static Task ProverStoreClaimAsync(Wallet wallet, string claimsJson)
        {
            ParamGuard.NotNull(wallet, "wallet");
            ParamGuard.NotNullOrWhiteSpace(claimsJson, "claimsJson");

            var taskCompletionSource = new TaskCompletionSource <bool>();
            var commandHandle        = PendingCommands.Add(taskCompletionSource);

            var commandResult = IndyNativeMethods.indy_prover_store_claim(
                commandHandle,
                wallet.Handle,
                claimsJson,
                CallbackHelper.TaskCompletingNoValueCallback
                );

            CallbackHelper.CheckResult(commandResult);

            return(taskCompletionSource.Task);
        }