From 5e7d94d8a7d701177863ca20e3b99b422bb7327e Mon Sep 17 00:00:00 2001 From: Ethan Celletti Date: Thu, 25 Jan 2024 14:08:04 -0800 Subject: [PATCH] Asset canister example and API (#119) * Init * more docs * Final --- samples/Sample.CLI/Program.cs | 206 +- samples/Sample.CLI/README.md | 44 + src/Agent/API.xml | 1667 ++++++++++++++++- src/Agent/Identities/IdentityUtil.cs | 45 +- .../AssetCanister/AssetCanisterApiClient.cs | 657 +++++++ .../Standards/AssetCanister/Models/Asset.cs | 106 ++ .../AssetCanister/Models/AssetCanisterArgs.cs | 100 + .../Models/BatchOperationKind.cs | 200 ++ .../Models/CertifiedTreeResult.cs | 42 + .../Models/CommitBatchArguments.cs | 44 + .../Models/CommitProposedBatchRequest.cs | 44 + .../Models/ComputeEvidenceArguments.cs | 44 + .../Models/ConfigurationResponse.cs | 51 + .../AssetCanister/Models/ConfigureRequest.cs | 51 + .../Models/CreateAssetArguments.cs | 69 + .../AssetCanister/Models/CreateBatchResult.cs | 35 + .../Models/CreateChunkRequest.cs | 43 + .../AssetCanister/Models/CreateChunkResult.cs | 35 + .../Models/DeleteAssetArguments.cs | 35 + .../Models/DeleteBatchArguments.cs | 35 + .../Models/GetAssetPropertiesResult.cs | 61 + .../AssetCanister/Models/GetChunkRequest.cs | 61 + .../AssetCanister/Models/GetChunkResult.cs | 34 + .../AssetCanister/Models/GetRequest.cs | 43 + .../AssetCanister/Models/GetResult.cs | 68 + .../AssetCanister/Models/GrantPermission.cs | 43 + .../AssetCanister/Models/HttpRequest.cs | 69 + .../AssetCanister/Models/HttpResponse.cs | 61 + .../AssetCanister/Models/ListPermitted.cs | 32 + .../AssetCanister/Models/Permission.cs | 23 + .../AssetCanister/Models/RevokePermission.cs | 43 + .../Models/SetAssetContentArguments.cs | 49 + .../Models/SetAssetPropertiesRequest.cs | 68 + .../AssetCanister/Models/SetPermissions.cs | 43 + .../AssetCanister/Models/StoreRequest.cs | 59 + .../Models/StreamingCallbackHttpResponse.cs | 45 + .../Models/StreamingCallbackToken.cs | 62 + .../AssetCanister/Models/StreamingStrategy.cs | 122 ++ .../Models/UnsetAssetContentArguments.cs | 35 + .../AssetCanister/Models/UpgradeArgs.cs | 30 + .../AssetCanister/Models/ValidationResult.cs | 107 ++ src/Candid/API.xml | 19 + src/Candid/Mapping/Mappers/TupleMapper.cs | 1 + src/Candid/Models/CandidTypedValue.cs | 12 + src/Candid/Models/Types/Base.cs | 11 +- src/Candid/Models/Values/CandidValue.cs | 14 + 46 files changed, 4740 insertions(+), 28 deletions(-) create mode 100644 samples/Sample.CLI/README.md create mode 100644 src/Agent/Standards/AssetCanister/AssetCanisterApiClient.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/Asset.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/AssetCanisterArgs.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/BatchOperationKind.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CertifiedTreeResult.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CommitBatchArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CommitProposedBatchRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/ComputeEvidenceArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/ConfigurationResponse.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/ConfigureRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CreateAssetArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CreateBatchResult.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CreateChunkRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/CreateChunkResult.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/DeleteAssetArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/DeleteBatchArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/GetAssetPropertiesResult.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/GetChunkRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/GetChunkResult.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/GetRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/GetResult.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/GrantPermission.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/HttpRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/HttpResponse.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/ListPermitted.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/Permission.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/RevokePermission.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/SetAssetContentArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/SetAssetPropertiesRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/SetPermissions.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/StoreRequest.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/StreamingCallbackHttpResponse.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/StreamingCallbackToken.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/StreamingStrategy.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/UnsetAssetContentArguments.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/UpgradeArgs.cs create mode 100644 src/Agent/Standards/AssetCanister/Models/ValidationResult.cs diff --git a/samples/Sample.CLI/Program.cs b/samples/Sample.CLI/Program.cs index 382bc3cb..0438db48 100644 --- a/samples/Sample.CLI/Program.cs +++ b/samples/Sample.CLI/Program.cs @@ -10,34 +10,198 @@ using System.Collections.Generic; using EdjCase.ICP.Agent; using System.IO; +using Sample.Shared.Governance.Models; +using System.Reflection.Metadata.Ecma335; +using EdjCase.ICP.Agent.Standards.AssetCanister; +using System.Text; +using EdjCase.ICP.Agent.Standards.AssetCanister.Models; public class Program { +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + [Verb("upload-asset", HelpText = "Upload a file to an asset canister.")] + class UploadOptions + { + [Option('u', "url", Required = false, HelpText = "The url to the boundy node", Default = "https://ic0.app")] + public string? Url { get; set; } + + [Option('c', "canister-id", Required = true, HelpText = "The asset canister id to upload to")] + public string CanisterId { get; set; } + + [Option('f', "file-path", Required = true, HelpText = "The path to the file to upload.")] + public string FilePath { get; set; } + + [Option('k', "asset-key", Required = true, HelpText = "The name of the asset to upload")] + public string Key { get; set; } + + [Option('t', "content-type", Required = true, HelpText = "The content type of the asset to upload (e.g text/plain)")] + public string ContentType { get; set; } + + [Option('e', "encoding", Required = true, HelpText = "The encoding of the asset to upload (e.g UTF-8)")] + public string Encoding { get; set; } + + [Option('i', "identity-pem-path", Required = false, HelpText = "The path to an identity pem file to auth the download")] + public string IdentityPEMFilePath { get; set; } + + [Option('p', "identity-pem-password", Required = false, HelpText = "The password for the identity PEM file")] + public string IdentityPassword { get; set; } + }; + + [Verb("download-asset", HelpText = "Download a file from an asset canister.")] + class DownloadOptions + { + [Option('u', "url", Required = false, HelpText = "The url to the boundy node", Default = "https://ic0.app")] + public string? Url { get; set; } + + [Option('c', "canister-id", Required = true, HelpText = "The asset canister id to download from")] + public string CanisterId { get; set; } + + [Option('f', "file-path", Required = true, HelpText = "The path to the file to save to")] + public string FilePath { get; set; } + + [Option('k', "asset-key", Required = true, HelpText = "The name of the asset to download")] + public string Key { get; set; } + + [Option('e', "encoding", Required = true, HelpText = "The encoding of the asset to download (e.g UTF-8)")] + public string Encoding { get; set; } + + [Option('i', "identity-pem-path", Required = false, HelpText = "The path to an identity PEM file to auth the download")] + public string IdentityPEMFilePath { get; set; } + + [Option('p', "identity-pem-password", Required = false, HelpText = "The password for the identity PEM file")] + public string IdentityPassword { get; set; } + }; - public static async Task Main() + +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public static async Task Main(string[] args) + { + var result = Parser.Default.ParseArguments(args) + .WithNotParsed(errors => { }); + await result + .WithParsedAsync(async options => + { + IIdentity? identity = null; + if (options.IdentityPEMFilePath != null) + { + identity = IdentityUtil.FromPemFile(options.IdentityPEMFilePath, options.IdentityPassword); + } + Uri httpBoundryNodeUrl = new Uri(options.Url!); + var agent = new HttpAgent(identity, httpBoundryNodeUrl); + Samples s = new(agent); + + Principal canisterId = Principal.FromText(options.CanisterId!); + await s.UploadChunkedFileAsync( + canisterId, + options.Key, + options.ContentType, + options.Encoding, + options.FilePath + ); + }); + + await result + .WithParsedAsync(async options => + { + IIdentity? identity = null; + if (options.IdentityPEMFilePath != null) + { + identity = IdentityUtil.FromPemFile(options.IdentityPEMFilePath, options.IdentityPassword); + } + Uri httpBoundryNodeUrl = new Uri(options.Url!); + var agent = new HttpAgent(identity, httpBoundryNodeUrl); + Samples s = new(agent); + + Principal canisterId = Principal.FromText(options.CanisterId!); + await s.DownloadFileAsync(canisterId, options.Key, options.Encoding, options.FilePath); + }); + + } + + private class Samples { - IIdentity? identity = null; - var agent = new HttpAgent(identity); - Principal canisterId = Principal.FromText("rrkah-fqaaa-aaaaa-aaaaq-cai"); - var client = new GovernanceApiClient(agent, canisterId); - ulong proposalId = 110174; - Console.WriteLine($"Getting info for proposal {proposalId}..."); - OptionalValue proposalInfo = await client.GetProposalInfo(proposalId); - - CandidTypedValue rawCandid = CandidTypedValue.FromObject(proposalInfo); - Console.WriteLine("ProposalInfo:\n" + rawCandid.Value.ToString()); - - Console.WriteLine(); - Console.WriteLine($"Getting the state for the governance canister ({canisterId})..."); - var paths = new List + private IAgent agent; + public Samples(IAgent agent) { - }; - ReadStateResponse readStateResponse = await agent.ReadStateAsync(canisterId, paths); + this.agent = agent; + } - Console.WriteLine("State:\n" + readStateResponse.Certificate.Tree); + //public async Task GetProposalAsync() + //{ + // Principal canisterId = Principal.FromText("rrkah-fqaaa-aaaaa-aaaaq-cai"); + // var client = new GovernanceApiClient(this.agent, canisterId); + // ulong proposalId = 110174; + // Console.WriteLine($"Getting info for proposal {proposalId}..."); + // OptionalValue proposalInfo = await client.GetProposalInfo(proposalId); - Console.WriteLine("Press ENTER to exit"); - Console.ReadLine(); + // CandidTypedValue rawCandid = CandidTypedValue.FromObject(proposalInfo); + // Console.WriteLine("ProposalInfo:\n" + rawCandid.Value.ToString()); + //} + + //public async Task GetGovernanceCanisterState() + //{ + // Principal canisterId = Principal.FromText("rrkah-fqaaa-aaaaa-aaaaq-cai"); + // Console.WriteLine(); + // Console.WriteLine($"Getting the state for the governance canister ({canisterId})..."); + // var paths = new List + // { + // }; + // ReadStateResponse readStateResponse = await this.agent.ReadStateAsync(canisterId, paths); + + // Console.WriteLine("State:\n" + readStateResponse.Certificate.Tree); + + //} + + public async Task DownloadFileAsync( + Principal canisterId, + string key, + string encoding, + string outputFilePath + ) + { + var client = new AssetCanisterApiClient(this.agent, canisterId); + + Console.WriteLine($"Downloading asset '{key}'..."); + GetResult result = await client.GetAsync(key, new List { encoding }); + File.WriteAllBytes(outputFilePath, result.Content); + Console.WriteLine($"Downloaded asset '{key}' to {outputFilePath}"); + } + + public async Task UploadChunkedFileAsync( + Principal canisterId, + string key, + string contentType, + string encoding, + string filePath + ) + { + var client = new AssetCanisterApiClient(this.agent, canisterId); + Console.WriteLine($"Uploading chunks for asset '{key}'..."); + Stream? contentStream = null; + try + { + contentStream = File.OpenRead(filePath); + + await client.UploadAssetChunkedAsync( + key: key, + contentType: contentType, + contentEncoding: encoding, + contentStream: contentStream, + sha256: null, + allowRawAccess: true, + enableAliasing: true, + headers: new List<(string, string)> + { + }, + maxAge: 2_000_000_000_000 + ); + } + finally + { + contentStream?.Dispose(); + } + Console.WriteLine($"Asset '{key}' is fully uploaded"); + } } -} \ No newline at end of file +} diff --git a/samples/Sample.CLI/README.md b/samples/Sample.CLI/README.md new file mode 100644 index 00000000..796178bf --- /dev/null +++ b/samples/Sample.CLI/README.md @@ -0,0 +1,44 @@ +# ICP.NET CLI Samples + +## Usage +``` +cd samples/Sample.CLI + +dotnet run +``` + +### Asset upload example +Command: upload-asset + +Required: +- canister_id - The asset canister id to use +- asset_key - The key/id of the asset +- encoding - The encoding of the file (e.g UTF-8) +- content_type - The content type of the asset (e.g text/plain) +- file_path - The path of the file to upload + +Optional: +- ic_url - Defaults to ic0.app. Use if wanting to use local (e.g http://127.0.0.1:4943) +- pem_file_path - Use to set identity of upload request. Defaults to anonymous identity +- pem_password - Use if the pem_file_path is set and it is encrypted +``` +dotnet run -- upload-asset -c {canister_id} -k {asset_key} -e {encoding} -t {content_type} -f {file_path} -u {ic_url} -i {pem_file_path} -p {pem_password} +``` + + +### Asset download example +Command: download-asset + +Required: +- canister_id - The asset canister id to use +- asset_key - The key/id of the asset +- encoding - The encoding of the file (e.g UTF-8) +- output_file_path - The path of the file to download to + +Optional: +- ic_url - Defaults to ic0.app. Use if wanting to use local (e.g http://127.0.0.1:4943) +- pem_file_path - Use to set identity of upload request. Defaults to anonymous identity +- pem_password - Use if the pem_file_path is set and it is encrypted +``` +dotnet run -- download-asset -u {ic_url} -c {canister_id} -k {asset_key} -e {encoding} -f {output_file_path} -i {pem_file_path} -p {pem_password} +``` diff --git a/src/Agent/API.xml b/src/Agent/API.xml index d34aec09..8f3cf9d3 100644 --- a/src/Agent/API.xml +++ b/src/Agent/API.xml @@ -466,18 +466,28 @@ A raw Ed25519 private key Ed25519 identity - + + + Parses a PEM file into the proper IIdentity class + + The file path of a PEM file + Optional. The password of the encrypted PEM file + IIdentity for the private key + + Parses a PEM file into the proper IIdentity class The stream of a PEM file + Optional. The password of the encrypted PEM file IIdentity for the private key - + Parses a PEM file into the proper IIdentity class The text reader of a PEM file + Optional. The password of the encrypted PEM file IIdentity for the private key @@ -1173,6 +1183,1659 @@ Internet Computer, agents must have an independent trustworthy source for this data, and must not be tempted to fetch it from this insecure location + + + Represents a client for interacting with the Asset Canister API. + + + + + The maximum size of an ingress message in bytes. + + + + + The maximum size of a file chunk + It is set to just under 2MB. + + + + + The IC agent + + + + + The asset canister id + + + + + The optional custom candid converter for request and response objects + + + + + Initializes a new instance of the class. + + The agent used for communication. + The ID of the asset canister. + The Candid converter to use for encoding and decoding values (optional). + + + + A helper method to upload an asset to the asset canister. + If the asset is larger than , it will be chunked. + If the asset is smaller than , it will be uploaded in a single request. + See for more advanced options + + The key of the asset. + The content type of the asset. + The content encoding of the asset. + The content of the asset. + The SHA256 hash of the asset (optional). + + + + A helper method to upload an asset to the asset canister in chunks + + The key of the asset. + The content type of the asset. + The content encoding of the asset. + The stream containing the asset content. + The SHA256 hash of the asset content. + Specifies whether raw access is allowed for the asset. + Specifies whether aliasing is enabled for the asset. + Additional headers to be included in the request. + The maximum age of the asset in seconds. + + + + Retrieves the API version for the asset canister + + The API version + + + + Retrieves the specified asset with the given accept encodings + + The asset key to get + A list of encodings to accept for the asset + The result of the get request + + + + Retrieves a chunk of data from the asset canister. + + The key of the asset. + The content encoding of the asset. + The index of the chunk. + The SHA256 hash of the chunk (optional). + The result of the chunk retrieval operation. + + + + Retrieves a list of assets from the asset canister + + List of assets + + + + Retrieves the certified tree of the asset canister + + The certified tree result. + + + + Creates a new batch for asset operations. + + The result of the batch creation operation. + + + + Creates a new chunk in a batch. + + The ID of the batch. + The content of the chunk. + The result of the chunk creation operation. + + + + Commits a batch of operations to the asset canister. + + The ID of the batch. + The operations to commit. + + + + Proposes a batch of operations for later commitment. + + The ID of the batch. + The operations to propose. + + + + Commits a previously proposed batch of operations. + + The ID of the batch. + The evidence for the proposed batch. + + + + Computes evidence for a proposed batch of operations. + + The ID of the batch. + The maximum number of iterations (optional). + The computed evidence. + + + + Deletes a batch of operations. + + The ID of the batch. + + + + Creates a new asset in the asset canister. + + The key of the asset. + The content type of the asset. + The maximum age of the asset in seconds (optional). + Additional headers for the asset (optional). + Specifies whether aliasing is enabled for the asset (optional). + Specifies whether raw access is allowed for the asset (optional). + + + + Sets the content for an asset in the asset canister. + + The key of the asset. + The content encoding of the asset. + The IDs of the chunks comprising the asset content. + The SHA256 hash of the asset content (optional). + + + + Removes a content encoding from an asset in the asset canister. + + The key of the asset. + The content encoding to remove. + + + + Deletes an asset from the asset canister. + + The key of the asset to delete. + + + + Deletes all assets from the asset canister. + + + + + Stores an asset in the asset canister. + + The key of the asset. + The content type of the asset. + The content encoding of the asset. + The content of the asset. + The SHA256 hash of the asset (optional). + + + + Grants the Commit permission to an identity + + The principal to authorize. + + + + Revokes the Commit permission from a principal. + + The principal to deauthorize. + + + + Retrieves a list of principals with the Commit permission. + + List of principals. + + + + Grants a permission to an identity + + The principal to grant permission to. + The permission to grant. + + + + Revokes a permission from a principal. + + The principal to revoke permission from. + The permission to revoke. + + + + Retrieves a list of principals with a specified permission. + + The permission to check. + List of principals. + + + + Takes ownership of the asset canister. + + + + + Retrieves properties of a specific asset. + + The key of the asset. + The asset properties. + + + + Sets properties for an asset in the asset canister. + + The request containing the asset properties to set. + + + + Retrieves the configuration of the asset canister. + + The configuration response. + + + + Configures the asset canister. + + The request containing the configuration settings. + + + + Validates the granting of a permission to a principal. + + The principal to grant permission to. + The permission to grant. + The validation result. + + + + Validates the revocation of a permission from a principal. + + The principal to revoke permission from. + The permission to revoke. + The validation result. + + + + Validates the taking of ownership of the asset canister. + + The validation result. + + + + Validates the commitment of a proposed batch of operations. + + The request containing the proposed batch details. + The validation result. + + + + Validates the configuration settings for the asset canister. + + The request containing the configuration settings. + The validation result. + + + + Represents an asset in the asset canister. + + + + + The key of the asset. + + + + + The content type of the asset. + + + + + A list of encodings for the asset. + + + + + Initializes a new instance of the class. + + The key of the asset. + The content type of the asset. + A list of encodings for the asset. + + + + Initializes a new instance of the class. + + + + + Represents an encoding of an asset. + + + + + The content encoding of the asset. + + + + + The SHA256 hash of the asset content. + + + + + The length of the asset content. + + + + + The last modified timestamp of the asset content. + + + + + Initializes a new instance of the class. + + The content encoding of the asset. + The SHA256 hash of the asset content. + The length of the asset content. + The last modified timestamp of the asset content. + + + + Initializes a new instance of the class. + + + + + Represents arguments for asset canister operations, supporting different variants. + + + + + The tag indicating the type of the asset canister argument. + + + + + The value of the asset canister argument. + + + + + Initializes a new instance of the class. + + The tag indicating the type of the argument. + The value of the argument. + + + + Protected constructor for . + + + + + Creates an instance of for the 'Init' operation. + + A new instance of . + + + + Creates an instance of for the 'Upgrade' operation. + + The upgrade arguments. + A new instance of . + + + + Retrieves the 'Upgrade' arguments from the instance. + + The 'Upgrade' arguments. + + + + Validates that the current tag matches the expected tag. + + The expected tag. + Thrown if the current tag does not match the expected tag. + + + + Enumerates the tags for different types of asset canister arguments. + + + + + Tag for initialization arguments. + + + + + Tag for upgrade arguments. + + + + + Represents a batch operation kind for asset canister operations, supporting different variants. + + + + + The tag indicating the type of the batch operation. + + + + + The value of the batch operation. + + + + + Initializes a new instance of the class. + + The tag indicating the type of the operation. + The value of the operation. + + + + Protected constructor for . + + + + + Creates an instance of for the 'CreateAsset' operation. + + The arguments for the 'CreateAsset' operation. + A new instance of . + + + + Creates an instance of for the 'SetAssetContent' operation. + + The arguments for the 'SetAssetContent' operation. + A new instance of . + + + + Creates an instance of for the 'SetAssetProperties' operation. + + The arguments for the 'SetAssetProperties' operation. + A new instance of . + + + + Creates an instance of for the 'UnsetAssetContent' operation. + + The arguments for the 'UnsetAssetContent' operation. + A new instance of . + + + + Creates an instance of for the 'DeleteAsset' operation. + + The arguments for the 'DeleteAsset' operation. + A new instance of . + + + + Creates an instance of for the 'Clear' operation. + + A new instance of . + + + + Retrieves the 'CreateAsset' arguments from the instance. + + The 'CreateAsset' arguments. + + + + Retrieves the 'SetAssetContent' arguments from the instance. + + The 'SetAssetContent' arguments. + + + + Retrieves the 'SetAssetProperties' arguments from the instance. + + The 'SetAssetProperties' arguments. + + + + Retrieves the 'UnsetAssetContent' arguments from the instance. + + The 'UnsetAssetContent' arguments. + + + + Retrieves the 'DeleteAsset' arguments from the instance. + + The 'DeleteAsset' arguments. + + + + Validates that the current tag matches the expected tag. + + The expected tag. + Thrown if the current tag does not match the expected tag. + + + + Enumerates the tags for different types of batch operations. + + + + + Tag for the 'CreateAsset' operation. + + + + + Tag for the 'SetAssetContent' operation. + + + + + Tag for the 'SetAssetProperties' operation. + + + + + Tag for the 'UnsetAssetContent' operation. + + + + + Tag for the 'DeleteAsset' operation. + + + + + Tag for the 'Clear' operation. + + + + + Represents the result of a certified tree query to the asset canister. + + + + + The certificate associated with the certified tree. + + + + + The binary representation of the certified tree. + + + + + Initializes a new instance of the class with specified certificate and tree. + + The certificate associated with the certified tree. + The binary representation of the certified tree. + + + + Initializes a new instance of the class. + + + + + Represents the arguments for committing a batch of operations in the asset canister. + + + + + The unique identifier of the batch. + + + + + A list of operations to be committed in the batch. + + + + + Initializes a new instance of the class with specified batch ID and operations. + + The unique identifier of the batch. + A list of operations to be committed in the batch. + + + + Initializes a new instance of the class. + + + + + Represents a request to commit a proposed batch of operations in the asset canister. + + + + + The unique identifier of the proposed batch. + + + + + The evidence required to commit the proposed batch. + + + + + Initializes a new instance of the class with specified batch ID and evidence. + + The unique identifier of the proposed batch. + The evidence required to commit the proposed batch. + + + + Initializes a new instance of the class. + + + + + Represents the arguments for computing evidence for a proposed batch in the asset canister. + + + + + The unique identifier of the batch for which evidence is being computed. + + + + + The maximum number of iterations to use in the computation of evidence. + + + + + Initializes a new instance of the class with specified batch ID and maximum iterations. + + The unique identifier of the batch. + The maximum number of iterations for the evidence computation. + + + + Initializes a new instance of the class. + + + + + Represents the response for the configuration of an asset canister. + + + + + Maximum number of batches allowed for upload at one time. + + + + + Maximum number of chunks across all batches being uploaded. + + + + + Maximum total size of content bytes across all chunks being uploaded. + + + + + Initializes a new instance of the class with specified configuration values. + + Maximum number of batches allowed for upload at one time. + Maximum number of chunks across all batches being uploaded. + Maximum total size of content bytes across all chunks being uploaded. + + + + Initializes a new instance of the class. + + + + + Represents a request to configure the asset canister with limits on batches, chunks, and bytes. + + + + + Optional maximum number of batches being uploaded at one time. + + + + + Optional maximum number of chunks across all batches being uploaded. + + + + + Optional maximum total size of content bytes across all chunks being uploaded. + + + + + Initializes a new instance of the class with specified limits. + + Optional maximum number of batches. + Optional maximum number of chunks. + Optional maximum size of bytes. + + + + Initializes a new instance of the class without specified limits. + + + + + Represents the arguments for creating a new asset in the asset canister. + + + + + Unique key identifier for the asset. + + + + + Content type of the asset (e.g., 'text/plain', 'image/jpeg'). + + + + + Optional maximum age for caching the asset. + + + + + Optional list of additional HTTP headers for the asset. + + + + + Optional flag to enable aliasing for the asset. + + + + + Optional flag to allow raw access to the asset. + + + + + Constructor for creating asset arguments with specified properties. + + Asset key. + Content type of the asset. + Maximum age for caching. + Additional HTTP headers. + Flag for enabling aliasing. + Flag for allowing raw access. + + + + Represents the result of creating a new batch in the asset canister. + + + + + Unique identifier for the created batch. + + + + + Initializes a new instance of the class with a specified batch ID. + + Unique identifier for the batch. + + + + Initializes a new instance of the class. + + + + + Represents a request to create a chunk in an asset canister batch. + + + + + Unique identifier for the batch to which the chunk belongs. + + + + + Content of the chunk as a byte array. + + + + + Initializes a new instance of the CreateChunkRequest class with specified batch ID and content. + + Unique identifier for the batch. + Content of the chunk as a byte array. + + + + Initializes a new instance of the CreateChunkRequest class. + + + + + Represents the result of a 'create_chunk' operation on an asset canister. + + + + + Unique identifier for the created chunk. + + + + + Initializes a new instance of the CreateChunkResult class with a specified chunk ID. + + Unique identifier for the chunk. + + + + Initializes a new instance of the CreateChunkResult class. + + + + + Represents the arguments for deleting an asset in the asset canister. + + + + + The key of the asset to delete. + + + + + Initializes a new instance of the DeleteAssetArguments class with a specified asset key. + + The key of the asset to delete. + + + + Initializes a new instance of the DeleteAssetArguments class. + + + + + Represents the arguments for deleting a batch in the asset canister. + + + + + Unique identifier for the batch to be deleted. + + + + + Initializes a new instance of DeleteBatchArguments with a specified batch ID. + + Unique identifier for the batch. + + + + Initializes a new instance of DeleteBatchArguments. + + + + + Represents the result of a request to get asset properties from an asset canister. + + + + + Maximum age of the asset for caching purposes. + + + + + List of additional HTTP headers to be set when serving the asset. + + + + + Indicates whether the asset can be retrieved from raw.ic0.app or raw.icp0.io. + + + + + Indicates if the asset's key might be an alias for another asset. + + + + + Constructor for initializing GetAssetPropertiesResult with specific values. + + Maximum age of the asset for caching. + List of additional HTTP headers for the asset. + Flag for raw access availability of the asset. + Flag indicating if the asset key is an alias. + + + + Default constructor for GetAssetPropertiesResult. + + + + + Represents a request to retrieve a specific chunk of an asset's content encoding from an asset canister. + + + + + Unique identifier for the asset. + + + + + Content encoding type of the asset (e.g., 'gzip', 'identity'). + + + + + Index of the chunk within the asset's content encoding. + + + + + Optional SHA-256 hash of the entire asset encoding for validation. + + + + + Initializes a new instance of the GetChunkRequest class with specified parameters. + + Asset key. + Content encoding type. + Chunk index. + Optional SHA-256 hash for validation. + + + + Initializes a new instance of the GetChunkRequest class. + + + + + Represents the result of a 'get_chunk' method call to an asset canister. + + + + + Content of the asset chunk. + + + + + Initializes a new instance of the GetChunkResult class with specified content. + + Byte array representing the content of the chunk. + + + + Initializes a new instance of the GetChunkResult class. + + + + + Represents a request for retrieving an asset from the asset canister. + + + + + The key identifying the asset to retrieve. + + + + + List of acceptable content encodings for the asset. + + + + + Initializes a new instance of the GetRequest class with specified key and acceptable encodings. + + The asset key. + List of acceptable content encodings. + + + + Initializes a new instance of the GetRequest class. + + + + + Represents the result of a 'get' operation from the asset canister. + + + + + The content of the asset. + + + + + The MIME type of the asset. + + + + + The encoding of the asset content. + + + + + The SHA-256 hash of the asset, if available. + + + + + The total length of the asset in chunks. + + + + + Initializes a new instance of the GetResult class with specified details. + + The content of the asset. + The MIME type of the asset. + The encoding of the asset content. + The SHA-256 hash of the asset, if available. + The total length of the asset in chunks. + + + + Initializes a new instance of the GetResult class. + + + + + Represents a request to grant a permission to a principal in the asset canister. + + + + + The principal to which the permission will be granted. + + + + + The permission to be granted. + + + + + Initializes a new instance of the GrantPermission class with specified principal and permission. + + The principal to grant permission to. + The permission to be granted. + + + + Initializes a new instance of the GrantPermission class. + + + + + Represents an HTTP request for the Asset Canister. + + + + + HTTP method (e.g., GET, POST). + + + + + URL of the request. + + + + + List of HTTP headers. + + + + + Body of the request as a list of bytes. + + + + + Optional certificate version. + + + + + Constructs an HttpRequest with specified parameters. + + HTTP method. + URL of the request. + List of HTTP headers. + Body of the request as a list of bytes. + Optional certificate version. + + + + Default constructor for HttpRequest. + + + + + Represents an HTTP response from the asset canister. + + + + + HTTP status code of the response. + + + + + List of headers included in the response. + + + + + Body of the response as a list of bytes. + + + + + Optional streaming strategy for the response. + + + + + Initializes a new instance of the HttpResponse class with specified parameters. + + HTTP status code of the response. + List of headers included in the response. + Body of the response as a list of bytes. + Optional streaming strategy for the response. + + + + Initializes a new instance of the HttpResponse class. + + + + + Represents a request to list principals with a specified permission in the asset canister. + + + + + The specific permission to query for. + + + + + Initializes a new instance of the ListPermitted class with a specified permission. + + The permission to query for. + + + + Initializes a new instance of the ListPermitted class. + + + + + Enum representing the different types of permissions for interacting with an asset canister. + + + + + Permission allowing changes to the assets served by the asset canister. + + + + + Permission allowing a principal to grant and revoke permissions to other principals. + + + + + Permission allowing the upload of data to the canister to be committed later by a principal with the Commit permission. + + + + + Represents a request to revoke a permission from a principal in the asset canister. + + + + + The principal from whom the permission will be revoked. + + + + + The permission to be revoked. + + + + + Initializes a new instance of the RevokePermission class with specified principal and permission. + + The principal from whom the permission will be revoked. + The permission to be revoked. + + + + Initializes a new instance of the RevokePermission class. + + + + + Represents a request to set asset content with chunks in the asset canister. + + + + + Unique identifier for the asset. + + + + + The content encoding of the asset (e.g UTF-8) + + + + + A list of chunk ids that have been uploaded, to use as the content bytes + + + + + Optional. The SHA256 hash of the entire content bytes, for validation of the chunk bytes + + + + Unique identifier for the asset. + The content encoding of the asset (e.g UTF-8) + A list of chunk ids that have been uploaded, to use as the content bytes + Optional. The SHA256 hash of the entire content bytes, for validation of the chunk bytes + + + + Represents a request to set properties of an asset in the asset canister. + + + + + Unique identifier for the asset. + + + + + Optional. The max age (in nanoseconds) for the asset + + + + + Optional. The headers for the asset + + + + + Optional. Whether to allow raw access to the asset + + + + + Optional. Whether the asset is aliased + + + + + Initializes a new instance of the class. + + The key of the asset. + The maximum age of the asset. + The headers of the asset. + Indicates whether raw access is allowed for the asset. + Indicates whether the asset is aliased. + + + + Represents a request to set permessions for identities in the asset canister. + + + + + A list of identities that can prepare an asset + + + + + A list of identities that can commit an asset + + + + + A list of identities that can manage permissions + + + + + Initializes a new instance of the class. + + The list of principals with prepare permissions. + The list of principals with commit permissions. + The list of principals with manage permissions. + + + + Represents a request to store a small asset in the asset canister. + + + + + Unique identifier for the asset. + + + + + The content type of the asset (e.g text/plain) + + + + + The content encoding of the asset (e.g UTF-8) + + + + + The content bytes of the asset + + + + + Optional. The SHA256 hash of the entire content bytes, for validation of the bytes + + + + + Represents a request to store an asset in the canister. + + The key of the asset. + The content type of the asset. + The content encoding of the asset. + The content of the asset. + The SHA256 hash of the asset content. + + + + Represents a response from the streaming callback method + + + + + The returned bytes for the streaming callback + + + + + Optional. The token to use for the next streaming callback + + + + + Represents an HTTP response for a streaming callback. + + The body of the response. + The optional token associated with the response. + + + + Initializes a new instance of the class. + + + + + Represents a single result of streaming an asset from the asset canister + + + + + Unique identifier for the asset. + + + + + The content encoding of the asset (e.g UTF-8) + + + + + The index of the chunk to stream + + + + + Optional. The SHA256 hash of the entire content bytes, for validation of the bytes + + + + + Initializes a new instance of the class. + + The key associated with the token. + The content encoding of the token. + The index of the token. + The SHA256 value of the token. + + + + Initializes a new instance of the class. + + + + + Represents a strategy for streaming from an asset canister + + + + + The tag for the streaming strategy variant + + + + + The value for the streaming strategy variant + + + + + Represents a strategy for streaming from an asset canister + + The tag for the streaming strategy variant + The value for the streaming strategy variant + + + + Initializes a new instance of the class. + + + + + Creates a new streaming strategy with a callback + + The callback info + The streaming strategy variant + + + + Casts the streaming strategy to a callback + + The Callback info + + + + Represents information about a callback function and its associated token. + + + + + The callback function + + + + + The streaming callback token + + + + + Initializes a new instance of the class. + + The callback function. + The streaming callback token. + + + + Initializes a new instance of the class. + + + + + Represents all the options for the streaming strategy variant + + + + + For callback streaming + + + + + Represents a request to remove the content encoding for an asset + + + + + Unique identifier for the asset. + + + + + The content encoding of the asset (e.g UTF-8) + + + + + Initializes a new instance of the class. + + The key of the asset. + The encoding of the asset content. + + + + Represents a request for upgrading the asset canister with options + + + + + Optional. The permissions to set for the asset canister + + + + + Creates a new instance of the class. + + Optional value for setting permissions. + + + + Represents a result from calling a validation method + + + + + The tag for the validation result variant + + + + + The value for the validation result variant + + + + + Represents a result from calling a validation method + + The tag for the validation result variant + The value for the validation result variant + + + + Initializes a new instance of the class. + + + + + Creates a new validation result with an ok value + + The validation message + The OK validation result variant + + + + Creates a new validation result with an error value + + The error message + The error validation result variant + + + + Casts the validation result to an ok message + + The ok message + + + + Casts the validation result to an error message + + The error message + + + + The tag for the validation result variant + + + + + The ok variant + + + + + The error variant + + A pre-generated client for the ICRC1 standard diff --git a/src/Agent/Identities/IdentityUtil.cs b/src/Agent/Identities/IdentityUtil.cs index 999cf826..7c9e3b2d 100644 --- a/src/Agent/Identities/IdentityUtil.cs +++ b/src/Agent/Identities/IdentityUtil.cs @@ -50,16 +50,30 @@ public static Ed25519Identity FromEd25519PrivateKey(byte[] privateKey) return Ed25519Identity.FromPrivateKey(privateKey); } + /// + /// Parses a PEM file into the proper IIdentity class + /// + /// The file path of a PEM file + /// Optional. The password of the encrypted PEM file + /// IIdentity for the private key + public static IIdentity FromPemFile(string pemFilePath, string? password) + { + using (FileStream stream = File.OpenRead(pemFilePath)) + { + return FromPemFile(stream, password); + } + } /// /// Parses a PEM file into the proper IIdentity class /// /// The stream of a PEM file + /// Optional. The password of the encrypted PEM file /// IIdentity for the private key - public static IIdentity FromPemFile(Stream pemFile) + public static IIdentity FromPemFile(Stream pemFile, string? password) { using (StreamReader reader = new StreamReader(pemFile)) { - return FromPemFile(reader); + return FromPemFile(reader, password); } } @@ -67,11 +81,21 @@ public static IIdentity FromPemFile(Stream pemFile) /// Parses a PEM file into the proper IIdentity class /// /// The text reader of a PEM file + /// Optional. The password of the encrypted PEM file /// IIdentity for the private key - public static IIdentity FromPemFile(TextReader pemFileReader) + public static IIdentity FromPemFile(TextReader pemFileReader, string? password) { - PemReader pemReader = new PemReader(pemFileReader); + IPasswordFinder? passwordFinder = null; + if (password != null) + { + passwordFinder = new StaticPassworFinder(password); + }; + PemReader pemReader = new PemReader(pemFileReader, passwordFinder); object obj = pemReader.ReadObject(); + if (obj == null) + { + throw new Exception("Could not read PEM file"); + } if (obj is AsymmetricCipherKeyPair aKeyPair && aKeyPair.Private is ECPrivateKeyParameters ecPrivateKey) { @@ -94,5 +118,18 @@ public static IIdentity FromPemFile(TextReader pemFileReader) throw new NotImplementedException($"PEM data of type '{obj.GetType()}' is not yet supported"); } } + + private class StaticPassworFinder : IPasswordFinder + { + private readonly string password; + public StaticPassworFinder(string password) + { + this.password = password; + } + public char[] GetPassword() + { + return this.password.ToCharArray(); + } + } } } diff --git a/src/Agent/Standards/AssetCanister/AssetCanisterApiClient.cs b/src/Agent/Standards/AssetCanister/AssetCanisterApiClient.cs new file mode 100644 index 00000000..f12b1541 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/AssetCanisterApiClient.cs @@ -0,0 +1,657 @@ +using EdjCase.ICP.Agent.Agents; +using EdjCase.ICP.Candid.Models; +using EdjCase.ICP.Candid; +using System.Threading.Tasks; +using EdjCase.ICP.Agent.Responses; +using System.Collections.Generic; +using System.IO; +using System; +using EdjCase.ICP.Agent.Standards.AssetCanister.Models; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister +{ + /// + /// Represents a client for interacting with the Asset Canister API. + /// + public class AssetCanisterApiClient + { + /// + /// The maximum size of an ingress message in bytes. + /// + public const int MAX_INGRESS_MESSAGE_SIZE = 2 * 1024 * 1024; // 2MB + /// + /// The maximum size of a file chunk + /// It is set to just under 2MB. + /// + public const int MAX_CHUNK_SIZE = MAX_INGRESS_MESSAGE_SIZE - 200; // Just under 2MB + + /// + /// The IC agent + /// + public IAgent Agent { get; } + + /// + /// The asset canister id + /// + public Principal CanisterId { get; } + + /// + /// The optional custom candid converter for request and response objects + /// + public CandidConverter? Converter { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The agent used for communication. + /// The ID of the asset canister. + /// The Candid converter to use for encoding and decoding values (optional). + public AssetCanisterApiClient( + IAgent agent, + Principal canisterId, + CandidConverter? converter = default + ) + { + this.Agent = agent; + this.CanisterId = canisterId; + this.Converter = converter; + } + + /// + /// A helper method to upload an asset to the asset canister. + /// If the asset is larger than , it will be chunked. + /// If the asset is smaller than , it will be uploaded in a single request. + /// See for more advanced options + /// + /// The key of the asset. + /// The content type of the asset. + /// The content encoding of the asset. + /// The content of the asset. + /// The SHA256 hash of the asset (optional). + public async Task UploadAssetSimpleAsync( + string key, + string contentType, + string contentEncoding, + byte[] content, + byte[]? sha256 = null + ) + { + if (content.Length >= MAX_CHUNK_SIZE) + { + // Chunk if too large + using MemoryStream stream = new MemoryStream(content); + await this.UploadAssetChunkedAsync( + key, + contentType, + contentEncoding, + stream, + sha256 + ); + return; + } + await this.StoreAsync( + key, + contentType, + contentEncoding, + content, + sha256 + ); + } + + /// + /// A helper method to upload an asset to the asset canister in chunks + /// + /// The key of the asset. + /// The content type of the asset. + /// The content encoding of the asset. + /// The stream containing the asset content. + /// The SHA256 hash of the asset content. + /// Specifies whether raw access is allowed for the asset. + /// Specifies whether aliasing is enabled for the asset. + /// Additional headers to be included in the request. + /// The maximum age of the asset in seconds. + public async Task UploadAssetChunkedAsync( + string key, + string contentType, + string contentEncoding, + Stream contentStream, + byte[]? sha256 = null, + bool? allowRawAccess = null, + bool? enableAliasing = null, + List<(string, string)>? headers = null, + ulong? maxAge = null + ) + { + CreateBatchResult createBatchResult = await this.CreateBatchAsync(); + + try + { + List chunkIds = new(); + byte[] buffer = new byte[MAX_CHUNK_SIZE]; + while (true) + { + int bytesRead = await contentStream.ReadAsync(buffer.AsMemory()); + if (bytesRead <= 0) + { + break; + } + byte[] chunkBytes = bytesRead < buffer.Length + ? buffer[0..(bytesRead - 1)] + : buffer; + CreateChunkResult result = await this.CreateChunkAsync(createBatchResult.BatchId, chunkBytes); + chunkIds.Add(result.ChunkId); + } + + OptionalValue sha256Opt = sha256 == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(sha256); + + OptionalValue allowRawAccessOpt = allowRawAccess == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(allowRawAccess.Value); + + OptionalValue enableAliasingOpt = enableAliasing == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(enableAliasing.Value); + + OptionalValue> headersOpt = headers == null + ? OptionalValue>.NoValue() + : OptionalValue>.WithValue(headers); + + OptionalValue maxAgeOpt = maxAge == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(maxAge.Value); + + + List operations = new List + { + BatchOperationKind.CreateAsset(new CreateAssetArguments(key, contentType, maxAgeOpt, headersOpt, enableAliasingOpt, allowRawAccessOpt)), + BatchOperationKind.SetAssetContent(new SetAssetContentArguments(key, contentEncoding, chunkIds, sha256Opt)) + }; + + await this.CommitBatchAsync(createBatchResult.BatchId, operations); + + } + catch + { + // Rollback batch + await this.DeleteBatchAsync(createBatchResult.BatchId); + } + } + + /// + /// Retrieves the API version for the asset canister + /// + /// The API version + public async Task GetApiVersionAsync() + { + CandidArg arg = CandidArg.FromCandid(); + QueryResponse response = await this.Agent.QueryAsync(this.CanisterId, "api_version", arg); + CandidArg reply = response.ThrowOrGetReply(); + return reply.ToObjects(this.Converter); + } + + /// + /// Retrieves the specified asset with the given accept encodings + /// + /// The asset key to get + /// A list of encodings to accept for the asset + /// The result of the get request + public async Task GetAsync(string key, List acceptEncodings) + { + GetRequest request = new(key, acceptEncodings); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + QueryResponse response = await this.Agent.QueryAsync(this.CanisterId, "get", arg); + CandidArg reply = response.ThrowOrGetReply(); + return reply.ToObjects(this.Converter); + } + + /// + /// Retrieves a chunk of data from the asset canister. + /// + /// The key of the asset. + /// The content encoding of the asset. + /// The index of the chunk. + /// The SHA256 hash of the chunk (optional). + /// The result of the chunk retrieval operation. + public async Task GetChunkAsync( + string key, + string contentEncoding, + UnboundedUInt index, + byte[]? sha256 = null + ) + { + OptionalValue sha256Opt = sha256 == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(sha256); + GetChunkRequest request = new(key, contentEncoding, index, sha256Opt); + + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + QueryResponse response = await this.Agent.QueryAsync(this.CanisterId, "get_chunk", arg); + CandidArg reply = response.ThrowOrGetReply(); + return reply.ToObjects(this.Converter); + } + + /// + /// Retrieves a list of assets from the asset canister + /// + /// List of assets + public async Task> ListAsync() + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.EmptyRecord()); + QueryResponse response = await this.Agent.QueryAsync(this.CanisterId, "list", arg); + CandidArg reply = response.ThrowOrGetReply(); + return reply.ToObjects>(this.Converter); + } + + /// + /// Retrieves the certified tree of the asset canister + /// + /// The certified tree result. + public async Task GetCertifiedTreeAsync() + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.EmptyRecord()); + QueryResponse response = await this.Agent.QueryAsync(this.CanisterId, "certified_tree", arg); + CandidArg reply = response.ThrowOrGetReply(); + return reply.ToObjects(this.Converter); + } + + /// + /// Creates a new batch for asset operations. + /// + /// The result of the batch creation operation. + public async Task CreateBatchAsync() + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.EmptyRecord()); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "create_batch", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Creates a new chunk in a batch. + /// + /// The ID of the batch. + /// The content of the chunk. + /// The result of the chunk creation operation. + public async Task CreateChunkAsync(UnboundedUInt batchId, byte[] content) + { + CreateChunkRequest request = new(batchId, content); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "create_chunk", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Commits a batch of operations to the asset canister. + /// + /// The ID of the batch. + /// The operations to commit. + public async Task CommitBatchAsync(UnboundedUInt batchId, List operations) + { + CommitBatchArguments request = new(batchId, operations); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "commit_batch", arg); + } + + /// + /// Proposes a batch of operations for later commitment. + /// + /// The ID of the batch. + /// The operations to propose. + public async Task ProposeCommitBatchAsync(UnboundedUInt batchId, List operations) + { + CommitBatchArguments request = new(batchId, operations); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "propose_commit_batch", arg); + } + + /// + /// Commits a previously proposed batch of operations. + /// + /// The ID of the batch. + /// The evidence for the proposed batch. + public async Task CommitProposedBatchAsync(UnboundedUInt batchId, byte[] evidence) + { + CommitProposedBatchRequest request = new(batchId, evidence); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "commit_proposed_batch", arg); + } + + /// + /// Computes evidence for a proposed batch of operations. + /// + /// The ID of the batch. + /// The maximum number of iterations (optional). + /// The computed evidence. + public async Task> ComputeEvidenceAsync(UnboundedUInt batchId, ushort? maxIterations = null) + { + OptionalValue maxIterationsOpt = maxIterations == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(maxIterations.Value); + ComputeEvidenceArguments request = new ComputeEvidenceArguments(batchId, maxIterationsOpt); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "compute_evidence", arg); + return reply.ToObjects>(this.Converter); + } + + /// + /// Deletes a batch of operations. + /// + /// The ID of the batch. + public async Task DeleteBatchAsync(UnboundedUInt batchId) + { + DeleteBatchArguments request = new(batchId); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "delete_batch", arg); + } + + /// + /// Creates a new asset in the asset canister. + /// + /// The key of the asset. + /// The content type of the asset. + /// The maximum age of the asset in seconds (optional). + /// Additional headers for the asset (optional). + /// Specifies whether aliasing is enabled for the asset (optional). + /// Specifies whether raw access is allowed for the asset (optional). + + public async Task CreateAssetAsync( + string key, + string contentType, + ulong? maxAge = null, + List<(string, string)>? headers = null, + bool? enableAliasing = null, + bool? allowRawAccess = null + ) + { + OptionalValue maxAgeOpt = maxAge == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(maxAge.Value); + + OptionalValue> headersOpt = headers == null + ? OptionalValue>.NoValue() + : OptionalValue>.WithValue(headers); + + OptionalValue enableAliasingOpt = enableAliasing == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(enableAliasing.Value); + + OptionalValue allowRawAccessOpt = allowRawAccess == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(allowRawAccess.Value); + CreateAssetArguments request = new( + key, + contentType, + maxAgeOpt, + headersOpt, + enableAliasingOpt, + allowRawAccessOpt + ); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "create_asset", arg); + } + + /// + /// Sets the content for an asset in the asset canister. + /// + /// The key of the asset. + /// The content encoding of the asset. + /// The IDs of the chunks comprising the asset content. + /// The SHA256 hash of the asset content (optional). + public async Task SetAssetContentAsync( + string key, + string contentEncoding, + List chunkIds, + byte[]? sha256 = null + ) + { + OptionalValue sha256Opt = sha256 == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(sha256); + SetAssetContentArguments request = new(key, contentEncoding, chunkIds, sha256Opt); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "set_asset_content", arg); + } + + /// + /// Removes a content encoding from an asset in the asset canister. + /// + /// The key of the asset. + /// The content encoding to remove. + + public async Task UnsetAssetContentAsync(string key, string contentEncoding) + { + UnsetAssetContentArguments request = new(key, contentEncoding); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "unset_asset_content", arg); + } + + /// + /// Deletes an asset from the asset canister. + /// + /// The key of the asset to delete. + public async Task DeleteAssetAsync(string key) + { + DeleteAssetArguments request = new(key); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "delete_asset", arg); + } + + /// + /// Deletes all assets from the asset canister. + /// + public async Task ClearAsync() + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.EmptyRecord()); + await this.Agent.CallAndWaitAsync(this.CanisterId, "clear", arg); + } + + /// + /// Stores an asset in the asset canister. + /// + /// The key of the asset. + /// The content type of the asset. + /// The content encoding of the asset. + /// The content of the asset. + /// The SHA256 hash of the asset (optional). + public async Task StoreAsync( + string key, + string contentType, + string contextEncoding, + byte[] content, + byte[]? sha256 = null + ) + { + OptionalValue sha256Opt = sha256 == null + ? OptionalValue.NoValue() + : OptionalValue.WithValue(sha256); + StoreRequest request = new(key, contentType, contextEncoding, content, sha256Opt); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "store", arg); + } + + /// + /// Grants the Commit permission to an identity + /// + /// The principal to authorize. + public async Task AuthorizeAsync(Principal principal) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(principal, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "authorize", arg); + } + + /// + /// Revokes the Commit permission from a principal. + /// + /// The principal to deauthorize. + public async Task DeauthorizeAsync(Principal principal) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(principal, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "deauthorize", arg); + } + + /// + /// Retrieves a list of principals with the Commit permission. + /// + /// List of principals. + public async Task> ListAuthorizedAsync() + { + CandidArg arg = CandidArg.FromCandid(); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "list_authorized", arg); + return reply.ToObjects>(this.Converter); + } + + /// + /// Grants a permission to an identity + /// + /// The principal to grant permission to. + /// The permission to grant. + public async Task GrantPermissionAsync(Principal principal, Permission permission) + { + GrantPermission request = new(principal, permission); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "grant_permission", arg); + } + + /// + /// Revokes a permission from a principal. + /// + /// The principal to revoke permission from. + /// The permission to revoke. + public async Task RevokePermissionAsync(Principal principal, Permission permission) + { + RevokePermission request = new RevokePermission(principal, permission); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "revoke_permission", arg); + } + + /// + /// Retrieves a list of principals with a specified permission. + /// + /// The permission to check. + /// List of principals. + public async Task> ListPermittedAsync(Permission withPermission) + { + ListPermitted request = new ListPermitted(withPermission); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "list_permitted", arg); + return reply.ToObjects>(this.Converter); + } + + /// + /// Takes ownership of the asset canister. + /// + public async Task TakeOwnershipAsync() + { + CandidArg arg = CandidArg.FromCandid(); + await this.Agent.CallAndWaitAsync(this.CanisterId, "take_ownership", arg); + } + + /// + /// Retrieves properties of a specific asset. + /// + /// The key of the asset. + /// The asset properties. + public async Task GetAssetPropertiesAsync(string key) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(key, this.Converter)); + QueryResponse response = await this.Agent.QueryAsync(this.CanisterId, "get_asset_properties", arg); + CandidArg reply = response.ThrowOrGetReply(); + return reply.ToObjects(this.Converter); + } + + /// + /// Sets properties for an asset in the asset canister. + /// + /// The request containing the asset properties to set. + public async Task SetAssetPropertiesAsync(SetAssetPropertiesRequest request) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "set_asset_properties", arg); + } + + /// + /// Retrieves the configuration of the asset canister. + /// + /// The configuration response. + public async Task GetConfigurationAsync() + { + CandidArg arg = CandidArg.FromCandid(); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "get_configuration", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Configures the asset canister. + /// + /// The request containing the configuration settings. + public async Task ConfigureAsync(ConfigureRequest request) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + await this.Agent.CallAndWaitAsync(this.CanisterId, "configure", arg); + } + + /// + /// Validates the granting of a permission to a principal. + /// + /// The principal to grant permission to. + /// The permission to grant. + /// The validation result. + public async Task ValidateGrantPermissionAsync(Principal principal, Permission permission) + { + GrantPermission request = new(principal, permission); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "validate_grant_permission", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Validates the revocation of a permission from a principal. + /// + /// The principal to revoke permission from. + /// The permission to revoke. + /// The validation result. + public async Task ValidateRevokePermissionAsync(Principal principal, Permission permission) + { + RevokePermission request = new(principal, permission); + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "validate_revoke_permission", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Validates the taking of ownership of the asset canister. + /// + /// The validation result. + public async Task ValidateTakeOwnershipAsync() + { + CandidArg arg = CandidArg.FromCandid(); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "validate_take_ownership", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Validates the commitment of a proposed batch of operations. + /// + /// The request containing the proposed batch details. + /// The validation result. + public async Task ValidateCommitProposedBatchAsync(CommitProposedBatchRequest request) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "validate_commit_proposed_batch", arg); + return reply.ToObjects(this.Converter); + } + + /// + /// Validates the configuration settings for the asset canister. + /// + /// The request containing the configuration settings. + /// The validation result. + public async Task ValidateConfigureAsync(ConfigureRequest request) + { + CandidArg arg = CandidArg.FromCandid(CandidTypedValue.FromObject(request, this.Converter)); + CandidArg reply = await this.Agent.CallAndWaitAsync(this.CanisterId, "validate_configure", arg); + return reply.ToObjects(this.Converter); + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/Asset.cs b/src/Agent/Standards/AssetCanister/Models/Asset.cs new file mode 100644 index 00000000..ebb330ce --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/Asset.cs @@ -0,0 +1,106 @@ +using EdjCase.ICP.Candid.Models; +using System.Collections.Generic; +using EdjCase.ICP.Candid.Mapping; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents an asset in the asset canister. + /// + public class Asset + { + /// + /// The key of the asset. + /// + [CandidName("key")] + public string Key { get; set; } + + /// + /// The content type of the asset. + /// + [CandidName("content_type")] + public string ContentType { get; set; } + + /// + /// A list of encodings for the asset. + /// + [CandidName("encodings")] + public List Encodings { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The key of the asset. + /// The content type of the asset. + /// A list of encodings for the asset. + public Asset(string key, string contentType, List encodings) + { + this.Key = key; + this.ContentType = contentType; + this.Encodings = encodings; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public Asset() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } + + /// + /// Represents an encoding of an asset. + /// + public class Encoding + { + /// + /// The content encoding of the asset. + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// The SHA256 hash of the asset content. + /// + [CandidName("sha256")] + public OptionalValue Sha256 { get; set; } + + /// + /// The length of the asset content. + /// + [CandidName("length")] + public UnboundedUInt Length { get; set; } + + /// + /// The last modified timestamp of the asset content. + /// + [CandidName("modified")] + public UnboundedInt Modified { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The content encoding of the asset. + /// The SHA256 hash of the asset content. + /// The length of the asset content. + /// The last modified timestamp of the asset content. + public Encoding(string contentEncoding, OptionalValue sha256, UnboundedUInt length, UnboundedInt modified) + { + this.ContentEncoding = contentEncoding; + this.Sha256 = sha256; + this.Length = length; + this.Modified = modified; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public Encoding() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/AssetCanisterArgs.cs b/src/Agent/Standards/AssetCanister/Models/AssetCanisterArgs.cs new file mode 100644 index 00000000..417f229a --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/AssetCanisterArgs.cs @@ -0,0 +1,100 @@ +using EdjCase.ICP.Candid.Mapping; +using System; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents arguments for asset canister operations, supporting different variants. + /// + [Variant] + public class AssetCanisterArgs + { + /// + /// The tag indicating the type of the asset canister argument. + /// + [VariantTagProperty] + public AssetCanisterArgsTag Tag { get; set; } + + /// + /// The value of the asset canister argument. + /// + [VariantValueProperty] + public object? Value { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The tag indicating the type of the argument. + /// The value of the argument. + public AssetCanisterArgs(AssetCanisterArgsTag tag, object? value) + { + this.Tag = tag; + this.Value = value; + } + + /// + /// Protected constructor for . + /// + protected AssetCanisterArgs() + { + } + + /// + /// Creates an instance of for the 'Init' operation. + /// + /// A new instance of . + public static AssetCanisterArgs Init() + { + return new AssetCanisterArgs(AssetCanisterArgsTag.Init, null); + } + + /// + /// Creates an instance of for the 'Upgrade' operation. + /// + /// The upgrade arguments. + /// A new instance of . + public static AssetCanisterArgs Upgrade(UpgradeArgs info) + { + return new AssetCanisterArgs(AssetCanisterArgsTag.Upgrade, info); + } + + /// + /// Retrieves the 'Upgrade' arguments from the instance. + /// + /// The 'Upgrade' arguments. + public UpgradeArgs AsUpgrade() + { + this.ValidateTag(AssetCanisterArgsTag.Upgrade); + return (UpgradeArgs)this.Value!; + } + + /// + /// Validates that the current tag matches the expected tag. + /// + /// The expected tag. + /// Thrown if the current tag does not match the expected tag. + private void ValidateTag(AssetCanisterArgsTag tag) + { + if (!this.Tag.Equals(tag)) + { + throw new InvalidOperationException($"Cannot cast '{this.Tag}' to type '{tag}'"); + } + } + } + + /// + /// Enumerates the tags for different types of asset canister arguments. + /// + public enum AssetCanisterArgsTag + { + /// + /// Tag for initialization arguments. + /// + Init, + + /// + /// Tag for upgrade arguments. + /// + Upgrade + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/BatchOperationKind.cs b/src/Agent/Standards/AssetCanister/Models/BatchOperationKind.cs new file mode 100644 index 00000000..f8a6ae52 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/BatchOperationKind.cs @@ -0,0 +1,200 @@ +using EdjCase.ICP.Candid.Mapping; +using System; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a batch operation kind for asset canister operations, supporting different variants. + /// + [Variant] + public class BatchOperationKind + { + /// + /// The tag indicating the type of the batch operation. + /// + [VariantTagProperty] + public BatchOperationKindTag Tag { get; set; } + + /// + /// The value of the batch operation. + /// + [VariantValueProperty] + public object? Value { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The tag indicating the type of the operation. + /// The value of the operation. + public BatchOperationKind(BatchOperationKindTag tag, object? value) + { + this.Tag = tag; + this.Value = value; + } + + /// + /// Protected constructor for . + /// + protected BatchOperationKind() + { + } + + /// + /// Creates an instance of for the 'CreateAsset' operation. + /// + /// The arguments for the 'CreateAsset' operation. + /// A new instance of . + public static BatchOperationKind CreateAsset(CreateAssetArguments info) + { + return new BatchOperationKind(BatchOperationKindTag.CreateAsset, info); + } + + /// + /// Creates an instance of for the 'SetAssetContent' operation. + /// + /// The arguments for the 'SetAssetContent' operation. + /// A new instance of . + public static BatchOperationKind SetAssetContent(SetAssetContentArguments info) + { + return new BatchOperationKind(BatchOperationKindTag.SetAssetContent, info); + } + + /// + /// Creates an instance of for the 'SetAssetProperties' operation. + /// + /// The arguments for the 'SetAssetProperties' operation. + /// A new instance of . + public static BatchOperationKind SetAssetProperties(SetAssetPropertiesRequest info) + { + return new BatchOperationKind(BatchOperationKindTag.SetAssetProperties, info); + } + + /// + /// Creates an instance of for the 'UnsetAssetContent' operation. + /// + /// The arguments for the 'UnsetAssetContent' operation. + /// A new instance of . + public static BatchOperationKind UnsetAssetContent(UnsetAssetContentArguments info) + { + return new BatchOperationKind(BatchOperationKindTag.UnsetAssetContent, info); + } + + /// + /// Creates an instance of for the 'DeleteAsset' operation. + /// + /// The arguments for the 'DeleteAsset' operation. + /// A new instance of . + public static BatchOperationKind DeleteAsset(DeleteAssetArguments info) + { + return new BatchOperationKind(BatchOperationKindTag.DeleteAsset, info); + } + + /// + /// Creates an instance of for the 'Clear' operation. + /// + /// A new instance of . + public static BatchOperationKind Clear() + { + return new BatchOperationKind(BatchOperationKindTag.Clear, null); + } + + /// + /// Retrieves the 'CreateAsset' arguments from the instance. + /// + /// The 'CreateAsset' arguments. + public CreateAssetArguments AsCreateAsset() + { + this.ValidateTag(BatchOperationKindTag.CreateAsset); + return (CreateAssetArguments)this.Value!; + } + + /// + /// Retrieves the 'SetAssetContent' arguments from the instance. + /// + /// The 'SetAssetContent' arguments. + public SetAssetContentArguments AsSetAssetContent() + { + this.ValidateTag(BatchOperationKindTag.SetAssetContent); + return (SetAssetContentArguments)this.Value!; + } + + /// + /// Retrieves the 'SetAssetProperties' arguments from the instance. + /// + /// The 'SetAssetProperties' arguments. + public SetAssetPropertiesRequest AsSetAssetProperties() + { + this.ValidateTag(BatchOperationKindTag.SetAssetProperties); + return (SetAssetPropertiesRequest)this.Value!; + } + + /// + /// Retrieves the 'UnsetAssetContent' arguments from the instance. + /// + /// The 'UnsetAssetContent' arguments. + public UnsetAssetContentArguments AsUnsetAssetContent() + { + this.ValidateTag(BatchOperationKindTag.UnsetAssetContent); + return (UnsetAssetContentArguments)this.Value!; + } + + /// + /// Retrieves the 'DeleteAsset' arguments from the instance. + /// + /// The 'DeleteAsset' arguments. + public DeleteAssetArguments AsDeleteAsset() + { + this.ValidateTag(BatchOperationKindTag.DeleteAsset); + return (DeleteAssetArguments)this.Value!; + } + + /// + /// Validates that the current tag matches the expected tag. + /// + /// The expected tag. + /// Thrown if the current tag does not match the expected tag. + private void ValidateTag(BatchOperationKindTag tag) + { + if (!this.Tag.Equals(tag)) + { + throw new InvalidOperationException($"Cannot cast '{this.Tag}' to type '{tag}'"); + } + } + } + + /// + /// Enumerates the tags for different types of batch operations. + /// + public enum BatchOperationKindTag + { + /// + /// Tag for the 'CreateAsset' operation. + /// + CreateAsset, + + /// + /// Tag for the 'SetAssetContent' operation. + /// + SetAssetContent, + + /// + /// Tag for the 'SetAssetProperties' operation. + /// + SetAssetProperties, + + /// + /// Tag for the 'UnsetAssetContent' operation. + /// + UnsetAssetContent, + + /// + /// Tag for the 'DeleteAsset' operation. + /// + DeleteAsset, + + /// + /// Tag for the 'Clear' operation. + /// + Clear + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CertifiedTreeResult.cs b/src/Agent/Standards/AssetCanister/Models/CertifiedTreeResult.cs new file mode 100644 index 00000000..a16cc77a --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CertifiedTreeResult.cs @@ -0,0 +1,42 @@ +using EdjCase.ICP.Candid.Mapping; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the result of a certified tree query to the asset canister. + /// + public class CertifiedTreeResult + { + /// + /// The certificate associated with the certified tree. + /// + [CandidName("certificate")] + public byte[] Certificate { get; set; } + + /// + /// The binary representation of the certified tree. + /// + [CandidName("tree")] + public byte[] Tree { get; set; } + + /// + /// Initializes a new instance of the class with specified certificate and tree. + /// + /// The certificate associated with the certified tree. + /// The binary representation of the certified tree. + public CertifiedTreeResult(byte[] certificate, byte[] tree) + { + this.Certificate = certificate; + this.Tree = tree; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CertifiedTreeResult() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CommitBatchArguments.cs b/src/Agent/Standards/AssetCanister/Models/CommitBatchArguments.cs new file mode 100644 index 00000000..d7bd92e4 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CommitBatchArguments.cs @@ -0,0 +1,44 @@ +using EdjCase.ICP.Candid.Mapping; +using System.Collections.Generic; +using BatchId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the arguments for committing a batch of operations in the asset canister. + /// + public class CommitBatchArguments + { + /// + /// The unique identifier of the batch. + /// + [CandidName("batch_id")] + public BatchId BatchId { get; set; } + + /// + /// A list of operations to be committed in the batch. + /// + [CandidName("operations")] + public List Operations { get; set; } + + /// + /// Initializes a new instance of the class with specified batch ID and operations. + /// + /// The unique identifier of the batch. + /// A list of operations to be committed in the batch. + public CommitBatchArguments(BatchId batchId, List operations) + { + this.BatchId = batchId; + this.Operations = operations; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CommitBatchArguments() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CommitProposedBatchRequest.cs b/src/Agent/Standards/AssetCanister/Models/CommitProposedBatchRequest.cs new file mode 100644 index 00000000..baa02fc9 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CommitProposedBatchRequest.cs @@ -0,0 +1,44 @@ +using EdjCase.ICP.Candid.Mapping; +using System.Collections.Generic; +using BatchId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to commit a proposed batch of operations in the asset canister. + /// + public class CommitProposedBatchRequest + { + /// + /// The unique identifier of the proposed batch. + /// + [CandidName("batch_id")] + public BatchId BatchId { get; set; } + + /// + /// The evidence required to commit the proposed batch. + /// + [CandidName("evidence")] + public byte[] Evidence { get; set; } + + /// + /// Initializes a new instance of the class with specified batch ID and evidence. + /// + /// The unique identifier of the proposed batch. + /// The evidence required to commit the proposed batch. + public CommitProposedBatchRequest(BatchId batchId, byte[] evidence) + { + this.BatchId = batchId; + this.Evidence = evidence; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CommitProposedBatchRequest() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/ComputeEvidenceArguments.cs b/src/Agent/Standards/AssetCanister/Models/ComputeEvidenceArguments.cs new file mode 100644 index 00000000..85356121 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/ComputeEvidenceArguments.cs @@ -0,0 +1,44 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; +using BatchId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the arguments for computing evidence for a proposed batch in the asset canister. + /// + public class ComputeEvidenceArguments + { + /// + /// The unique identifier of the batch for which evidence is being computed. + /// + [CandidName("batch_id")] + public BatchId BatchId { get; set; } + + /// + /// The maximum number of iterations to use in the computation of evidence. + /// + [CandidName("max_iterations")] + public OptionalValue MaxIterations { get; set; } + + /// + /// Initializes a new instance of the class with specified batch ID and maximum iterations. + /// + /// The unique identifier of the batch. + /// The maximum number of iterations for the evidence computation. + public ComputeEvidenceArguments(BatchId batchId, OptionalValue maxIterations) + { + this.BatchId = batchId; + this.MaxIterations = maxIterations; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public ComputeEvidenceArguments() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/ConfigurationResponse.cs b/src/Agent/Standards/AssetCanister/Models/ConfigurationResponse.cs new file mode 100644 index 00000000..73d74d0f --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/ConfigurationResponse.cs @@ -0,0 +1,51 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the response for the configuration of an asset canister. + /// + public class ConfigurationResponse + { + /// + /// Maximum number of batches allowed for upload at one time. + /// + [CandidName("max_batches")] + public OptionalValue MaxBatches { get; set; } + + /// + /// Maximum number of chunks across all batches being uploaded. + /// + [CandidName("max_chunks")] + public OptionalValue MaxChunks { get; set; } + + /// + /// Maximum total size of content bytes across all chunks being uploaded. + /// + [CandidName("max_bytes")] + public OptionalValue MaxBytes { get; set; } + + /// + /// Initializes a new instance of the class with specified configuration values. + /// + /// Maximum number of batches allowed for upload at one time. + /// Maximum number of chunks across all batches being uploaded. + /// Maximum total size of content bytes across all chunks being uploaded. + public ConfigurationResponse(OptionalValue maxBatches, OptionalValue maxChunks, OptionalValue maxBytes) + { + this.MaxBatches = maxBatches; + this.MaxChunks = maxChunks; + this.MaxBytes = maxBytes; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public ConfigurationResponse() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/ConfigureRequest.cs b/src/Agent/Standards/AssetCanister/Models/ConfigureRequest.cs new file mode 100644 index 00000000..1b521bfa --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/ConfigureRequest.cs @@ -0,0 +1,51 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to configure the asset canister with limits on batches, chunks, and bytes. + /// + public class ConfigureRequest + { + /// + /// Optional maximum number of batches being uploaded at one time. + /// + [CandidName("max_batches")] + public OptionalValue> MaxBatches { get; set; } + + /// + /// Optional maximum number of chunks across all batches being uploaded. + /// + [CandidName("max_chunks")] + public OptionalValue> MaxChunks { get; set; } + + /// + /// Optional maximum total size of content bytes across all chunks being uploaded. + /// + [CandidName("max_bytes")] + public OptionalValue> MaxBytes { get; set; } + + /// + /// Initializes a new instance of the class with specified limits. + /// + /// Optional maximum number of batches. + /// Optional maximum number of chunks. + /// Optional maximum size of bytes. + public ConfigureRequest(OptionalValue> maxBatches, OptionalValue> maxChunks, OptionalValue> maxBytes) + { + this.MaxBatches = maxBatches; + this.MaxChunks = maxChunks; + this.MaxBytes = maxBytes; + } + + /// + /// Initializes a new instance of the class without specified limits. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public ConfigureRequest() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CreateAssetArguments.cs b/src/Agent/Standards/AssetCanister/Models/CreateAssetArguments.cs new file mode 100644 index 00000000..fd8d82f9 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CreateAssetArguments.cs @@ -0,0 +1,69 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; +using System.Collections.Generic; +using Key = System.String; +using HeaderField = System.ValueTuple; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the arguments for creating a new asset in the asset canister. + /// + public class CreateAssetArguments + { + /// + /// Unique key identifier for the asset. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// Content type of the asset (e.g., 'text/plain', 'image/jpeg'). + /// + [CandidName("content_type")] + public string ContentType { get; set; } + + /// + /// Optional maximum age for caching the asset. + /// + [CandidName("max_age")] + public OptionalValue MaxAge { get; set; } + + /// + /// Optional list of additional HTTP headers for the asset. + /// + [CandidName("headers")] + public OptionalValue> Headers { get; set; } + + /// + /// Optional flag to enable aliasing for the asset. + /// + [CandidName("enable_aliasing")] + public OptionalValue EnableAliasing { get; set; } + + /// + /// Optional flag to allow raw access to the asset. + /// + [CandidName("allow_raw_access")] + public OptionalValue AllowRawAccess { get; set; } + + /// + /// Constructor for creating asset arguments with specified properties. + /// + /// Asset key. + /// Content type of the asset. + /// Maximum age for caching. + /// Additional HTTP headers. + /// Flag for enabling aliasing. + /// Flag for allowing raw access. + public CreateAssetArguments(Key key, string contentType, OptionalValue maxAge, OptionalValue> headers, OptionalValue enableAliasing, OptionalValue allowRawAccess) + { + this.Key = key; + this.ContentType = contentType; + this.MaxAge = maxAge; + this.Headers = headers; + this.EnableAliasing = enableAliasing; + this.AllowRawAccess = allowRawAccess; + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CreateBatchResult.cs b/src/Agent/Standards/AssetCanister/Models/CreateBatchResult.cs new file mode 100644 index 00000000..3eaf26d8 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CreateBatchResult.cs @@ -0,0 +1,35 @@ +using EdjCase.ICP.Candid.Mapping; +using BatchId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the result of creating a new batch in the asset canister. + /// + public class CreateBatchResult + { + /// + /// Unique identifier for the created batch. + /// + [CandidName("batch_id")] + public BatchId BatchId { get; set; } + + /// + /// Initializes a new instance of the class with a specified batch ID. + /// + /// Unique identifier for the batch. + public CreateBatchResult(BatchId batchId) + { + this.BatchId = batchId; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CreateBatchResult() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CreateChunkRequest.cs b/src/Agent/Standards/AssetCanister/Models/CreateChunkRequest.cs new file mode 100644 index 00000000..49baf985 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CreateChunkRequest.cs @@ -0,0 +1,43 @@ +using EdjCase.ICP.Candid.Mapping; +using BatchId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to create a chunk in an asset canister batch. + /// + public class CreateChunkRequest + { + /// + /// Unique identifier for the batch to which the chunk belongs. + /// + [CandidName("batch_id")] + public BatchId BatchId { get; set; } + + /// + /// Content of the chunk as a byte array. + /// + [CandidName("content")] + public byte[] Content { get; set; } + + /// + /// Initializes a new instance of the CreateChunkRequest class with specified batch ID and content. + /// + /// Unique identifier for the batch. + /// Content of the chunk as a byte array. + public CreateChunkRequest(BatchId batchId, byte[] content) + { + this.BatchId = batchId; + this.Content = content; + } + + /// + /// Initializes a new instance of the CreateChunkRequest class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CreateChunkRequest() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/CreateChunkResult.cs b/src/Agent/Standards/AssetCanister/Models/CreateChunkResult.cs new file mode 100644 index 00000000..ad1ef87f --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/CreateChunkResult.cs @@ -0,0 +1,35 @@ +using EdjCase.ICP.Candid.Mapping; +using ChunkId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the result of a 'create_chunk' operation on an asset canister. + /// + public class CreateChunkResult + { + /// + /// Unique identifier for the created chunk. + /// + [CandidName("chunk_id")] + public ChunkId ChunkId { get; set; } + + /// + /// Initializes a new instance of the CreateChunkResult class with a specified chunk ID. + /// + /// Unique identifier for the chunk. + public CreateChunkResult(ChunkId chunkId) + { + this.ChunkId = chunkId; + } + + /// + /// Initializes a new instance of the CreateChunkResult class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CreateChunkResult() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/DeleteAssetArguments.cs b/src/Agent/Standards/AssetCanister/Models/DeleteAssetArguments.cs new file mode 100644 index 00000000..579423fc --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/DeleteAssetArguments.cs @@ -0,0 +1,35 @@ +using EdjCase.ICP.Candid.Mapping; +using Key = System.String; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the arguments for deleting an asset in the asset canister. + /// + public class DeleteAssetArguments + { + /// + /// The key of the asset to delete. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// Initializes a new instance of the DeleteAssetArguments class with a specified asset key. + /// + /// The key of the asset to delete. + public DeleteAssetArguments(Key key) + { + this.Key = key; + } + + /// + /// Initializes a new instance of the DeleteAssetArguments class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public DeleteAssetArguments() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/DeleteBatchArguments.cs b/src/Agent/Standards/AssetCanister/Models/DeleteBatchArguments.cs new file mode 100644 index 00000000..c03b8f2e --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/DeleteBatchArguments.cs @@ -0,0 +1,35 @@ +using EdjCase.ICP.Candid.Mapping; +using BatchId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the arguments for deleting a batch in the asset canister. + /// + public class DeleteBatchArguments + { + /// + /// Unique identifier for the batch to be deleted. + /// + [CandidName("batch_id")] + public BatchId BatchId { get; set; } + + /// + /// Initializes a new instance of DeleteBatchArguments with a specified batch ID. + /// + /// Unique identifier for the batch. + public DeleteBatchArguments(BatchId batchId) + { + this.BatchId = batchId; + } + + /// + /// Initializes a new instance of DeleteBatchArguments. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public DeleteBatchArguments() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/GetAssetPropertiesResult.cs b/src/Agent/Standards/AssetCanister/Models/GetAssetPropertiesResult.cs new file mode 100644 index 00000000..957c748d --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/GetAssetPropertiesResult.cs @@ -0,0 +1,61 @@ +using EdjCase.ICP.Candid.Models; +using System.Collections.Generic; +using EdjCase.ICP.Candid.Mapping; +using HeaderField = System.ValueTuple; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the result of a request to get asset properties from an asset canister. + /// + public class GetAssetPropertiesResult + { + /// + /// Maximum age of the asset for caching purposes. + /// + [CandidName("max_age")] + public OptionalValue MaxAge { get; set; } + + /// + /// List of additional HTTP headers to be set when serving the asset. + /// + [CandidName("headers")] + public OptionalValue> Headers { get; set; } + + /// + /// Indicates whether the asset can be retrieved from raw.ic0.app or raw.icp0.io. + /// + [CandidName("allow_raw_access")] + public OptionalValue AllowRawAccess { get; set; } + + /// + /// Indicates if the asset's key might be an alias for another asset. + /// + [CandidName("is_aliased")] + public OptionalValue IsAliased { get; set; } + + /// + /// Constructor for initializing GetAssetPropertiesResult with specific values. + /// + /// Maximum age of the asset for caching. + /// List of additional HTTP headers for the asset. + /// Flag for raw access availability of the asset. + /// Flag indicating if the asset key is an alias. + public GetAssetPropertiesResult(OptionalValue maxAge, OptionalValue> headers, OptionalValue allowRawAccess, OptionalValue isAliased) + { + this.MaxAge = maxAge; + this.Headers = headers; + this.AllowRawAccess = allowRawAccess; + this.IsAliased = isAliased; + } + + /// + /// Default constructor for GetAssetPropertiesResult. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GetAssetPropertiesResult() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/GetChunkRequest.cs b/src/Agent/Standards/AssetCanister/Models/GetChunkRequest.cs new file mode 100644 index 00000000..8ab97afb --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/GetChunkRequest.cs @@ -0,0 +1,61 @@ +using EdjCase.ICP.Candid.Models; +using EdjCase.ICP.Candid.Mapping; +using ChunkId = EdjCase.ICP.Candid.Models.UnboundedUInt; +using Key = System.String; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to retrieve a specific chunk of an asset's content encoding from an asset canister. + /// + public class GetChunkRequest + { + /// + /// Unique identifier for the asset. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// Content encoding type of the asset (e.g., 'gzip', 'identity'). + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// Index of the chunk within the asset's content encoding. + /// + [CandidName("index")] + public ChunkId Index { get; set; } + + /// + /// Optional SHA-256 hash of the entire asset encoding for validation. + /// + [CandidName("sha256")] + public OptionalValue Sha256 { get; set; } + + /// + /// Initializes a new instance of the GetChunkRequest class with specified parameters. + /// + /// Asset key. + /// Content encoding type. + /// Chunk index. + /// Optional SHA-256 hash for validation. + public GetChunkRequest(Key key, string contentEncoding, ChunkId index, OptionalValue sha256) + { + this.Key = key; + this.ContentEncoding = contentEncoding; + this.Index = index; + this.Sha256 = sha256; + } + + /// + /// Initializes a new instance of the GetChunkRequest class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GetChunkRequest() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/GetChunkResult.cs b/src/Agent/Standards/AssetCanister/Models/GetChunkResult.cs new file mode 100644 index 00000000..f52e6179 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/GetChunkResult.cs @@ -0,0 +1,34 @@ +using EdjCase.ICP.Candid.Mapping; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the result of a 'get_chunk' method call to an asset canister. + /// + public class GetChunkResult + { + /// + /// Content of the asset chunk. + /// + [CandidName("content")] + public byte[] Content { get; set; } + + /// + /// Initializes a new instance of the GetChunkResult class with specified content. + /// + /// Byte array representing the content of the chunk. + public GetChunkResult(byte[] content) + { + this.Content = content; + } + + /// + /// Initializes a new instance of the GetChunkResult class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GetChunkResult() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/GetRequest.cs b/src/Agent/Standards/AssetCanister/Models/GetRequest.cs new file mode 100644 index 00000000..715292f5 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/GetRequest.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using EdjCase.ICP.Candid.Mapping; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request for retrieving an asset from the asset canister. + /// + internal class GetRequest + { + /// + /// The key identifying the asset to retrieve. + /// + [CandidName("key")] + public string Key { get; set; } + + /// + /// List of acceptable content encodings for the asset. + /// + [CandidName("accept_encodings")] + public List AcceptEncodings { get; set; } + + /// + /// Initializes a new instance of the GetRequest class with specified key and acceptable encodings. + /// + /// The asset key. + /// List of acceptable content encodings. + public GetRequest(string key, List acceptEncodings) + { + this.Key = key; + this.AcceptEncodings = acceptEncodings; + } + + /// + /// Initializes a new instance of the GetRequest class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GetRequest() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/GetResult.cs b/src/Agent/Standards/AssetCanister/Models/GetResult.cs new file mode 100644 index 00000000..706ca78e --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/GetResult.cs @@ -0,0 +1,68 @@ +using EdjCase.ICP.Candid.Models; +using EdjCase.ICP.Candid.Mapping; +using ChunkId = EdjCase.ICP.Candid.Models.UnboundedUInt; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents the result of a 'get' operation from the asset canister. + /// + public class GetResult + { + /// + /// The content of the asset. + /// + [CandidName("content")] + public byte[] Content { get; set; } + + /// + /// The MIME type of the asset. + /// + [CandidName("content_type")] + public string ContentType { get; set; } + + /// + /// The encoding of the asset content. + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// The SHA-256 hash of the asset, if available. + /// + [CandidName("sha256")] + public OptionalValue Sha256 { get; set; } + + /// + /// The total length of the asset in chunks. + /// + [CandidName("total_length")] + public ChunkId TotalLength { get; set; } + + /// + /// Initializes a new instance of the GetResult class with specified details. + /// + /// The content of the asset. + /// The MIME type of the asset. + /// The encoding of the asset content. + /// The SHA-256 hash of the asset, if available. + /// The total length of the asset in chunks. + public GetResult(byte[] content, string contentType, string contentEncoding, OptionalValue sha256, ChunkId totalLength) + { + this.Content = content; + this.ContentType = contentType; + this.ContentEncoding = contentEncoding; + this.Sha256 = sha256; + this.TotalLength = totalLength; + } + + /// + /// Initializes a new instance of the GetResult class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GetResult() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/GrantPermission.cs b/src/Agent/Standards/AssetCanister/Models/GrantPermission.cs new file mode 100644 index 00000000..15a06fbc --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/GrantPermission.cs @@ -0,0 +1,43 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to grant a permission to a principal in the asset canister. + /// + public class GrantPermission + { + /// + /// The principal to which the permission will be granted. + /// + [CandidName("to_principal")] + public Principal ToPrincipal { get; set; } + + /// + /// The permission to be granted. + /// + [CandidName("permission")] + public Permission Permission { get; set; } + + /// + /// Initializes a new instance of the GrantPermission class with specified principal and permission. + /// + /// The principal to grant permission to. + /// The permission to be granted. + public GrantPermission(Principal toPrincipal, Permission permission) + { + this.ToPrincipal = toPrincipal; + this.Permission = permission; + } + + /// + /// Initializes a new instance of the GrantPermission class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GrantPermission() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/HttpRequest.cs b/src/Agent/Standards/AssetCanister/Models/HttpRequest.cs new file mode 100644 index 00000000..36f1a2f9 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/HttpRequest.cs @@ -0,0 +1,69 @@ +using EdjCase.ICP.Candid.Mapping; +using System.Collections.Generic; +using EdjCase.ICP.Candid.Models; +using HeaderField = System.ValueTuple; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents an HTTP request for the Asset Canister. + /// + public class HttpRequest + { + /// + /// HTTP method (e.g., GET, POST). + /// + [CandidName("method")] + public string Method { get; set; } + + /// + /// URL of the request. + /// + [CandidName("url")] + public string Url { get; set; } + + /// + /// List of HTTP headers. + /// + [CandidName("headers")] + public List Headers { get; set; } + + /// + /// Body of the request as a list of bytes. + /// + [CandidName("body")] + public List Body { get; set; } + + /// + /// Optional certificate version. + /// + [CandidName("certificate_version")] + public OptionalValue CertificateVersion { get; set; } + + /// + /// Constructs an HttpRequest with specified parameters. + /// + /// HTTP method. + /// URL of the request. + /// List of HTTP headers. + /// Body of the request as a list of bytes. + /// Optional certificate version. + public HttpRequest(string method, string url, List headers, List body, OptionalValue certificateVersion) + { + this.Method = method; + this.Url = url; + this.Headers = headers; + this.Body = body; + this.CertificateVersion = certificateVersion; + } + + /// + /// Default constructor for HttpRequest. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public HttpRequest() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/HttpResponse.cs b/src/Agent/Standards/AssetCanister/Models/HttpResponse.cs new file mode 100644 index 00000000..5cfdb4e4 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/HttpResponse.cs @@ -0,0 +1,61 @@ +using EdjCase.ICP.Candid.Mapping; +using System.Collections.Generic; +using EdjCase.ICP.Candid.Models; +using HeaderField = System.ValueTuple; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents an HTTP response from the asset canister. + /// + public class HttpResponse + { + /// + /// HTTP status code of the response. + /// + [CandidName("status_code")] + public ushort StatusCode { get; set; } + + /// + /// List of headers included in the response. + /// + [CandidName("headers")] + public List Headers { get; set; } + + /// + /// Body of the response as a list of bytes. + /// + [CandidName("body")] + public List Body { get; set; } + + /// + /// Optional streaming strategy for the response. + /// + [CandidName("streaming_strategy")] + public OptionalValue StreamingStrategy { get; set; } + + /// + /// Initializes a new instance of the HttpResponse class with specified parameters. + /// + /// HTTP status code of the response. + /// List of headers included in the response. + /// Body of the response as a list of bytes. + /// Optional streaming strategy for the response. + public HttpResponse(ushort statusCode, List headers, List body, OptionalValue streamingStrategy) + { + this.StatusCode = statusCode; + this.Headers = headers; + this.Body = body; + this.StreamingStrategy = streamingStrategy; + } + + /// + /// Initializes a new instance of the HttpResponse class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public HttpResponse() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/ListPermitted.cs b/src/Agent/Standards/AssetCanister/Models/ListPermitted.cs new file mode 100644 index 00000000..115cfa5a --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/ListPermitted.cs @@ -0,0 +1,32 @@ +using EdjCase.ICP.Candid.Mapping; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to list principals with a specified permission in the asset canister. + /// + public class ListPermitted + { + /// + /// The specific permission to query for. + /// + [CandidName("permission")] + public Permission Permission { get; set; } + + /// + /// Initializes a new instance of the ListPermitted class with a specified permission. + /// + /// The permission to query for. + public ListPermitted(Permission permission) + { + this.Permission = permission; + } + + /// + /// Initializes a new instance of the ListPermitted class. + /// + public ListPermitted() + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/Permission.cs b/src/Agent/Standards/AssetCanister/Models/Permission.cs new file mode 100644 index 00000000..48da59d8 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/Permission.cs @@ -0,0 +1,23 @@ +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Enum representing the different types of permissions for interacting with an asset canister. + /// + public enum Permission + { + /// + /// Permission allowing changes to the assets served by the asset canister. + /// + Commit, + + /// + /// Permission allowing a principal to grant and revoke permissions to other principals. + /// + ManagePermissions, + + /// + /// Permission allowing the upload of data to the canister to be committed later by a principal with the Commit permission. + /// + Prepare + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/RevokePermission.cs b/src/Agent/Standards/AssetCanister/Models/RevokePermission.cs new file mode 100644 index 00000000..2eb7e5f4 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/RevokePermission.cs @@ -0,0 +1,43 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to revoke a permission from a principal in the asset canister. + /// + public class RevokePermission + { + /// + /// The principal from whom the permission will be revoked. + /// + [CandidName("of_principal")] + public Principal OfPrincipal { get; set; } + + /// + /// The permission to be revoked. + /// + [CandidName("permission")] + public Permission Permission { get; set; } + + /// + /// Initializes a new instance of the RevokePermission class with specified principal and permission. + /// + /// The principal from whom the permission will be revoked. + /// The permission to be revoked. + public RevokePermission(Principal ofPrincipal, Permission permission) + { + this.OfPrincipal = ofPrincipal; + this.Permission = permission; + } + + /// + /// Initializes a new instance of the RevokePermission class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public RevokePermission() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/SetAssetContentArguments.cs b/src/Agent/Standards/AssetCanister/Models/SetAssetContentArguments.cs new file mode 100644 index 00000000..ce407fe6 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/SetAssetContentArguments.cs @@ -0,0 +1,49 @@ +using EdjCase.ICP.Candid.Mapping; + +using EdjCase.ICP.Candid.Models; +using System.Collections.Generic; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to set asset content with chunks in the asset canister. + /// + public class SetAssetContentArguments + { + /// + /// Unique identifier for the asset. + /// + [CandidName("key")] + public string Key { get; set; } + + /// + /// The content encoding of the asset (e.g UTF-8) + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// A list of chunk ids that have been uploaded, to use as the content bytes + /// + [CandidName("chunk_ids")] + public List ChunkIds { get; set; } + + /// + /// Optional. The SHA256 hash of the entire content bytes, for validation of the chunk bytes + /// + [CandidName("sha256")] + public OptionalValue Sha256 { get; set; } + + /// Unique identifier for the asset. + /// The content encoding of the asset (e.g UTF-8) + /// A list of chunk ids that have been uploaded, to use as the content bytes + /// Optional. The SHA256 hash of the entire content bytes, for validation of the chunk bytes + public SetAssetContentArguments(string key, string contentEncoding, List chunkIds, OptionalValue sha256) + { + this.Key = key; + this.ContentEncoding = contentEncoding; + this.ChunkIds = chunkIds; + this.Sha256 = sha256; + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/SetAssetPropertiesRequest.cs b/src/Agent/Standards/AssetCanister/Models/SetAssetPropertiesRequest.cs new file mode 100644 index 00000000..03799ac4 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/SetAssetPropertiesRequest.cs @@ -0,0 +1,68 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; + +using System.Collections.Generic; +using Key = System.String; +using HeaderField = System.ValueTuple; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to set properties of an asset in the asset canister. + /// + public class SetAssetPropertiesRequest + { + /// + /// Unique identifier for the asset. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// Optional. The max age (in nanoseconds) for the asset + /// + [CandidName("max_age")] + public OptionalValue> MaxAge { get; set; } + + /// + /// Optional. The headers for the asset + /// + [CandidName("headers")] + public OptionalValue>> Headers { get; set; } + + /// + /// Optional. Whether to allow raw access to the asset + /// + [CandidName("allow_raw_access")] + public OptionalValue> AllowRawAccess { get; set; } + + /// + /// Optional. Whether the asset is aliased + /// + [CandidName("is_aliased")] + public OptionalValue> IsAliased { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The key of the asset. + /// The maximum age of the asset. + /// The headers of the asset. + /// Indicates whether raw access is allowed for the asset. + /// Indicates whether the asset is aliased. + public SetAssetPropertiesRequest( + Key key, + OptionalValue> maxAge, + OptionalValue>> headers, + OptionalValue> allowRawAccess, + OptionalValue> isAliased + ) + { + this.Key = key; + this.MaxAge = maxAge; + this.Headers = headers; + this.AllowRawAccess = allowRawAccess; + this.IsAliased = isAliased; + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/SetPermissions.cs b/src/Agent/Standards/AssetCanister/Models/SetPermissions.cs new file mode 100644 index 00000000..ff84f395 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/SetPermissions.cs @@ -0,0 +1,43 @@ +using EdjCase.ICP.Candid.Mapping; +using System.Collections.Generic; +using EdjCase.ICP.Candid.Models; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to set permessions for identities in the asset canister. + /// + public class SetPermissions + { + /// + /// A list of identities that can prepare an asset + /// + [CandidName("prepare")] + public List Prepare { get; set; } + + /// + /// A list of identities that can commit an asset + /// + [CandidName("commit")] + public List Commit { get; set; } + + /// + /// A list of identities that can manage permissions + /// + [CandidName("manage_permissions")] + public List ManagePermissions { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The list of principals with prepare permissions. + /// The list of principals with commit permissions. + /// The list of principals with manage permissions. + public SetPermissions(List prepare, List commit, List managePermissions) + { + this.Prepare = prepare; + this.Commit = commit; + this.ManagePermissions = managePermissions; + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/StoreRequest.cs b/src/Agent/Standards/AssetCanister/Models/StoreRequest.cs new file mode 100644 index 00000000..4737f44f --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/StoreRequest.cs @@ -0,0 +1,59 @@ +using EdjCase.ICP.Candid.Models; +using EdjCase.ICP.Candid.Mapping; +using Key = System.String; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to store a small asset in the asset canister. + /// + public class StoreRequest + { + /// + /// Unique identifier for the asset. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// The content type of the asset (e.g text/plain) + /// + [CandidName("content_type")] + public string ContentType { get; set; } + + /// + /// The content encoding of the asset (e.g UTF-8) + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// The content bytes of the asset + /// + [CandidName("content")] + public byte[] Content { get; set; } + + /// + /// Optional. The SHA256 hash of the entire content bytes, for validation of the bytes + /// + [CandidName("sha256")] + public OptionalValue Sha256 { get; set; } + + /// + /// Represents a request to store an asset in the canister. + /// + /// The key of the asset. + /// The content type of the asset. + /// The content encoding of the asset. + /// The content of the asset. + /// The SHA256 hash of the asset content. + public StoreRequest(Key key, string contentType, string contentEncoding, byte[] content, OptionalValue sha256) + { + this.Key = key; + this.ContentType = contentType; + this.ContentEncoding = contentEncoding; + this.Content = content; + this.Sha256 = sha256; + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/StreamingCallbackHttpResponse.cs b/src/Agent/Standards/AssetCanister/Models/StreamingCallbackHttpResponse.cs new file mode 100644 index 00000000..85ff0cfd --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/StreamingCallbackHttpResponse.cs @@ -0,0 +1,45 @@ +using EdjCase.ICP.Candid.Mapping; +using System.Collections.Generic; +using EdjCase.ICP.Candid.Models; + + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a response from the streaming callback method + /// + public class StreamingCallbackHttpResponse + { + /// + /// The returned bytes for the streaming callback + /// + [CandidName("body")] + public byte[] Body { get; set; } + + /// + /// Optional. The token to use for the next streaming callback + /// + [CandidName("token")] + public OptionalValue Token { get; set; } + + /// + /// Represents an HTTP response for a streaming callback. + /// + /// The body of the response. + /// The optional token associated with the response. + public StreamingCallbackHttpResponse(byte[] body, OptionalValue token) + { + this.Body = body; + this.Token = token; + } + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + + public StreamingCallbackHttpResponse() + { + } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/StreamingCallbackToken.cs b/src/Agent/Standards/AssetCanister/Models/StreamingCallbackToken.cs new file mode 100644 index 00000000..eeaa54c0 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/StreamingCallbackToken.cs @@ -0,0 +1,62 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; +using System.Collections.Generic; +using Key = System.String; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a single result of streaming an asset from the asset canister + /// + public class StreamingCallbackToken + { + /// + /// Unique identifier for the asset. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// The content encoding of the asset (e.g UTF-8) + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// The index of the chunk to stream + /// + [CandidName("index")] + public UnboundedUInt Index { get; set; } + + /// + /// Optional. The SHA256 hash of the entire content bytes, for validation of the bytes + /// + [CandidName("sha256")] + public OptionalValue Sha256 { get; set; } + + + /// + /// Initializes a new instance of the class. + /// + /// The key associated with the token. + /// The content encoding of the token. + /// The index of the token. + /// The SHA256 value of the token. + public StreamingCallbackToken(Key key, string contentEncoding, UnboundedUInt index, OptionalValue sha256) + { + this.Key = key; + this.ContentEncoding = contentEncoding; + this.Index = index; + this.Sha256 = sha256; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public StreamingCallbackToken() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/StreamingStrategy.cs b/src/Agent/Standards/AssetCanister/Models/StreamingStrategy.cs new file mode 100644 index 00000000..798387f1 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/StreamingStrategy.cs @@ -0,0 +1,122 @@ +using EdjCase.ICP.Candid.Mapping; + +using System; +using EdjCase.ICP.Candid.Models.Values; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a strategy for streaming from an asset canister + /// + [Variant] + public class StreamingStrategy + { + /// + /// The tag for the streaming strategy variant + /// + [VariantTagProperty] + public StreamingStrategyTag Tag { get; set; } + + /// + /// The value for the streaming strategy variant + /// + [VariantValueProperty] + public object? Value { get; set; } + + + /// + /// Represents a strategy for streaming from an asset canister + /// + /// The tag for the streaming strategy variant + /// The value for the streaming strategy variant + public StreamingStrategy(StreamingStrategyTag tag, object? value) + { + this.Tag = tag; + this.Value = value; + } + + /// + /// Initializes a new instance of the class. + /// + protected StreamingStrategy() + { + } + + /// + /// Creates a new streaming strategy with a callback + /// + /// The callback info + /// The streaming strategy variant + public static StreamingStrategy Callback(StreamingStrategy.CallbackInfo info) + { + return new StreamingStrategy(StreamingStrategyTag.Callback, info); + } + + /// + /// Casts the streaming strategy to a callback + /// + /// The Callback info + public StreamingStrategy.CallbackInfo AsCallback() + { + this.ValidateTag(StreamingStrategyTag.Callback); + return (StreamingStrategy.CallbackInfo)this.Value!; + } + + private void ValidateTag(StreamingStrategyTag tag) + { + if (!this.Tag.Equals(tag)) + { + throw new InvalidOperationException($"Cannot cast '{this.Tag}' to type '{tag}'"); + } + } + + /// + /// Represents information about a callback function and its associated token. + /// + public class CallbackInfo + { + /// + /// The callback function + /// + [CandidName("callback")] + public CandidFunc Callback { get; set; } + + /// + /// The streaming callback token + /// + [CandidName("token")] + public StreamingCallbackToken Token { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The callback function. + /// The streaming callback token. + public CallbackInfo(CandidFunc callback, StreamingCallbackToken token) + { + this.Callback = callback; + this.Token = token; + } + + /// + /// Initializes a new instance of the class. + /// +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public CallbackInfo() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + } + } + } + + /// + /// Represents all the options for the streaming strategy variant + /// + public enum StreamingStrategyTag + { + /// + /// For callback streaming + /// + Callback + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/UnsetAssetContentArguments.cs b/src/Agent/Standards/AssetCanister/Models/UnsetAssetContentArguments.cs new file mode 100644 index 00000000..5c459aa5 --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/UnsetAssetContentArguments.cs @@ -0,0 +1,35 @@ +using EdjCase.ICP.Candid.Mapping; +using Key = System.String; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request to remove the content encoding for an asset + /// + public class UnsetAssetContentArguments + { + /// + /// Unique identifier for the asset. + /// + [CandidName("key")] + public Key Key { get; set; } + + /// + /// The content encoding of the asset (e.g UTF-8) + /// + [CandidName("content_encoding")] + public string ContentEncoding { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The key of the asset. + /// The encoding of the asset content. + public UnsetAssetContentArguments(Key key, string contentEncoding) + { + this.Key = key; + this.ContentEncoding = contentEncoding; + } + + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/UpgradeArgs.cs b/src/Agent/Standards/AssetCanister/Models/UpgradeArgs.cs new file mode 100644 index 00000000..d3a09d1d --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/UpgradeArgs.cs @@ -0,0 +1,30 @@ +using EdjCase.ICP.Candid.Mapping; +using EdjCase.ICP.Candid.Models; + + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a request for upgrading the asset canister with options + /// + public class UpgradeArgs + { + /// + /// Optional. The permissions to set for the asset canister + /// + [CandidName("set_permissions")] + public OptionalValue SetPermissions { get; set; } + + + /// + /// Creates a new instance of the class. + /// + /// Optional value for setting permissions. + public UpgradeArgs(OptionalValue setPermissions) + { + this.SetPermissions = setPermissions; + } + + + } +} diff --git a/src/Agent/Standards/AssetCanister/Models/ValidationResult.cs b/src/Agent/Standards/AssetCanister/Models/ValidationResult.cs new file mode 100644 index 00000000..ae752d8e --- /dev/null +++ b/src/Agent/Standards/AssetCanister/Models/ValidationResult.cs @@ -0,0 +1,107 @@ +using EdjCase.ICP.Candid.Mapping; + +using System; + +namespace EdjCase.ICP.Agent.Standards.AssetCanister.Models +{ + /// + /// Represents a result from calling a validation method + /// + [Variant] + public class ValidationResult + { + /// + /// The tag for the validation result variant + /// + [VariantTagProperty] + public ValidationResultTag Tag { get; set; } + + /// + /// The value for the validation result variant + /// + [VariantValueProperty] + public object? Value { get; set; } + + + /// + /// Represents a result from calling a validation method + /// + /// The tag for the validation result variant + /// The value for the validation result variant + public ValidationResult(ValidationResultTag tag, object? value) + { + this.Tag = tag; + this.Value = value; + } + + /// + /// Initializes a new instance of the class. + /// + protected ValidationResult() + { + } + + /// + /// Creates a new validation result with an ok value + /// + /// The validation message + /// The OK validation result variant + public static ValidationResult Ok(string message) + { + return new ValidationResult(ValidationResultTag.Ok, message); + } + + /// + /// Creates a new validation result with an error value + /// + /// The error message + /// The error validation result variant + public static ValidationResult Err(string message) + { + return new ValidationResult(ValidationResultTag.Err, message); + } + + /// + /// Casts the validation result to an ok message + /// + /// The ok message + public string AsOk() + { + this.ValidateTag(ValidationResultTag.Ok); + return (string)this.Value!; + } + + /// + /// Casts the validation result to an error message + /// + /// The error message + public string AsErr() + { + this.ValidateTag(ValidationResultTag.Err); + return (string)this.Value!; + } + + private void ValidateTag(ValidationResultTag tag) + { + if (!this.Tag.Equals(tag)) + { + throw new InvalidOperationException($"Cannot cast '{this.Tag}' to type '{tag}'"); + } + } + } + + /// + /// The tag for the validation result variant + /// + public enum ValidationResultTag + { + /// + /// The ok variant + /// + Ok, + /// + /// The error variant + /// + Err + } +} diff --git a/src/Candid/API.xml b/src/Candid/API.xml index 04dd8e65..7faaf9bf 100644 --- a/src/Candid/API.xml +++ b/src/Candid/API.xml @@ -1119,6 +1119,12 @@ An array of values to use as vector items A candid typed value of the array + + + A helper method to create a typed record value with no fields + + A candid typed value of the empty record + A mapping of compound type definition to `EncodedCompoundTypes` index to be used as reference @@ -1941,6 +1947,12 @@ Principal candid type + + + Helper method to create a Blob/Vec Nat8 candid type + + Blob/Vec Nat8 candid type + Helper method to create a Null candid type @@ -3426,6 +3438,13 @@ An principal value to convert to a candid principal Candid principal value + + + Helper method to create a blob/vec nat8 value from a byte array + + A byte array to convert to a blob/vec nat8 + Candid vector value of nat8's + Helper method to create a null value diff --git a/src/Candid/Mapping/Mappers/TupleMapper.cs b/src/Candid/Mapping/Mappers/TupleMapper.cs index 3d7bb774..58bf899c 100644 --- a/src/Candid/Mapping/Mappers/TupleMapper.cs +++ b/src/Candid/Mapping/Mappers/TupleMapper.cs @@ -69,6 +69,7 @@ public CandidValue Map(object value, CandidConverter converter) object propValue = tuple[i]; CandidValue v = converter.FromObject(propValue); fields.Add(CandidTag.FromId((uint)i), v); + i++; } return new CandidRecord(fields); } diff --git a/src/Candid/Models/CandidTypedValue.cs b/src/Candid/Models/CandidTypedValue.cs index 448a6ca4..f00494b2 100644 --- a/src/Candid/Models/CandidTypedValue.cs +++ b/src/Candid/Models/CandidTypedValue.cs @@ -563,5 +563,17 @@ CandidValue[] values new CandidVectorType(innerType) ); } + + /// + /// A helper method to create a typed record value with no fields + /// + /// A candid typed value of the empty record + public static CandidTypedValue EmptyRecord() + { + return new CandidTypedValue( + new CandidRecord(new Dictionary()), + new CandidRecordType(new Dictionary()) + ); + } } } diff --git a/src/Candid/Models/Types/Base.cs b/src/Candid/Models/Types/Base.cs index 08795645..2987f234 100644 --- a/src/Candid/Models/Types/Base.cs +++ b/src/Candid/Models/Types/Base.cs @@ -201,6 +201,15 @@ public static CandidPrimitiveType Principal() return new CandidPrimitiveType(PrimitiveType.Principal); } + /// + /// Helper method to create a Blob/Vec Nat8 candid type + /// + /// Blob/Vec Nat8 candid type + public static CandidVectorType Blob() + { + return new CandidVectorType(CandidType.Nat8()); + } + /// /// Helper method to create a Null candid type /// @@ -237,4 +246,4 @@ public static CandidOptionalType Opt(CandidType inner) return new CandidOptionalType(inner); } } -} \ No newline at end of file +} diff --git a/src/Candid/Models/Values/CandidValue.cs b/src/Candid/Models/Values/CandidValue.cs index 83e6aabb..11eab839 100644 --- a/src/Candid/Models/Values/CandidValue.cs +++ b/src/Candid/Models/Values/CandidValue.cs @@ -550,6 +550,20 @@ public static CandidPrimitive Principal(Principal value) return new CandidPrimitive(PrimitiveType.Principal, value); } + /// + /// Helper method to create a blob/vec nat8 value from a byte array + /// + /// A byte array to convert to a blob/vec nat8 + /// Candid vector value of nat8's + public static CandidVector Blob(byte[] value) + { + return new CandidVector( + value + .Select(CandidValue.Nat8) + .ToArray() + ); + } + /// /// Helper method to create a null value