Skip to content

Commit

Permalink
Merge branch 'master' into feat/simple-dao-template
Browse files Browse the repository at this point in the history
  • Loading branch information
zhifenglee-aelf authored Jun 28, 2024
2 parents ae19cb0 + 85fcb31 commit 91aed46
Show file tree
Hide file tree
Showing 18 changed files with 3,733 additions and 0 deletions.
21 changes: 21 additions & 0 deletions templates/NftSaleContract/.template.config/template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "http://json.schemastore.org/template",
"author": "AElf",
"classifications": [
"AElf/SmartContract"
],
"identity": "AElf.Contract.NftSale.Template",
"name": "AElf Contract NftSale Template",
"shortName": "aelf-nft-sale",
"tags": {
"language": "C#",
"type": "project"
},
"sourceName": "NftSale",
"symbols": {
"NamespacePath": {
"type": "parameter",
"replaces": "AElf.Contracts.NftSale"
}
}
}
11 changes: 11 additions & 0 deletions templates/NftSaleContract/src/ContractReferences.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using AElf.Contracts.Consensus.AEDPoS;
using AElf.Contracts.MultiToken;

namespace AElf.Contracts.NftSale
{
public partial class NftSaleState
{
internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; }
internal AEDPoSContractContainer.AEDPoSContractReferenceState ConsensusContract { get; set; }
}
}
159 changes: 159 additions & 0 deletions templates/NftSaleContract/src/NftSale.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
using AElf.Contracts.MultiToken;
using AElf.Sdk.CSharp;
using AElf.Types;
using Google.Protobuf.WellKnownTypes;

namespace AElf.Contracts.NftSale
{
// Contract class must inherit the base class generated from the proto file
public class NftSale : NftSaleContainer.NftSaleBase
{
// Initializes the contract
public override Empty Initialize(NftPrice input)
{
// Check if the contract is already initialized
Assert(State.Initialized.Value == false, "Already initialized.");
// Set the contract state
State.Initialized.Value = true;
// Set the owner address
State.Owner.Value = Context.Sender;
State.NftPrice.Value = input.Price;

// Initialize the token contract
State.TokenContract.Value = Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName);
// The below code can be used to replace the above line. The below is a showcase of how you can reference to any contracts.
State.ConsensusContract.Value = Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName);

return new Empty();
}

// transfer nft
public override Empty Purchase(PurchaseInput input)
{
var price = State.NftPrice.Value;
// transfer token
State.TokenContract.TransferFrom.Send(new TransferFromInput
{
From = Context.Sender,
To = Context.Self,
Symbol = price.Symbol,
Amount = price.Amount * input.Amount
});
// transfer nft
State.TokenContract.Transfer.Send(new TransferInput
{
To = Context.Sender,
Symbol = input.Symbol,
Amount = input.Amount
});

Context.Fire(new SaleNft
{
To = Context.Self,
Symbol = input.Symbol,
Amount = input.Amount,
});

return new Empty();
}

//
public override Empty SetPriceAndSymbol(NftPrice input)
{
AssertIsOwner();
State.NftPrice.Value = input.Price;
return new Empty();
}

public override Price GetPrice(Empty input)
{
return State.NftPrice.Value;
}


// Withdraws a specified amount of tokens from the contract.
// This method can only be called by the owner of the contract.
// After the tokens are transferred, a WithdrawEvent is fired to notify any listeners about the withdrawal.
public override Empty Withdraw(Int64Value input)
{
AssertIsOwner();

// Transfer the token from the contract to the sender
State.TokenContract.Transfer.Send(new TransferInput
{
To = Context.Sender,
Symbol = State.NftPrice.Value.Symbol,
Amount = input.Value
});

// Emit an event to notify listeners about the withdrawal
Context.Fire(new WithdrawEvent
{
Amount = input.Value,
From = Context.Self,
To = Context.Sender
});

return new Empty();
}

// Deposits a specified amount of tokens into the contract.
// This method can only be called by the owner of the contract.
// After the tokens are transferred, a DepositEvent is fired to notify any listeners about the deposit.
public override Empty Deposit(DepositeInput input)
{
AssertIsOwner();

// Transfer the token from the sender to the contract
State.TokenContract.TransferFrom.Send(new TransferFromInput
{
From = Context.Sender,
To = Context.Self,
Symbol = input.Symbol,
Amount = input.Amount
});

// Emit an event to notify listeners about the deposit
Context.Fire(new DepositEvent
{
Amount = input.Amount,
From = Context.Sender,
To = Context.Self
});

return new Empty();
}


// A method that read the contract's current balance
public override Int64Value GetContractBalance(GetContractBalanceInput input)
{
// Get the balance of the contract
var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput
{
Owner = input.Address,
Symbol = State.NftPrice.Value.Symbol
}).Balance;

// Wrap the value in the return type
return new Int64Value
{
Value = balance
};
}

// This method is used to ensure that only the owner of the contract can perform certain actions.
// If the context sender is not the owner, an exception is thrown with the message "Unauthorized to perform the action."
private void AssertIsOwner()
{
Assert(Context.Sender == State.Owner.Value, "Unauthorized to perform the action.");
}

// A method that read the contract's owner
public override StringValue GetOwner(Empty input)
{
return State.Owner.Value == null ? new StringValue() : new StringValue {Value = State.Owner.Value.ToBase58()};
}
}

}
28 changes: 28 additions & 0 deletions templates/NftSaleContract/src/NftSale.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>AElf.Contracts.NftSale</RootNamespace>
<IsContract>true</IsContract>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup>
<ObjPath>$(MSBuildProjectDirectory)/$(BaseIntermediateOutputPath)$(Configuration)/$(TargetFramework)/</ObjPath>
</PropertyGroup>

<Target Name="ProtoGeneratedRecognition" AfterTargets="CoreCompile">
<ItemGroup>
<Compile Include="$(ObjPath)Protobuf/**/*.cs"/>
</ItemGroup>
</Target>

<ItemGroup>
<PackageReference Include="AElf.Sdk.CSharp" Version="1.5.0"/>
<PackageReference Include="AElf.Tools" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>

15 changes: 15 additions & 0 deletions templates/NftSaleContract/src/NftSaleState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using AElf.Sdk.CSharp.State;
using AElf.Types;

namespace AElf.Contracts.NftSale
{
// The state class is access the blockchain state
public partial class NftSaleState : ContractState
{
// A state to check if contract is initialized
public BoolState Initialized { get; set; }
// A state to store the owner address
public SingletonState<Address> Owner { get; set; }
public SingletonState<Price> NftPrice { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
syntax = "proto3";

import "aelf/core.proto";
import "aelf/options.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/wrappers.proto";
import "Protobuf/reference/acs12.proto";
// The namespace of this class
option csharp_namespace = "AElf.Contracts.NftSale";

service NftSale {
// The name of the state class the smart contract is going to use to access blockchain state
option (aelf.csharp_state) = "AElf.Contracts.NftSale.NftSaleState";
option (aelf.base) = "Protobuf/reference/acs12.proto";

rpc Initialize (NftPrice) returns (google.protobuf.Empty) {
}

rpc Purchase (PurchaseInput) returns (google.protobuf.Empty) {
}

rpc SetPriceAndSymbol (NftPrice) returns (google.protobuf.Empty) {
}

rpc GetPrice (google.protobuf.Empty) returns (Price) {
option (aelf.is_view) = true;
}

rpc GetSymbol (google.protobuf.Empty) returns (NftSymbol) {
option (aelf.is_view) = true;
}

rpc Withdraw (google.protobuf.Int64Value) returns (google.protobuf.Empty) {
}

rpc Deposit (DepositeInput) returns (google.protobuf.Empty) {
}

rpc TransferOwnership (aelf.Address) returns (google.protobuf.Empty) {
}

rpc GetContractBalance (GetContractBalanceInput) returns (google.protobuf.Int64Value) {
option (aelf.is_view) = true;
}

rpc GetOwner (google.protobuf.Empty) returns (google.protobuf.StringValue) {
option (aelf.is_view) = true;
}
}

message DepositeInput{
string symbol = 1; // nft
int64 amount = 2; // token amount
}

message Price {
string symbol = 1; // token type
int64 amount = 2; // token price
}

message NftSymbol {
string symbol = 1;
}

message NftPrice{
// // The token symbol price
Price price = 1;
// The token symbol
string symbol = 2;
}

message PurchaseInput {
// The token symbol to transfer.
string symbol = 2;
// The amount to to transfer.
int64 amount = 3;
// The memo.
string memo = 4;
// Transaction information
Price price = 5;
}

message SaleNft {
option (aelf.is_event) = true;
// The destination address of the transferred token.
aelf.Address to = 2 [(aelf.is_indexed) = true];
// The symbol of the transferred token.
string symbol = 3 [(aelf.is_indexed) = true];
// The amount of the transferred token.
int64 amount = 4;
// The memo.
string memo = 5;
}

message GetContractBalanceInput{
aelf.Address address = 1;
}

// An event that will be emitted from contract method call when Withdraw is called.
message WithdrawEvent {
option (aelf.is_event) = true;
int64 amount = 1;
aelf.Address from = 2;
aelf.Address to = 3;
}

// An event that will be emitted from contract method call when Deposit is called.
message DepositEvent {
option (aelf.is_event) = true;
int64 amount = 1;
string symbol = 2;
aelf.Address from = 3;
aelf.Address to = 4;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto3";

import "aelf/core.proto";

option csharp_namespace = "AElf.Contracts.NftSale";

message AuthorityInfo {
aelf.Address contract_address = 1;
aelf.Address owner_address = 2;
}
Loading

0 comments on commit 91aed46

Please sign in to comment.