Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mini app #199

Merged
merged 7 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions contract/Forest/ForestContractState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ public partial class ForestContractState : ContractState
public SingletonState<int> MaxBatchCancelOfferCount { get; set; }

public SingletonState<int> MaxBatchCancelListCount { get; set; }

public SingletonState<string> TreePointsHashVerifyKey { get; set; }
/// Address -> TreePointsInfo
public MappedState<Address, TreePointsInfo> TreePointsMap { get; set; }
/// Address -> timestamp 13
public MappedState<Address, long> TreePointsAddTimeMap { get; set; }
/// Address -> activityId -> timestamp 13
public MappedState<Address, string, long> TreePointsActivityClaimTimeMap { get; set; }
/// Address -> timestamp 13
public MappedState<Address, long> TreePointsLevelUpgradeTimeMap { get; set; }


}
}
8 changes: 8 additions & 0 deletions contract/Forest/ForestContract_Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,12 @@ private void AssertBalanceEnoughForList(string symbol, Address address, long cur
var listedAmount = GetEffectiveNFTListedTotalAmount(address, symbol);
Assert(currentBalance >= (listedAmount + amount), $"The balance is not enough. Please reset it.");
}

private void CheckPointsRequestHash(string request, string hash)
{
var key = State.TreePointsHashVerifyKey.Value;
Assert(!string.IsNullOrEmpty(key), "Need SetTreePointsHashVerifyKey");
var requestHash = HashHelper.ComputeFrom(string.Concat(request, key));
Assert(hash.Equals(requestHash.ToHex()), "Unverified requests");
}
}
163 changes: 163 additions & 0 deletions contract/Forest/ForestContract_Tree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using AElf;
using AElf.Contracts.MultiToken;
using AElf.Sdk.CSharp;
using Google.Protobuf.WellKnownTypes;

namespace Forest;

public partial class ForestContract
{
public override Empty AddTreePoints(AddTreePointsInput input)
{
AssertContractInitialized();
Assert(input != null, "Invalid param");
Assert(!input.Address.Value.IsNullOrEmpty(), "Invalid param Address");
Assert(input.Points > 0, "Invalid param Points");
Assert(!string.IsNullOrEmpty(input.RequestHash), "Invalid param RequestHash");
Assert(input.OpTime != null && input.OpTime > 0, "Invalid param OpTime");
Assert(Context.Sender == input.Address, "Param Address is not Sender");

var requestStr = string.Concat(input.Address.ToBase58(), input.Points, input.PointsType, input.OpTime);
CheckPointsRequestHash(requestStr, input.RequestHash);

var lastAddTime = State.TreePointsAddTimeMap[input.Address];
Assert(input.OpTime > lastAddTime, "Invalid param OpTime");

var treePointsInfo = State.TreePointsMap[input.Address];
if (treePointsInfo != null)
{
treePointsInfo.Points += input.Points;
}
else
{
treePointsInfo = new TreePointsInfo()
{
Owner = input.Address,
Points = input.Points,
Level = 1
};
}

State.TreePointsMap[input.Address] = treePointsInfo;
State.TreePointsAddTimeMap[input.Address] = input.OpTime;

//event
Context.Fire(new TreePointsAdded()
{
Owner = input.Address,
Points = input.Points,
PointsType = input.PointsType,
OpTime = input.OpTime,
TotalPoints = treePointsInfo.Points,
RequestHash = input.RequestHash
});
return new Empty();
}
public override Empty ClaimTreePoints(ClaimTreePointsInput input)
{
AssertContractInitialized();
Assert(input != null, "Invalid param");
Assert(!input.Address.Value.IsNullOrEmpty(), "Invalid param Address");
Assert(input.Points >= 0, "Invalid param Points");
Assert(!string.IsNullOrEmpty(input.ActivityId), "Invalid param ActivityId");
Assert(!string.IsNullOrEmpty(input.RequestHash), "Invalid param RequestHash");
Assert(input.OpTime != null && input.OpTime > 0, "Invalid param OpTime");
Assert(input.Reward != null && !string.IsNullOrEmpty(input.Reward.Symbol) && input.Reward.Amount > 0, "Invalid param Reward");
Assert(Context.Sender == input.Address, "Param Address is not Sender");

var requestStr = string.Concat(input.Address.ToBase58(), input.ActivityId,input.Points, input.OpTime);
requestStr = string.Concat(requestStr, input.Reward.Symbol, input.Reward.Amount);
CheckPointsRequestHash(requestStr, input.RequestHash);

var lastOpTime = State.TreePointsActivityClaimTimeMap[input.Address][input.ActivityId];
Assert(lastOpTime == 0, "You have already participated in this activity");
Assert(input.OpTime > lastOpTime, "Invalid param OpTime");

var treePointsInfo = State.TreePointsMap[input.Address];
Assert(treePointsInfo != null, "your points is zero");
Assert(treePointsInfo.Points >= input.Points, "You don't have enough points");
treePointsInfo.Points -= input.Points;
State.TreePointsMap[input.Address] = treePointsInfo;
State.TreePointsActivityClaimTimeMap[input.Address][input.ActivityId] = input.OpTime;

//transfer award
var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput
{
Symbol = input.Reward.Symbol,
Owner = Context.Self
});
Assert(balance.Balance >= input.Reward.Amount,$"The platform does not have enough {input.Reward.Symbol}");
State.TokenContract.Transfer.Send(new TransferInput
{
To = input.Address,
Symbol = input.Reward.Symbol,
Amount = input.Reward.Amount
});
//event
Context.Fire(new TreePointsClaimed()
{
Owner = input.Address,
Points = input.Points,
ActivityId = input.ActivityId,
OpTime = input.OpTime,
RewardSymbol = input.Reward.Symbol,
RewardAmount = input.Reward.Amount,
TotalPoints = treePointsInfo.Points,
RequestHash = input.RequestHash
});
return new Empty();
}
public override Empty SetTreePointsHashVerifyKey(StringValue input)
{
AssertContractInitialized();
Assert(input != null && !string.IsNullOrEmpty(input.Value), "Invalid param key");
var key = State.TreePointsHashVerifyKey.Value;
if (string.IsNullOrEmpty(key))
{
State.TreePointsHashVerifyKey.Value = input.Value;
return new Empty();
}
AssertSenderIsAdmin();
State.TreePointsHashVerifyKey.Value = input.Value;
return new Empty();
}

public override Empty TreeLevelUpgrade(TreeLevelUpgradeInput input)
{
AssertContractInitialized();
Assert(input != null, "Invalid param");
Assert(!input.Address.Value.IsNullOrEmpty(), "Invalid param Address");
Assert(input.Points > 0, "Invalid param Points");
Assert(!string.IsNullOrEmpty(input.RequestHash), "Invalid param RequestHash");
Assert(input.OpTime != null && input.OpTime > 0, "Invalid param OpTime");
Assert(input.UpgradeLevel > 0, "Invalid UpgradeLevel, Should be greater than 0");
Assert(Context.Sender == input.Address, "Param Address is not Sender");

var requestStr = string.Concat(input.Address.ToBase58(), input.Points, input.OpTime, input.UpgradeLevel);
CheckPointsRequestHash(requestStr, input.RequestHash);

var lastOpTime = State.TreePointsLevelUpgradeTimeMap[input.Address];
Assert(input.OpTime > lastOpTime, "Invalid param OpTime");

var treePointsInfo = State.TreePointsMap[input.Address];
Assert(treePointsInfo != null, "your points is zero");
Assert(treePointsInfo.Points >= input.Points, "You don't have enough points");
Assert(treePointsInfo.Level < input.UpgradeLevel, $"You are already level{input.UpgradeLevel}");

treePointsInfo.Points -= input.Points;
State.TreePointsMap[input.Address] = treePointsInfo;
State.TreePointsLevelUpgradeTimeMap[input.Address] = input.OpTime;

//event
Context.Fire(new TreeLevelUpgraded()
{
Owner = input.Address,
Points = input.Points,
OpTime = input.OpTime,
UpgradeLevel = input.UpgradeLevel,
TotalPoints = treePointsInfo.Points,
RequestHash = input.RequestHash
});
return new Empty();
}
}
5 changes: 5 additions & 0 deletions contract/Forest/ForestContract_Views.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,9 @@ public override Int32Value GetMaxBatchCancelListCount(Empty input)
{
return new Int32Value { Value = State.MaxBatchCancelListCount.Value };
}

public override TreePointsInfo GetTreePoints(Address input)
{
return State.TreePointsMap[input];
}
}
91 changes: 91 additions & 0 deletions protobuf/forest_contract.proto
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ service ForestContract {
rpc GetMaxBatchCancelListCount(google.protobuf.Empty) returns (google.protobuf.Int32Value){
option (aelf.is_view) = true;
}

rpc AddTreePoints(AddTreePointsInput) returns (google.protobuf.Empty){
}

rpc ClaimTreePoints(ClaimTreePointsInput) returns (google.protobuf.Empty){
}

rpc TreeLevelUpgrade(TreeLevelUpgradeInput) returns (google.protobuf.Empty){
}

rpc GetTreePoints(aelf.Address) returns (TreePointsInfo){
option (aelf.is_view) = true;
}

rpc SetTreePointsHashVerifyKey(google.protobuf.StringValue)returns (google.protobuf.Empty){
}
}

// Structs.
Expand Down Expand Up @@ -234,6 +250,11 @@ message WhitelistInfoList{
repeated WhitelistInfo whitelists = 1;
}

message TreePointsInfo {
aelf.Address owner = 1;
int64 points = 2;
int64 level = 3;
}
// Inputs.

message InitializeInput {
Expand Down Expand Up @@ -460,6 +481,42 @@ message CreateArtInfo {
Price cost_price = 8;
string painting_style = 9;
}
message AddTreePointsInput {
aelf.Address address = 1;
int64 points = 2;
int32 points_type =3;
int64 op_time = 4;
string request_hash = 5;
}

message ClaimTreePointsInput {
aelf.Address address = 1;
int64 points = 2;
string activity_id = 3;
int64 op_time = 4;
TreeReward reward = 5;
string request_hash = 6;
}

message TreeLevelUpgradeInput {
aelf.Address address = 1;
int64 points = 2;
int64 op_time = 3;
int32 upgrade_level = 4;
string request_hash = 5;
}

message TreeReward {
string symbol = 1;
int64 amount = 2;
}

enum TreePointsType {
NORMALONE = 0;
NORMALTWO = 1;
INVITE = 2;
}


// Events

Expand Down Expand Up @@ -631,3 +688,37 @@ message ArtCreated {
string painting_style = 9;
}

message TreePointsAdded {
option (aelf.is_event) = true;
aelf.Address owner = 1;
int64 points = 2;
int32 points_type = 3;
int64 op_time = 4;
int64 total_points = 5;
string request_hash = 6;
}

message TreePointsClaimed {
option (aelf.is_event) = true;
aelf.Address owner = 1;
int64 points = 2;
string activity_id = 3;
int64 op_time = 4;
string reward_symbol = 5;
int64 reward_amount = 6;
int64 total_points = 7;
string request_hash = 8;
}

message TreeLevelUpgraded {
option (aelf.is_event) = true;
aelf.Address owner = 1;
int64 points = 2;
int32 upgrade_level = 3;
int64 op_time = 4;
int64 total_points = 5;
string request_hash = 6;
}



Loading
Loading