• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bmresearch / Solnet / 10672350157

02 Sep 2024 07:46PM UTC coverage: 77.453% (+0.2%) from 77.239%
10672350157

push

github

BifrostTitan
Agave v2.0 Migration

Updated the RPC client and removed deprecated code from the SDK.
Cleaned up all the warnings across the solution and added a few sys-vars that were missing.
Generate Seed in Mnemonic class now uses System.Security.Cryptography instead of bouncy castle sdk

1111 of 1682 branches covered (66.05%)

Branch coverage included in aggregate %.

6 of 10 new or added lines in 6 files covered. (60.0%)

18 existing lines in 4 files now uncovered.

5117 of 6359 relevant lines covered (80.47%)

1328281.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Solnet.Programs/Abstract/TransactionalBaseClient.cs
1
using Solnet.Rpc;
2
using Solnet.Rpc.Builders;
3
using Solnet.Rpc.Core.Http;
4
using Solnet.Rpc.Models;
5
using Solnet.Rpc.Types;
6
using Solnet.Wallet;
7
using System;
8
using System.Collections.Generic;
9
using System.Linq;
10
using System.Text;
11
using System.Threading.Tasks;
12

13
namespace Solnet.Programs.Abstract
14
{
15
    /// <summary>
16
    /// Transactional base client. Extends Base client and adds functionality related to transactions and error retrieval.
17
    /// </summary>
18
    /// <typeparam name="TEnum">The error enum type. 
19
    /// The enum values need to match the program error codes and be correctly mapped in BuildErrorsDictionary abstract method. </typeparam>
20
    public abstract class TransactionalBaseClient<TEnum> : BaseClient where TEnum : Enum
21
    {
22
        /// <summary>
23
        /// Mapping from error codes to error values (code, message and enum).
24
        /// </summary>
25
        protected Dictionary<uint, ProgramError<TEnum>> ProgramErrors { get; }
×
26

27
        /// <summary>
28
        /// Function that builds a mapping between error codes and error values.
29
        /// This is used to populate the ProgramErrors dictionary that powers the GetProgramError methods.
30
        /// </summary>
31
        /// <returns>The dictionary with the possible errors.</returns>
32
        protected abstract Dictionary<uint, ProgramError<TEnum>> BuildErrorsDictionary();
33

34
        /// <summary>
35
        /// 
36
        /// </summary>
37
        /// <param name="rpcClient"></param>
38
        /// <param name="streamingRpcClient"></param>
39
        /// <param name="programId">The program ID.</param>
40
        protected TransactionalBaseClient(IRpcClient rpcClient, IStreamingRpcClient streamingRpcClient, PublicKey programId) : base(rpcClient, streamingRpcClient, programId)
×
41
        {
42
            ProgramErrors = BuildErrorsDictionary();
×
43
        }
×
44

45
        /// <summary>
46
        /// Signs and sends a given <c>TransactionInstruction</c> using signing delegate.
47
        /// </summary>
48
        /// <param name="instruction">The transaction to be sent.</param>
49
        /// <param name="feePayer">The fee payer.</param>
50
        /// <param name="signingCallback">The callback used to sign the transaction. 
51
        /// This delegate is called once for each <c>PublicKey</c> account that needs write permissions according to the transaction data.</param>
52
        /// <param name="commitment">The commitment parameter for the RPC request.</param>
53
        /// <returns></returns>
54
        protected async Task<RequestResult<string>> SignAndSendTransaction(TransactionInstruction instruction, PublicKey feePayer, 
55
            Func<byte[], PublicKey, byte[]> signingCallback, Commitment commitment = Commitment.Finalized)
56
        {
57
            TransactionBuilder tb = new TransactionBuilder();
×
58
            tb.AddInstruction(instruction);
×
59

NEW
60
            var recentHash = await RpcClient.GetLatestBlockHashAsync();
×
61

62
            tb.SetRecentBlockHash(recentHash.Result.Value.Blockhash);
×
63
            tb.SetFeePayer(feePayer);
×
64

65
            var wireFmt = tb.CompileMessage();
×
66

67
            var msg = Message.Deserialize(wireFmt);
×
68

69
            for (int i = 0; i < msg.Header.RequiredSignatures; i++)
×
70
            {
71
                tb.AddSignature(signingCallback(wireFmt, msg.AccountKeys[i]));
×
72
            }
73

74
            return await RpcClient.SendTransactionAsync(tb.Serialize(), commitment: commitment);
×
75
        }
×
76

77
        /// <summary>
78
        /// Try to retrieve a custom program error from a transaction or simulation result.
79
        /// </summary>
80
        /// <param name="logs">The transaction error or simulation result.</param>
81
        /// <returns>The possible program error, if it was caused by this program.</returns>
82
        public ProgramError<TEnum> GetProgramError(SimulationLogs logs)
83
        {
84
            if (logs is { Error: { InstructionError: { Type: InstructionErrorType.Custom } } })
×
85
            {
86
                var id = logs.Error.InstructionError.CustomError.Value;
×
87

88
                if (ProgramIdKey != null && logs.Logs?.Length > 2)
×
89
                {
90
                    var progReturn = logs.Logs[logs.Logs.Length - 1];
×
91
                    
92
                    //check if error came from this program, in case its a multiple prog tx
93
                    if (!progReturn.StartsWith("Program " + ProgramIdKey.Key)) return null;
×
94
                }
95

96
                ProgramErrors.TryGetValue(id, out var error);
×
97
                return error;
×
98
            }
99
            return null;
×
100
        }
101

102
        /// <summary>
103
        /// Try to retrieve a custom program error from a transaction or simulation result.
104
        /// </summary>
105
        /// <param name="error">The transaction error or simulation result.</param>
106
        /// <returns>The possible program error, if it was caused by this program.</returns>
107
        public ProgramError<TEnum> GetProgramError(TransactionError error)
108
        {
109
            if (error is { InstructionError: { Type: InstructionErrorType.Custom } })
×
110
            {
111
                var id = error.InstructionError.CustomError.Value;
×
112

113
                ProgramErrors.TryGetValue(id, out var err);
×
114
                return err;
×
115
            }
116
            return null;
×
117
        }
118

119
    }
120

121
    /// <summary>
122
    /// Represents a program error and the respective message.
123
    /// </summary>
124
    /// <typeparam name="T">The underlying enum type. Enum values need to match program error codes.</typeparam>
125
    public class ProgramError<T> where T : Enum
126
    {
127
        /// <summary>
128
        /// The error kinda according to the enum.
129
        /// </summary>
130
        public T ErrorKind { get; private set; }
×
131

132
        /// <summary>
133
        /// The error message.
134
        /// </summary>
135
        public string Message { get; private set; }
×
136

137
        /// <summary>
138
        /// The error code, according to the enum and program definition.
139
        /// </summary>
140
        public uint ErrorCode { get; private set; }
×
141

142
        /// <summary>
143
        /// Default constructor that populates all values.
144
        /// </summary>
145
        /// <param name="value">The corresponding error value.</param>
146
        /// <param name="message">The error message that matches the error value.</param>
147
        public ProgramError(T value, string message)
×
148
        {
149
            ErrorCode = ((IConvertible)value).ToUInt32(null);
×
150
            Message = message;
×
151
            ErrorKind = value;
×
152
        }
×
153
    }
154
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc