bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 41쪽 중 22쪽
r mnemonics required. Underpinned by social recovery and decentralized guardian design, Portkey safeguards users' assets from centralized control and theft. Portkey has a unique payment delegation mechanism which enables interested parties to function as delegatees to pay for user activities on users' behalf. This means that users can create accounts for free and fees for other usages may also be covered in Portkey.
Portkey also provides crypto on/off-ramp services, allowing users to exchange fiat with crypto freely. It supports the storage and management of various digital assets such as tokens, NFTs, etc. The compatibility with multi-chains and seamless connection to all kinds of DApps makes Portkey a great way to enter the world of Web3.
With DID solution as its core, Portkey provides both Portkey Wallet and Portkey SDKs.
For more information, you may visit the official documentation for Portkey at
https://doc.portkey.finance/
.
Download the Chrome extension for Portkey from
https://chromewebstore.google.com/detail/portkey-wallet/iglbgmakmggfkoidiagnhknlndljlolb
.
info
The Portkey extension supports Chrome browser only (for now). Please ensure that you are using Chrome browser.
You may download Chrome from
https://www.google.com/intl/en_sg/chrome/
.
Once you have downloaded the extension, you should see the following on your browser as shown below.
Click on
Get Start
and you should see the following interface as shown below.
Sign up
Switch to
aelf Testnet
network by selecting it:
danger
Please make sure you are using
aelf Testnet
in order to be able to receive your testnet tokens from the Faucet.
Proceed to sign up with a Google Account or your preferred login method and complete the necessary accounts creation prompts and you should observe the following interface once you have signed up.
With that, you have successfully created your very first Portkey wallet within seconds. How easy was that?
info
It is highly recommended to pin the Portkey wallet extension for easier access and navigation to your Portkey wallet!
Next, click on ‘Open Portkey’ and you should now observe the following as shown below.
Connect Portkey Wallet
Click on
"Connect Wallet"
to connect your Portkey wallet.
The button will change to
"Your Wallet Address"
when the connection is successful.
Start The Game
Click on
"Start The Game"
button to Start The Tic Tac Toe Game.
You will receive a transaction request on your portkey wallet to
Sign
the transaction.
Click on
Sign
the transaction.
After the transaction is successfully processed, your game will start ✅.
As we have
Started the Game
successfully, let's start to perform the moves and enjoy the game.
Perform the Move
Let's start to make the moves and play the game.
tip
Your first move will always be
"X"
as shown in the picture below.
Click on the first square of the board, as shown in the picture below.
You will receive a transaction request on your Portkey wallet to
Sign
for making the move.
After the transaction is successfully processed, your first move will be submitted to blockchain ✅.
Now it's turn of move by the opponent and the move sign will change from
"X"
to
"O"
. Your active turn is
"O"
now, as shown in the picture below.
Click on the middle square of the board for
"O"
, as shown in the picture below.
You will receive a transaction request on your Portkey wallet to
Sign
for the second move.
Click on
Sign
the transaction.
After the transaction is successfully processed, your second move will be submitted to the blockchain ✅.
Now you can continue making other moves as demonstrated above.
After winning the game, you will see this winning screen with the corresponding move (
X
or
O
).
Click on the
Start Again
button to continue playing the Tic-Tac-Toe game with aelf blockchain. Enjoy!
You will be redirected again to the
Welcome screen
of the Game.
success
🎉 Congratulations Learners! You have successfully built your Tic-Tac-Toe dApp with aelf Blockchain.
🎯 Conclusion
🎉 Congratulations on successfully completing the
Tic Tac Toe dApp
tutorial! 🎉 You've achieved significant milestones, from setting up your development environment to deploying and interacting with your Tic-Tac-Toe smart contract on the aelf blockchain. 🌟
📚 What You've Learned
Throughout this tutorial, you've mastered:
🛠️ Setting Up Your Development Environment:
You equipped your workspace by installing and configuring all the necessary tools to get your smart contract project off the ground.
💻 Developing Your Smart Contract:
You built the core logic of your Tic Tac Toe game, writing and compiling the smart contract that manages game states, moves, and outcomes.
🚀 Deploying the Smart Contract:
You successfully deployed your Tic Tac Toe smart contract to the aelf blockchain, making it live and ready for gameplay.
🔧 Interacting with Your Deployed Smart Contract through the dApp:
You connected your frontend to the blockchain, configured the Portkey provider, and implemented essential functions like wallet connectivity, game initialization, and move management.
🔍 Final Output
By now, you should have:
📜 A deployed Tic-Tac-Toe smart contract that governs the game's rules and manages players' moves on the blockchain.
💻 A fully functional Tic-Tac-Toe dApp, allowing users to connect their wallets, start a game, make moves, and determine the winner, all in a decentralized manner.
➡️ What's Next?
With the foundation laid, consider advancing your Tic-Tac-Toe dApp with more sophisticated features:
📈 Enhancing Game Logic:
Add more features like AI opponents, multiplayer functionality, or scoring systems to make the game more engaging.
🔒 Improving Security:
Secure your game by applying best practices in smart contract security to protect users' data and gameplay integrity.
🌍 Exploring Cross-Chain Capabilities:
Expand your dApp’s reach by exploring aelf’s cross-chain interoperability, enabling interactions with other blockchains.
Blockchain technology and decentralized applications offer limitless possibilities. With your Tic-Tac-Toe dApp, you're now poised to continue innovating and exploring new horizons with aelf. 🚀
Happy coding and expanding your
Tic-Tac-Toe dApp!
😊
Step 1 - Setting up your development environment
Step 2 - Develop Smart Contract
Start Your Smart Contract Project
Adding Your Smart Contract Code
Building Smart Contract
Step 3 - Deploy Smart Contract
Step 4 - Interact with Your Deployed Smart Contract through dApp
Project Setup
Configure Portkey Provider & Write Connect Wallet Function
Configure Connect Wallet Function
Check Contract Initialization
Initialize Contract
Fetch Game Status
Fetch Board Data
Start Game
Perform the Move
Run Application
🎯 Conclusion
## /quick-start/developers/expense-tracker
On this page
Description
: The Expense Tracker dApp is a decentralized application that enables users to manage and monitor their personal finances on the aelf blockchain. It provides a user-friendly interface for recording expenses, categorizing them, and tracking spending habits, with all data securely stored and verified on the aelf blockchain.
Purpose
: The purpose of the Expense Tracker dApp is to showcase the integration of personal finance management with blockchain technology, offering enhanced transparency and security for users' financial data. It serves as a practical example of decentralized applications in everyday use cases, while also providing a learning platform for smart contract development and blockchain-based financial solutions.
Difficulty Level
: Moderate
Step 1 - Setting up your development environment
Local
Codespaces
Basic knowledge of terminal commands
IDE
- Install
VS Code
Note for Apple Silicon users:
Ensure that Rosetta is installed, if it is not, use the following command:
Terminal
softwareupdate --install-rosetta
Install Required Packages
Install dotnet 8.0.x SDK
Install aelf contract templates
Linux and macOs
Windows
Terminal
dotnet new
--install
AElf.ContractTemplates
Command Prompt
dotnet new
install
AElf.ContractTemplates
AELF.ContractTemplates contains various predefined templates for the ease of developing smart contracts on the aelf blockchain.
Install aelf deploy tool
Terminal
dotnet tool
install
--global
aelf.deploy
aelf.deploy is a utility tool for deploying smart contracts on the aelf blockchain.
Please remember to export PATH after installing aelf.deploy.
info
ℹ️ Note: If you have installed aelf.deploy and your terminal says that there is no such command available, please uninstall and install aelf.deploy.
Install Node.js and Yarn
Install Node.js
Install Yarn
Install aelf-command
Linux and macOs
Windows
Terminal
sudo
npm
i
-g
aelf-command
Command Prompt
npm
i
-g
aelf-command
aelf-command is a CLI tool for interacting with the aelf blockchain, enabling tasks like creating wallets and managing transactions.
Provide required permissions while installing aelf-command globally.
Visit
aelf-devcontainer-template
.
Click the
Use this template
button. Choose
Create a new repository
.
Enter a suitable repository name. Click
Create repository
.
Within the GitHub interface of your new repository, click on
Code
.
Select
Codespaces
.
Click on the
+
sign to create a new Codespace.
After some time, your workspace will load with the contents of the repository.
You can now continue your development using GitHub Codespaces.
Step 2 - Develop Smart Contract
Start Your Smart Contract Project
Open your
Terminal
.
Enter the following command to generate a new project:
Terminal
mkdir
expense-tracker-dapp
cd
expense-tracker-dapp
dotnet new aelf
-n
ExpenseTracker
Adding Your Smart Contract Code
Now that we have a template Expense Tracker project, we can customise the template to incorporate our own contract logic.
Let's start by implementing methods to handle the basic functionality of adding an expense, updating a selected expense, deleting a selected expense, list all the expenses, and retrieves the details of a specific expense within the contract state. Expense tracker dApp includes the below functionalities like:
AddExpense: Adds a new expense to the contract state.
UpdateExpense: Updates an existing expense’s details such as description, category, amount, and currency.
DeleteExpense: Deletes an expense based on the given expense ID.
ListExpenses: Lists all expenses associated with a specific owner.
GetExpense: Retrieves the details of a specific expense based on the provided expense ID.
Enter this command in your
Terminal
.
Terminal
cd
src
Defining Methods and Messages
Rename the proto file name
hello_world_contract.proto
inside folder
Protobuf/contract/
to
expense_tracker.proto
:
Terminal
mv
Protobuf/contract/hello_world_contract.proto Protobuf/contract/expense_tracker.proto
The
.proto
file defines the structure and serialization of data, ensuring consistent communication and data exchange between the contract and external systems.
Open the project with your IDE.
The implementation of
expense_tracker.proto
file inside folder
src/Protobuf/contract/
is as follows:
expense_tracker.proto
syntax
=
"proto3"
;
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.ExpenseTracker"
;
service
ExpenseTracker
{
option
(
aelf
.
csharp_state
)
=
"AElf.Contracts.ExpenseTracker.ExpenseTrackerState"
;
option
(
aelf
.
base
)
=
"Protobuf/reference/acs12.proto"
;
rpc
Initialize
(
google
.
protobuf
.
Empty
)
returns
(
google
.
protobuf
.
Empty
)
{
}
rpc
AddExpense
(
ExpenseInput
)
returns
(
google
.
protobuf
.
StringValue
)
{
}
rpc
UpdateExpense
(
ExpenseUpdateInput
)
returns
(
google
.
protobuf
.
Empty
)
{
}
rpc
DeleteExpense
(
google
.
protobuf
.
StringValue
)
returns
(
google
.
protobuf
.
Empty
)
{
}
rpc
ListExpenses
(
google
.
protobuf
.
StringValue
)
returns
(
ExpenseList
)
{
option
(
aelf
.
is_view
)
=
true
;
}
rpc
GetExpense
(
google
.
protobuf
.
StringValue
)
returns
(
Expense
)
{
option
(
aelf
.
is_view
)
=
true
;
}
rpc
GetInitialStatus
(
google
.
protobuf
.
Empty
)
returns
(
google
.
protobuf
.
BoolValue
)
{
option
(
aelf
.
is_view
)
=
true
;
}
}
message
Expense
{
string
expense_id
=
1
;
string
description
=
2
;
string
category
=
3
;
int64
amount
=
4
;
// Store as cents
string
currency
=
5
;
string
owner
=
6
;
int64
created_at
=
7
;
int64
updated_at
=
8
;
}
message
ExpenseInput
{
string
description
=
1
;
string
category
=
2
;
int64
amount
=
3
;
// Store as cents
string
currency
=
4
;
}
message
ExpenseUpdateInput
{
string
expense_id
=
1
;
string
description
=
2
;
string
category
=
3
;
int64
amount
=
4
;
// Store as cents
string
currency
=
5
;
}
message
ExpenseList
{
repeated
Expense
expenses
=
1
;
}
rpc
methods define the callable functions within the contract, allowing external systems to interact with the contract's logic.
message
represent the structured data exchanged between the contract and external systems.
Define Contract States
The implementation of the Expense Tracker smart contract state inside file
src/ExpenseTrackerState.cs
is as follows:
src/ExpenseTrackerState.cs
using
AElf
.
Sdk
.
CSharp
.
State
;
using
AElf
.
Types
;
namespace
AElf
.
Contracts
.
ExpenseTracker
{
public
class
ExpenseTrackerState
:
ContractState
{
public
BoolState
Initialized
{
get
;
set
;
}
public
SingletonState
<
Address
>
Owner
{
get
;
set
;
}
public
MappedState
<
string
,
Expense
>
Expenses
{
get
;
set
;
}
// Mapping of expense ID to Expense
public
MappedState
<
string
,
bool
>
ExpenseExistence
{
get
;
set
;
}
// Mapping to track expense existence
public
StringState
ExpenseIds
{
get
;
set
;
}
// Concatenated string of expense IDs
public
Int32State
ExpenseCounter
{
get
;
set
;
}
// Counter for generating unique IDs
}
}
The
State.cs
file in the aelf blockchain smart contract holds the variables that store the contract's data, making sure this data is saved and accessible whenever the contract needs it.
Implement Expense Tracker Smart Contract
The implementation of the Expense Tracker smart contract inside file
src/ExpenseTracker.cs
is as follows:
src/ExpenseTracker.cs
using
Google
.
Protobuf
.
WellKnownTypes
;
using
System
.
Collections
.
Generic
;
namespace
AElf
.
Contracts
.
ExpenseTracker
{
public
class
ExpenseTracker
:
ExpenseTrackerContainer
.
ExpenseTrackerBase
{
public
override
Empty
Initialize
(
Empty
input
)
{
if
(
State
.
Initialized
.
Value
)
{
return
new
Empty
(
)
;
}
State
.
Initialized
.
Value
=
true
;
State
.
Owner
.
Value
=
Context
.
Sender
;
State
.
ExpenseIds
.
Value
=
""
;
State
.
ExpenseCounter
.
Value
=
0
;
return
new
Empty
(
)
;
}
public
override
StringValue
AddExpense
(
ExpenseInput
input
)
{
if
(
!
State
.
Initialized
.
Value
)
{
return
new
StringValue
{
Value
=
"Contract not initialized."
}
;
}
var
expenseId
=
(
State
.
ExpenseCounter
.
Value
+
1
)
.
ToString
(
)
;
State
.
ExpenseCounter
.
Value
++
;
var
timestamp
=
Context
.
CurrentBlockTime
.
Seconds
;
State
.
Expenses
[
expenseId
]
=
new
Expense
{
ExpenseId
=
expenseId
,
Description
=
input
.
Description
,
Category
=
input
.
Category
,
Amount
=
input
.
Amount
,
// Now using int64 for amount
Currency
=
input
.
Currency
,
CreatedAt
=
timestamp
,
UpdatedAt
=
timestamp
,
Owner
=
Context
.
Sender
.
ToString
(
)
.
Trim
(
'"'
)
,
}
;
State
.
ExpenseExistence
[
expenseId
]
=
true
;
var
existingExpenseIds
=
State
.
ExpenseIds
.
Value
;
existingExpenseIds
+=
string
.
IsNullOrEmpty
(
existingExpenseIds
)
?
expenseId
:
$",
{
expenseId
}
"
;
State
.
ExpenseIds
.
Value
=
existingExpenseIds
;
return
new
StringValue
{
Value
=
expenseId
}
;
}
public
override
Empty
UpdateExpense
(
ExpenseUpdateInput
input
)
{
var
expense
=
State
.
Expenses
[
input
.
ExpenseId
]
;
if
(
expense
==
null
)
{
return
new
Empty
(
)
;
// Handle case if expense doesn't exist
}
expense
.
Description
=
input
.
Description
??
expense
.
Description
;
expense
.
Category
=
input
.
Category
??
expense
.
Category
;
expense
.
Amount
=
input
.
Amount
!=
0
?
input
.
Amount
:
expense
.
Amount
;
// Now using int64 for amount
expense
.
Currency
=
input
.
Currency
??
expense
.
Currency
;
expense
.
UpdatedAt
=
Context
.
CurrentBlockTime
.
Seconds
;
State
.
Expenses
[
input
.
ExpenseId
]
=
expense
;
return
new
Empty
(
)
;
}
public
override
Empty
DeleteExpense
(
StringValue
input
)
{
State
.
Expenses
.
Remove
(
input
.
Value
)
;
State
.
ExpenseExistence
.
Remove
(
input
.
Value
)
;
var
existingExpenseIds
=
State
.
ExpenseIds
.
Value
.
Split
(
','
)
;
var
newExpenseIds
=
new
List
<
string
>
(
existingExpenseIds
.
Length
)
;
foreach
(
var
expenseId
in
existingExpenseIds
)
{
if
(
expenseId
!=
input
.
Value
)
{
newExpenseIds
.
Add
(
expenseId
)
;
}
}
State
.
ExpenseIds
.
Value
=
string
.
Join
(
","
,
newExpenseIds
)
;
return
new
Empty
(
)
;
}
public
override
ExpenseList
ListExpenses
(
StringValue
input
)
{
var
owner
=
input
.
Value
;
// Get the owner value from the input
var
expenseList
=
new
ExpenseList
(
)
;
var
expenseIds
=
State
.
ExpenseIds
.
Value
.
Split
(
','
)
;
foreach
(
var
expenseId
in
expenseIds
)
{
var
expense
=
State
.
Expenses
[
expenseId
]
;
if
(
expense
!=
null
&&
expense
.
Owner
==
owner
)
// Filter expenses by owner
{
expenseList
.
Expenses
.
Add
(
expense
)
;
}
}
return
expenseList
;
}
public
override
Expense
GetExpense
(
StringValue
input
)
{
var
expense
=
State
.
Expenses
[
input
.
Value
]
;
if
(
expense
==
null
)
{
return
new
Expense
{
ExpenseId
=
input
.
Value
,
Description
=
"Expense not found."
}
;
}
return
expense
;
}
public
override
BoolValue
GetInitialStatus
(
Empty
input
)
{
return
new
BoolValue
{
Value
=
State
.
Initialized
.
Value
}
;
}
}
}
Building Smart Contract
Build the smart contract code with the following command inside
src
folder:
Terminal
dotnet build
You should see
ExpenseTracker.dll.patched
in the directory
ExpenseTracker/src/bin/Debug/net.6.0
Step 3 - Deploy Smart Contract
Create A Wallet
To send transactions on the aelf blockchain, you must have a wallet.
Run this command to create aelf wallet.
Terminal
aelf-command create
You will be prompted to save your account, please do
save
your account as shown below:
Terminal
? Save account info into a file?
(
Y/n
)
Y
Make sure to choose Y to save your account information.
tip
ℹ️ Note: If you do not save your account information (by selecting n or N), do not export the wallet password. Only
proceed to the next
step if you have saved your account information.
Next, enter and confirm your password. Then export your wallet password as shown below:
Linux and macOs
Windows
Terminal
export
WALLET_PASSWORD
=
"YOUR_WALLET_PASSWORD"
Command Prompt
$env
:WALLET_PASSWORD
=
"YOUR_WALLET_PASSWORD"
Acquire Testnet Tokens (Faucet) for Development
To deploy smart contracts or execute on-chain transactions on aelf, you'll require testnet ELF tokens.
Get ELF Tokens
Go to
https://faucet-ui.aelf.dev
Enter your address and click
Get Tokens
.
Deploy Smart Contract:
The smart contract needs to be deployed on the chain before users can interact with it.
Run the following command to deploy a contract. Remember to export the path of ExpenseTracker.dll.patched to CONTRACT_PATH.
Linux and macOs
Windows
Terminal
export
CONTRACT_PATH
=
$(
find
~+
.
-path
"*patched*"
|
head
-n
1
)
Terminal
ael프로젝트로 돌아가기