public async Task <TraceState <TState, TLinkData> > CancelTransferAsync <TLinkData>(TransferResponseInput <TLinkData> input) { // retrieve parent link TransferResponseInput <TLinkData> headLinkInput = new TransferResponseInput <TLinkData>(input.TraceId, null); TraceLink <TLinkData> parentLink = await this.GetHeadLinkAsync <TLinkData>(headLinkInput); TLinkData data = input.Data; SdkConfig sdkConfig = await this.GetConfigAsync(); String workflowId = sdkConfig.WorkflowId; String configId = sdkConfig.ConfigId; String accountId = sdkConfig.AccountId; TraceLinkBuilderConfig <TLinkData> cfg = new TraceLinkBuilderConfig <TLinkData>() { // provide workflow id WorkflowId = workflowId, // and workflow config id ConfigId = configId, // and parent link to append to the existing trace ParentLink = parentLink }; // use a TraceLinkBuilder to create the first link // only provide workflowId to initiate a new trace TraceLinkBuilder <TLinkData> linkBuilder = new TraceLinkBuilder <TLinkData>(cfg); linkBuilder // this is to cancel the transfer .ForCancelTransfer(data) // add creator info .WithCreatedBy(accountId); // call createLink helper return(await this.CreateLinkAsync(linkBuilder)); }
/// <summary> /// The GetTraceDetails /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="input">The input<see cref="GetTraceDetailsInput"/></param> /// <returns>The <see cref="Task{TraceDetails{TLinkData}}"/></returns> public async Task <TraceDetails <TLinkData> > GetTraceDetailsAsync <TLinkData>(GetTraceDetailsInput input) { Dictionary <string, object> getTraceDetailsInput = JsonHelper.ObjectToMap(input); // delegate the graphql request execution // execute graphql query GraphQLResponse <dynamic> jsonResponse = await this.client.GraphqlAsync(GraphQL.QUERY_GETTRACEDETAILS, getTraceDetailsInput, null, null); var trace = jsonResponse.Data.trace; var info = trace.links.info; int totalCount = (int)trace.links.totalCount; IList <TraceLink <TLinkData> > links = new List <TraceLink <TLinkData> >(); // get all the groups that are owned by one of my accounts foreach (var lNode in trace.links.nodes) { JObject nodeRaw = lNode.raw; TLinkData nodeData = JsonHelper.ObjectToObject <TLinkData>(lNode.data); links.Add((TraceLink <TLinkData>)TraceLink <TLinkData> .FromObject <TLinkData>(nodeRaw.ToString(Newtonsoft.Json.Formatting.None), nodeData)); } // the details response object return(new TraceDetails <TLinkData>(links, totalCount, info.ToObject <Info>())); }
/// <summary> /// The PullTrace /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="input">The input<see cref="PullTransferInput{TLinkData}"/></param> /// <returns>The <see cref="Task{TraceState{TState, TLinkData}}"/></returns> public async Task <TraceState <TState, TLinkData> > PullTraceAsync <TLinkData>(PullTransferInput <TLinkData> input) { // retrieve parent link TransferResponseInput <TLinkData> headLinkInput = new TransferResponseInput <TLinkData>(input.TraceId, null); TraceLink <TLinkData> parentLink = await this.GetHeadLinkAsync <TLinkData>(headLinkInput); TLinkData data = input.Data; SdkConfig sdkConfig = await this.GetConfigAsync(); string workflowId = sdkConfig.WorkflowId; string userId = sdkConfig.UserId; string groupId = sdkConfig.GroupId; TraceLinkBuilderConfig <TLinkData> cfg = new TraceLinkBuilderConfig <TLinkData>() { // provide workflow id WorkflowId = workflowId, // and parent link to append to the existing trace ParentLink = parentLink }; // use a TraceLinkBuilder to create the first link // only provide workflowId to initiate a new trace TraceLinkBuilder <TLinkData> linkBuilder = new TraceLinkBuilder <TLinkData>(cfg); // this is a push transfer linkBuilder.ForPullTransfer(groupId, data).WithCreatedBy(userId); // call createLink helper return(await this.CreateLinkAsync(linkBuilder)); }
/// <summary> /// Given a trace id or a previous link return the previous link. /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="input"> .traceId the id of the trace </param> /// <returns>The <see cref="Task{TraceLink{TLinkData}}"/></returns> public async Task <TraceLink <TLinkData> > GetHeadLinkAsync <TLinkData>(ParentLink <TLinkData> input) { TraceLink <TLinkData> headLink = input.PrevLink; // if prevLink was not provided if (headLink == null && input.TraceId != null) { Dictionary <String, object> variables = new Dictionary <String, object> { { "traceId", input.TraceId } }; string query = GraphQL.QUERY_GETHEADLINK; // execute graphql query GraphQLResponse <dynamic> jsonResponse = await this.client.GraphqlAsync(query, variables, null, null); var trace = jsonResponse.Data.trace; string raw = trace.head.raw.ToString(); TLinkData data = JsonHelper.ObjectToObject <TLinkData>(trace.head.data); // convert the raw response to a link object headLink = new TraceLink <TLinkData>(Stratumn.Chainscript.Link.FromObject(raw), data); } if (headLink != null) { return(headLink); } else { throw new TraceSdkException("Previous link or trace Id must be provided"); } }
/// <summary> /// Creates a new Link from the given builder, signs it and executes the GraphQL /// mutation. /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="linkBuilder">The linkBuilder<see cref="TraceLinkBuilder{TLinkData}"/></param> /// <returns>The <see cref="Task{TraceState{TState, TLinkData}}"/></returns> private async Task <TraceState <TState, TLinkData> > CreateLinkAsync <TLinkData>(TraceLinkBuilder <TLinkData> linkBuilder) { // extract signing key from config SdkConfig sdkConfig = await GetConfigAsync(); Ed25519PrivateKeyParameters signingPrivateKey = sdkConfig.SigningPrivateKey; // build the link TraceLink <TLinkData> link = linkBuilder.Build(); // sign the link link.Sign(signingPrivateKey.GetEncoded(), "[version,data,meta]"); string linkObjJson = JsonHelper.ToJson(link.ALink); Dictionary <string, object> linkObj = JsonHelper.ObjectToMap(link.GetLink()); Dictionary <string, object> dataObj = JsonHelper.ObjectToMap(((TraceLink <TLinkData>)link).FormData()); Dictionary <string, object> variables = new Dictionary <string, object> { ["link"] = linkObj, ["data"] = dataObj }; // Debug.WriteLine("Request : " + JsonHelper.ToJson(dataObj)); // execute graphql query GraphQLResponse jsonResponse = await this.client.GraphqlAsync(GraphQL.MUTATION_CREATELINK, variables, null, null); var trace = jsonResponse.Data.createLink.trace; return(this.MakeTraceState <TLinkData>(trace)); }
/// <summary> /// Helper method used to reject a transfer request. Note that group /// is calculated from parent link. Parent link must have been provided! /// </summary> /// <param name="data"> the optional data </param> /// <returns>The <see cref="TraceLinkBuilder{TLinkData}"/></returns> public TraceLinkBuilder <TLinkData> ForRejectTransfer(TLinkData data) { TraceLink <TLinkData> parent = this.ParentLink; string action = TraceActionType.REJECT_TRANSFER.ToString(); string type = TraceLinkType.OWNED.ToString(); this.WithGroup(parent.Group()) .WithHashedData(data) .WithAction(action) .WithProcessState(type); return(this); }
/// <summary> /// Helper method used to cancel a transfer request. Note that owner and group /// are calculated from parent link. Parent link must have been provided! /// </summary> /// <param name="data"> the optional data </param> /// <returns>The <see cref="TraceLinkBuilder{TLinkData}"/></returns> public TraceLinkBuilder <TLinkData> ForCancelTransfer(TLinkData data) { TraceLink <TLinkData> parent = this.ParentLink; string action = TraceActionType.CANCEL_TRANSFER.ToString(); string type = TraceLinkType.OWNED.ToString(); this.WithOwner(parent.Owner().GetAccount()) .WithGroup(parent.Group()) .WithHashedData(data) .WithAction(action) .WithProcessState(type); return(this); }
/// <summary> /// Creates a new Link from the given builder, signs it and executes the GraphQL /// mutation. /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="linkBuilder">The linkBuilder<see cref="TraceLinkBuilder{TLinkData}"/></param> /// <param name="firstTry">if this is not the first try, do not retry</param> /// <returns>The <see cref="Task{TraceState{TState, TLinkData}}"/></returns> private async Task <TraceState <TState, TLinkData> > CreateLinkAsync <TLinkData>(TraceLinkBuilder <TLinkData> linkBuilder, bool firstTry = true) { // extract signing key from config SdkConfig sdkConfig = await GetConfigAsync(); Ed25519PrivateKeyParameters signingPrivateKey = sdkConfig.SigningPrivateKey; // build the link TraceLink <TLinkData> link = linkBuilder.Build(); // sign the link link.Sign(signingPrivateKey.GetEncoded(), "[version,data,meta]"); string linkObjJson = JsonHelper.ToJson(link.ALink); Dictionary <string, object> linkObj = JsonHelper.ObjectToMap(link.GetLink()); Dictionary <string, object> dataObj = JsonHelper.ObjectToMap(((TraceLink <TLinkData>)link).FormData()); Dictionary <string, object> variables = new Dictionary <string, object> { ["link"] = linkObj, ["data"] = dataObj }; try { // execute graphql query GraphQLResponse <dynamic> jsonResponse = await this.client.GraphqlAsync(GraphQL.MUTATION_CREATELINK, variables, null, null); var trace = jsonResponse.Data.createLink.trace; return(this.MakeTraceState <TLinkData>(trace)); } catch (TraceSdkException e) { if (firstTry && e.Message == ERROR_CONFIG_DEPRECATED) { var cfg = await this.GetConfigAsync(true); linkBuilder.WithConfigId(cfg.ConfigId); link.GetLink().Signatures.Clear(); return(await this.CreateLinkAsync(linkBuilder, false)); } throw e; } }
/// <summary> /// Helper method used for transfer of ownership requests (push). Note /// that group is calculated from parent link. Parent link must have /// been provided! /// </summary> /// <param name="to"> the group to which the transfer is made for </param> /// <param name="action"> the action (_PUSH_OWNERSHIP_ or _PULL_OWNERSHIP_) </param> /// <param name="type"> the type (PUSHING OR PULLING) </param> /// <param name="data"> the optional data </param> /// <returns>The <see cref="TraceLinkBuilder{TLinkData}"/></returns> public TraceLinkBuilder <TLinkData> ForTransferRequest(string to, TraceActionType action, TraceLinkType type, TLinkData data) { TraceLink <TLinkData> parent = this.ParentLink; this.WithGroup(parent.Group()) .WithHashedData(data) .WithAction(action.ToString()) .WithProcessState(type.ToString()); this.metadata.Inputs = new string[] { to }; this.metadata.LastFormId = parent.Form() != null?parent.Form() : parent.LastForm(); return(this); }
/// <summary> /// The MakeTraceState /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="trace">The trace<see cref="dynamic"/></param> /// <returns>The <see cref="TraceState{TState, TLinkData}"/></returns> private TraceState <TState, TLinkData> MakeTraceState <TLinkData>(dynamic trace) { JObject raw = trace.head.raw; var data = trace.head.data; string rawJson = raw.ToString(Newtonsoft.Json.Formatting.None); var linkObj = JsonHelper.FromJson <Link>(rawJson); TraceLink <TLinkData> headLink = new TraceLink <TLinkData>(new Stratumn.Chainscript.Link(linkObj), JsonHelper.ObjectToObject <TLinkData>(data)); TraceState <TState, TLinkData> traceState = new TraceState <TState, TLinkData>(headLink.TraceId(), headLink, headLink.CreatedAt(), headLink.CreatedBy(), JsonHelper.ObjectToObject <TState>(trace.state.data), trace.tags ?? new string[0], headLink.Group() ); return(traceState); }
/// <summary> /// The AppendLink /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="input">The input<see cref="AppendLinkInput{TLinkData}"/></param> /// <returns>The <see cref="Task{TraceState{TState, TLinkData}}"/></returns> public async Task <TraceState <TState, TLinkData> > AppendLinkAsync <TLinkData>(AppendLinkInput <TLinkData> input) { // retrieve parent link TransferResponseInput <TLinkData> headLinkInput = new TransferResponseInput <TLinkData>(input.TraceId, null); TraceLink <TLinkData> parentLink = await this.GetHeadLinkAsync <TLinkData>(headLinkInput); //extract info from input string actionKey = input.ActionKey; TLinkData data = input.Data; string groupLabel = input.GroupLabel; SdkConfig sdkConfig = await this.GetConfigAsync(); string workflowId = sdkConfig.WorkflowId; string configId = sdkConfig.ConfigId; string accountId = sdkConfig.AccountId; string groupId = sdkConfig.GetGroupId(groupLabel); // upload files and transform data await this.UploadFilesInLinkData(data); TraceLinkBuilderConfig <TLinkData> cfg = new TraceLinkBuilderConfig <TLinkData>() { // provide workflow id WorkflowId = workflowId, // and workflow config id ConfigId = configId, // and parent link to append to the existing trace ParentLink = parentLink }; // use a TraceLinkBuilder to create the first link // only provide workflowId to initiate a new trace TraceLinkBuilder <TLinkData> linkBuilder = new TraceLinkBuilder <TLinkData>(cfg); // this is an attestation linkBuilder.ForAttestation(actionKey, data) .WithGroup(groupId) .WithCreatedBy(accountId); // call createLink helper return(await this.CreateLinkAsync(linkBuilder)); }
/// <summary> /// The AppendLink /// </summary> /// <typeparam name="TLinkData"></typeparam> /// <param name="input">The input<see cref="AppendLinkInput{TLinkData}"/></param> /// <returns>The <see cref="Task{TraceState{TState, TLinkData}}"/></returns> public async Task <TraceState <TState, TLinkData> > AppendLinkAsync <TLinkData>(AppendLinkInput <TLinkData> input) { // retrieve parent link TransferResponseInput <TLinkData> headLinkInput = new TransferResponseInput <TLinkData>(input.TraceId, null); TraceLink <TLinkData> parentLink = await this.GetHeadLinkAsync <TLinkData>(headLinkInput); //extract info from input string formId = input.FormId; TLinkData data = input.Data; SdkConfig sdkConfig = await this.GetConfigAsync(); string workflowId = sdkConfig.WorkflowId; string userId = sdkConfig.UserId; string ownerId = sdkConfig.OwnerId; string groupId = sdkConfig.GroupId; IDictionary <string, string> actionNames = sdkConfig.ActionNames; // upload files and transform data await this.UploadFilesInLinkData(data); TraceLinkBuilderConfig <TLinkData> cfg = new TraceLinkBuilderConfig <TLinkData>() { // provide workflow id WorkflowId = workflowId, // and parent link to append to the existing trace ParentLink = parentLink }; // use a TraceLinkBuilder to create the first link // only provide workflowId to initiate a new trace TraceLinkBuilder <TLinkData> linkBuilder = new TraceLinkBuilder <TLinkData>(cfg); // this is an attestation linkBuilder.ForAttestation(formId, actionNames.ContainsKey(formId)?actionNames[formId]:null, data) .WithOwner(ownerId) .WithGroup(groupId) .WithCreatedBy(userId); // call createLink helper return(await this.CreateLinkAsync(linkBuilder)); }
public async Task <TraceState <TState, TLinkData> > AcceptTransferAsync <TLinkData>(TransferResponseInput <TLinkData> input) { // retrieve parent link TraceLink <TLinkData> parentLink = await this.GetHeadLinkAsync(input); //extract info from input TLinkData data = input.Data; string groupLabel = input.GroupLabel; SdkConfig sdkConfig = await this.GetConfigAsync(); String workflowId = sdkConfig.WorkflowId; string configId = sdkConfig.ConfigId; String accountId = sdkConfig.AccountId; String groupId = sdkConfig.GetGroupId(groupLabel); TraceLinkBuilderConfig <TLinkData> cfg = new TraceLinkBuilderConfig <TLinkData>() { // provide workflow id WorkflowId = workflowId, // and workflow config id ConfigId = configId, // and parent link to append to the existing trace ParentLink = parentLink }; // use a TraceLinkBuilder to create the first link // only provide workflowId to initiate a new trace TraceLinkBuilder <TLinkData> linkBuilder = new TraceLinkBuilder <TLinkData>(cfg); // this is an attestation linkBuilder.ForAcceptTransfer(data) // add group info .WithGroup(groupId) // add creator info .WithCreatedBy(accountId); // call createLink helper return(await CreateLinkAsync(linkBuilder)); }