Dynamic Flow and Smart Contracts

Flow and Smart Contracts

Considering the fact that some substantial changes are needed for redesigning the Smart Contracts to the advanced way of handling all the transactions, we'll structure them from the beginning using a two-layer architecture:

  • the first layer will contain one main wrapper contract that will operate just like a control tower

  • the second one will be represented by permanent contracts which handle resources, items and new potential collections.

We will introduce a new collection-1 Smart Contract. The whole structure will be the following: The new Smart Contract we have introduced is meant to come up with some major improvements. It is supposed to allow the user not only to accomplish story fights and other basic operations but also to mine and harvest. For this, it will contain new resources and items: gold-bar, ruby, axe and pickaxe.

SIP Contracts

If until now we had one single contract that used to handle all the flow, now we have to restructure it a little bit. Firstly, we will split the main semi-fungible-token Smart Contract into two other contracts:

  • one that will handle the resources (gold, energy-power, wood, and iron)

  • another one for the items (swords, armor, etc.).

Then, we will introduce the new collection-1 contract.

Resources Contract

This contract will keep all the initial resources tokens' information. Here will be defined all tokens having the ids between u1 and u4: gold, energy-power, wood, iron. This is what the token-name and token-uri dictionaries will look like in the resources contract:

(define-map token-name { id: uint } { name: (string-ascii 256), type: (string-ascii 256), values: {dmg: uint, health: uint, defense: uint} })

(map-set token-name {id: u1} {name: "gold", type: "resource", values: {dmg: u0, health: u0, defense: u0}})
(map-set token-name {id: u2} {name: "energy-power", type: "resource", values: {dmg: u0, health: u0, defense: u0}})
(map-set token-name {id: u3} {name: "wood", type: "resource", values: {dmg: u0, health: u0, defense: u0}})
(map-set token-name {id: u4} {name: "iron", type: "resource", values: {dmg: u0, health: u0, defense: u0}})
(define-map token-uri { id: uint } { url: (string-ascii 256) })

(map-set token-uri {id: u1} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/1.png"})
(map-set token-uri {id: u2} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/2.png"})
(map-set token-uri {id: u3} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/3.png"})
(map-set token-uri {id: u4} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/4.png"})

Then, we will keep in the resources contract the SIP functions, too: mint, mint-user, burn, is-owned-needed, balance functions, transfer functions, set-token-uri, get-token-uri. These functions will have the exact same structure as the ones in the Base SFTs chapter.

Items Contract

The Items Contract's structure will follow the Resources Contract's. The main difference is the token-ids handled inside it. Instead of handling the resources flows, we will handle here the initial items tokens:

(define-map token-name { id: uint } { name: (string-ascii 256), type: (string-ascii 256), values: {dmg: uint, health: uint, defense: uint} })

(map-set token-name {id: u5} {name: "wooden_sword_1", type: "sword", values: {dmg: u1, health: u0, defense: u0}})
(map-set token-name {id: u6} {name: "wooden_sword_2", type: "sword", values: {dmg: u2, health: u0, defense: u0}})
(map-set token-name {id: u7} {name: "wooden_sword_3", type: "sword", values: {dmg: u4, health: u0, defense: u0}})
(map-set token-name {id: u8} {name: "iron_sword_1", type: "sword", values: {dmg: u3, health: u0, defense: u0}})
(map-set token-name {id: u9} {name: "iron_sword_2", type: "sword", values: {dmg: u6, health: u0, defense: u0}})
(map-set token-name {id: u10} {name: "iron_sword_3", type: "sword", values: {dmg: u9, health: u0, defense: u0}})
(map-set token-name {id: u11} {name: "enhanced_sword_1", type: "sword", values: {dmg: u11, health: u0, defense: u0}})
(map-set token-name {id: u12} {name: "enhanced_sword_2", type: "sword", values: {dmg: u15, health: u0, defense: u0}})
(map-set token-name {id: u13} {name: "enhanced_sword_3", type: "sword", values: {dmg: u19, health: u0, defense: u0}})

(map-set token-name {id: u14} {name: "wooden_armor_1", type: "armor", values: {dmg: u0, health: u10, defense: u5}})
(map-set token-name {id: u15} {name: "wooden_armor_2", type: "armor", values: {dmg: u0, health: u15, defense: u8}})
(map-set token-name {id: u16} {name: "wooden_armor_3", type: "armor", values: {dmg: u0, health: u20, defense: u11}})
(map-set token-name {id: u17} {name: "iron_armor_1", type: "armor", values: {dmg: u0, health: u15, defense: u10}})
(map-set token-name {id: u18} {name: "iron_armor_2", type: "armor", values: {dmg: u0, health: u25, defense: u14}})
(map-set token-name {id: u19} {name: "iron_armor_3", type: "armor", values: {dmg: u0, health: u35, defense: u18}})
(map-set token-name {id: u20} {name: "enhanced_armor_1", type: "armor", values: {dmg: u0, health: u50, defense: u25}})
(map-set token-name {id: u21} {name: "enhanced_armor_2", type: "armor", values: {dmg: u0, health: u65, defense: u30}})
(map-set token-name {id: u22} {name: "enhanced_armor_3", type: "armor", values: {dmg: u0, health: u80, defense: u35}})

(map-set token-name {id: u23} {name: "wooden_shield_1", type: "shield", values: {dmg: u0, health: u0, defense: u5}})
(map-set token-name {id: u24} {name: "wooden_shield_2", type: "shield", values: {dmg: u0, health: u0, defense: u10}})
(map-set token-name {id: u25} {name: "wooden_shield_3", type: "shield", values: {dmg: u0, health: u0, defense: u15}})
(map-set token-name {id: u26} {name: "iron_shield_1", type: "shield", values: {dmg: u0, health: u0, defense: u13}})
(map-set token-name {id: u27} {name: "iron_shield_2", type: "shield", values: {dmg: u0, health: u0, defense: u19}})
(map-set token-name {id: u28} {name: "iron_shield_3", type: "shield", values: {dmg: u0, health: u0, defense: u25}})
(map-set token-name {id: u29} {name: "enhanced_shield_1", type: "shield", values: {dmg: u0, health: u0, defense: u35}})
(map-set token-name {id: u30} {name: "enhanced_shield_2", type: "shield", values: {dmg: u0, health: u0, defense: u45}})
(map-set token-name {id: u31} {name: "enhanced_shield_3", type: "shield", values: {dmg: u0, health: u0, defense: u55}})

(map-set token-name {id: u32} {name: "wooden_helmet_1", type: "helmet", values: {dmg: u0, health: u10, defense: u0}})
(map-set token-name {id: u33} {name: "wooden_helmet_2", type: "helmet", values: {dmg: u0, health: u17, defense: u0}})
(map-set token-name {id: u34} {name: "wooden_helmet_3", type: "helmet", values: {dmg: u0, health: u24, defense: u0}})
(map-set token-name {id: u35} {name: "iron_helmet_1", type: "helmet", values: {dmg: u0, health: u20, defense: u0}})
(map-set token-name {id: u36} {name: "iron_helmet_2", type: "helmet", values: {dmg: u0, health: u30, defense: u0}})
(map-set token-name {id: u37} {name: "iron_helmet_3", type: "helmet", values: {dmg: u0, health: u40, defense: u0}})
(map-set token-name {id: u38} {name: "enhanced_helmet_1", type: "helmet", values: {dmg: u0, health: u55, defense: u0}})
(map-set token-name {id: u39} {name: "enhanced_helmet_2", type: "helmet", values: {dmg: u0, health: u70, defense: u0}})
(map-set token-name {id: u40} {name: "enhanced_helmet_3", type: "helmet", values: {dmg: u0, health: u85, defense: u0}})

(map-set token-name {id: u41} {name: "wooden_shoes_1", type: "shoes", values: {dmg: u3, health: u0, defense: u2}})
(map-set token-name {id: u42} {name: "wooden_shoes_2", type: "shoes", values: {dmg: u4, health: u0, defense: u4}})
(map-set token-name {id: u43} {name: "wooden_shoes_3", type: "shoes", values: {dmg: u5, health: u0, defense: u6}})
(map-set token-name {id: u44} {name: "iron_shoes_1", type: "shoes", values: {dmg: u3, health: u0, defense: u5}})
(map-set token-name {id: u45} {name: "iron_shoes_2", type: "shoes", values: {dmg: u4, health: u0, defense: u8}})
(map-set token-name {id: u46} {name: "iron_shoes_3", type: "shoes", values: {dmg: u5, health: u0, defense: u11}})
(map-set token-name {id: u47} {name: "enhanced_shoes_1", type: "shoes", values: {dmg: u3, health: u0, defense: u14}})
(map-set token-name {id: u48} {name: "enhanced_shoes_2", type: "shoes", values: {dmg: u4, health: u0, defense: u18}})
(map-set token-name {id: u49} {name: "enhanced_shoes_3", type: "shoes", values: {dmg: u5, health: u0, defense: u22}})
(define-map token-uri { id: uint } { url: (string-ascii 256) })

(map-set token-uri {id: u5} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/5.png"})
(map-set token-uri {id: u6} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/6.png"})
(map-set token-uri {id: u7} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/7.png"})
(map-set token-uri {id: u8} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/8.png"})
(map-set token-uri {id: u9} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/9.png"})
(map-set token-uri {id: u10} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/10.png"})
(map-set token-uri {id: u11} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/11.png"})
(map-set token-uri {id: u12} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/12.png"})
(map-set token-uri {id: u13} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/13.png"})
(map-set token-uri {id: u14} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/14.png"})
(map-set token-uri {id: u15} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/15.png"})
(map-set token-uri {id: u16} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/16.png"})
(map-set token-uri {id: u17} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/17.png"})
(map-set token-uri {id: u18} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/18.png"})
(map-set token-uri {id: u19} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/19.png"})
(map-set token-uri {id: u20} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/20.png"})
(map-set token-uri {id: u21} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/21.png"})
(map-set token-uri {id: u22} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/22.png"})
(map-set token-uri {id: u23} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/23.png"})
(map-set token-uri {id: u24} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/24.png"})
(map-set token-uri {id: u25} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/25.png"})
(map-set token-uri {id: u26} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/26.png"})
(map-set token-uri {id: u27} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/27.png"})
(map-set token-uri {id: u28} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/28.png"})
(map-set token-uri {id: u29} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/29.png"})
(map-set token-uri {id: u30} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/30.png"})
(map-set token-uri {id: u31} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/31.png"})
(map-set token-uri {id: u32} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/32.png"})
(map-set token-uri {id: u33} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/33.png"})
(map-set token-uri {id: u34} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/34.png"})
(map-set token-uri {id: u35} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/35.png"})
(map-set token-uri {id: u36} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/36.png"})
(map-set token-uri {id: u37} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/37.png"})
(map-set token-uri {id: u38} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/38.png"})
(map-set token-uri {id: u39} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/39.png"})
(map-set token-uri {id: u40} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/40.png"})
(map-set token-uri {id: u41} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/41.png"})
(map-set token-uri {id: u42} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/42.png"})
(map-set token-uri {id: u43} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/43.png"})
(map-set token-uri {id: u44} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/44.png"})
(map-set token-uri {id: u45} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/45.png"})
(map-set token-uri {id: u46} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/46.png"})
(map-set token-uri {id: u47} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/47.png"})
(map-set token-uri {id: u48} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/48.png"})
(map-set token-uri {id: u49} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/49.png"})

Collection-1 Contract

This contract is intended to be one the game's owner decided to add after the game's first launch. It comes with some major improvements: introducing the axe and the pickaxe and the gold-bar and ruby resources. The two resources added can be obtained through the gameplay after successfully mining. This implies new functions: one for mining, and one for harvesting which will be found inside Main-SC.

This is how token-name and token-uri look inside collection-1 contract:

(define-map token-name { id: uint } { name: (string-ascii 256), type: (string-ascii 256), values: {dmg: uint, health: uint, defense: uint} })

(map-set token-name {id: u50} {name: "gold-bar", type: "resource", values: {dmg: u0, health: u0, defense: u0}})
(map-set token-name {id: u51} {name: "ruby", type: "resource", values: {dmg: u0, health: u0, defense: u0}})
(map-set token-name {id: u52} {name: "iron_axe", type: "axe", values: {dmg: u4, health: u3, defense: u0}})
(map-set token-name {id: u53} {name: "gold_axe", type: "axe", values: {dmg: u10, health: u5, defense: u0}})
(map-set token-name {id: u54} {name: "ruby_axe", type: "axe", values: {dmg: u18, health: u6, defense: u0}})
(map-set token-name {id: u55} {name: "iron_pickaxe", type: "pickaxe", values: {dmg: u5, health: u3, defense: u0}})
(map-set token-name {id: u56} {name: "gold_pickaxe", type: "pickaxe", values: {dmg: u12, health: u5, defense: u0}})
(map-set token-name {id: u57} {name: "ruby_pickaxe", type: "pickaxe", values: {dmg: u22, health: u6, defense: u0}})
(define-map token-uri { id: uint } { url: (string-ascii 256) })

(map-set token-uri {id: u50} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/50.png"})
(map-set token-uri {id: u51} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/51.png"})
(map-set token-uri {id: u52} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/52.png"})
(map-set token-uri {id: u53} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/53.png"})
(map-set token-uri {id: u54} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/54.png"})
(map-set token-uri {id: u55} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/55.png"})
(map-set token-uri {id: u56} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/56.png"})
(map-set token-uri {id: u57} {url: "ipfs://QmcQzR4zcamVTzCPfCRBYywHVHGVncB2o3YpojvRmakVkC/57.png"})

Main-SC

As we have said before, the Main-SC contract works just like a control tower for all other contracts located on the second architectural layer. For this, all the SIP characteristic functions, the ones that handle the whole token flow will be found inside the permanent contracts (resources, items, collection-1). For calling them, we will need wrappers inside Main-SC. Furthermore, the main operations' functions will be held in the wrapper contract, too. In conclusion, all the token functions will have wrappers: mint-wrapper, mint-wrapper-user, mint-wrapper-admin, burn-wrapper, get-balance-wrapper, is-owned-needed-wrapper, transfer-wrapper. To clarify, this is what the mint-wrapper looks like:

(define-public (mint-wrapper (token-id uint) (amount uint) (recipient principal)) 
  (if (< token-id u5) 
    (contract-call? .resources mint token-id amount recipient) 
    (if (< token-id u50) 
      (contract-call? .items mint token-id amount recipient) 
      (if (< token-id u58) 
        (contract-call? .collection-1 mint token-id amount recipient)
        err-inexistent-item))))

It can be observed that the wrapper has three conditionals. This is the exactly same number as the permanent contracts, and this is not a coincidence. Technically, the mint-wrapper checks whether the given token-id belongs to the resources contract, items contract, or collection-1 contract. After this step, it calls the mint function located in the proper token contract. The same happens for the other wrappers:

(define-private (mint-wrapper-user (token-id uint) (amount uint) (recipient principal)) 
  (if (< token-id u5) 
    (as-contract (contract-call? .resources mint-user token-id amount recipient))
    (if (< token-id u50) 
      (as-contract (contract-call? .items mint-user token-id amount recipient))
      (if (< token-id u58) 
        (as-contract (contract-call? .collection-1 mint-user token-id amount recipient))
        err-inexistent-item))))
(define-private (mint-wrapper-admin (token-id uint) (amount uint) (recipient principal))
  (begin
    (some 
      (if (< token-id u5) 
        (contract-call? .resources mint token-id amount recipient) 
        (if (< token-id u50) 
          (contract-call? .items mint token-id amount recipient) 
          (if (< token-id u58) 
            (contract-call? .collection-1 mint token-id amount recipient)
            err-inexistent-item))))
    recipient))
(define-public (burn-wrapper (burn-tuple {resource-id: uint, resource-qty: uint}))
  (if (< (get resource-id burn-tuple) u5)
    (contract-call? .resources burn (get resource-id burn-tuple) (get resource-qty burn-tuple) tx-sender) 
    (if (< (get resource-id burn-tuple) u50) 
      (contract-call? .items burn (get resource-id burn-tuple) (get resource-qty burn-tuple) tx-sender)
      (if (< (get resource-id burn-tuple) u58)
        (contract-call? .collection-1 burn (get resource-id burn-tuple) (get resource-qty burn-tuple) tx-sender)
        err-inexistent-item))))is
(define-read-only (get-balance-wrapper (token-id uint) (who principal)) 
  (if (< token-id u5) 
    (contract-call? .resources get-balance token-id who) 
    (if (< token-id u50) 
      (contract-call? .items get-balance token-id who) 
      (if (< token-id u58) 
        (contract-call? .collection-1 get-balance token-id who)
        err-inexistent-item))))  
(define-private (is-owned-needed-wrapper (item {resource-id: uint, resource-qty: uint})) 
  (unwrap-panic 
    (if (< (get resource-id item) u5) 
      (contract-call? .resources is-owned-needed item) 
      (if (< (get resource-id item) u50) 
        (contract-call? .items is-owned-needed item) 
        (if (< (get resource-id item) u58) 
          (contract-call? .collection-1 is-owned-needed item) 
          err-inexistent-item)))))
(define-public (transfer-wrapper (token-id uint) (amount uint) (sender principal) (recipient principal)) 
  (if (< token-id u5) 
    (contract-call? .resources transfer token-id amount sender recipient) 
    (if (< token-id u50) 
      (contract-call? .items transfer token-id amount sender recipient) 
      (if (< token-id u58) 
        (contract-call? .collection-1 transfer token-id amount sender recipient) 
        err-inexistent-item))))

The operations' functions (level-up, crafting, acquisition) will be held here, too. The difference from the previous SFTs basic is represented by the new functions: reward-mining and reward-harvesting. These are a result of the collection-1 improvements and will imply two additional dictionaries, too. Also, when the user first starts the game he will be allowed to call the claim-starter-kit function and get the resources needed in the beginning.

Mining dictionary

(define-map mining-reward-system { token-id: uint, mining-time: uint } (list 100 { resource-id: uint, resource-qty: uint }))

(map-set mining-reward-system {token-id: u55, mining-time: u5} (list {resource-id: u4, resource-qty: u1}))
(map-set mining-reward-system {token-id: u55, mining-time: u10} (list {resource-id: u4, resource-qty: u3}))
(map-set mining-reward-system {token-id: u55, mining-time: u20} (list {resource-id: u4, resource-qty: u5} {resource-id: u50, resource-qty: u1}))
(map-set mining-reward-system {token-id: u56, mining-time: u5} (list {resource-id: u4, resource-qty: u4}))
(map-set mining-reward-system {token-id: u56, mining-time: u10} (list {resource-id: u4, resource-qty: u11} {resource-id: u50, resource-qty: u2}))
(map-set mining-reward-system {token-id: u56, mining-time: u20} (list {resource-id: u4, resource-qty: u25} {resource-id: u50, resource-qty: u3} {resource-id: u51, resource-qty: u1}))
(map-set mining-reward-system {token-id: u57, mining-time: u5} (list {resource-id: u4, resource-qty: u12} {resource-id: u50, resource-qty: u1}))
(map-set mining-reward-system {token-id: u57, mining-time: u10} (list {resource-id: u4, resource-qty: u18} {resource-id: u50, resource-qty: u2} {resource-id: u51, resource-qty: u1}))
(map-set mining-reward-system {token-id: u57, mining-time: u20} (list {resource-id: u4, resource-qty: u29} {resource-id: u50, resource-qty: u4} {resource-id: u51, resource-qty: u3}))

Harvesting dictionary

(define-map harvesting-system { token-id: uint, harvesting-time: uint } (list 100 { resource-id: uint, resource-qty: uint }))

(map-set harvesting-system {token-id: u52, harvesting-time: u5} (list {resource-id: u3, resource-qty: u1}))
(map-set harvesting-system {token-id: u52, harvesting-time: u10} (list {resource-id: u3, resource-qty: u3}))
(map-set harvesting-system {token-id: u52, harvesting-time: u20} (list {resource-id: u3, resource-qty: u7}))
(map-set harvesting-system {token-id: u53, harvesting-time: u5} (list {resource-id: u3, resource-qty: u5}))
(map-set harvesting-system {token-id: u53, harvesting-time: u10} (list {resource-id: u3, resource-qty: u12}))
(map-set harvesting-system {token-id: u53, harvesting-time: u20} (list {resource-id: u3, resource-qty: u26}))
(map-set harvesting-system {token-id: u54, harvesting-time: u5} (list {resource-id: u3, resource-qty: u20}))
(map-set harvesting-system {token-id: u54, harvesting-time: u10} (list {resource-id: u3, resource-qty: u45}))
(map-set harvesting-system {token-id: u54, harvesting-time: u20} (list {resource-id: u3, resource-qty: u100}))

Starter kit dictionary

(define-map starter-kit-system { user: principal } { claimed: bool })

The functions that will handle each of the two new operations will be the following:

(define-read-only (get-harvesting-rewards (token-id uint) (harvesting-time uint))
    (let ((token-urr (map-get? harvesting-system {token-id: token-id, harvesting-time: harvesting-time})))
      (ok token-urr)))

(define-public (set-harvesting-rewards (token-id uint) (harvesting-time uint) (resource-achieved (list 100 {resource-id: uint, resource-qty: uint})))
  (begin 
    (asserts! (is-eq tx-sender contract-owner) err-owner-only)    
    (ok (map-set harvesting-system {token-id: token-id, harvesting-time: harvesting-time} resource-achieved))))
    
(define-public (reward-harvesting (token-id uint) (harvesting-time uint) (user principal))
  (begin
    (asserts! (is-eq tx-sender contract-owner) err-owner-only)
    (asserts! (not (is-none (unwrap-panic (get-harvesting-rewards token-id harvesting-time)))) err-not-some)
    (let ((harvesting-rewards (unwrap-panic (get-harvesting-rewards token-id harvesting-time)))) 
      (asserts! (is-some harvesting-rewards) err-not-some)
      (ok (fold mint-harvesting-rewards (unwrap-panic harvesting-rewards) user)))))
(define-read-only (get-mining-rewards (token-id uint) (mining-time uint))
    (let ((token-urr (map-get? mining-reward-system {token-id: token-id, mining-time: mining-time})))
      (ok token-urr)))

(define-public (set-mining-rewards (token-id uint) (mining-time uint) (resource-achieved (list 100 {resource-id: uint, resource-qty: uint})))
  (begin 
    (asserts! (is-eq tx-sender contract-owner) err-owner-only)    
    (ok (map-set mining-reward-system {token-id: token-id, mining-time: mining-time} resource-achieved))))
    
(define-public (reward-harvesting (token-id uint) (harvesting-time uint) (user principal))
  (begin
    (asserts! (is-eq tx-sender contract-owner) err-owner-only)
    (asserts! (not (is-none (unwrap-panic (get-harvesting-rewards token-id harvesting-time)))) err-not-some)
    (let ((harvesting-rewards (unwrap-panic (get-harvesting-rewards token-id harvesting-time)))) 
      (asserts! (is-some harvesting-rewards) err-not-some)
      (ok (fold mint-rewards (unwrap-panic harvesting-rewards) user)))))
(define-read-only (get-starter-kit-status (user principal))
  (let ((claimed (map-get? starter-kit-system {user: user})))
    (ok claimed)))

(define-public (claim-starter-kit)
  (begin 
    (asserts! (is-none (map-get? starter-kit-system {user: tx-sender})) err-already-claimed)
    (some (mint-wrapper-user u1 u15 tx-sender))
    (some (mint-wrapper-user u2 u100 tx-sender))
    (ok (map-set starter-kit-system {user: tx-sender} {claimed: true}))))

Each of the reward-mining and reward-harvesting functions will use a wrapper that handles minting resources won by the player after successfully finishing new operations.

(define-private (mint-rewards (reward-tuple {resource-id: uint, resource-qty: uint}) (user principal)) 
  (mint-wrapper-admin (get resource-id reward-tuple) (get resource-qty reward-tuple) user))

Last updated