入门 Sui Move 开发:7. 实现一个简单的兑换合约

  • greyhao
  • 发布于 1天前
  • 阅读 204

在 Sui 上实现一个简单的币对兑换合约。

如果你是初学者,强烈建议看下前几节内容:

入门 Sui Move 开发:1. 环境安装 

 入门 Sui Move 开发:2. 常用命令、编写并发布 Hello World 合约

入门 Sui Move 开发:3. Sui Move 语法和设计模式 

入门 Sui Move 开发:4. Sui Move 中集合、对象、泛型、动态字段

入门 Sui Move 开发:5. 发布同质化代币 — NFT

入门 Sui Move 开发:6. 发布一个小游戏合约

内容概览

本节将完成一组固定币对兑换的合约。代码方面主要还是 coinbalance 模块的使用。更多细节可以看以下代码注释。

兑换步骤

以现实生活中去银行换美元为例,需要有以下步骤:

现实兑换 合约兑换
预约换汇 创建池子
银行准备美元 池子中添加币
人到银行,给出人民币并得到等值美元 将币种 A 放入池子,池子将等值的币种 B 转出给用户

通过以上步骤,我们的合约中大概需要:

  • 兑换池-- 包含可以兑换的币种数量
  • 给兑换池中添加币
  • 币种的兑换汇率
  • 兑换币种
  • 从池子里提取币种

合约代码

下面合约中可以兑换的币对可以替换成自己的币合约。

/// Module: swap_greyhao
/// A SAMPLE SWAP CONTRACT
module swap_greyhao::swap_greyhao {
  /*
  实现思路:
  兑换需要有兑换池;兑换池包含可以兑换的coin;---》 所以需要 SwapPool 结构体
  池子默认需要添加一些币,然后才能正常兑换;---》所以需要 add_xx_to_pool 方法
  任何人都可以加池子或在池子里兑换,但是只有管理员可以提取(真实合约并不是这样);---》所以需要 Admin 结构体,提现的时候检验权限
  管理员可以从池子里提取;---》 withdraw_xx_from_pool 方法
  初始化的时候需要创建好池子;---》 init 方法中初始化 SwapPool、Admin
  兑换有汇率可以先固定值 5;
  兑换:根据汇率将 A 兑换成等值的 B,并转给兑换者;---》 swap_xx 方法
*/

  use coin_greyhao::greyhaocoin::GREYHAOCOIN;
  use coin_greyhao::greyhaofaucet::GREYHAOFAUCET;
  use sui::balance::{Balance, zero};
  use sui::coin::{Coin, from_balance};
  use sui::transfer::{share_object, transfer, public_transfer};

  const EPOOLINSUFFICIENTBALANCE: u64 = 0;
  const EUSERINSUFFICIENTBALANCE: u64 = 1;

  public struct SwapPool has key {
    id: UID,
    coin: Balance<GREYHAOCOIN>,
    faucet_coin: Balance<GREYHAOFAUCET>
  }

  public struct Admin has key {
    id: UID,
  }

  // 初始化
  fun init(ctx: &mut TxContext) {
    // 创建池子
    let swapPool = SwapPool {
      id: object::new(ctx),
      coin: zero(),
      faucet_coin: zero(),
    };
    share_object(swapPool);

    // 设置提现权限
    let admin = Admin {
      id: object::new(ctx)
    };
    transfer(admin, ctx.sender());
  }

  // 添加 coin 到池子
  public entry fun add_coin_to_pool(swap_pool: &mut SwapPool, in_coin: &mut Coin<GREYHAOCOIN>, amount: u64, ctx: &mut TxContext) {
    let in_obj = in_coin.split(amount, ctx);
    swap_pool.coin.join(in_obj.into_balance());
  }

  public entry fun add_faucet_to_pool(swap_pool: &mut SwapPool, in_coin: &mut Coin<GREYHAOFAUCET>, amount: u64, ctx: &mut TxContext) {
    let in_obj = in_coin.split(amount, ctx);
    swap_pool.faucet_coin.join(in_obj.into_balance());
  }

  // 币兑换水龙头币
  public entry fun swap_to_faucet(swap_pool: &mut SwapPool, in_coin: &mut Coin<GREYHAOCOIN>, amount: u64, ctx: &mut TxContext) {
    assert!(in_coin.value() >= amount, EUSERINSUFFICIENTBALANCE);
    let swap_obj = in_coin.split(amount, ctx);
    // 需要转出的数量
    let out_amount = amount * 5;
    assert!(swap_pool.faucet_coin.value() >= out_amount, EPOOLINSUFFICIENTBALANCE);
    // 用户的币转入池子
    swap_pool.coin.join(swap_obj.into_balance());
    // 池子的币转给用户
    let out_balance = swap_pool.faucet_coin.split(out_amount);
    public_transfer(from_balance(out_balance, ctx), ctx.sender());
  }

  // 水龙头币兑换币
  public entry fun swap_to_coin(swap_pool: &mut SwapPool, in_coin: &mut Coin<GREYHAOFAUCET>, amount: u64, ctx: &mut TxContext) {
    assert!(in_coin.value() >= amount, EUSERINSUFFICIENTBALANCE);
    //分割要兑换的币(真实情况可能是前端处理好)
    let in_obj = in_coin.split(amount, ctx);
    // 需要转出的数量
    let out_amount = amount / 5;
    assert!(swap_pool.coin.value() >= out_amount, EPOOLINSUFFICIENTBALANCE);
    // 用户的币转入池子
    swap_pool.faucet_coin.join(in_obj.into_balance());
    // 池子的币转给用户
    let out_balance = swap_pool.coin.split(out_amount);
    let out_coin = from_balance(out_balance, ctx);
    public_transfer(out_coin, ctx.sender());
  }

  // 管理员从池子里提取
  public entry fun withdraw_coin_from_pool(_: &Admin, swap_pool: &mut SwapPool, amount: u64, ctx: &mut TxContext) {
    assert!(swap_pool.coin.value() >= amount, EUSERINSUFFICIENTBALANCE);
    let outBalance = swap_pool.coin.split(amount);
    public_transfer(from_balance(outBalance, ctx), ctx.sender());
  }

  public entry fun withdraw_faucet_from_pool(_: &Admin, swap_pool: &mut SwapPool, amount: u64, ctx: &mut TxContext) {
    assert!(swap_pool.faucet_coin.value() >= amount, EUSERINSUFFICIENTBALANCE);
    let out_b = swap_pool.faucet_coin.split(amount);
    let out_c = from_balance(out_b, ctx);
    public_transfer(out_c, ctx.sender());
  }

}

如果觉得本节内容对你有所帮助,可以点赞鼓励下。

如果你对文章中内容有任何疑问可以留言。

点赞 0
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
greyhao
greyhao
Sui 合约开发打怪升级中 & 多年前端/手机端开发 & 低成本撸毛选手 欢迎一起学习交流