Sui Move 实现一个简单的店铺买卖模型 —— Simple Buy-Sell Module

  • Nigdle
  • 更新于 2024-04-16 16:41
  • 阅读 918

Sui Move 实现一个简单的店铺买卖模型 —— Simple Buy-Sell Module

一:功能简介

一个简单的店铺买卖只涉及了买家和卖家,买家只有购买这一个动作,而卖家则需要支持货品上架、更新、产品迭代等基础功能。

二:结构设计

2.1 商店

商店的部分信息应当是公开透明的,尤其是产品相关,甚至是营业额,但是这个权限又不能放得太开,否则所有人都可以操作这家店铺。<br>所以,我们用ShopCap来限定权限,其所有者就是店铺拥有者,只有手握对应令牌的人,才可以对店铺进行深度操作(货品上架、下架、信息修改、提现等);而Shop的相关信息则是直接面向所有人,所有人都可以查看店铺信息,特别是其中的产品信息,而这些人没有ShopCap,所以不用担心他人提现等安全问题。

ShopCap结构当中不需要过多的内容,只要有一个UID让其能够被拥有即可。<br>Shop当中最为关键的自然是余额balance以及产品commodity如何进行存储的问题,前者有 $\mathit {Sui}\ \mathit {Move}$ 提供的货币相关的库,而后者我们在这里选用动态数组 $\mathit {vector}$ 来存储产品信息。这里应该有更好的选择,但本着学习实践的原则还是选择了它,因为其它的一些数据结构,像是table甚至是linked_table在前篇都有用过

public struct ShopCap has key {
    id: UID,
}

public struct Shop has key {
    id: UID,
    name: String,
    balance: Balance&lt;SUI>,
    commodity: vector&lt;Item>,
}

vector当中的每一个元素都是Item类型,这是我们自定义的一个结构,它存储了每一个产品的信息,这里最主要的是库存和价格。<br>它只需要被存储,所以赋予store能力,由于其中的属性都很简单,所以加上了drop能力使其能够在被抛弃时自动解构。<br>id作为每一个产品的唯一标识,同时也是顾客购买时用来对应自己想要买的究竟是哪一个产品的唯一途径。

public struct Item has store, drop {
    id: ID,
    name: String,
    introduction: String,
    stock: u64,
    price: u64,
}

2.2 顾客

顾客的信息其实没什么需要记录的,在本篇内容当中,我们只需要一个新建一个Product并将其所有权传给顾客,以此来代表该顾客购买了某一件产品,当然,Product结构当中需要存储对应产品的相关信息。

public struct Product has key {
    id: UID,
    item_id: ID,
    name: String,
    introduction: String,
}

三:功能实现

3.1 商店

3.1.1 创建商店

不仅要创建Shop,同时还要创建ShopCap,前者所有人共享可见,而后者只属于店主。

entry fun create_shop(name: String, ctx: &mut TxContext) {
    // only ShopCap holders can make subsequent modifications to the shop
    transfer::transfer(ShopCap {id: object::new(ctx)}, tx_context::sender(ctx));

    // anyone can view shop information
    transfer::share_object(Shop {
        id: object::new(ctx),
        name,
        balance: balance::zero(),
        commodity: vector::empty&lt;Item>(),
    });
}

3.1.2 提现

只有拥有对应ShopCap的店家才可以进行提现,前提是店铺当中的余额balance大于零。

entry fun withdraw(_shop_cap: &ShopCap, shop: &mut Shop, ctx: &mut TxContext) {
    // assert the balance
    assert!(shop.balance.value() > 0, ErrNotBalance);

    // take all balance
    let all = shop.balance.withdraw_all();

    // transfer the coin
    transfer::public_transfer(coin::from_balance(all, ctx), tx_context::sender(ctx));
}

3.1.3 注销店铺

注销店铺时需要注意,ShopCap也需要注销,因为店铺不存在了,其对应的凭证权限也没了用处,与此同时,在处理Shop的时候别忘记摧毁balancevector,其中如果仍有值,需要先进行处理,使其为空。<br>在其它大多数情况下,如果不满足空的条件可以直接assert进行报错,得益于交易的原子性,一切都会恢复到交易之前的状态,而在本篇当中,一切都很简单,所以可以直接处理。

entry fun destroy_shop(shop_cap: ShopCap, mut shop: Shop, ctx: &mut TxContext) {
    // withdraw
    if (shop.balance.value() > 0) {
        withdraw(&shop_cap, &mut shop, ctx);
    };

    // destroy ShopCap
    let ShopCap {id} = shop_cap;
    object::delete(id);

    // destroy Shop
    let Shop {
        id,
        name: _,
        balance,
        mut commodity,
    } = shop;
    object::delete(id);
    // destroy balance
    balance.destroy_zero();
    // destroy vector
    while (commodity.length() > 0) {
        commodity.pop_back();
    };
    commodity.destroy_empty();
}

3.1.4 上架新品

提供新品信息,将其存入Shop当中的commodity里,顾客后续就可以通过Shop进行查看。<br>这里的关键是ID如何进行获取,我们采用源码当中UID生成的类似方式,借助tx_context库中的fresh_object_address函数,根据ctx生成唯一的address,再用address自带的to_id函数来将其转变为ID

entry fun create_item(
    _shop_cap: &ShopCap,
    shop: &mut Shop,
    name: String,
    introduction: String,
    stock: u64,
    price: u64,
    ctx: &mut TxContext
) {
    // create Item
    let item = Item {
        id: tx_context::fresh_object_address(ctx).to_id(), // address.to_id()
        name,
        introduction,
        stock,
        price,
    };

    // store it
    shop.commodity.push_back(item);
}

3.1.5 更新库存

根据ID来确定究竟需要更新的是哪一个产品,通过遍历vector来确认。<br>当货架上的品类很多很多的时候,遍历这一操作可能会消耗大量的gas,这也是上面提到的,可以使用更适配的数据结构的原因之一,不过在初学者阶段,多用用相关的结构调用也是必要的。

entry fun modify_stock(_shop_cap: &ShopCap, shop: &mut Shop, id: ID, stock: u64) {
    let mut i = 0;
    let mut modify_success = false;

    while (i &lt; shop.commodity.length()) {
        let item = &mut shop.commodity[i];

        // check if the correct item
        if (id != item.id) {
            i = i + 1;
            continue
        };

        // modify the stock and break this while
        modify_success = true;
        item.stock = stock;
        break
    };

    // assert success
    assert!(modify_success, ErrNotItem);
}

3.1.6 下架产品

类似的,也是通过ID来匹配删除。

entry fun remove_item(_shop_cap: &ShopCap, shop: &mut Shop, id: ID) {
    let mut i = 0;
    let mut modify_success = false;

    while (i &lt; shop.commodity.length()) {
        let item = &mut shop.commodity[i];

        // check if the correct item
        if (id != item.id) {
            i = i + 1;
            continue
        };

        // remove the item and break this while
        modify_success = true;
        shop.commodity.remove(i);
        break
    };

    // assert success
    assert!(modify_success, ErrNotItem);
}

3.2 顾客

在这里,顾客单独写了一个module,不要忘记在里面通过use simple_buy_sell::shop::Shop将上述的shop引入。<br>为了更好地撰写顾客的购买功能,我们先在shop.move当中添加两个辅助函数,也就是下面的 $\text {3.2.1}$ 和 $\text {3.2.2}$,至于原因呢,就是在不同的module中,不可以直接通过.的方式来获取对应结构体对象当中的值。如果你在自主实现的时候写在用一份文件当中,可以忽略这一点

3.2.1 获取产品信息

根据顾客挑选的ID匹配后返回对应商品的信息,在本篇当中最重要的就是其价格,当然,前提是对应的商品库存非零,同时令对应的库存减一。<br>当返回的值不只一个的时候,用()将它们括起来,中间用逗号分隔。

public fun get(shop: &mut Shop, id: ID): (String, String, u64) {
    let mut i = 0;
    while (i &lt; shop.commodity.length() && shop.commodity[i].id != id) {
        i = i + 1;
    };

    // assert the correct item id
    assert!(i &lt; shop.commodity.length(), ErrNotItem);

    let item = &mut shop.commodity[i];
    // assert the stock
    assert!(item.stock > 0, ErrNotEnoughItem);
    // decrease the stock
    item.stock = item.stock - 1;

    // return
    (item.name, item.introduction, item.price)
}

3.2.2 余额合并

当用户提供的Coin&lt;SUI>充足的时候(大于产品价格),将其分割出对应price的值合并到Shop当中的余额。

public fun join(shop: &mut Shop, coin: Coin&lt;SUI>) {
    shop.balance.join(coin.into_balance());
}

3.2.3 购买

有了上面两个辅助函数,购买功能的实现就只剩下了Product创建并移交所有权,当然,过程当中传入的Coin&lt;SUI>需要做后续处理(剩余余额为零时摧毁,否则交还给顾客)。

entry fun buy(shop: &mut Shop, item_id: ID, mut sui: Coin&lt;SUI>, ctx: &mut TxContext) {
    let (name, introduction, price) = shop.get(item_id);

    // assert the coin value
    assert!(sui.value() >= price, ErrNotEnoughPrice);

    // transfer coin
    let pay_coin = sui.split(price, ctx);
    shop.join(pay_coin);

    // deal with remaining currency
    if (sui.value() == 0) {
        sui.destroy_zero();
    } else {
        transfer::public_transfer(sui, tx_context::sender(ctx));
    };

    // get the product
    transfer::transfer(Product {
        id: object::new(ctx),
        item_id,
        name,
        introduction,
    }, tx_context::sender(ctx));
}

在老版本的 $\mathit {Sui}\ \mathit {Move}$ 当中,这个写法sui: Coin&lt;SUI>得到的传入的值是可变的,但是在 $\text {2024}$ 新版本当中是不可变的,所以才需要在前面加mut来修饰。<br>类似的,在变量赋值的时候也是这样,例如:let i = 0以及let mut i = 0,在前面的循环当中为什么用后者就是这个原因。<br>不过,这个mut并不会让所有权变得更加复杂,还是如老版本一致。

四:链上部署并交互

4.1 发布

  • 运行命令

sui client publish --gas-budget 100000000

  • 重要输出
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes                                                                                   │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects:                                                                                 │
│  ┌──                                                                                             │
│  │ ObjectID: 0xd1e438b61bc067fe1dd982b0a0d0d7ec8a4e5b14d70fb0bdc181f53d5cb49845                  │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                    │
│  │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│  │ ObjectType: 0x2::package::UpgradeCap                                                          │
│  │ Version: 28131879                                                                             │
│  │ Digest: 84ZDVcf2Sj4orHDK7xx9YqKqJHHaKiSoSdjy8vCMzUUv                                          │
│  └──                                                                                             │
│ Mutated Objects:                                                                                 │
│  ┌──                                                                                             │
│  │ ObjectID: 0x266848e4e91a7a43a72b63f20760e1341e81f8970d8201a792a48959dfe2e0b9                  │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                    │
│  │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 ) │
│  │ ObjectType: 0x2::coin::Coin&lt;0x2::sui::SUI>                                                    │
│  │ Version: 28131879                                                                             │
│  │ Digest: 8bs9kriYfaUafxLRQ9iH8q584UHdQjxkWAZQ1u1xXwxH                                          │
│  └──                                                                                             │
│ Published Objects:                                                                               │
│  ┌──                                                                                             │
│  │ PackageID: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad                 │
│  │ Version: 1                                                                                    │
│  │ Digest: 5kHUEVJQKee9uBf1m6AuT27EBGuRizKzjRMhVwbA8swe                                          │
│  │ Modules: cuntomer, shop                                                                       │
│  └──                                                                                             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
  • 添加环境变量

export PACKAGE_ID=0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad

4.2 创建商店

  • 运行命令

sui client call --package $PACKAGE_ID --module shop --function create_shop --args my_first_shop --gas-budget 10000000

  • 重要输出
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes                                                                                    │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects:                                                                                  │
│  ┌──                                                                                              │
│  │ ObjectID: 0x1168e00b20902a8c3148794c72c526677aaded597c823f6245ccc455ea11d1e4                   │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                     │
│  │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 )  │
│  │ ObjectType: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::ShopCap  │
│  │ Version: 28131880                                                                              │
│  │ Digest: 3MZNgei3UmzZWRBoLgTh2z313Rt8HF9Whs6P1xrhLFwh                                           │
│  └──                                                                                              │
│  ┌──                                                                                              │
│  │ ObjectID: 0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779                   │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                     │
│  │ Owner: Shared                                                                                  │
│  │ ObjectType: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop     │
│  │ Version: 28131880                                                                              │
│  │ Digest: JABUj677UPKV8HKy11Bc8F9qhobi97mmsa1eRzZWPWfB                                           │
│  └──                                                                                              │
│ Mutated Objects:                                                                                  │
│  ┌──                                                                                              │
│  │ ObjectID: 0x266848e4e91a7a43a72b63f20760e1341e81f8970d8201a792a48959dfe2e0b9                   │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                     │
│  │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 )  │
│  │ ObjectType: 0x2::coin::Coin&lt;0x2::sui::SUI>                                                     │
│  │ Version: 28131880                                                                              │
│  │ Digest: 8s7n8Puq6GZQRUyHArdh7GJzHB6G44XUgiKggwQgw6E7                                           │
│  └──                                                                                              │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
  • 添加环境变量
export SHOPCAP=0x1168e00b20902a8c3148794c72c526677aaded597c823f6245ccc455ea11d1e4
export SHOP=0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779

4.3 上架新品

  • 运行命令

sui client call --package $PACKAGE_ID --module shop --function create_item --args $SHOPCAP $SHOP my_first_product first_product_desc 1 369963 --gas-budget 10000000

  • 重要输出
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes                                                                                    │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Mutated Objects:                                                                                  │
│  ┌──                                                                                              │
│  │ ObjectID: 0x1168e00b20902a8c3148794c72c526677aaded597c823f6245ccc455ea11d1e4                   │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                     │
│  │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 )  │
│  │ ObjectType: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::ShopCap  │
│  │ Version: 28131881                                                                              │
│  │ Digest: 8MjbJQRSDTRbyyNWt5AVEA2itSbbuAixZmqPnnxM775B                                           │
│  └──                                                                                              │
│  ┌──                                                                                              │
│  │ ObjectID: 0x266848e4e91a7a43a72b63f20760e1341e81f8970d8201a792a48959dfe2e0b9                   │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                     │
│  │ Owner: Account Address ( 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67 )  │
│  │ ObjectType: 0x2::coin::Coin&lt;0x2::sui::SUI>                                                     │
│  │ Version: 28131881                                                                              │
│  │ Digest: Gz8L5KXeDGveZVW7icq8Ew9qdZSKTUKkfh4QZsvoM2dc                                           │
│  └──                                                                                              │
│  ┌──                                                                                              │
│  │ ObjectID: 0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779                   │
│  │ Sender: 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67                     │
│  │ Owner: Shared                                                                                  │
│  │ ObjectType: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop     │
│  │ Version: 28131881                                                                              │
│  │ Digest: DbpXTbKxnFccBTZswxDJz9cLPVbQnesF3dEqzkUFE7RB                                           │
│  └──                                                                                              │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
  • 查看Shop
sui client object $SHOP

# output:
╭───────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ objectId      │  0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779                                                                              │
│ version       │  28131881                                                                                                                                        │
│ digest        │  DbpXTbKxnFccBTZswxDJz9cLPVbQnesF3dEqzkUFE7RB                                                                                                    │
│ objType       │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop                                                                  │
│ owner         │ ╭────────┬─────────────────────────────────────────╮                                                                                             │
│               │ │ Shared │ ╭────────────────────────┬────────────╮ │                                                                                             │
│               │ │        │ │ initial_shared_version │  28131880  │ │                                                                                             │
│               │ │        │ ╰────────────────────────┴────────────╯ │                                                                                             │
│               │ ╰────────┴─────────────────────────────────────────╯                                                                                             │
│ prevTx        │  4ctXs8jppLhFYFAtidr2YgAmT6VHNrgu6W34MTJTeSRo                                                                                                    │
│ storageRebate │  2067200                                                                                                                                         │
│ content       │ ╭───────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│               │ │ dataType          │  moveObject                                                                                                              │ │
│               │ │ type              │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop                                          │ │
│               │ │ hasPublicTransfer │  false                                                                                                                   │ │
│               │ │ fields            │ ╭───────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │
│               │ │                   │ │ balance   │  0                                                                                                       │ │ │
│               │ │                   │ │ commodity │ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │
│               │ │                   │ │           │ │ ╭────────┬─────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ │
│               │ │                   │ │           │ │ │ type   │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Item         │ │ │ │ │
│               │ │                   │ │           │ │ │ fields │ ╭──────────────┬──────────────────────────────────────────────────────────────────────╮ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ id           │  0x3b808241908b5d2cf4dbbc66cfc0b519eb9bd7ed7f8974d833dc2c085c07340d  │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ introduction │  first_product_desc                                                  │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ name         │  my_first_product                                                    │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ price        │  369963                                                              │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ stock        │  1                                                                   │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ ╰──────────────┴──────────────────────────────────────────────────────────────────────╯ │ │ │ │ │
│               │ │                   │ │           │ │ ╰────────┴─────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │
│               │ │                   │ │           │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │
│               │ │                   │ │ id        │ ╭────┬──────────────────────────────────────────────────────────────────────╮                            │ │ │
│               │ │                   │ │           │ │ id │  0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779  │                            │ │ │
│               │ │                   │ │           │ ╰────┴──────────────────────────────────────────────────────────────────────╯                            │ │ │
│               │ │                   │ │ name      │  my_first_shop                                                                                           │ │ │
│               │ │                   │ ╰───────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │
│               │ ╰───────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
  • 记录ID

export ITEMID=0x3b808241908b5d2cf4dbbc66cfc0b519eb9bd7ed7f8974d833dc2c085c07340d

4.4 购买

  • 切换用户

sui client switch --address &lt;alias>

  • 记录Coin
sui client gas

# choose one of the CoinIDs which the balance is enough to purchase
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId                                                          │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x516586df0c5e9c9567696840981f720d64335ac6e8ad409f4ba4843b8dc2274a │ 100                │ 0.00             │
│ 0x82ec01655d746b42dba5c5951841472e5d1715e74238a5ef8e39d0b0566dc3be │ 996585540          │ 0.99             │
│ 0x8ef6503cb330c4114bc7995a403adf4015190d8effc02504fd849377caa6499b │ 967262964          │ 0.96             │
│ 0xad3fa2545f5db01bd4d349871df5af4d6de913600e7e3e032d5229c006d35851 │ 100                │ 0.00             │
│ 0xcb24b30fe196f4f2ca6d5f8d87a273bf168f7f86f6b7ae3f1f20fc5cf447e557 │ 990920960          │ 0.99             │
│ 0xe4f2d7831241583d534271d8d777d7558290124779e98e03b059a2fe108d37b0 │ 989                │ 0.00             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

# export it
export COIN=0x82ec01655d746b42dba5c5951841472e5d1715e74238a5ef8e39d0b0566dc3be
  • 运行命令

sui client call --package $PACKAGE_ID --module cuntomer --function buy --args $SHOP $ITEMID $COIN --gas-budget 10000000

注意: 到这里才发现顾客代码最上面的模块名customer打成了cuntomer,既然事已至此,只能先吃饭了哦不,先调用了┭┮﹏┭┮(以后注意)

  • 重要输出
╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes                                                                                        │
├───────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects:                                                                                      │
│  ┌──                                                                                                  │
│  │ ObjectID: 0x254bf6a1d6eba45c4c46493c416d743c616d7d8839dafd21c6ea55fa0fa20a43                       │
│  │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b                         │
│  │ Owner: Account Address ( 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b )      │
│  │ ObjectType: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::cuntomer::Product  │
│  │ Version: 28131882                                                                                  │
│  │ Digest: 56giajkY6hdUFxLd5jrdjquWYV4ZypLLuJFQvVk6rAgj                                               │
│  └──                                                                                                  │
│ Mutated Objects:                                                                                      │
│  ┌──                                                                                                  │
│  │ ObjectID: 0x82ec01655d746b42dba5c5951841472e5d1715e74238a5ef8e39d0b0566dc3be                       │
│  │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b                         │
│  │ Owner: Account Address ( 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b )      │
│  │ ObjectType: 0x2::coin::Coin&lt;0x2::sui::SUI>                                                         │
│  │ Version: 28131882                                                                                  │
│  │ Digest: DKfyM1wsnx4u9zDMqqBeLbW8nctRhPyhJqgxcjgHQLzy                                               │
│  └──                                                                                                  │
│  ┌──                                                                                                  │
│  │ ObjectID: 0x8ef6503cb330c4114bc7995a403adf4015190d8effc02504fd849377caa6499b                       │
│  │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b                         │
│  │ Owner: Account Address ( 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b )      │
│  │ ObjectType: 0x2::coin::Coin&lt;0x2::sui::SUI>                                                         │
│  │ Version: 28131882                                                                                  │
│  │ Digest: 8oHBrgmZKnp69nkivc7xTB8kEHde9cMchyVGh1A3tjAS                                               │
│  └──                                                                                                  │
│  ┌──                                                                                                  │
│  │ ObjectID: 0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779                       │
│  │ Sender: 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b                         │
│  │ Owner: Shared                                                                                      │
│  │ ObjectType: 0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop         │
│  │ Version: 28131882                                                                                  │
│  │ Digest: 9We2z3NPJqwwqCoyhBVWsvMEqv5ZpuPQgHcAVXjXmxwL                                               │
│  └──                                                                                                  │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯

可以通过sui client object &lt;ObjectID>来查看Product信息是否是自己想要购买的那一个产品,以及Shop当中对应产品的库存是否减少了 $\text 1$。

4.5 更新库存

  • 再次尝试购买,得到报错
Error executing transaction: Failure {
    error: "MoveAbort(MoveLocation { module: ModuleId { address: b36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad, name: Identifier(\"shop\") }, function: 6, instruction: 54, function_name: Some(\"get\") }, 2) in command 0",
}

原因是库存不足。

  • 添加库存

sui client call --package $PACKAGE_ID --module shop --function modify_stock --args $SHOPCAP $SHOP $ITEMID 1000 --gas-budget 10000000

  • 报错
RPC call failed: ErrorObject { code: ServerError(-32002), message: "Transaction execution failed due to issues with transaction inputs, please review the errors and try again: Transaction was not signed by the correct sender: Object 0x1168e00b20902a8c3148794c72c526677aaded597c823f6245ccc455ea11d1e4 is owned by account address 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67, but given owner/signer address is 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b.", data: None }

Caused by:
    RPC call failed: ErrorObject { code: ServerError(-32002), message: "Transaction execution failed due to issues with transaction inputs, please review the errors and try again: Transaction was not signed by the correct sender: Object 0x1168e00b20902a8c3148794c72c526677aaded597c823f6245ccc455ea11d1e4 is owned by account address 0x9e4092b6a894e6b168aa1c6c009f5c1c1fcb83fb95e5aa39144e1d2be4ee0d67, but given owner/signer address is 0xf6029b82e355f627b0e3d8941d63e139c4b73b495a2017ef48aaf17cc377457b.", data: None }

因为当前用户(顾客)并没有ShopCap的所有权,所以我们切换回店主再次调用。

  • 成功后查看Shop
╭───────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ objectId      │  0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779                                                                              │
│ version       │  28131884                                                                                                                                        │
│ digest        │  DkahtiGN2WDFa5zwus62oRGk8pXtgwvLo5FHdHc8pNip                                                                                                    │
│ objType       │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop                                                                  │
│ owner         │ ╭────────┬─────────────────────────────────────────╮                                                                                             │
│               │ │ Shared │ ╭────────────────────────┬────────────╮ │                                                                                             │
│               │ │        │ │ initial_shared_version │  28131880  │ │                                                                                             │
│               │ │        │ ╰────────────────────────┴────────────╯ │                                                                                             │
│               │ ╰────────┴─────────────────────────────────────────╯                                                                                             │
│ prevTx        │  8Js8x4Cq9J1M7cUhEWS8BC2KuM6DVHzXeVos2MW9pQY1                                                                                                    │
│ storageRebate │  2067200                                                                                                                                         │
│ content       │ ╭───────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│               │ │ dataType          │  moveObject                                                                                                              │ │
│               │ │ type              │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop                                          │ │
│               │ │ hasPublicTransfer │  false                                                                                                                   │ │
│               │ │ fields            │ ╭───────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │
│               │ │                   │ │ balance   │  369963                                                                                                  │ │ │
│               │ │                   │ │ commodity │ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │
│               │ │                   │ │           │ │ ╭────────┬─────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ │
│               │ │                   │ │           │ │ │ type   │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Item         │ │ │ │ │
│               │ │                   │ │           │ │ │ fields │ ╭──────────────┬──────────────────────────────────────────────────────────────────────╮ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ id           │  0x3b808241908b5d2cf4dbbc66cfc0b519eb9bd7ed7f8974d833dc2c085c07340d  │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ introduction │  first_product_desc                                                  │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ name         │  my_first_product                                                    │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ price        │  369963                                                              │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ │ stock        │  1000                                                                │ │ │ │ │ │
│               │ │                   │ │           │ │ │        │ ╰──────────────┴──────────────────────────────────────────────────────────────────────╯ │ │ │ │ │
│               │ │                   │ │           │ │ ╰────────┴─────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │
│               │ │                   │ │           │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │
│               │ │                   │ │ id        │ ╭────┬──────────────────────────────────────────────────────────────────────╮                            │ │ │
│               │ │                   │ │           │ │ id │  0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779  │                            │ │ │
│               │ │                   │ │           │ ╰────┴──────────────────────────────────────────────────────────────────────╯                            │ │ │
│               │ │                   │ │ name      │  my_first_shop                                                                                           │ │ │
│               │ │                   │ ╰───────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │ │
│               │ ╰───────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

可以发现,库存已经由 $\text 0$ 变成了 $\text {1000}$。

4.6 下架产品

  • 运行命令

sui client call --package $PACKAGE_ID --module shop --function remove_item --args $SHOPCAP $SHOP $ITEMID --gas-budget 10000000

  • 查看Shop可以发现货架空了
╭───────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ objectId      │  0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779                                                   │
│ version       │  28131885                                                                                                             │
│ digest        │  BZxb2tchuVEfoqRr1GAYi3xTHajsHiqovpoPBMh4MpTd                                                                         │
│ objType       │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop                                       │
│ owner         │ ╭────────┬─────────────────────────────────────────╮                                                                  │
│               │ │ Shared │ ╭────────────────────────┬────────────╮ │                                                                  │
│               │ │        │ │ initial_shared_version │  28131880  │ │                                                                  │
│               │ │        │ ╰────────────────────────┴────────────╯ │                                                                  │
│               │ ╰────────┴─────────────────────────────────────────╯                                                                  │
│ prevTx        │  DLQpLwJEqpA5jCZcqddm7ArZmqKc3cRBZNRqtW7tKi9R                                                                         │
│ storageRebate │  1428800                                                                                                              │
│ content       │ ╭───────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────╮ │
│               │ │ dataType          │  moveObject                                                                                   │ │
│               │ │ type              │  0xb36940dff6fcbda820ceec457fff1f8cb401cb75aa07e7c9a36928949781a8ad::shop::Shop               │ │
│               │ │ hasPublicTransfer │  false                                                                                        │ │
│               │ │ fields            │ ╭───────────┬───────────────────────────────────────────────────────────────────────────────╮ │ │
│               │ │                   │ │ balance   │  369963                                                                       │ │ │
│               │ │                   │ │ commodity │                                                                               │ │ │
│               │ │                   │ │ id        │ ╭────┬──────────────────────────────────────────────────────────────────────╮ │ │ │
│               │ │                   │ │           │ │ id │  0xf7ccf14adeb8557862ea435c57c403646750793e28207776ae8a86c08e5ba779  │ │ │ │
│               │ │                   │ │           │ ╰────┴──────────────────────────────────────────────────────────────────────╯ │ │ │
│               │ │                   │ │ name      │  my_first_shop                                                                │ │ │
│               │ │                   │ ╰───────────┴───────────────────────────────────────────────────────────────────────────────╯ │ │
│               │ ╰───────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

4.7 提现

  • 运行命令

sui client call --package $PACKAGE_ID --module shop --function withdraw --args $SHOPCAP $SHOP --gas-budget 10000000

  • 查看余额
sui client gas

# output:
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId                                                          │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0x03335f68ff3616af7e000b113c56a5ad53e8e8209784ca0a5623f70997c8d948 │ 10                 │ 0.00             │
│ 0x266848e4e91a7a43a72b63f20760e1341e81f8970d8201a792a48959dfe2e0b9 │ 659262424          │ 0.65             │
│ 0x2b057028a2ce30115dfddf330f3d25e5bb72dad28421a61d1ee6b3c98c81e900 │ 369963             │ 0.00             │
│ 0x2b58970568741e980b433ab092da5a1f08317b53b5b4724cc6fc45435f80ea34 │ 11                 │ 0.00             │
│ 0x3309da2eb2919265feff786cd9167cdee8055fea52649bd33b92adfb3732e4c5 │ 10                 │ 0.00             │
│ 0x47b46755e4603b0479ca251a23d35d8bb09f370eec11c9113b284eb318566b59 │ 990                │ 0.00             │
│ 0x8395ab2385bd34aa1275a0eb6e9e9253fcb6aa67c5216a9c58cbeedb3f12941a │ 763788220          │ 0.76             │
│ 0x86c7602927f18a8887f814c75a2201ee45e6b56eeba7de77c6587fd5882cce9f │ 0                  │ 0.00             │
│ 0xb3968ae4bf71a60d2ed4d39b2dc89cd184fca813a0a6e4d5abea26492f953ef2 │ 990                │ 0.00             │
│ 0xe24536eec6d0289205e19571169fac8b3b29c8148545184a243e22d34a8ee07e │ 855053848          │ 0.85             │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯

其中的 $\text {369963}$ 就是我们的收入,它对应的gasCoinId跟我们调用后输出的信息当中的新建的Coin&lt;SUI>也能够对应上。

4.8 注销店铺

  • 运行命令

sui client call --package $PACKAGE_ID --module shop --function destroy_shop --args $SHOPCAP $SHOP --gas-budget 10000000

这个时候,再通过sui client object &lt;ObjectID>查看Shop或者ShopCap,会报错提示这两个对象已经不存在了。

五:加入组织,共同进步!

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

0 条评论

请先 登录 后评论
Nigdle
Nigdle
0xa745...Fe19
江湖只有他的大名,没有他的介绍。