metapro
  • 🤝Welcome!
  • 💻metapro market
    • Set your account
    • Connect wallet + web3 login
    • Side panel
      • Transfer NFT
        • Multiple transfer (Airdrop NFT)
          • Import CSV List
      • Sell NFT
        • Initial NFT Selling (INS)
          • How to setup INS auction
          • How to buy on INS auction
        • Buy Now
          • How to setup Buy Now auction
          • How to buy on Buy Now auction
        • Auction (Bidding)
          • How to setup Auction
          • How to buy on Auction
      • All NFT assets
    • Buy Crypto
    • Top Menu
      • Profile
        • Profile Marketplace
        • My games
        • My assets
          • Royalty
        • Activities
      • Referral Panel
        • Register your downline
        • Downline wallets
        • My referral link
      • Profile Settings
      • Developer Portal
      • Logout
    • Assets
      • Marketplace
        • Auction Card
      • Most favorite
      • Newest assets
        • Asset Card
    • Games
      • Show all games
    • Leaderboard
    • Create asset (minter)
      • Gaming asset specification
      • How to create (mint) asset
        • 1. Setup NFT token
        • 2. Setup metadata
        • 3. Add meta asset
        • 4. Mint meta asset
        • 5. Meta asset created
    • Developers Portal
      • Create team
      • Create game
      • Developers Portal Panel
      • Unity Plugin
      • How to list game on metapro market?
    • Creators
    • Teams
    • Users
    • Wallet App
    • Launcher
    • Market and auction component fees
  • 🚀METAPRO LAUNCHER
    • What is metapro launcher?
    • Download launcher
    • Set your account
      • Login to launcher
    • Home
    • Games
      • Game card on launcher
        • Assets in this game
      • Install game on launcher
      • Update game on launcher
    • My games
      • Installed
      • Not installed
      • Wishlist
    • My assets
      • Collected assets
      • Created assets
      • Wishlist
    • NODEs app
  • 📱metapro one
    • About non-custodial wallet
    • Download & set up
      • Create new metapro wallet
      • Import existing wallet
    • Settings
      • Avatar
      • Multiple wallets
      • Wallet name
      • Private Key
        • Protect Private Key
        • How to find my Private Key
      • Recovery Phrases
        • Protect Recovery Phrases
        • How to find my Recovery Phrases
      • Application version
    • Network switch
    • Deposit (Tokens and Collectibles)
    • Send (Tokens and Collectibles)
      • Send Tokens
      • Send Collectibles (NFT)
    • Buy (Buy and Sell Crypto)
    • Browser
    • My assets
      • Tokens
        • Asset view
        • Adding Tokens
        • Activities
      • Collectibles (NFT)
      • Game assets (NFTma)
    • Explore
      • Apps
      • Collections (NFT)
      • Game assets (NFTma)
    • How to claim Airdrop
    • How to import wallet from MetaMask to metapro
    • Supported devices
  • ⛓️metapro protocol
    • API
      • Users service
      • Teams service
      • Apps service
      • Nft service
      • Nft events service
    • Meta asset
    • Metadata structure
    • Protocole structure
    • Unity Plugin
      • About metapro Unity plugin
      • What's new
      • Guides
        • Installation
        • Requirements
        • Package samples
        • Quick start
          • 1. Editor
            • Access tool
            • Import game key
            • Download resources
            • App data object
            • Change game key
            • Use app data in script
          • 2. Play mode (PC)
            • Enable Web3 in your game
            • Choose provider
            • Connect wallet
            • Login with Web3
            • Display user data
            • Show app tokens
            • Use user and app data from script
          • 3. Play mode (Mobile)
            • Enable Web3 in Your game
            • Choose provider
            • Connect wallet
            • Login with Web3
        • AFP (Additional Features Packages)
          • 1. Safe token transfer
          • 2. Phoenix
        • Troubleshooting
      • Reference
        • MetaproAPPSetup
        • Editor Window
        • Plugin Manager
        • Web3 connection providers
          • metapro
          • Wallet Connect
          • MetaMask
        • WindowController
        • AFP (Additional Features Packages)
          • SafeTransferFrom
          • Phoenix
  • 🛠️WALLET CONNECTOR
    • Introduction
    • Basic informations
      • Next 13 integration
      • React integration
      • Manual installation
  • 👨‍💻Developer Documentation
    • Introduction to Developer Documentation
      • What is a Meta asset?
      • What are the Benefits of Using Tokens as Access Keys for the Game Application
      • Why should I Choose the Meta Assets as the Access Keys for the Game Application?
      • How Does It Work, Exactly?
    • Available Environments
    • Blockchain Communication and information retrieval
      • How can we verify/distinguish a user?
      • How can we track a user's transactions?
      • What information can we obtain?
    • Integration with the Leaderboard service
    • Integration for in-Wallet Apps
    • Integration for Telegram Mini Apps
      • Integration Architecture and Configuration
      • Authorization and Session Management
      • Example Integration and Features
      • Code Examples from the Repository
      • Summary and Appendices
    • Developer documentation for the Construct 3 Plugin
      • Construct 3 - Install plugin
      • Plugin Configuration
      • User onboarding and authorization
      • User Management
      • Score System
      • Leaderboard System
      • Referral System
      • Gameplay
      • Smart Contract Interactions
      • User NFTs
      • Error Handling
      • Additional Getters for Plugin Properties
    • Integration Web3 with Your Game
      • What is Web3
      • Blockchain Basics
      • Differences between chains
      • What is a NFT
      • Advantages of Web3 Gaming
      • Examples of Web3 Games
    • Onboarding the Web3 Player
      • Value for Players
      • Explanation of Cryptocurrency Wallet
      • Rewards for Tournament Participation
      • Reselling Owned Assets
      • Integration of Metapro Wallet Connector
      • Displaying Data for Unlogged Users
      • How to Get Authorization Data
      • User Authorization Benefits
    • Creating Your First Meta Asset
      • The Difference between NFT and Meta Asset
      • Security and Transparency
      • Concept and Value of Meta Assets
      • How and Where to Create Your Meta Asset
        • Step-by-Step Guide on How to Create Your Asset
        • Explanation of URI (Metadata structure)
        • Explanation of the Meta Asset Data taken from our Back End
    • Implementing Meta Assets into Your Game
      • Integrate your Meta Asset to your game using Unity
      • Verify User Tokens Ownership
      • Displaying All User-Owned Tokens
      • Displaying All Assets Assigned to the Game on the Metapro Market
    • Smart Contracts
      • MetaproINS
        • Read Contract
        • Write Contract
      • MetaproBuyNow
        • Read Contract
        • Write Contract
      • MetaproAuction
        • Read Contract
        • Write Contract
      • MetaproMetaAsset
        • Read Contract
        • Write Contract
      • MetaproRoyalty
        • Read Contract
        • Write Contract
      • MetaproReferral
        • Read Contract
        • Write Contract
      • MetaproAirdrop
        • Read Contract
        • Write Contract
    • Universal Links & App Links with WalletConnect
  • 🔎General information
    • Blockchain
    • Blockchain Network Fee
    • Blockchain Native Token
    • Token ERC-1155 vs ERC-721
  • 📄Release Notes
    • Introduction to the Release Notes
    • Marketplace Updates
      • Release 07.03.2024
      • Release 06.03.2024
      • Release 04.03.2024
      • Release 19.02.2024
      • Release 24.01.2024
      • Release 09.01.2024
      • Release 03.01.2024
      • Release 21.12.2023
      • Release 18.12.2023
      • Release 13.12.2023
      • Release 12.12.2023
      • Release 02.12.2023
      • Release 30.11.2023
      • Release 24.11.2023
      • Release 22.11.2023
      • Release 17.11.2023
      • Release 13.11.2023
      • Release 09.11.2023
      • Release 08.11.2023
      • Release 07.11.2023
      • Release 31.10.2023
      • Release 26.10.2023
      • Release 25.10.2023
      • Release 24.10.2023
      • Release 18.10.2023
      • Release 05.10.2023
      • Release 03.10.2023
      • Release 29.09.2023
      • Release 18.09.2023
      • Release 14.09.2023
      • Release 12.09.2023
      • Release 06.09.2023
      • Release 25.08.2023
      • Release 17.08.2023
      • Release 04.08.2023
      • Release 31.07.2023
      • Release 21.07.2023
      • Release 18.07.2023
      • Release 13.07.2023
    • Games Launcher Updates
      • Release 13.03.2024
      • Release 24.01.2024
      • Release 04.01.2024
      • Release 22.11.2023
      • Release 03.10.2023
      • Release 31.07.2023
      • Release 27.07.2023
      • Release 20.07.2023
      • Release 13.07.2023
    • Wallet Updates
      • Release 04.03.2024
      • Release 03.10.2023
      • Release 29.09.2023
      • Release 15.09.2023
      • Release 30.08.2023
      • Release 18.07.2023
Powered by GitBook
On this page
  • Send transaction request
  • Action Parameters:
  • Process Flow:
  • Usage Example:
  • Transaction Status
  • Action Parameters:
  • Read data request
  • Action Parameters:
  • Process Flow:
  • Usage Example:
  • Read multiple data request
  • Action Parameters:
  • Process Flow:
  • Usage Example:
  • Send Crypto tokens
  • Action Parameters:
  • Process Flow:
  • Usage Example:
  • Life scenario based on the shop functionality (testnet)
  • Current player score retrieval step
  • Player token balance retrieval
  • Player token mints count and max token mints retrieval
  • Minting
  1. Developer Documentation
  2. Developer documentation for the Construct 3 Plugin

Smart Contract Interactions

PreviousGameplayNextUser NFTs

Last updated 6 months ago

Send transaction request

The Send Contract Transaction action enables you to interact with a smart contract by sending a transaction to a specified contract address. It utilizes a JSON stringified representation of the contract's ABI (Application Binary Interface), focusing specifically on the function you intend to call. Although you can provide the complete ABI, it is recommended to include only the specific function being called for better optimization.

Action Parameters:

  • Contract Address: The address of the smart contract.

"0x35214dc712C4F1571ec7F6cf957c3050ca8e863D" // example
  • ABI: A JSON stringified representation of the ABI (Application Binary Interface). It is recommended to include only the relevant function for optimization. You can get it from a blockchain scan for example:

    You can pass only a single definition of the function that will be used during contract interaction or the whole ABI element

[
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "_to",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "_tokenId",
                "type": "uint256"
            },
            {
                "internalType": "uint256",
                "name": "_amount",
                "type": "uint256"
            },
            {
                "internalType": "bytes",
                "name": "data",
                "type": "bytes"
            }
        ],
        "name": "mint",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
] // example
  • Function Name: The name of the function being called in the ABI

"mint" // example
  • Input Data: A JSON stringified representation of the input data required for the function call. Example format:

"{'_to':'123','_tokenId':1,'_amount':1}" // example

Process Flow:

  1. Check Account: First, the function checks if your account is available. If you're not connected to an account, it will stop and show an error message saying the account is missing.

  2. Prepare the Contract: It checks the technical setup of the contract to ensure the function you're calling exists. If it doesn’t, you’ll get an error saying the function isn’t found. It also checks that the inputs you’ve given (like addresses or values) match what the function expects.

  3. Set Status to Pending: Once everything looks good, the transaction status is set to "pending." This means that the transaction is about to start.

  4. Switch to the Correct Network: The function makes sure you're on the correct blockchain network (like Ethereum or Binance Smart Chain) to send the transaction. This happens automatically.

  5. Estimate Fees: It calculates how much gas (or transaction fee) is needed for the action you're about to do on the blockchain. This ensures you don’t run out of gas during the transaction.

  6. Send the Transaction: The transaction is sent to the blockchain. If you’re sending tokens, it makes sure the amount and recipient are correct. It also takes the current network fee into account to avoid overpaying for gas. Once it’s sent, you’ll get a transaction hash—a unique code that tracks the transaction.

  7. Wait for Confirmation: The function waits for the transaction to be confirmed by the blockchain. It checks every few seconds to see if the transaction has gone through. If it takes too long (more than 2 minutes), it stops and tells you the confirmation timed out.

  8. Final Status:

    • If the transaction goes through successfully, it updates the status to "success."

    • If something goes wrong (like the transaction fails or is rejected), the status changes to "error" and it tells you what went wrong.

  9. Error Handling: If something goes wrong at any point—whether it’s a connection issue, an error with the contract, or a transaction failure—the function will stop, log the problem, and show you an error message so you know what happened.

Once the transaction is successfully sent and confirmed, the action updates the last transaction hash, which can be retrieved using the Get Last Transaction Hash expression. Additionally, the On Transaction Sent condition is triggered, indicating that the transaction has been successfully processed and confirmed.

Usage Example:

Transaction Status

The Set Transaction Status action allows you to manually update the internal status of the transaction. This can be useful for debugging or custom logic where you need to set a specific status based on the flow of your application.

Action Parameters:

  • Status: A string representing the new status of the transaction (e.g., "pending", "success", "error").

The Get Transaction Status expression retrieves the current status of the last transaction processed. It returns the status as a string, allowing you to check if a transaction is pending, successful, or has encountered an error. This expression is useful for displaying the status or making decisions based on the transaction outcome.

Read data request

The Read Contract Data action allows you to interact with a smart contract by calling a function and reading data from it. This action uses a JSON stringified representation of the contract's Application Binary Interface (ABI) and focuses on the function you want to read from. While you can provide the entire ABI, it is recommended to only include the specific function being called to optimize the request by reducing unnecessary data.

Action Parameters:

  • Contract Address: The address of the smart contract.

"0x35214dc712C4F1571ec7F6cf957c3050ca8e863D" // example
  • ABI: A JSON stringified representation of the ABI (Application Binary Interface)

[
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_tokenId",
                "type": "uint256"
            }
        ],
        "name": "tokenMaxMints",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    }
] // example
  • Function Name: The name of the function being called in the ABI

"tokenMaxMints" // example
  • Input Data: A JSON stringified representation of the input data required for the function call. Example format:

"[['0x6CBa743401e000eb29d17d6f3406CA0143e38203'], [1]]" // example

Process Flow:

  1. Understanding the Contract: The function starts by looking at the provided ABI (the blueprint of the contract). It uses the function name you provided to find the specific part of the contract you're trying to interact with. If the function doesn’t exist, you’ll get an error saying the function wasn’t found.

  2. Check Your Inputs: The data you’re sending (like addresses or amounts) is checked to make sure it matches what the contract function expects. If the number of inputs doesn’t match, the function will stop and show an error, helping you avoid sending wrong data.

  3. Connect to the Blockchain: The function connects to the blockchain using a Web3 provider. This is like connecting to the internet but for blockchain. It uses the URL you provide to talk to the right blockchain network.

  4. Set Up the Contract: Once connected, the function gets ready to interact with the contract by setting it up with the provided contract address and the ABI (contract blueprint). This allows the function to communicate directly with the deployed smart contract.

  5. Fetch Data from the Contract: The contract’s function is called using the inputs you provided (e.g., addresses, token amounts). It fetches the data you want from the blockchain, like checking balances or getting transaction details.

  6. Prepare the Data: Once the data is retrieved from the contract, it’s formatted and stored in a special variable for later use. This makes it easier to read and use later in your project.

  7. Success Notification: After the data is successfully retrieved and stored, the function triggers an event to let you know the contract data has been received. This is like a notification saying the task is complete.

  8. Error Handling: If anything goes wrong—whether it’s an issue with the function, inputs, or blockchain interaction—the error is logged and you’ll get a message explaining what went wrong. This helps you understand and fix the issue quickly.

Once the data is successfully read, the action updates the last read contract data, which can be retrieved using the Get Last Read Contract Data expression. Additionally, the On Contract Data Received condition is triggered, indicating that the data has been successfully retrieved from the contract.

Usage Example:

Read multiple data request

The Read Multiple Contract Data action allows for reading data from multiple functions of a smart contract in a single request. This is particularly useful when you need to fetch various pieces of data from a contract without making multiple separate requests, thus improving efficiency

Action Parameters:

  • Contract Address: The address of the smart contract to interact with.

"0x35214dc712C4F1571ec7F6cf957c3050ca8e863D" // example
  • ABI: A JSON stringified representation of the contract's ABI (Application Binary Interface). The ABI defines the functions and events of the contract.

[
    {
        "inputs": [
            {
                "internalType": "uint256",
                "name": "_tokenId",
                "type": "uint256"
            }
        ],
        "name": "tokenMaxMints",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "_wallet",
                "type": "address"
            },
            {
                "internalType": "uint256",
                "name": "_tokenId",
                "type": "uint256"
            }
        ],
        "name": "walletMintsOf",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    }
] // example
  • Function Names: A JSON stringified array containing the names of the functions to call. Each function should be present in the provided ABI.

"['tokenMaxMints','walletMintsOf']" // example
  • Inputs Data: A JSON stringified array where each element corresponds to the input data for each function being called. The input data should match the number and order of arguments expected by each function.

"[[1],['"&userAccount&"', 1]]" // example

Process Flow:

  1. Reading the Contract's Blueprint (ABI): The ABI is like the instructions manual for a smart contract. This function reads the ABI to understand what the contract can do. If there’s a problem with this step, like if the ABI isn’t formatted properly, it will stop and let you know.

  2. Understanding What Functions and Inputs Are Needed: The function names (what the contract is supposed to do) and the input data (the details the contract needs to perform those functions) are checked. It makes sure everything matches correctly. For example, if you’re trying to use a function that doesn’t exist or provide the wrong details, it will stop and show an error.

  3. Connecting to the Blockchain: The function connects to the blockchain using the URL you’ve provided. This step is important because it allows the function to communicate with the smart contract and ask it to do something.

  4. Setting Up Communication with the Contract: Once connected, the function sets up a way to talk to the smart contract by using the ABI and contract address. This is like opening a channel to send requests to the contract.

  5. Calling Multiple Functions: The function then goes through each of the functions you’ve listed, checks that it exists in the contract, and makes sure the inputs are correct. If everything matches, it will call the contract to perform that action. If something doesn’t match, it will stop and inform you.

  6. Running Everything at Once: Since multiple functions can be called, the function handles them all at the same time in the background. This means it can get all the results as quickly as possible without waiting for each one individually.

  7. Saving the Results: Once the contract has completed all its tasks, the results are organized and saved for future use. You’ll be able to see the results in a format that’s easy to understand.

  8. Notifying You When It’s Done: After everything is completed successfully, the function sends a signal (OnMultipleReadContractDataReceived) to let you know the process is finished and the data is ready.

  9. Handling Problems: If something goes wrong at any step—whether it’s a missing function, wrong input, or an issue connecting to the blockchain—the function logs the problem and alerts you with an error message, so you can fix it easily.

Once the data is successfully read, the action updates the last multiple-read contract data, which can be retrieved using the Get Multiple Last Read Contract Data expression. Additionally, the On Multiple Contract Data Received condition is triggered, indicating that the data has been successfully retrieved from the contract.

Usage Example:

Send Crypto tokens

The Send Crypto action enables the user to send a specified amount of cryptocurrency (native token or ERC-20 tokens) to a given recipient's address. The function automatically switches to the target chain if necessary and uses either the native chain token (e.g., ETH, MATIC) or tokens from a specified contract address.

Action Parameters:

  • Token Address (optional): The contract address of the token being transferred (leave empty (e.g. "") for native currency)

"0x2ef45c9eE0B16acBE87D0f0ac50cE0f67993e923" // example
"1000000000000000000" // example
  • Receiver: The address of the recipient who will receive the funds

"0x32Be343B94f860124dC4fEe278FDCBD38C102D88" // example

Process Flow:

  1. Native Token Transfer: If no token address is provided, the function will treat this as a native cryptocurrency transfer. It estimates the gas required, gets the current gas price, and sends the specified amount to the receiver's address.

  2. Token Transfer: If a token address is provided, the function will transfer an ERC-20 token by interacting with the transfer method from the ERC-20 ABI. It estimates the gas for the transaction, retrieves the gas price, and performs the transfer.

  3. Transaction Status Tracking: The transaction status is set to pending when the transaction starts. It waits for the transaction confirmation, using a timeout of 120 seconds. During this period, the function periodically checks if the transaction has been confirmed by retrieving its receipt. If confirmed, the status is updated to success; if not, it is set to error.

  4. Error Handling: If the transaction fails, or if the confirmation timeout is reached, an error is thrown.

Once the transaction is successfully sent, the action triggers the On Transaction Sent condition, and the transaction hash can be retrieved using the Get Last Transaction Hash expression.

Usage Example:

Life scenario based on the shop functionality (testnet)

Current player score retrieval step

Player token balance retrieval

  • Contract Address "0x35214dc712C4F1571ec7F6cf957c3050ca8e863D"

  • ABI [ { "inputs": [ { "internalType": "address[]", "name": "accounts", "type": "address[]" }, { "internalType": "uint256[]", "name": "ids", "type": "uint256[]" } ], "name": "balanceOfBatch", "outputs": [ { "internalType": "uint256[]", "name": "", "type": "uint256[]" } ], "stateMutability": "view", "type": "function" } ]

  • Function Name balanceOfBatch

  • RPC URL "https://rpc-amoy.polygon.technology/"

The contract address "0x35214dc712C4F1571ec7F6cf957c3050ca8e863D" contains a function called balanceOfBatch. This function takes two inputs:

  1. An array of account addresses (in this case, three instances of the userAccount, which represents the player's wallet address).

  2. An array of token IDs ([1, 2, 3]), which correspond to the different spaceships or NFTs the player can own.

The purpose of calling this function is to fetch the balances of these tokens (IDs 1, 2, and 3) for the player's account. The contract will return an array of balances for each of the requested token IDs, where:

  • A positive value means the player owns the corresponding token.

  • A value of 0 means the player does not own that token.

For example, the input data would look like this: [['userAccount', 'userAccount', 'userAccount'], [1, 2, 3]], which asks for the balances of token IDs 1, 2, and 3 for the player's account (userAccount).

By calling this function, we want to determine which spaceships the player owns and how many of each, allowing us to update the shop interface based on their ownership status.

    // Define ship mappings for better maintainability
    const shipMappings = [
      { name: "Cerbal_3", id: 3 },
      { name: "Cerbal_2", id: 2 },
      { name: "Cerbal_4", id: 4 },
    ];
    const DEFAULT_SHIP_NAME = "Cerbal_1";
    const DEFAULT_SHIP_ID = 1;

    const selectedShip = runtime.globalVars.SelectedShip;
    const userNftBalances =
      runtime.objects.JSON.getFirstInstance().getJsonDataCopy().userNfts; // Example response: [1, 1, 0]

    // Enrich the NFT data with ship information
    const enrichedNfts = userNftBalances.map((balance, index) => ({
      ...shipMappings[index],
      balance: Number(balance),
    }));

    // Function to update button and availability
    const updateShipInfo = (nft) => {
      const shipButton =
        runtime.objects[ShopButtonTextc${nft.id}].getFirstInstance();
      const availableVarName = c${nft.id}Available;

      if (nft.name === selectedShip) {
        runtime.globalVars[availableVarName] = 1;
        shipButton.text = "SELECTED";
      } else if (nft.balance > 0) {
        runtime.globalVars[availableVarName] = 1;
        shipButton.text = "SELECT";
      } else {
        const shipData = runtime.objects[nft.name].getFirstInstance().instVars;
        runtime.globalVars[availableVarName] = 0;
        shipButton.text = ${shipData.Price} PT;
      }
    };

    // Update each NFT's info based on selection and balance
    [
      ...enrichedNfts,
      { name: DEFAULT_SHIP_NAME, id: DEFAULT_SHIP_ID, balance: 1 },
    ].forEach(updateShipInfo);

This code is responsible for managing and updating the availability and status of different spaceships in a game shop based on the player's ownership and selection.

  1. Spaceship List: The game has several spaceships (like Cerbal_2, Cerbal_3, etc.), each represented by an ID. There is also a default ship (Cerbal_1).

  2. Player's Ownership: The game checks which spaceships the player owns by looking at their NFT balances, which are retrieved from the previously read contract data and saved in a local JSON. If the player owns a specific spaceship, the balance for that ship will be greater than 0. The userNfts data is stored in a JSON format like this:

    {
        "userNfts": [
            1,   // Player owns token 1 
            0,   // Player does not own token 2 
            1    // Player owns token 3
        ]
    }

    In this example, we are checking tokens [1, 2, 3], and each result represents the balance for the corresponding spaceship at the same index. So, token 1 has a balance of 1 (owned), token 2 has a balance of 0 (not owned), and token 3 has a balance of 1 (owned).

  3. Ship Button Updates: For each spaceship, the code updates the corresponding button in the shop:

    • If the player selected a spaceship (comparing it to the selectedShip global variable), the button displays "SELECTED."

    • If the player owns a spaceship but hasn’t selected it, the button displays "SELECT."

    • If the player doesn’t own the spaceship, the button displays the spaceship's price in points (PT).

In short, this logic ensures the shop displays the correct options (price, select, or selected) for each spaceship based on the player's ownership and current selection.

Player token mints count and max token mints retrieval

  • Contract Address "0x35214dc712C4F1571ec7F6cf957c3050ca8e863D"

  • ABI [ { "inputs":[ { "internalType":"uint256", "name":"_tokenId", "type":"uint256" } ], "name":"tokenMaxMints", "outputs":[ { "internalType":"uint256", "name":"", "type":"uint256" } ], "stateMutability":"view", "type":"function" }, { "inputs":[ { "internalType":"address", "name":"_wallet", "type":"address" }, { "internalType":"uint256", "name":"_tokenId", "type":"uint256" } ], "name":"walletMintsOf", "outputs":[ { "internalType":"uint256", "name":"", "type":"uint256" } ], "stateMutability":"view", "type":"function" } ]

  • Function Names "['tokenMaxMints','walletMintsOf','tokenMaxMints','walletMintsOf','tokenMaxMints','walletMintsOf']"

  • RPC URL "https://rpc-amoy.polygon.technology/"

We are interacting with a smart contract at the address:

Contract Address: "0x35214dc712C4F1571ec7F6cf957c3050ca8e863D"

We are using two functions—tokenMaxMints and walletMintsOf—to retrieve specific data for each spaceship (NFT) the player interacts with. The purpose of this call is twofold:

  1. tokenMaxMints: This function checks the maximum number of times each specific NFT (spaceship) can be minted by a player. For example, we want to know the maximum minting limit for token IDs 1, 2, and 3 (which correspond to different spaceships).

  2. walletMintsOf: This function checks how many times the player has already minted a specific NFT. We will check this for the current player’s wallet (userAccount) and for each spaceship (NFT token IDs 1, 2, and 3).

The input data is structured as follows:

  • The first parameter for tokenMaxMints is the token ID (1, 2, or 3).

  • The parameters for walletMintsOf include the player's wallet address (userAccount) and the token ID (1, 2, or 3).

For example:

  • tokenMaxMints(1) retrieves the maximum number of times the player can mint the first spaceship.

  • walletMintsOf(userAccount, 1) retrieves how many times the player has already minted the first spaceship.

  • This same process is repeated for token IDs 2 and 3.

So, we are calling multiple functions to:

  • Retrieve the maximum number of mints allowed per player for tokens 1, 2, and 3.

  • Retrieve the number of times the current player (userAccount) has already minted tokens 1, 2, and 3.

By combining these results, we can determine both the minting limit and the player's current minting status for each spaceship.

// Retrieve all instances of the objects
const ShopMaxMintsTextInstances = runtime.objects.ShopMaxMintsText.getAllInstances();
const ShopCurrentMintsTextInstances = runtime.objects.ShopCurrentMintsText.getAllInstances();

// Define function mappings for better maintainability
const functionMapping = [
  { name: 'tokenMaxMints', tag: 'C3' },
  { name: 'walletMintsOf', tag: 'C3' },
  { name: 'tokenMaxMints', tag: 'C2' },
  { name: 'walletMintsOf', tag: 'C2' },
  { name: 'tokenMaxMints', tag: 'C4' },
  { name: 'walletMintsOf', tag: 'C4' },
];

// Example data for max mints
const tokenMaxMints = runtime.objects.JSON.getFirstInstance().getJsonDataCopy().tokensMaxMints; // Example: [10, 0, 5, 0, 1, 0]

// Validate the length of `tokenMaxMints` to avoid out-of-bounds issues
if (tokenMaxMints?.length < functionMapping.length) {
  console.warn('Mismatch between tokenMaxMints length and functionMapping length.');
}

// Iterate over function mappings and update the instances
functionMapping.forEach((fn, index) => {
  // Ensure we don't exceed the bounds of the tokenMaxMints array
  if (index >= tokenMaxMints.length) {
    console.warn(`Index ${index} is out of bounds for tokenMaxMints.`);
    return;
  }

  // Update text for ShopMaxMintsText instances when the name matches 'tokenMaxMints'
  if (fn.name === 'tokenMaxMints') {
    ShopMaxMintsTextInstances.forEach((instance) => {
      if (instance.hasTags(fn.tag)) {
        instance.text = String(tokenMaxMints[index]);
      }
    });
  } else {
    // Update text for ShopCurrentMintsText instances when the name matches 'walletMintsOf'
    ShopCurrentMintsTextInstances.forEach((instance) => {
      if (instance.hasTags(fn.tag)) {
        instance.text = String(tokenMaxMints[index]);
      }
    });
  }
});

This code updates the display in a game shop to show how many times a player can mint (create) a specific spaceship (NFT) and how many they have already minted. Here's how it works:

  1. Text Objects: The game has text objects that show two things:

    • The maximum number of mints allowed for each spaceship (ShopMaxMintsText).

    • The number of mints the player has already done for each spaceship (ShopCurrentMintsText).

  2. Mapping Spaceships: The code uses a predefined list (called functionMapping) to match each spaceship with its minting information (maximum mints and current mints). Each spaceship in the game is identified by a tag like C3, C2, or C4, which helps the code find the correct spaceship to update.

  3. Pulling Mint Data: The data about minting is stored in a JSON format, which looks like this:

    {
        "tokensMaxMints": [
            5,   // Max mints for token 1 (tokenMaxMints)
            0,   // Mints already done for token 1 (walletMintsOf)
            10,  // Max mints for token 2 (tokenMaxMints)
            0,   // Mints already done for token 2 (walletMintsOf)
            1,   // Max mints for token 3 (tokenMaxMints)
            0    // Mints already done for token 3 (walletMintsOf)
        ]
    }
    • The first number (e.g., 5, 10, 1) shows how many times the player can mint that spaceship.

    • The second number (e.g., 0, 0, 0) shows how many times the player has already minted that spaceship.

  4. Updating the Shop: The code checks if the data is correct and avoids errors. Then, based on the tag (like C3, C2, or C4), it updates the text for each spaceship in the shop to show the current mint status, such as:

    • "Mints 5" (how many times you can mint this spaceship).

    • "of 0" (how many times a player already minted it).

In summary, this code ensures the shop accurately shows how many times the player can mint each spaceship and how many they’ve already minted.

Minting

In order to purchase a spaceship in the Stellar Ride shop, we first need to mint the NFT that corresponds to the selected spaceship. Our application allows this action if the player does not already own the given NFT and has a sufficient number of points in their account (current balance). When these conditions are met, on the On touch event, we call the defined function mintShip (1) to initiate the process of interacting with the smart contract and the subsequent logic involved in purchasing the spaceship.

  • Contract Address "0x35214dc712C4F1571ec7F6cf957c3050ca8e863D"

  • ABI [ { "inputs": [ { "internalType": "address", "name": "_to", "type": "address" }, { "internalType": "uint256", "name": "_tokenId", "type": "uint256" }, { "internalType": "uint256", "name": "_amount", "type": "uint256" }, { "internalType": "bytes", "name": "data", "type": "bytes" } ], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]

  • Function Name "mint"

  • Chain ID 80002

We are interacting with a smart contract at the address:

Contract Address: "0x35214dc712C4F1571ec7F6cf957c3050ca8e863D"

The contract has a mint function that allows us to mint (create) a new NFT for the player. Here's how the process works:

  1. Function Name: The function we are calling is named mint.

  2. Input Parameters:

    • _to: The player's wallet address, represented by the userAccount variable. This is the address to which the minted NFT will be assigned.

    • _tokenId: The ID of the spaceship (NFT) being minted, passed as the tokenID variable from function parameter.

    • _amount: The number of NFTs to mint, passed as the amount variable from function parameter (usually 1).

    • data: An additional data parameter, passed as '0x', which is commonly used as a placeholder in minting operations.

  3. Chain ID: The transaction will be executed on the blockchain with Chain ID 80002, which represents the testnet version of Polygon (Amoy).

  4. Action: We are sending a transaction using the mint function of the contract. This transaction will mint the specified spaceship NFT for the player, transferring it to their wallet address (userAccount).

Purpose:

  • The goal of this transaction is to mint a new spaceship (NFT) for the player if they meet the required conditions (sufficient balance, not already owning the spaceship).

const processedShipName = runtime.globalVars.processedShipName
const shipData = runtime.objects[processedShipName].getFirstInstance().instVars

runtime.callFunction("onShipsHasMinted", shipData.Price, processedShipName)
  • The price of the spaceship (shipData.Price).

  • The local name of the spaceship (e.g., Cerbal_2).

The spaceship data is retrieved from the Construct instance by using the processedShipName to reference the specific spaceship currently being processed.

Stellar Ride shop UI

Shop event sheet from Construct 3

Chain ID: The target chain ID (in decimals) specifies the blockchain network where the transaction will be sent.

RPC URL: The URL of the Remote Procedure Call (RPC) endpoint for interacting with the blockchain.

RPC URL: The RPC endpoint for interacting with the blockchain.

Amount: The amount of cryptocurrency or token to be sent. Provided in proper stringified unit. For unit conversion look:

Chain ID: The target blockchain network (in decimals) on which the transaction will be executed.

The first thing we do in the On start layout event is call the action from the metapro plugin (1) to determine the user's current points balance. After retrieving it, we assign the value fetched from the metapro plugin's (2) to the global variable currentScore. Based on this, we are able to assign the value to the text object Shop_CurrentScore_Text.

Each of the following spaceship (except the default one) is a representation of an ERC-1155 token, which a player can own upon purchase (minting), provided they have sufficient funds. On the On start layout event, we call a defined function in Construct 3 called getUserTokenBalance (1). The given function contains a call to the action (2) from the metapro plugin, which accepts the following parameters:

Input Data "[['"& userAccount &"', '"& userAccount &"', '"& userAccount &"'], [1,2,3]]" NOTE: The global variable userAccount is fetched from the metapro plugin's expression, which represents the user's account retrieved from the Web 3 provider at the start of the application.

When the contract data is successfully read, the event (3) is triggered, where we retrieve the saved data from the expression into a JSON under the key userNfts. This is done to further process the data and determine the status of the buttons under each spaceship in the shop—the function updateShipData (4) is responsible for this. updateShipData script:

On the On start layout, we call the getTokenMaxMints function (1) to determine how many of each specific NFT the player has already minted and what the maximum minting limit per player is. The given function contains the action (2) from the metapro plugin, which will check the above data for each spaceship. To achieve this, we will use the following parameters:

Input Data "[[1],['"&userAccount&"', 1], [2],['"&userAccount&"', 2], [3],['"&userAccount&"', 3]]" NOTE: The global variable userAccount is fetched from the metapro plugin's expression, which represents the user's account retrieved from the Web 3 provider at the start of the application.

When the data is successfully received, the event (3) will be triggered, indicating that we can retrieve the data using the expression. This data will be used to set the labels under each spaceship as follows: MINTS ${number_of_user_mints} of ${number_of_token_max_mints}. Script:

The mintShip function accepts parameters specifying the token ID of the spaceship being minted and the local name we have assigned to that specific spaceship. The first thing we do is set the global variable processedShipName to the value of shipName, indicating that a minting process is underway and specifying which spaceship is being processed in the transaction. Next, we set the properties of a modal on the UI to inform the player that the transaction is in progress. Finally, we call the actual action (2) from the metapro plugin, which is responsible for minting the selected NFT on the blockchain for the player. To achieve this, we will use the following parameters:

Input Data "['"& userAccount & "', "& tokenID &", "& amount &", '0x']" NOTE: The global variable userAccount is fetched from the metapro plugin's expression, which represents the user's account retrieved from the Web 3 provider at the start of the application.

Once the transaction is successfully executed on the blockchain, the spaceship (NFT) will be transferred to the player's account and we will receive a transaction hash from expression.

When the transaction is confirmed (appears on the blockchain), the event is triggered. Our application checks if the global variable processedShipName has a value assigned, which indicates that we are currently minting a spaceship. If this condition is met, we run a script that calls the function onShipHasMinted (3). This function is passed information from the Construct instance variables of the spaceship. The spaceship data includes:

The function onShipHasMinted, triggered after a successful blockchain transaction, begins by updating the player's current score through the action from the metapro plugin. It then updates the text displayed on the UI using the expression. The global variable selectedShip is set to the newly minted local name of the spaceship, indicating that the player has selected this spaceship as active for the game. Next, we reset the transaction-related variables, such as processedShipName, modal properties used on the UI, and using the action from the metapro plugin, we change the transaction status back to "initial". Additionally, we refresh the player's data by calling and .

During the minting process (when the variable processedShipName is different from an empty string), every second we listen for potential errors. To do this, we check the expression from the metapro plugin to see if it is equal to "error". If at any point the transaction throws an error (indicating that the minting process has failed), we inform the player by updating the modal properties on the UI and reset the transaction-related variables, just as we would in the case of a successful transaction.

👨‍💻
https://chainlist.org/
https://chainlist.org/
https://chainlist.org/
https://etherscan.io/unitconverter
https://chainlist.org/
Read contract data
On Contract Data Received
Get Last Read Contract Data
Read Multiple Contract Data
On Multiple Contract Data Received
Get Multiple Last Read Contract Data
Send contract transaction
Get Last Transaction Hash
On Transaction Sent
Get Transaction Status
https://amoy.polygonscan.com/address/0x35214dc712C4F1571ec7F6cf957c3050ca8e863D#code
Set transaction status
getUserTokenBalance
getTokenMaxMint
Request user score
Get Current Score expression
Update user score
Get Current Score
Get Account
Get Account
Get Account