2024-12-17 16:06:06 +01:00
using BlockchainUtils ;
using CodexContractsPlugin.Marketplace ;
2023-12-20 10:55:29 +01:00
using GethPlugin ;
2023-09-19 13:39:24 +02:00
using Logging ;
2023-12-20 11:34:23 +01:00
using Nethereum.ABI ;
2025-03-04 15:24:25 +01:00
using Nethereum.Contracts ;
2025-08-13 15:23:31 +02:00
using Nethereum.Hex.HexConvertors.Extensions ;
2023-12-20 11:34:23 +01:00
using Nethereum.Util ;
2024-04-09 13:24:30 +02:00
using Newtonsoft.Json ;
using Newtonsoft.Json.Converters ;
2023-12-20 09:48:22 +01:00
using Utils ;
2023-09-19 13:39:24 +02:00
namespace CodexContractsPlugin
2023-09-19 10:24:43 +02:00
{
public interface ICodexContracts
{
2023-09-20 10:13:29 +02:00
CodexContractsDeployment Deployment { get ; }
2023-09-19 13:39:24 +02:00
2023-12-18 13:32:58 +01:00
bool IsDeployed ( ) ;
2023-12-15 11:02:06 +01:00
string MintTestTokens ( IHasEthAddress owner , TestToken testTokens ) ;
string MintTestTokens ( EthAddress ethAddress , TestToken testTokens ) ;
2023-10-30 13:30:14 +01:00
TestToken GetTestTokenBalance ( IHasEthAddress owner ) ;
TestToken GetTestTokenBalance ( EthAddress ethAddress ) ;
2025-07-31 12:53:11 +02:00
string TransferTestTokens ( EthAddress to , TestToken amount ) ;
2023-12-20 09:48:22 +01:00
2024-05-31 10:06:34 +02:00
ICodexContractsEvents GetEvents ( TimeRange timeRange ) ;
ICodexContractsEvents GetEvents ( BlockInterval blockInterval ) ;
2025-07-07 15:53:26 +02:00
EthAddress ? GetSlotHost ( byte [ ] requestId , decimal slotIndex ) ;
RequestState GetRequestState ( byte [ ] requestId ) ;
2025-05-03 08:35:34 +02:00
Request GetRequest ( byte [ ] requestId ) ;
2025-03-04 15:24:25 +01:00
ulong GetPeriodNumber ( DateTime utc ) ;
2025-08-15 12:02:33 +02:00
TimeRange GetPeriodTimeRange ( ulong periodNumber ) ;
2024-11-25 15:45:09 +01:00
void WaitUntilNextPeriod ( ) ;
2025-08-15 12:02:33 +02:00
bool IsProofRequired ( byte [ ] requestId , decimal slotIndex ) ;
2025-08-13 15:23:31 +02:00
byte [ ] GetSlotId ( byte [ ] requestId , decimal slotIndex ) ;
2025-07-03 11:03:13 +02:00
ICodexContracts WithDifferentGeth ( IGethNode node ) ;
2025-03-04 15:24:25 +01:00
}
2024-04-09 13:24:30 +02:00
[JsonConverter(typeof(StringEnumConverter))]
2024-01-22 16:27:32 +01:00
public enum RequestState
{
New ,
Started ,
Cancelled ,
Finished ,
Failed
}
2023-09-19 10:24:43 +02:00
public class CodexContractsAccess : ICodexContracts
{
2023-09-19 13:39:24 +02:00
private readonly ILog log ;
2023-10-30 13:30:14 +01:00
private readonly IGethNode gethNode ;
2023-09-19 13:39:24 +02:00
2023-10-30 13:30:14 +01:00
public CodexContractsAccess ( ILog log , IGethNode gethNode , CodexContractsDeployment deployment )
2023-09-19 10:24:43 +02:00
{
2023-09-19 13:39:24 +02:00
this . log = log ;
2023-10-30 13:30:14 +01:00
this . gethNode = gethNode ;
2023-09-20 09:16:57 +02:00
Deployment = deployment ;
2023-09-19 10:24:43 +02:00
}
2023-09-20 10:13:29 +02:00
public CodexContractsDeployment Deployment { get ; }
2023-09-19 13:39:24 +02:00
2023-12-18 13:32:58 +01:00
public bool IsDeployed ( )
{
2023-12-20 09:48:22 +01:00
return ! string . IsNullOrEmpty ( StartInteraction ( ) . GetTokenName ( Deployment . TokenAddress ) ) ;
2023-12-18 13:32:58 +01:00
}
2023-12-15 11:02:06 +01:00
public string MintTestTokens ( IHasEthAddress owner , TestToken testTokens )
2023-09-19 16:22:07 +02:00
{
2023-12-15 11:02:06 +01:00
return MintTestTokens ( owner . EthAddress , testTokens ) ;
2023-09-19 16:22:07 +02:00
}
2023-12-15 11:02:06 +01:00
public string MintTestTokens ( EthAddress ethAddress , TestToken testTokens )
2023-09-19 13:39:24 +02:00
{
2024-05-22 11:06:34 +02:00
return StartInteraction ( ) . MintTestTokens ( ethAddress , testTokens . TstWei , Deployment . TokenAddress ) ;
2023-09-19 13:39:24 +02:00
}
2023-10-30 13:30:14 +01:00
public TestToken GetTestTokenBalance ( IHasEthAddress owner )
2023-09-19 16:22:07 +02:00
{
2023-10-30 13:30:14 +01:00
return GetTestTokenBalance ( owner . EthAddress ) ;
2023-09-19 16:22:07 +02:00
}
2023-10-30 13:30:14 +01:00
public TestToken GetTestTokenBalance ( EthAddress ethAddress )
2023-09-19 13:39:24 +02:00
{
2023-12-20 09:48:22 +01:00
var balance = StartInteraction ( ) . GetBalance ( Deployment . TokenAddress , ethAddress . Address ) ;
2024-05-22 11:06:34 +02:00
return balance . TstWei ( ) ;
2023-09-19 13:39:24 +02:00
}
2023-12-20 09:48:22 +01:00
2025-07-31 12:53:11 +02:00
public string TransferTestTokens ( EthAddress to , TestToken amount )
2025-07-03 11:03:13 +02:00
{
2025-07-31 12:53:11 +02:00
return StartInteraction ( ) . TransferTestTokens ( Deployment . TokenAddress , to . Address , amount . TstWei ) ;
2025-07-03 11:03:13 +02:00
}
2024-05-31 10:06:34 +02:00
public ICodexContractsEvents GetEvents ( TimeRange timeRange )
2023-12-20 09:48:22 +01:00
{
2024-05-31 10:06:34 +02:00
return GetEvents ( gethNode . ConvertTimeRangeToBlockRange ( timeRange ) ) ;
2023-12-20 09:48:22 +01:00
}
2024-05-31 10:06:34 +02:00
public ICodexContractsEvents GetEvents ( BlockInterval blockInterval )
2024-01-22 16:05:04 +01:00
{
2024-05-31 10:06:34 +02:00
return new CodexContractsEvents ( log , gethNode , Deployment , blockInterval ) ;
2023-12-20 13:21:53 +01:00
}
2025-07-07 15:53:26 +02:00
public EthAddress ? GetSlotHost ( byte [ ] requestId , decimal slotIndex )
2025-03-04 15:24:25 +01:00
{
2025-07-07 15:53:26 +02:00
var slotId = GetSlotId ( requestId , slotIndex ) ;
2023-12-20 11:34:23 +01:00
var func = new GetHostFunction
{
2025-03-04 15:24:25 +01:00
SlotId = slotId
2023-12-20 11:34:23 +01:00
} ;
2024-01-26 17:29:57 -05:00
var address = gethNode . Call < GetHostFunction , string > ( Deployment . MarketplaceAddress , func ) ;
if ( string . IsNullOrEmpty ( address ) ) return null ;
return new EthAddress ( address ) ;
2023-12-20 11:34:23 +01:00
}
2025-07-07 15:53:26 +02:00
public RequestState GetRequestState ( byte [ ] requestId )
2024-01-22 16:27:32 +01:00
{
2025-07-07 15:53:26 +02:00
if ( requestId = = null ) throw new ArgumentNullException ( nameof ( requestId ) ) ;
if ( requestId . Length ! = 32 ) throw new InvalidDataException ( nameof ( requestId ) + $"{nameof(requestId)} length should be 32 bytes, but was: {requestId.Length}" + requestId . Length ) ;
2024-01-22 16:27:32 +01:00
var func = new RequestStateFunction
{
2025-07-07 15:53:26 +02:00
RequestId = requestId
2024-01-22 16:27:32 +01:00
} ;
return gethNode . Call < RequestStateFunction , RequestState > ( Deployment . MarketplaceAddress , func ) ;
}
2025-05-03 08:35:34 +02:00
public Request GetRequest ( byte [ ] requestId )
{
2025-07-07 15:53:26 +02:00
if ( requestId = = null ) throw new ArgumentNullException ( nameof ( requestId ) ) ;
if ( requestId . Length ! = 32 ) throw new InvalidDataException ( nameof ( requestId ) + $"{nameof(requestId)} length should be 32 bytes, but was: {requestId.Length}" + requestId . Length ) ;
2025-05-03 08:35:34 +02:00
var func = new GetRequestFunction
{
RequestId = requestId
} ;
var request = gethNode . Call < GetRequestFunction , GetRequestOutputDTO > ( Deployment . MarketplaceAddress , func ) ;
return request . ReturnValue1 ;
}
2025-03-04 15:24:25 +01:00
public ulong GetPeriodNumber ( DateTime utc )
{
DateTimeOffset utco = DateTime . SpecifyKind ( utc , DateTimeKind . Utc ) ;
var now = utco . ToUnixTimeSeconds ( ) ;
var periodSeconds = ( int ) Deployment . Config . Proofs . Period ;
var result = now / periodSeconds ;
return Convert . ToUInt64 ( result ) ;
}
2025-08-15 12:02:33 +02:00
public TimeRange GetPeriodTimeRange ( ulong periodNumber )
{
var periodSeconds = ( ulong ) Deployment . Config . Proofs . Period ;
var startUtco = Convert . ToInt64 ( periodSeconds * periodNumber ) ;
var endUtco = Convert . ToInt64 ( periodSeconds * ( periodNumber + 1 ) ) ;
var start = DateTimeOffset . FromUnixTimeSeconds ( startUtco ) . UtcDateTime ;
var end = DateTimeOffset . FromUnixTimeSeconds ( endUtco ) . UtcDateTime ;
return new TimeRange ( start , end ) ;
}
2024-11-25 15:45:09 +01:00
public void WaitUntilNextPeriod ( )
2024-11-22 16:09:18 +01:00
{
2024-11-25 15:45:09 +01:00
var now = DateTimeOffset . UtcNow . ToUnixTimeSeconds ( ) ;
var periodSeconds = ( int ) Deployment . Config . Proofs . Period ;
var secondsLeft = now % periodSeconds ;
Thread . Sleep ( TimeSpan . FromSeconds ( secondsLeft + 1 ) ) ;
2024-11-22 16:09:18 +01:00
}
2025-08-15 12:02:33 +02:00
public bool IsProofRequired ( byte [ ] requestId , decimal slotIndex )
2025-03-04 15:24:25 +01:00
{
2025-07-07 15:53:26 +02:00
var slotId = GetSlotId ( requestId , slotIndex ) ;
2025-08-15 12:02:33 +02:00
return IsProofRequired ( slotId ) ;
2025-03-04 15:24:25 +01:00
}
2025-07-03 11:03:13 +02:00
public ICodexContracts WithDifferentGeth ( IGethNode node )
{
return new CodexContractsAccess ( log , node , Deployment ) ;
}
2025-08-13 15:23:31 +02:00
public byte [ ] GetSlotId ( byte [ ] requestId , decimal slotIndex )
2025-03-05 15:55:10 +01:00
{
var encoder = new ABIEncode ( ) ;
var encoded = encoder . GetABIEncoded (
2025-07-07 15:53:26 +02:00
new ABIValue ( "bytes32" , requestId ) ,
2025-03-05 15:55:10 +01:00
new ABIValue ( "uint256" , slotIndex . ToBig ( ) )
) ;
return Sha3Keccack . Current . CalculateHash ( encoded ) ;
}
2025-08-13 15:23:31 +02:00
private bool IsProofRequired ( byte [ ] slotId )
2025-03-04 15:24:25 +01:00
{
var func = new IsProofRequiredFunction
{
Id = slotId
} ;
2025-08-13 15:23:31 +02:00
var result = gethNode . Call < IsProofRequiredFunction , IsProofRequiredOutputDTO > ( Deployment . MarketplaceAddress , func ) ;
2025-03-04 15:24:25 +01:00
return result . ReturnValue1 ;
}
2023-12-20 09:48:22 +01:00
private ContractInteractions StartInteraction ( )
{
return new ContractInteractions ( log , gethNode ) ;
}
2023-09-19 10:24:43 +02:00
}
}