Sui.

Explore

Connect with communities and discover new ideas.

Sui.X.Peera.

Earn Your Share of 1000 Sui

Gain Reputation Points & Get Rewards for Helping the Sui Community Grow.

Communities

Bounty

  • Xavier.eth.Peera.
    ForSuiJun 27, 2025
    +15

    Sui Transaction Failing: Objects Reserved for Another Transaction

    I'm encountering a persistent JsonRpcError when trying to execute transactions on Sui. The error indicates that objects are reserved for another transaction, even though I've implemented sequential transaction processing with delays. JsonRpcError: Failed to sign transaction by a quorum of validators because one or more of its objects is reserved for another transaction. Other transactions locking these objects: AV7coSQHWg5vN3S47xada6UiZGW54xxUNhRv1QUPqWK (stake 33.83) 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9 I've tried: Sequential transaction execution (waiting for previous transaction to complete) Added 3-second delays between transactions And still getting the same error consistently. Using Sui RPC for transaction submission. The same object ID appears multiple times in the lock list. Error occurs even with careful transaction sequencing. What causes objects to be "reserved" for other transactions? How can I properly check if an object is available before using it in a transaction? Are there best practices for handling object locks in Sui? Could this be related to transaction finality timing? Has anyone encountered this issue before? Any insights on proper object management in Sui transactions would be greatly appreciated!

    2
    4
  • Xavier.eth.Peera.
    ForSuiJun 17, 2025
    +15

    How do ability constraints interact with dynamic fields in heterogeneous collections?

    I'm building a marketplace that needs to handle multiple asset types with different ability requirements, and I've hit some fundamental questions about Move's type system. I want to store different asset types in the same collection, but they have different abilities: Regular NFTs: key + store (transferable) Soulbound tokens: key only (non-transferable) Custom assets with transfer restrictions public struct Marketplace has key { id: UID, listings: Bag, // Want to store different asset types here } // This works for transferable assets public fun list_transferable( marketplace: &mut Marketplace, asset: T, price: u64 ) { /* ... */ } // But how to handle soulbound assets? public fun list_soulbound( // No store ability marketplace: &mut Marketplace, asset_ref: &T, // Can only take reference price: u64 ) { /* How do I store metadata about this? */ } Key Questions: Ability Requirements: When using dynamic_field::add(), does V always need store at compile time? Can wrapper types work around this? Heterogeneous Storage: Can a single Bag store objects with different ability sets (key + store + copy vs key + store), and handle them differently at runtime? Type Safety: Since dynamic fields perform type erasure, how do I maintain type safety when retrieving values? What's the pattern for storing type metadata? Witness Pattern: How do ability constraints work with phantom types? Can I store Asset and Asset in the same collection and extract type info later? Building a system where NFTs, soulbound tokens, and restricted assets all need marketplace functionality but with different transfer semantics. I’ve tried wrapper types, multiple collections per ability set, separate type metadata storage. Each has tradeoffs between type safety, gas costs, and complexity.

    0
    4
  • Peera Admin.Peera.
    ForSuiMay 29, 2025
    +10

    Why does BCS require exact field order for deserialization when Move structs have named fields?

    Why does BCS require exact field order for deserialization when Move structs have named fields? I've been diving deep into BCS encoding/decoding in Move, particularly for cross-chain communication and off-chain data processing. While working through the examples in the Sui Move documentation, I encountered some behavior that seems counterintuitive and I'm trying to understand the underlying design decisions. According to the BCS specification, "there are no structs in BCS (since there are no types); the struct simply defines the order in which fields are serialized." This means when deserializing, we must use peel_* functions in the exact same order as the struct field definition. My Specific Questions: Design Rationale: Why does BCS require exact field order matching when Move structs have named fields? Wouldn't it be more robust to serialize field names alongside values, similar to JSON or other self-describing formats? Generic Type Interaction: The docs mention that "types containing generic type fields can be parsed up to the first generic type field." Consider this structure: struct ComplexObject has drop, copy { id: ID, owner: address, metadata: Metadata, generic_data: T, more_metadata: String, another_generic: U } How exactly does partial deserialization work here? Can I deserialize up to more_metadata and ignore both generic fields, or does the first generic field (generic_data) completely block further deserialization? Cross-Language Consistency: When using the @mysten/bcs JavaScript library to serialize data that will be consumed by Move contracts, what happens if: I accidentally reorder fields in the JavaScript object? The Move struct definition changes field order in a contract upgrade? I have nested structs with their own generic parameters? Practical Implications: In production systems, how do teams handle BCS schema evolution? Do you version your BCS schemas, or is the expectation that struct field order is immutable once deployed?

    5
    3

Newest

  • harry phan.Peera.
    ForSuiJul 08, 2025

    Sui CLI Cheat Sheet part 2

    Gas and Faucet with Sui CLI When you’re developing your apps, ideally, you’ll start out on devnet, then testnet before deploying to mainnet. Devnet and Testnet gas are free to acquire. But mainnet? nah. You can easily request gas on devnet with the client faucet command: sui client faucet For testnet, you’ll need to execute this cURL command to request gas: curl --location --request POST 'https://faucet.devnet.sui.io/v1/gas' \ --header 'Content-Type: application/json' \ --data-raw '{ "FixedAmountRequest": { "recipient": "" } }' You can also visit the official Sui faucet website to claim some Devnet and Testnet tokens. Use the client gas command to check the client’s available gas tokens on the current environment. sui client gas For mainnet transactions, you’ll need to acquire Sui from exchanges and fund your wallet. Publishing Packages You can publish packages on to the Sui network with the client publish command. sui client publish [OPTIONS] [package_path] Here’s an example command for publishing a package with 5000000 MIST gas budget. sui client publish --gas-budget 5000000 The gas budget isn’t fixed, you most likely want to check onchain for a suitable gas amount and pay it forward. Coin Management with Sui CLI When you’re working with SUI coins, You’ll probably need to merge and split them often—especially when youjuggling gas or sending different amounts to various contracts or users. If you’ve have two coins lying around, and you want to consolidate them, use the merge-coin command like this: sui client merge-coin --primary-coin --coin-to-merge The primary-coin is the one you’ll keep, and the coin-to-merge is the one that gets absorbed. Need to split a coin instead? Maybe you want to pay out to multiple recipients or just need different denominations. You can slice a coin up using split-coin like this: sui client split-coin --coin-id --amounts If you need to send out coins, you’ll use the client transfer-sui command like this: sui client transfer-sui --sui-coin-object-id --to It’s a simple handoff—you give it the coin ID and the recipient’s address, and it moves the funds. Sui has programmable transactions so you can send to multiple recipients at once with the pay-sui command: sui client pay-sui --input-coins --recipients --amounts You’ll pass a coin (or a list of coins), and then specify the recipients and how much each should get. It’s perfect for batch payments or distributing tokens in bulk. Object Management with Sui CLI Sui is all about objects. Contracts, tokens, and even your coins—they're all objects. To get detailed info on any object, just call: sui client object This will spit out all the metadata, owner info, and anything else the object is carrying. If your object has dynamic fields (like a registry or a growing data structure), you can dig into those too: sui client dynamic-field This is very handy feature you might use often during development. Programmable Transaction Blocks (PTBs) Sui is one of the few chains with native PTBs. Programmable Transaction Blocks let you bundle multiple operations into a single transaction—kinda like a mini-script that executes on-chain. Say you need to call a Move function directly from your CLI. You’ll do that like this: sui client ptb --move-call :::: "" Replace the package address, module name, and function you’re targeting. Then drop in the type and arguments as needed. And if you want to transfer multiple objects to another wallet in one go, you can use PTBs as well: sui client ptb --transfer-objects "[]" Wrap the object IDs in brackets if you’re sending more than one, and finish it off with the recipient’s address. Conclusion Hopefully, this article suffices for introducting you to the Sui CLI tool. It’s more than a client, there’s a lot you can do with this tool. If you ever need a quick refresher or you’re trying out a new command, make the Sui CLI Cheat Sheet your best friend. And when in doubt, the Sui Client CLI Docs have the full breakdown.

    0
  • harry phan.Peera.
    ForSuiJul 08, 2025

    Sui CLI Cheat Sheet part 1

    When developing smart contracts, it’s also essential to create a client that can interact with them. Beyond just pulling data from the blockchain, clients can also read from and execute functions defined by the contract’s available primitives. One of the most convenient tools for this job is the Sui CLI, as it allows you to make command-line calls from virtually any programming language you choose to use for your client. In this guide, I’ll walk you through the key commands you’ll commonly use while working with Sui. Getting Started with Sui CLI To begin, you’ll need to install the Sui CLI on your machine. The installation process depends on your operating system and preferred package manager. If you’re using a Unix-based system like macOS or Linux and have Homebrew installed, simply run the following command in your terminal to install the Sui CLI: brew install sui Execute this command on your terminal to install Sui CLI if you’re running Windows via Chocolatey: choco install sui Another route you can use is the Cargo (Rust package manager) route. First, you’ll need to have Rust installed (ships with cargo) and then execute this command to install Sui CLI. cargo install --locked --git https://github.com/MystenLabs/sui.git --branch testnet sui --features tracing You can always execute the --version flag to verify your installation and check the version of Sui CLI you have installed. sui --version One flag you’ll use frequently is the—- help flag for the description of every command: sui --help It works with almost every command. It should be your mantle whenever you’re stuck: Regardless of the command using -h or --help for help would always be handy. Environment Management with Sui CLI Every chain provides you with three fundamental networks: Mainnet, Testnet, and Devnet. You can also spawn a test chain locally to keep development in stealth mode. Here’s the command you’ll execute to spawn a local network. RUST_LOG="off,sui_node=info" sui start --with-faucet --force-regenesis The command calls the Sui CLI binary to start a faucet service and generate a new genesis block without persisting the local network state. Now, you can connect to the local network with the new-env command like this: sui client new-env --alias local --rpc sui client new-env --alias local --rpc http://127.0.0.1:9000 You can switch and activate any environment with this general command. sui client switch --env Now, you can use this command to set the active environment to the new local environment you’ve created. sui client switch --env local The command switches the currently active environment to the local network you’re running. Address and Key Management with Sui CLI You’ll be switching keys as you deploy smart contracts over the Sui CLI, so here’s how to do that. You can view the currently active address with the active-address command: sui client active-address You can list all the addresses in your client with the addresses command. sui client addresses You can switch addresses as you please with the --address flag before specifying the address. Key Management with Sui CLI When building your apps, for security or other reasons, you might want to run CLI commands to work with keys. The keytool command is You can list all the keys in a keystore with the list command like this: sui keytool list You can generate keys with the generate command followed with a specification of the scheme. sui keytool generate [OPTIONS] [DERIVATION_PATH] [WORD_LENGTH] You’re probably familiar with the ed25519 since that’s what most wallets use. Specify it like this. sui keytool generate ed25519 You should get the output with the Sui address, mnemonic and other details. sui keytool import "" ed25519 When you’ve imported it, you can switch to the keypair and start sending transactions with it.

    0
  • Sui Maxi.Peera.
    ForSuiJul 08, 2025

    What is a Dex Aggregator

    Let’s say you want to swap 1 SUI for USDC. The market rate says 1 SUI = 3 USDC, so you expect to receive 3 USDC in return. But when you actually make the trade, you end up with only 2.9 USDC. That 0.1 USDC loss is due to slippage—the price impact caused by shallow liquidity in the pool you're swapping through. This is where DEX aggregators come in. What Is a DEX Aggregator? A DEX aggregator is a powerful tool that helps you find the best price for your trade by scanning multiple decentralized exchanges (DEXs) in the ecosystem. Instead of routing your swap through just one pool, it looks across all available liquidity sources and chooses the most efficient route to reduce slippage and maximize returns. Two Types of Aggregators 1. Off-Chain Aggregators (Backend) These services run on a centralized backend that constantly queries DEX prices, simulates swap outcomes, and determines the best path. The final swap route is sent to your wallet or frontend for execution. ✅ Faster calculations ❌ Requires trust in the backend logic 2. On-Chain Aggregators (Smart Contract) Built entirely on smart contracts, these aggregators calculate and execute routes directly on-chain. Thanks to Sui's Programmable Transaction Blocks (PTBs), these smart contracts can perform atomic routing, meaning the entire multi-hop swap is executed as one transaction, ensuring: ✅ No risk of partial swaps ✅ Fully trustless ✅ Composable with other DeFi protocols on Sui Example 7K Aggregator Cetus So How Do Aggregators Calculate the Best Route? To determine the optimal path, a DEX aggregator evaluates multiple factors: Liquidity Depth**: Pools with more liquidity cause less price impact Swap Fees**: Lower fees lead to better net returns Slippage**: The price impact of large trades Gas Efficiency**: Routes with fewer hops or contracts are cheaper Real-Time Pool Data**: Aggregators simulate swap results across paths By combining all these inputs, the aggregator selects the route (or combination of routes) that gives the highest return for the user.

    0

Unanswered

  • 0xduckmove.Peera.
    ForSuiJul 08, 2025

    Is there a way to merge coins and split them in the same transaction using the sui sdk?

    We can use CoinWithBalance intent The CoinWithBalance intent handles all operations, including splitting and merging coins. This means you don’t always need to manually map the object ID, merge, and then split—CoinWithBalance takes care of everything automatically. import { coinWithBalance } from "@mysten/sui/transactions"; const coin = coinWithBalance({ balance: 1000000000, type: "0x9f992cc2430a1f442ca7a5ca7638169f5d5c00e0ebc3977a65e9ac6e497fe5ef::wal::WAL", }); `

    0
    0
  • Owen.Peera.
    Owen486
    ForSuiJun 11, 2025

    How to update a merchant's key in ObjectTable when it changes in the struct?

    Hi everyone, I'm just getting started with writing smart contracts and I'm working on my very first project. I'd love some help with an issue I'm stuck on. So far, I’ve created a Merchant struct that looks like this: id: a unique identifier (UID) owner: the address of the merchant key: a String used as a unique key balance: a u64 representing their balance I also made a MerchantRegistry struct to manage all merchants: id: another UID merchant_to_address: an ObjectTable mapping addresses to merchants merchant_to_key: an ObjectTable mapping keys to merchants I want to be able to look up a merchant either by their address or by their key. When a user updates their key inside the Merchant struct, the change doesn’t automatically update the key in the merchant_to_key table. That means the old key still points to the merchant, which breaks things. I tried removing the entry from the table and inserting it back with the new key, but I keep running into errors like: "Cannot ignore values without drop ability" I'm pretty sure this is a beginner mistake, but I haven't been able to find a clear explanation or solution anywhere. Is there a proper way to handle updating the key in both the struct and the lookup table?

    5
    0
  • 0xduckmove.Peera.
    ForSuiJun 06, 2025

    Whats the easiest frontend to upload walrus blobs?

    just a simple ui to upload to walrus? (besides tusky)

    2
    0

Trending

  • Vens.sui.Peera.
    ForSuiApr 29, 2025

    AMM Bot in Sui Ecosystem

    What are the key features and functionalities of AMM bots within the Sui ecosystem? How do they improve upon traditional trading mechanisms, and what advantages do they offer to users engaging with DeFi protocols on the Sui network? Do I need to build one or I can use Turbos Finance for example

    8
    2
  • 0xduckmove.Peera.
    ForSuiApr 08, 2025

    👀 SEAL- I Think Web3 Data Privacy Is About to Change

    👀SEAL is Live on Sui Testnet – I Think Web3 Data Privacy Is About to Change In the Web3, it’s common to hear phrases like “users own their data” or “decentralized by design”. But when you look closely, many applications still rely on centralized infrastructures to handle sensitive data — using services like AWS or Google Cloud for key management. This introduces a contradiction: decentralization on the surface, centralization underneath. But what if there was a way to manage secrets securely, without giving up decentralization?Introducing SEAL – Decentralized Secrets Management (DSM), now live on the Sui Testnet. SEAL aims to fix one of Web3’s biggest hypocrisies: shouting decentralization while secretly using AWS You maybe ask me: What is SEAL? SEAL is a protocol that lets you manage sensitive data securely and decentrally – built specifically for the Web3 world. Think of it as a privacy-first access control layer that plugs into your dApp. You can think of SEAL as a kind of programmable lock for your data. You don’t just lock and unlock things manually — you write policies directly into your smart contracts, using Move on Sui. Let’s say you’re building a dApp where: Only NFT holders can unlock a premium tutorial Or maybe a DAO has to vote before sensitive files are revealed Or you want metadata to be time-locked and only accessible after a specific date SEAL makes all of that possible. The access control lives onchain, fully automated, no need for an admin to manage it. Just logic, baked right into the blockchain. SEAL makes all of that possible. The access control lives onchain, fully automated, no need for an admin to manage it. Just logic, baked right into the blockchain. Another interesting piece is how SEAL handles encryption. It uses something called threshold encryption, which means: no single node can decrypt the data. It takes a group of servers to work together — kinda like multi-sig, but for unlocking secrets. This distributes trust and avoids the usual single-point-of-failure problem. And to keep things truly private, SEAL encrypts and decrypts everything on the client side. Your data is never visible to any backend. It stays in your hands — literally — on your device. and SEAL doesn’t care where you store your data. Whether it’s IPFS, Arweave, Walrus, or some other platform, SEAL doesn’t try to control that part. It just focuses on who’s allowed to see what, not where things are stored. So yeah, it’s not just a library or API — it’s an onchain-first, access-controlled, privacy-by-default layer for your dApp. SEAL fills a pretty critical gap. Let’s break that down a bit more. If you’re building a dApp that deals with any form of sensitive data — gated content, user documents, encrypted messages, even time-locked NFT metadata — you’ll run into the same problem: ➡️ How do you manage access securely, without relying on a centralized service? Without something like SEAL, most teams either: Use centralized tools like AWS KMS or Firebase, which clearly goes against decentralization Or try to patch together half-baked encryption logic themselves, which usually ends up brittle and hard to audit https://x.com/EmanAbio/status/1908240279720841425?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1908240279720841425%7Ctwgr%5E697f93dc65359d0c8c7d64ddede66c0c4adeadf1%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fwww.notion.so%2Fharryph%2FSEAL-Launches-on-Sui-Testnet-1cc4f8e09bb380969c0dcc627b96cc22 Neither of those scales well. Especially not when you’re trying to build trustless apps across multiple chains or communities. SEAL makes that entire process modular and programmable. You define your access rules in Move smart contracts, and SEAL handles the rest — key generation, decryption approvals, and access enforcement — all without anyone manually issuing keys or running backend checks. Even better, those rules are auditable and immutable — once they’re onchain, they follow the contract, not a human admin. So instead of asking “who should manage access to this data?” you just ask: “What logic should define access?” …and let the chain handle it. Clean and scalable. That’s what makes SEAL relevant for more than just “security tools” — it’s a base layer for any dApp that cares about privacy, compliance, or dynamic access logic. It’s a small shift — but it changes a lot about how we think of data in Web3. Instead of encrypting after deployment, or relying on external services, you start with privacy built-in — and access handled entirely by smart contract logic. And that’s exactly what Web3 needs right now. How Does SEAL Actually Work? We’ve covered what SEAL is and why Web3 needs it, let’s take a look at how it’s actually built under the hood. This part is where things get more technical — but in a good way. The architecture is elegant once you see how all the pieces fit together. At a high level, SEAL works by combining onchain access logic with offchain key management, using a technique called Identity-Based Encryption (IBE). This allows devs to encrypt data to an identity, and then rely on smart contracts to define who is allowed to decrypt it. Step 1: Access Rules in Smart Contracts (on Sui) Everything starts with the smart contract. When you’re using SEAL, you define a function called seal_approve in your Move contract — this is where you write your conditions for decryption. For example, here’s a simple time-lock rule written in Move: entry fun seal_approve(id: vector, c: &clock::Clock) { let mut prepared: BCS = bcs::new(id); let t = prepared.peel_u64(); let leftovers = prepared.into_remainder_bytes(); assert!((leftovers.length() == 0) && (c.timestamp_ms() >= t), ENoAccess); } Once deployed, this contract acts as the gatekeeper. Whenever someone wants to decrypt data, their request will get checked against this logic. If it passes, the key gets released. If not, they’re blocked. No one has to intervene. Step 2: Identity-Based Encryption (IBE) Here’s where the magic happens. Instead of encrypting data for a specific wallet address (like with PGP or RSA), SEAL uses identity strings — meaning you encrypt to something like: 0xwalletaddress dao_voted:proposal_xyz PkgId_2025_05_01 (a timestamp-based rule) or even game_user_nft_holder When the data is encrypted, it looks like this: Encrypt(mpk, identity, message) mpk = master public key (known to everyone) identity = the logic-defined recipient message = the actual data Later, if someone wants to decrypt, the key server checks if they match the policy (via the seal_approve call onchain). If it’s approved, it returns a derived private key for that identity. Derive(msk, identity) → sk Decrypt(sk, encrypted_data) The user can then decrypt the content locally. So encryption is done without needing to know who will decrypt ahead of time. You just define the conditions, and SEAL figures out the rest later. It’s dynamic. Step 3: The Key Server – Offchain, But Not Centralized You might wonder: who’s holding these master keys? This is where SEAL’s Key Server comes in. Think of it as a backend that: Holds the master secret key (msk) Watches onchain contracts (like your seal_approve logic) Only issues derived keys if the conditions are satisfied But — and this is key — SEAL doesn’t rely on just one key server. You can run it in threshold mode, where multiple independent servers need to agree before a decryption key is issued. For example: 3-of-5 key servers must approve the request. This avoids central points of failure and allows decentralization at the key management layer too. Even better, in the future SEAL will support MPC (multi-party computation) and enclave-based setups (like TEE) — so you can get even stronger guarantees without compromising usability. Step 4: Client-Side Decryption Once the key is returned to the user, the actual decryption happens on their device. This means: The server never sees your data The backend never stores decrypted content Only the user can access the final message It’s a solid privacy model. Even if someone compromises the storage layer (IPFS, Arweave, etc.), they still can’t read the data without passing the access logic. Here’s the quick mental model: This structure makes it easy to build dApps where access rules aren’t hardcoded — they’re dynamic, auditable, and fully integrated into your chain logic. The Team Behind SEAL SEAL is led by Samczsun, a well-known figure in the blockchain security community. Formerly a Research Partner at Paradigm, he has audited and saved multiple ecosystems from major exploits. Now, he’s focused full-time on building SEAL into a core piece of Web3’s privacy infrastructure. With his background and credibility, SEAL is not just another experimental tool — it’s a serious attempt at making decentralized data privacy both practical and scalable. As SEAL goes live on the Sui Testnet, it brings a new standard for how Web3 applications can manage secrets. By combining onchain access control, threshold encryption, and client-side privacy, SEAL offers a more trustworthy foundation for decentralized data handling. Whether you’re building dApps, DAOs, or decentralized games — SEAL provides a powerful toolkit to enforce access control and protect user data without compromising on decentralization. If Web3 is going to move forward, secure infrastructure like SEAL is not optional — it’s essential

    8
  • MarlKey.Peera.
    ForSuiApr 30, 2025

    Is the only way to publish Move packages through an EOA?

    I assume there is no way on Sui chain as there is no module on chain which publishes packages.

    7
    3