Skip to content

Commit ea3d9f7

Browse files
Adding custom raw decoder, QueryRaw and StringBytes32 custom raw decoder
Mainly there is mixmatch of bytes32 types and strings. this introduces the capability of doing custom decoding.
1 parent e61248f commit ea3d9f7

File tree

14 files changed

+152
-17
lines changed

14 files changed

+152
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Nethereum.ABI.Decoders
2+
{
3+
public interface ICustomRawDecoder<T>
4+
{
5+
T Decode(byte[] output);
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace Nethereum.ABI.Decoders
7+
{
8+
public class StringBytes32Decoder:ICustomRawDecoder<string>
9+
{
10+
public string Decode(byte[] output)
11+
{
12+
if(output.Length > 32)
13+
{
14+
//assuming that first 32 is the data index as this is the raw data
15+
return new StringTypeDecoder().Decode(output.Skip(32).ToArray());
16+
}
17+
else
18+
{
19+
return new Bytes32TypeDecoder().Decode<string>(output);
20+
}
21+
}
22+
}
23+
}

src/Nethereum.Contracts/CQS/ContractHandler.cs

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Threading;
22
using System.Threading.Tasks;
3+
using Nethereum.ABI.Decoders;
34
using Nethereum.ABI.FunctionEncoding.Attributes;
45
using Nethereum.Hex.HexTypes;
56
using Nethereum.RPC.Eth.DTOs;
@@ -172,8 +173,36 @@ public Task<TReturn> QueryAsync<TEthereumContractFunctionMessage, TReturn>(Block
172173
return QueryAsync<TEthereumContractFunctionMessage, TReturn>(ethereumContractFunctionMessage,
173174
blockParameter);
174175
}
176+
177+
public Task<byte[]> QueryRawAsync<TEthereumContractFunctionMessage>(TEthereumContractFunctionMessage ethereumContractFunctionMessage, BlockParameter blockParameter = null)
178+
where TEthereumContractFunctionMessage : ContractMessage, new()
179+
{
180+
SetAddressFrom(ethereumContractFunctionMessage);
181+
var queryHandler = EthApiContractService.GetContractQueryHandler<TEthereumContractFunctionMessage>();
182+
return queryHandler.QueryRawAsync(ethereumContractFunctionMessage,
183+
ContractAddress, blockParameter);
184+
}
185+
186+
public Task<byte[]> QueryRawAsync<TEthereumContractFunctionMessage>(BlockParameter blockParameter = null)
187+
where TEthereumContractFunctionMessage : ContractMessage, new()
188+
{
189+
var ethereumContractFunctionMessage = new TEthereumContractFunctionMessage();
190+
return QueryRawAsync<TEthereumContractFunctionMessage>(ethereumContractFunctionMessage,
191+
blockParameter);
192+
}
193+
194+
public async Task<TReturn> QueryRawAsync<TEthereumContractFunctionMessage, TCustomDecoder, TReturn>(BlockParameter blockParameter = null)
195+
where TEthereumContractFunctionMessage : ContractMessage, new()
196+
where TCustomDecoder : ICustomRawDecoder<TReturn>, new()
197+
{
198+
var ethereumContractFunctionMessage = new TEthereumContractFunctionMessage();
199+
var result = await QueryRawAsync<TEthereumContractFunctionMessage>(ethereumContractFunctionMessage,
200+
blockParameter);
201+
var decoder = new TCustomDecoder();
202+
return decoder.Decode(result);
203+
}
175204
#endif
176-
205+
177206
}
178207

179208
}

src/Nethereum.Contracts/CQS/ContractQueryHandler.cs

+14
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ public async Task<TFunctionOutput> QueryAsync<TFunctionOutput>(TContractMessage
3232
GetDefaultAddressFrom(contractFunctionMessage),
3333
GetMaximumGas(contractFunctionMessage), GetValue(contractFunctionMessage), block).ConfigureAwait(false);
3434
}
35+
36+
37+
public async Task<byte[]> QueryRawAsync(TContractMessage contractFunctionMessage,
38+
string contractAddress,
39+
BlockParameter block = null)
40+
41+
{
42+
var contract = Eth.GetContract<TContractMessage>(contractAddress);
43+
var function = contract.GetFunction<TContractMessage>();
44+
ValidateContractMessage(contractFunctionMessage);
45+
return await function.CallRawAsync(contractFunctionMessage,
46+
GetDefaultAddressFrom(contractFunctionMessage),
47+
GetMaximumGas(contractFunctionMessage), GetValue(contractFunctionMessage), block).ConfigureAwait(false);
48+
}
3549
}
3650

3751

src/Nethereum.Contracts/Function.cs

+31
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ public TransactionInput CreateTransactionInput(TFunctionInput functionInput, str
224224
return FunctionBuilder.CreateTransactionInput(functionInput, from, gas, gasPrice, value);
225225
}
226226

227+
227228

228229
public Task<TReturn> CallAsync<TReturn>()
229230
{
@@ -341,6 +342,36 @@ public Task<string> SendTransactionAsync(TFunctionInput functionInput,
341342
}
342343

343344
#if !DOTNET35
345+
346+
public Task<byte[]> CallRawAsync<TReturn>()
347+
{
348+
return base.CallRawAsync(CreateCallInputParameterless());
349+
}
350+
351+
public Task<byte[]> CallRawAsync<TReturn>(TFunctionInput functionInput)
352+
{
353+
return base.CallRawAsync(CreateCallInput(functionInput));
354+
}
355+
356+
public Task<byte[]> CallRawAsync(TFunctionInput functionInput, string from, HexBigInteger gas,
357+
HexBigInteger value)
358+
{
359+
return base.CallRawAsync(CreateCallInput(functionInput, from, gas, value));
360+
}
361+
362+
public Task<byte[]> CallRawAsync(TFunctionInput functionInput, string from, HexBigInteger gas,
363+
HexBigInteger value, BlockParameter block)
364+
{
365+
return base.CallRawAsync(CreateCallInput(functionInput, from, gas, value), block);
366+
}
367+
368+
public Task<byte[]> CallRawAsync(TFunctionInput functionInput,
369+
BlockParameter blockParameter)
370+
{
371+
return base.CallRawAsync(CreateCallInput(functionInput), blockParameter);
372+
}
373+
374+
344375
public Task<TransactionReceipt> SendTransactionAndWaitForReceiptAsync(TFunctionInput functionInput, string from,
345376
CancellationTokenSource receiptRequestCancellationToken = null)
346377
{

src/Nethereum.Contracts/FunctionBase.cs

+25
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Threading;
33
using System.Threading.Tasks;
44
using Nethereum.ABI.FunctionEncoding;
5+
using Nethereum.Hex.HexConvertors.Extensions;
56
using Nethereum.Hex.HexTypes;
67
using Nethereum.RPC.Eth.DTOs;
78
using Nethereum.RPC.Eth.Transactions;
@@ -37,6 +38,8 @@ protected Task<string> SendTransactionAsync(TransactionInput transactionInput)
3738
return TransactionManager.SendTransactionAsync(transactionInput);
3839
}
3940

41+
42+
4043
#if !DOTNET35
4144
protected Task<TransactionReceipt> SendTransactionAndWaitForReceiptAsync(TransactionInput transactionInput,
4245
CancellationTokenSource receiptRequestCancellationToken = null)
@@ -47,6 +50,28 @@ protected Task<TransactionReceipt> SendTransactionAndWaitForReceiptAsync(Transac
4750
#endif
4851

4952
#if !DOTNET35
53+
54+
protected async Task<byte[]> CallRawAsync(CallInput callInput)
55+
{
56+
var result =
57+
await
58+
EthCall.SendRequestAsync(callInput, DefaultBlock)
59+
.ConfigureAwait(false);
60+
61+
62+
return result.HexToByteArray();
63+
}
64+
65+
protected async Task<byte[]> CallRawAsync(CallInput callInput, BlockParameter block)
66+
{
67+
var result =
68+
await
69+
EthCall.SendRequestAsync(callInput, block)
70+
.ConfigureAwait(false);
71+
72+
return result.HexToByteArray();
73+
}
74+
5075
protected async Task<TReturn> CallAsync<TReturn>(CallInput callInput)
5176
{
5277
var result =

src/Nethereum.StandardTokenEIP20.IntegrationTests/Erc20TokenTester.cs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Linq;
22
using System.Numerics;
33
using System.Threading.Tasks;
4+
using Nethereum.ABI.Decoders;
45
using Nethereum.Hex.HexTypes;
56
using Nethereum.RPC.Eth.DTOs;
67
using Nethereum.RPC.Eth.Services;
@@ -41,8 +42,10 @@ public async void ShouldGetTheDaiFromMainnet()
4142
{
4243
var web3 = new Web3.Web3("https://mainnet.infura.io");
4344
var contractHandler = web3.Eth.GetContractHandler("0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359");
44-
var symbol = await contractHandler.QueryAsync<SymbolFunction, string>();
45-
var tokenName = await contractHandler.QueryAsync<NameFunction, string>();
45+
var stringBytes32Decoder = new StringBytes32Decoder();
46+
var symbol = await contractHandler.QueryRawAsync<SymbolFunction, StringBytes32Decoder, string>();
47+
var token = await contractHandler.QueryRawAsync<NameFunction, StringBytes32Decoder, string>();
48+
4649
}
4750

4851
[Fact]
@@ -59,11 +62,11 @@ public async void ShoulReturnData()
5962
});
6063

6164
var contractHandler = web3.Eth.GetContractHandler(receipt.ContractAddress);
62-
var symbol = await contractHandler.QueryAsync<SymbolFunction, string>();
63-
var tokenName = await contractHandler.QueryAsync<NameFunction, string>();
65+
var symbol = await contractHandler.QueryRawAsync<SymbolFunction, StringBytes32Decoder, string>();
66+
var token = await contractHandler.QueryRawAsync<NameFunction, StringBytes32Decoder, string>();
6467

6568
Assert.Equal("XST", symbol);
66-
Assert.Equal("XomeStandardToken", tokenName);
69+
Assert.Equal("XomeStandardToken", token);
6770
}
6871

6972
[Fact]

src/Nethereum.StandardTokenEIP20.IntegrationTests/StandardToken.sol

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
contract Standard_Token is Token {
3939

40-
uint256 constant private MAX_UINT256 = 2**256 - 1;
40+
uint256 constant private MAX_UINT256 = 2**256 - 1;
4141
mapping (address => uint256) public balances;
4242
mapping (address => mapping (address => uint256)) public allowed;
4343
uint256 public totalSupply;
@@ -49,11 +49,11 @@ contract Standard_Token is Token {
4949
They allow one to customise the token contract & in no way influences the core functionality.
5050
Some wallets/interfaces might not even bother to look at this information.
5151
*/
52-
bytes32 public name; //fancy name: eg Simon Bucks
52+
string public name; //fancy name: eg Simon Bucks
5353
uint8 public decimals; //How many decimals to show.
54-
bytes32 public symbol; //An identifier: eg SBX
54+
string public symbol; //An identifier: eg SBX
5555

56-
constructor(uint256 _initialAmount, bytes32 _tokenName, uint8 _decimalUnits, bytes32 _tokenSymbol) public {
56+
constructor(uint256 _initialAmount, string _tokenName, uint8 _decimalUnits, string _tokenSymbol) public {
5757
balances[msg.sender] = _initialAmount; // Give the creator all initial tokens
5858
totalSupply = _initialAmount; // Update total supply
5959
name = _tokenName; // Set the name for display purposes

src/Nethereum.StandardTokenEIP20/CQS/EIP20Deployment.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@ namespace Nethereum.StandardTokenEIP20.CQS
66
{
77
public class EIP20Deployment : ContractDeploymentMessage
88
{
9-
public static string BYTECODE = "608060405234801561001057600080fd5b5060405160808061056983398101604090815281516020808401518385015160609095015133600090815292839052939091208290556002919091556003556004805460ff90931660ff19909316929092179091556005556104f2806100776000396000f3006080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b3578063095ea7b3146100da57806318160ddd1461011257806323b872dd1461012757806327e235e314610151578063313ce567146101725780635c6581651461019d57806370a08231146101c457806395d89b41146101e5578063a9059cbb146101fa578063dd62ed3e1461021e575b600080fd5b3480156100bf57600080fd5b506100c8610245565b60408051918252519081900360200190f35b3480156100e657600080fd5b506100fe600160a060020a036004351660243561024b565b604080519115158252519081900360200190f35b34801561011e57600080fd5b506100c86102b1565b34801561013357600080fd5b506100fe600160a060020a03600435811690602435166044356102b7565b34801561015d57600080fd5b506100c8600160a060020a03600435166103ba565b34801561017e57600080fd5b506101876103cc565b6040805160ff9092168252519081900360200190f35b3480156101a957600080fd5b506100c8600160a060020a03600435811690602435166103d5565b3480156101d057600080fd5b506100c8600160a060020a03600435166103f2565b3480156101f157600080fd5b506100c861040d565b34801561020657600080fd5b506100fe600160a060020a0360043516602435610413565b34801561022a57600080fd5b506100c8600160a060020a036004358116906024351661049b565b60035481565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025481565b600160a060020a03831660008181526001602090815260408083203384528252808320549383529082905281205490919083118015906102f75750828110155b151561030257600080fd5b600160a060020a038085166000908152602081905260408082208054870190559187168152208054849003905560001981101561036457600160a060020a03851660009081526001602090815260408083203384529091529020805484900390555b83600160a060020a031685600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3506001949350505050565b60006020819052908152604090205481565b60045460ff1681565b600160209081526000928352604080842090915290825290205481565b600160a060020a031660009081526020819052604090205490565b60055481565b3360009081526020819052604081205482111561042f57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a039182166000908152600160209081526040808320939094168252919091522054905600a165627a7a72305820af136271fe9f2975b7bfa446cfaba0eea2d537bdd235577ca9768932f203b2e10029";
9+
10+
public static string BYTECODE = "608060405234801561001057600080fd5b506040516107843803806107848339810160409081528151602080840151838501516060860151336000908152808552959095208490556002849055908501805193959094919391019161006991600391860190610096565b506004805460ff191660ff8416179055805161008c906005906020840190610096565b5050505050610131565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d757805160ff1916838001178555610104565b82800160010185558215610104579182015b828111156101045782518255916020019190600101906100e9565b50610110929150610114565b5090565b61012e91905b80821115610110576000815560010161011a565b90565b610644806101406000396000f3006080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b3578063095ea7b31461013d57806318160ddd1461017557806323b872dd1461019c57806327e235e3146101c6578063313ce567146101e75780635c6581651461021257806370a082311461023957806395d89b411461025a578063a9059cbb1461026f578063dd62ed3e14610293575b600080fd5b3480156100bf57600080fd5b506100c86102ba565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101025781810151838201526020016100ea565b50505050905090810190601f16801561012f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014957600080fd5b50610161600160a060020a0360043516602435610348565b604080519115158252519081900360200190f35b34801561018157600080fd5b5061018a6103ae565b60408051918252519081900360200190f35b3480156101a857600080fd5b50610161600160a060020a03600435811690602435166044356103b4565b3480156101d257600080fd5b5061018a600160a060020a03600435166104b7565b3480156101f357600080fd5b506101fc6104c9565b6040805160ff9092168252519081900360200190f35b34801561021e57600080fd5b5061018a600160a060020a03600435811690602435166104d2565b34801561024557600080fd5b5061018a600160a060020a03600435166104ef565b34801561026657600080fd5b506100c861050a565b34801561027b57600080fd5b50610161600160a060020a0360043516602435610565565b34801561029f57600080fd5b5061018a600160a060020a03600435811690602435166105ed565b6003805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103405780601f1061031557610100808354040283529160200191610340565b820191906000526020600020905b81548152906001019060200180831161032357829003601f168201915b505050505081565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025481565b600160a060020a03831660008181526001602090815260408083203384528252808320549383529082905281205490919083118015906103f45750828110155b15156103ff57600080fd5b600160a060020a038085166000908152602081905260408082208054870190559187168152208054849003905560001981101561046157600160a060020a03851660009081526001602090815260408083203384529091529020805484900390555b83600160a060020a031685600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3506001949350505050565b60006020819052908152604090205481565b60045460ff1681565b600160209081526000928352604080842090915290825290205481565b600160a060020a031660009081526020819052604090205490565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103405780601f1061031557610100808354040283529160200191610340565b3360009081526020819052604081205482111561058157600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a039182166000908152600160209081526040808320939094168252919091522054905600a165627a7a7230582084c618322109054a21a57e27075384a6172ab854e4b2c2d35062a964a6bf593f0029";
1011

1112
public EIP20Deployment() : base(BYTECODE) { }
1213

1314
public EIP20Deployment(string byteCode) : base(byteCode) { }
1415

1516
[Parameter("uint256", "_initialAmount", 1)]
1617
public BigInteger InitialAmount { get; set; }
17-
[Parameter("bytes32", "_tokenName", 2)]
18+
[Parameter("string", "_tokenName", 2)]
1819
public string TokenName { get; set; }
1920
[Parameter("uint8", "_decimalUnits", 3)]
2021
public byte DecimalUnits { get; set; }
21-
[Parameter("bytes32", "_tokenSymbol", 4)]
22+
[Parameter("string", "_tokenSymbol", 4)]
2223
public string TokenSymbol { get; set; }
2324

25+
2426
}
2527
}

src/Nethereum.StandardTokenEIP20/CQS/NameFunction.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Nethereum.StandardTokenEIP20.CQS
55
{
6-
[Function("name", "bytes32")]
6+
[Function("name", "string")]
77
public class NameFunction:ContractMessage
88
{
99

src/Nethereum.StandardTokenEIP20/CQS/SymbolFunction.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Nethereum.StandardTokenEIP20.CQS
55
{
6-
[Function("symbol", "bytes32")]
6+
[Function("symbol", "string")]
77
public class SymbolFunction:ContractMessage
88
{
99

src/Nethereum.StandardTokenEIP20/DTOs/NameOutputDTO.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Nethereum.StandardTokenEIP20.DTOs
55
[FunctionOutput]
66
public class NameOutputDTO
77
{
8-
[Parameter("bytes32", "", 1)]
8+
[Parameter("string", "", 1)]
99
public string B {get; set;}
1010
}
1111
}

src/Nethereum.StandardTokenEIP20/DTOs/SymbolOutputDTO.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Nethereum.StandardTokenEIP20.DTOs
55
[FunctionOutput]
66
public class SymbolOutputDTO
77
{
8-
[Parameter("bytes32", "", 1)]
8+
[Parameter("string", "", 1)]
99
public string B {get; set;}
1010
}
1111
}

src/Nethereum.XUnitEthereumClients/EthereumClientIntegrationFixture.cs

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public EthereumClientIntegrationFixture()
108108

109109
public void Dispose()
110110
{
111+
if(!_process.HasExited)
111112
_process.Kill();
112113
Thread.Sleep(2000);
113114
DeleteData();

0 commit comments

Comments
 (0)