编写忠诚度智能合约
现在您已经设置了开发环境,让我们开始编写智能合约。
现在让我们开始编写代码:
编写忠诚度合约
导航到 sources/loyalty.move
。让我们逐行查看您将要编写的代码:
首先, metaschool
是包名称。它应该与我们使用命令 sui move new metaschool
初始化 Sui 工作区的文件夹名称相同。因此,如果您使用了任何其他名称,请务必在此处替换它。此外, loyalty
是模块名称。因此,如果您将其命名为 loyalty
之外的其他名称,请务必在此处进行更新。
#![allow(unused)] fn main() { module loyalty::loyalty }
- 此行定义了一个名为
metaschool::loyalty
的模块,它将包含忠诚度合同的实现。模块是一种组织代码并将相关功能分组在一起的方法。
#![allow(unused)] fn main() { use sui::clock::Clock; use sui::object::{Self, UID}; use sui::coin::{Self, Coin}; use sui::tx_context::TxContext; use sui::balance::{Self, Balance}; use deepbook::clob_v2::Pool; use deepbook::custodian_v2::AccountCap; use dex::eth::ETH; use dex::usdc::USDC; use dex::dex::{Self, DEX, Storage}; }
- 在这里,我们导入包含要在代码中使用的预构建函数和类型的模块。
#![allow(unused)] fn main() { public struct LoyaltyAccount has key, store { id: UID, stake: Balance<DEX>, points: u64 } public struct NFT has key, store { id: UID } }
- 现在我们定义了一个对象,其中包含程序中质押的 DEX 币数量以及每次交换累积的积分数量的信息。
现在让我们创建一个函数 create_account
,它创建一个帐户对象来跟踪用户积分和赌注金额,如下所示:
#![allow(unused)] fn main() { public fun create_account(ctx: &mut TxContext): LoyaltyAccount { LoyaltyAccount { id: object::new(ctx), stake: balance::zero(), points: 0 } } }
- 我们将创建另一个函数
loyalty_account_stake
,它允许模块读取LoyaltyAccount
中质押的 DEX 代币数量。我们还将创建一个函数loyalty_account_points
来读取LoyaltyAccount
中的点数。
#![allow(unused)] fn main() { public fun loyalty_account_stake(account: &LoyaltyAccount): u64 { balance::value(&account.stake) } public fun loyalty_account_points(account: &LoyaltyAccount): u64 { account.points } }
- 接下来,我们将创建一个 get_reward 函数,该函数向用户铸造 NFT,以换取 5 个积分。我们还需要确保在 NFT 铸币之后,这 5 个积分会从用户的账户中扣除。
#![allow(unused)] fn main() { public fun get_reward(account: &mut LoyaltyAccount, ctx: &mut TxContext): NFT { assert!(account.points >= 5, ENeeds5Points); let points_ref = &mut account.points; *points_ref = *points_ref - 5; NFT { id: object::new(ctx) } } }
- 最后,我们正在创建一个用于质押 DEX 币并赚取奖励的功能,如下所示:
#![allow(unused)] fn main() { public fun stake( account: &mut LoyaltyAccount, stake: Coin<DEX> ) { balance::join(&mut account.stake, coin::into_balance(stake)); } public fun unstake( account: &mut LoyaltyAccount, ctx: &mut TxContext ): Coin<DEX> { let value = loyalty_account_stake(account); coin::take(&mut account.stake, value, ctx) } public fun place_market_order( account: &mut LoyaltyAccount, self: &mut Storage, pool: &mut Pool<ETH, USDC>, account_cap: &AccountCap, quantity: u64, is_bid: bool, base_coin: Coin<ETH>, quote_coin: Coin<USDC>, c: &Clock, ctx: &mut TxContext, ): (Coin<ETH>, Coin<USDC>, Coin<DEX>) { let (eth, usdc, coin_dex) = dex::place_market_order(self, pool, account_cap, quantity, is_bid, base_coin, quote_coin, c, ctx); if (loyalty_account_stake(account) != 0) { let points_ref = &mut account.points; *points_ref = *points_ref + 1; }; (eth, usdc, coin_dex) } }
我们已成功创建忠诚度合同。
完整代码
最终合同应如下所示:
module loyalty::loyalty {
use sui::clock::Clock;
use sui::object::{Self, UID};
use sui::coin::{Self, Coin};
use sui::tx_context::TxContext;
use sui::balance::{Self, Balance};
use deepbook::clob_v2::Pool;
use deepbook::custodian_v2::AccountCap;
use dex::eth::ETH;
use dex::usdc::USDC;
use dex::dex::{Self, DEX, Storage};
const ENeeds5Points: u64 = 0;
public struct LoyaltyAccount has key, store {
id: UID,
// Amount of DEX Coin staked in the program
stake: Balance<DEX>,
// Amount of points accumulated per swap
points: u64
}
public struct NFT has key, store {
id: UID
}
// @dev It creates an account object to keep track of a user points and stake amount
public fun create_account(ctx: &mut TxContext): LoyaltyAccount {
LoyaltyAccount {
id: object::new(ctx),
stake: balance::zero(),
points: 0
}
}
// @dev It allows a module to read the amount of DEX coins staked in an `LoyaltyAccount`
public fun loyalty_account_stake(account: &LoyaltyAccount): u64 {
balance::value(&account.stake)
}
// @dev It allows a module to read the number of points in a `LoyaltyAccount`
public fun loyalty_account_points(account: &LoyaltyAccount): u64 {
account.points
}
// @dev It mints an NFT to the user in exchange for 5 points
public fun get_reward(account: &mut LoyaltyAccount, ctx: &mut TxContext): NFT {
// Make sure he has at least 5 points
assert!(account.points >= 5, ENeeds5Points);
// Deduct 5 points
let points_ref = &mut account.points;
*points_ref = *points_ref - 5;
// Mint the reward
NFT {
id: object::new(ctx)
}
}
public fun stake(
account: &mut LoyaltyAccount,
stake: Coin<DEX>
) {
// Deposit the coin in the contract
balance::join(&mut account.stake, coin::into_balance(stake));
}
public fun unstake(
account: &mut LoyaltyAccount,
ctx: &mut TxContext
): Coin<DEX> {
// Save the total balance amount in memory
let value = loyalty_account_stake(account);
// unstake the balance into a coin
coin::take(&mut account.stake, value, ctx)
}
// @ User can swap via the program to earn points
public fun place_market_order(
account: &mut LoyaltyAccount,
self: &mut Storage,
pool: &mut Pool<ETH, USDC>,
account_cap: &AccountCap,
quantity: u64,
is_bid: bool,
base_coin: Coin<ETH>,
quote_coin: Coin<USDC>,
c: &Clock,
ctx: &mut TxContext,
): (Coin<ETH>, Coin<USDC>, Coin<DEX>) {
let (eth, usdc, coin_dex) = dex::place_market_order(self, pool, account_cap, quantity, is_bid, base_coin, quote_coin, c, ctx);
// If the user has 0 DEX tokens staked he earns no points
if (loyalty_account_stake(account) != 0) {
// Borrow mut
let points_ref = &mut account.points;
// Increment
*points_ref = *points_ref + 1;
};
(eth, usdc, coin_dex)
}
// @dev It allows a test file to destroy the Loyalty Account object
#[test_only]
public fun destroy_account_for_testing(account: LoyaltyAccount) {
// @dev Properties without the drop ability must be destroyed via their libraries
let LoyaltyAccount { id, stake, points: _ } = account;
balance::destroy_for_testing(stake);
object::delete(id);
}
// @dev It allows a test file to destroy the NFT object
#[test_only]
public fun destroy_nft_for_testing(nft: NFT) {
let NFT { id} = nft;
object::delete(id);
}
}
小结
恭喜您完成忠诚合约。从这里开始只会变得更有趣!接下来,我们将部署我们的合约。下一节见