[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-sui-sui-publish":3,"mdc-ktb76s-key":36,"related-repo-sui-sui-publish":3438,"related-org-sui-sui-publish":3542},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":25,"repoUrl":26,"updatedAt":27,"license":28,"forks":29,"topics":30,"repo":31,"sourceUrl":34,"mdContent":35},"sui-publish","publish and upgrade Sui Move packages","Publishing, upgrading, and deploying Sui Move packages. Use this skill when the user needs to publish a package, upgrade a published package, deploy to multiple networks, serialize transactions for multisig signing, run a local Sui network (localnet), prepare for Mainnet launch, monitor production deployments, or debug dry run failures. Also use when the user asks about sui client publish, sui client upgrade, UpgradeCap, upgrade policies, Published.toml, --serialize-output, localnet, mainnet launch checklist, gas estimation, multisig publishing, production monitoring, rollback, incident response, devInspectTransactionBlock, or --dry-run.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"sui","Sui (Mysten Labs)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fsui.png","MystenLabs",[13,16,19,22],{"name":14,"slug":8,"type":15},"Sui","tag",{"name":17,"slug":18,"type":15},"Web3","web3",{"name":20,"slug":21,"type":15},"Deployment","deployment",{"name":23,"slug":24,"type":15},"Smart Contracts","smart-contracts",9,"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fskills","2026-07-16T06:01:47.944662",null,2,[],{"repoUrl":26,"stars":25,"forks":29,"topics":32,"description":33},[],"Sui development skills maintained by Mysten Labs","https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fskills\u002Ftree\u002FHEAD\u002Fsui-publish","---\nname: sui-publish\ndescription: >\n  Publishing, upgrading, and deploying Sui Move packages. Use this skill when the\n  user needs to publish a package, upgrade a published package, deploy to multiple\n  networks, serialize transactions for multisig signing, run a local Sui network\n  (localnet), prepare for Mainnet launch, monitor production deployments, or debug\n  dry run failures. Also use when the user asks about sui client publish, sui client\n  upgrade, UpgradeCap, upgrade policies, Published.toml, --serialize-output, localnet,\n  mainnet launch checklist, gas estimation, multisig publishing, production monitoring,\n  rollback, incident response, devInspectTransactionBlock, or --dry-run.\n---\n\n# Publishing, Deploying & Local Network\n\n> **MCP tool:** When available in your environment, also query the Sui documentation MCP server (`https:\u002F\u002Fsui.mcp.kapa.ai`) for up-to-date answers. Use it for verification and for details not covered by these reference files.\n\n> **Source constraint:** All information sourced exclusively from [docs.sui.io](https:\u002F\u002Fdocs.sui.io) and [MystenLabs\u002Fsui-stack-hello-world](https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fsui-stack-hello-world).\n\n## Publishing a package\n\n### Canonical hello-world publish flow\n\nFor the full-stack starter, publish the existing hello-world package only:\n\n```bash\ncd sui-stack-hello-world\u002Fmove\u002Fhello-world\nsui move build\nsui client publish\n```\n\nUse the package ID from the publish output to update `sui-stack-hello-world\u002Fui\u002Fsrc\u002Fconstants.ts` (`TESTNET_HELLO_WORLD_PACKAGE_ID`). Do not publish a separate counter package, and do not create a second project directory.\n\n### Pre-publish checklist\n\n1. Verify your active environment: `sui client active-env`\n2. Verify you have SUI tokens: `sui client balance`\n3. Build successfully: `sui move build`\n\n### Publish\n\n```bash\nsui client publish\n```\n\nThis deploys the package to the active network and returns:\n\n- A unique **package ID** (use this for all future interactions)\n- An **UpgradeCap** object (sent to your address, controls future upgrades)\n- Object IDs for anything created during `init` functions\n\n### Test publishing (ephemeral networks)\n\nUse `sui client test-publish` to publish a package to an ephemeral environment for testing without persisting state to a real network:\n\n```bash\nsui client test-publish\n```\n\nThis publishes the package, runs `init` functions, and returns the same output as `sui client publish` (package ID, UpgradeCap, created objects), but the deployment is not permanent. Use it to:\n\n- Verify that `init` functions execute correctly before committing to a real publish\n- Test publish + upgrade flows in CI without consuming Testnet\u002FDevnet resources\n- Validate gas costs and object creation before a Mainnet deploy\n\n`test-publish` respects `--build-env` for multi-environment packages:\n\n```bash\nsui client test-publish --build-env testnet\n```\n\n### After publishing\n\nThe publish transaction output lists the package ID under the **created objects** section (alongside the `UpgradeCap` and any objects created by `init` functions). The `published-at` field is also automatically added to your `Published.toml`. To interact with the published package:\n\n```bash\n# Call a function\nsui client call --package \u003CPACKAGE_ID> --module greeting --function new\n\n# Query an object\nsui client object \u003COBJECT_ID>\n```\n\n### \"Your package is already published\" error\n\nIf you see this error when running `sui client publish`, it means `Published.toml` already has an entry for your active environment. This happens when iterating on a package during development.\n\n- To **publish to a different network**, switch environments with `sui client switch --env \u003CENV>` and run `sui client publish` again. The toolchain tracks published addresses per environment in `Published.toml` automatically — do not delete `Published.toml`.\n- To **upgrade** the existing package on the same network, use `sui client upgrade` (see below).\n\n### Upgrading a published package\n\nPublished packages are immutable, but you can upgrade by publishing a new version linked to the original. The `UpgradeCap` object controls upgrade authority. **Important:** you can restrict the `UpgradeCap` in the same PTB as the `publish` command — for example, publishing and immediately calling `sui::package::only_additive_upgrades` in one atomic transaction. You can also destroy it entirely to make the package permanently immutable (see upgrade policies below).\n\n```bash\nsui client upgrade --upgrade-capability \u003CCAP_ID>\n```\n\n#### Finding your UpgradeCap\n\nThe `UpgradeCap` object ID is needed for every upgrade. There are several ways to find it:\n\n1. **Published.toml** (preferred): After publishing, the toolchain records the cap ID in `Published.toml` under the `upgrade-capability` field for each environment.\n2. **Query owned objects**: List all `UpgradeCap` objects owned by the publish address:\n   ```bash\n   sui client objects --type 0x2::package::UpgradeCap\n   ```\n3. **Publish transaction output**: The original `sui client publish` output includes the `UpgradeCap` object ID in the created objects list.\n4. **Explorer**: Search for your address on SuiVision (`suivision.xyz`) or Suiscan (`suiscan.xyz`) and filter owned objects by type `0x2::package::UpgradeCap`.\n\n#### Upgrade policies\n\nUpgrade policies restrict what can change:\n\n- **Compatible** (default): The most permissive policy. See detailed rules below.\n- **Additive:** New modules can be added, but existing modules cannot change at all.\n- **Dependency-only:** Only dependency versions can be updated. No code changes.\n\n**Restricting the UpgradeCap in the same PTB as publish:** You can restrict the `UpgradeCap` in the same programmable transaction block as the `publish` command itself — for example, calling `sui::package::only_additive_upgrades` on the `UpgradeCap` immediately after publishing, all within a single atomic transaction. This is the recommended approach for locking down upgrade policy from the start. Once restricted, you cannot widen the policy.\n\n**Other UpgradeCap options:**\n- **Transfer to a multisig address** for shared upgrade governance.\n- **Destroy the UpgradeCap** to make the package permanently immutable. Call `sui::package::make_immutable`, which consumes and destroys the `UpgradeCap` object. Once the cap is destroyed, no one can ever upgrade the package again — this is irreversible.\n\n#### Compatible upgrade rules (detailed)\n\nUnder the **compatible** policy, these changes are **allowed**:\n\n- Add new functions (public or private)\n- Add new modules\n- Change function implementations (body)\n- Add new struct types\n- Change private\u002Ffriend function signatures\n\nThese changes **break compatibility** and will be rejected:\n\n- Remove or rename an existing module\n- Remove or rename a public function\n- Change a public function's signature (parameters, return types, type parameters)\n- Remove, rename, or reorder struct fields\n- Change the type of a struct field\n- Add or remove struct abilities (`key`, `store`, `copy`, `drop`)\n- Remove a struct type entirely\n- Change a struct's type parameters\n\nBefore upgrading, review your diff against these rules. The `sui client upgrade` command will reject incompatible changes at build time with a descriptive error.\n\n### Type anchoring after upgrades\n\n**Struct types are permanently anchored to the original package ID where they were first published.** After an upgrade, the new package gets a new ID, but all objects created by the upgraded code still have their type rooted in the original package ID.\n\nThis has critical implications:\n- **Querying objects by type** (e.g., `listOwnedObjects` with a `type` filter) must use the **original** package ID.\n- **Calling functions** via `moveCall` must use the **upgraded** (latest) package ID.\n- **Frontend apps** should maintain both IDs: `ORIGINAL_PACKAGE_ID` for type queries and `PACKAGE_ID` for function calls.\n\n```ts\n\u002F\u002F Original publish → package ID 0x1234...\n\u002F\u002F After upgrade  → package ID 0x5678...\n\n\u002F\u002F Query: use ORIGINAL package ID\nclient.core.listOwnedObjects({\n  owner: addr,\n  type: '0x1234...::module::MyObject',  \u002F\u002F ✅ original ID\n});\n\n\u002F\u002F Call: use UPGRADED package ID\ntx.moveCall({\n  target: '0x5678...::module::my_function',  \u002F\u002F ✅ upgraded ID\n});\n```\n\n### Publishing to multiple networks\n\nTo publish to a different network (for example, from Testnet to Devnet), switch environments and publish again. Each network gives the package a different ID. The `Published.toml` file tracks published addresses per environment.\n\nBefore publishing to a new network, ensure you have tokens for that network:\n\n- **Testnet:** Free tokens through the web faucet at `faucet.sui.io`, Discord (`!faucet \u003CADDRESS>` in `#testnet-faucet`), or the TypeScript SDK (`requestSuiFromFaucetV2()`). **`sui client faucet` does not work on Testnet.**\n- **Devnet:** Free tokens via `sui client faucet`, the web faucet at `faucet.sui.io`, Discord (`!faucet \u003CADDRESS>` in `#devnet-faucet`), or the TypeScript SDK.\n- **Localnet:** Free tokens via `sui client faucet` or the local faucet at `127.0.0.1:5003\u002Fgas` or `127.0.0.1:9123\u002Fgas` (started with `sui start --with-faucet --force-regenesis`).\n- **Mainnet:** SUI tokens with real monetary value. Acquire through exchanges or transfers. No faucet available.\n\n### Serializing for external signing\n\nTo generate transaction bytes for signing by another party (for example, a multisig):\n\n```bash\nsui client publish --serialize-output\n```\n\nThis outputs base64 transaction bytes instead of executing.\n\n## Local network (localnet)\n\nLocalnet runs a full Sui network on your machine for offline development and rapid iteration. Start it with:\n\n```bash\nsui start --with-faucet --force-regenesis\n```\n\nThe `--force-regenesis` flag resets all on-chain state each time the network starts, giving you a clean environment on every restart. The `--with-faucet` flag starts a local faucet so you can fund addresses.\n\nTo connect the CLI to your localnet:\n\n```bash\nsui client switch --env localnet\n```\n\nGet local tokens via `sui client faucet` or by hitting the local faucet endpoint directly at `127.0.0.1:5003\u002Fgas` or `127.0.0.1:9123\u002Fgas`.\n\nLocalnet is useful for:\n- Offline development without depending on Testnet\u002FDevnet availability\n- Rapid iteration on publish and upgrade flows (reset state with each restart)\n- Testing `init` functions and object creation before deploying to a shared network\n\n## Mainnet launch checklist\n\nUse this checklist when preparing a package for Mainnet publishing. Every item should be verified before executing the publish transaction.\n\n### 1. Tests and coverage\n\nRun the full test suite and confirm all tests pass:\n\n```bash\nsui move test\n```\n\nFor coverage reporting (if your project requires a threshold):\n\n```bash\nsui move test --coverage\nsui move coverage summary\n```\n\nFix any failing tests before proceeding. Do not publish untested code to Mainnet.\n\n### 2. Dependencies and addresses\n\n- Verify `Move.toml` uses `edition = \"2024\"` and has no legacy `[addresses]` section or git-based Sui framework dependency.\n- Confirm `[environments]` includes a `mainnet` entry with the correct chain ID.\n- If using MVR dependencies (`{ r.mvr = \"@org\u002Fpackage\" }`), verify they resolve on Mainnet.\n- Run `sui move build` to confirm clean compilation with no warnings.\n\n### 3. Upgrade policy decision\n\nDecide your upgrade policy **before** publishing — you cannot widen it later:\n\n| Policy | What you can change | When to use |\n|---|---|---|\n| **Compatible** (default) | Add functions, add modules, update implementations. Cannot remove functions or change struct layouts. | Most packages — gives flexibility for bug fixes while preserving type safety. |\n| **Additive** | Add new modules only. Existing modules are frozen. | Packages where you want to extend functionality but guarantee existing code never changes. |\n| **Dependency-only** | Only update dependency versions. | Nearly-finalized packages that should only track framework updates. |\n| **Immutable** | Nothing. Package is permanently frozen. | Fully audited packages where immutability is a trust guarantee (e.g., token contracts). |\n\nTo restrict the policy in the same transaction as publish, include a `moveCall` to `sui::package::only_additive_upgrades`, `only_dep_upgrades`, or `make_immutable` on the `UpgradeCap` in your publish PTB.\n\n### 4. Gas estimation\n\nMainnet SUI has real monetary value. Estimate gas before publishing:\n\n```bash\nsui client publish --dry-run\n```\n\nThe dry-run output includes `computationCost`, `storageCost`, and `storageRebate`. The total gas required is `computationCost + storageCost - storageRebate`. Ensure your address holds enough SUI to cover this amount plus a margin.\n\n### 5. Signer and custody plan\n\nDecide who controls the publish address and the `UpgradeCap`:\n\n- **Single signer:** Simplest. One key publishes and holds the `UpgradeCap`. Suitable for personal projects or early-stage development.\n- **Multisig:** For teams or high-value packages. Create a multisig address, publish using `--serialize-output`, and have the required signers sign offline. Transfer the `UpgradeCap` to the multisig address in the same PTB as publish.\n- **Immutable on publish:** If no upgrades will ever be needed, destroy the `UpgradeCap` in the publish PTB (`sui::package::make_immutable`). This removes custody concerns entirely.\n\nFor multisig publishing:\n\n```bash\n# Generate unsigned transaction bytes\nsui client publish --serialize-output\n\n# Each signer signs the bytes, then combine and execute\n```\n\n### 6. Final pre-publish verification\n\nBefore executing the publish transaction on Mainnet:\n\n- [ ] `sui client active-env` returns `mainnet`\n- [ ] `sui client balance` shows sufficient SUI for gas (check dry-run estimate)\n- [ ] `sui move build` succeeds with no warnings\n- [ ] `sui move test` passes with all tests green\n- [ ] `Move.toml` has correct `edition`, no legacy format\n- [ ] Upgrade policy is decided and restriction call is included in the PTB (if applicable)\n- [ ] Signer key or multisig is ready\n- [ ] You have verified the package on Testnet first — same code, same tests, same publish flow\n\n## Dry runs and transaction debugging\n\nA dry run simulates a transaction without submitting it to the network. Use dry runs to:\n\n- Estimate gas costs before execution.\n- Verify that a transaction succeeds before asking a user to sign.\n- Debug failing transactions by inspecting the error before spending gas.\n\nWallets (like Slush) automatically perform dry runs before presenting a transaction for signing. If a dry run fails, the wallet shows an error instead of prompting.\n\nFrom the TypeScript SDK, use `devInspectTransactionBlock` to dry-run a transaction programmatically. From the CLI, the `--dry-run` flag simulates execution.\n\nWhen debugging a dry run failure: check that all object IDs are correct, the object versions are current, the sender has sufficient gas, the function arguments match the expected types, and the active environment (`sui client active-env`) matches the network where the package is published.\n\n## Production monitoring\n\nSui packages are immutable once published, so monitoring is critical — you cannot hotfix a live contract, only publish an upgrade.\n\n### What to monitor\n\n| Signal | How | Why |\n|---|---|---|\n| Failed transactions involving your package | Subscribe to transaction effects via gRPC streaming, filter by package ID | Detects Move aborts, gas failures, or unexpected reverts in production |\n| Gas spend | Track `gasUsed` from transaction effects | Catch unexpectedly expensive operations or gas drain attacks |\n| Event emission | Subscribe to events by type (`{packageId}::module::EventName`) via gRPC streaming | Core business telemetry — mints, transfers, admin actions, deny list changes |\n| Object creation\u002Fdeletion rates | Query or subscribe to object changes filtered by your types | Detect abnormal activity (mass minting, object spam) |\n| Admin\u002Fcap usage | Filter events for capability-gated actions | Detect unauthorized or unexpected admin operations |\n| Shared object contention | Monitor transaction latency for shared-object transactions | High contention degrades UX; may need object sharding |\n\n### Implementation\n\nUse gRPC streaming subscriptions for real-time monitoring:\n\n```ts\nfor await (const event of client.subscriptionService.subscribeEvents({\n  filter: { MoveEventModule: { package: PACKAGE_ID, module: 'my_module' } },\n})) {\n  \u002F\u002F Forward to your monitoring stack (Grafana, Datadog, PagerDuty, etc.)\n}\n```\n\nFor historical analysis, run a custom indexer (`sui-indexer-alt`) that writes relevant events and transaction effects to your own database. See the `accessing-data` skill's `indexers.md`.\n\nEmit events for every security-critical action in your Move code — admin changes, configuration updates, deny list modifications, object deletions. Events are the only way offchain systems can observe these actions.\n\n## Rollback and incident response\n\n**Sui packages cannot be rolled back.** Published bytecode is immutable. There is no `revert` or `rollback` command. Recovery means publishing a forward-fix upgrade.\n\n### If a bad upgrade is published\n\n1. **Assess scope.** Determine which functions are affected. Existing objects created by prior versions are still valid — their types are anchored to the original package ID.\n2. **Publish a fix upgrade immediately.** Write the corrected code, run tests, dry-run on Testnet, then `sui client upgrade` on Mainnet. The new package ID replaces the old one for all future calls.\n3. **Update frontends.** Point `PACKAGE_IDS` to the new (fixed) package ID. Type queries still use `ORIGINAL_PACKAGE_IDS`.\n4. **Communicate.** If the bug affected user-facing behavior, notify users through your app's channels.\n\n### If the UpgradeCap is compromised\n\nAn attacker with the `UpgradeCap` can publish arbitrary code under your package. Mitigation:\n\n- **If you still hold the cap:** Immediately restrict it (`only_dep_upgrades` or `make_immutable`) to prevent further malicious upgrades.\n- **If the attacker holds the cap:** You cannot recover upgrade authority. Publish a new package, migrate users, and communicate the migration. This is why multisig custody of the `UpgradeCap` matters for production packages.\n\n### If a shared object is corrupted\n\nA buggy function may write invalid state to a shared object. Since shared objects are mutable by any transaction:\n\n- **If you can upgrade:** Publish an upgrade with a repair function that fixes the corrupted state. Gate it behind an `AdminCap`.\n- **If the package is immutable:** The only option is to deploy a new package with a migration function that reads the old object's data (if accessible) and creates corrected objects.\n\n### Prevention checklist\n\n- [ ] `UpgradeCap` held by multisig or restricted to `additive` \u002F `dep_only`\n- [ ] All upgrades tested on Testnet with the same code, same publish flow\n- [ ] Admin actions emit events for monitoring\n- [ ] Critical shared objects have repair functions gated behind capabilities\n- [ ] Frontend can switch package IDs without a redeploy (environment config, not hardcoded)\n",{"data":37,"body":38},{"name":4,"description":6},{"type":39,"children":40},"root",[41,50,75,108,115,122,127,192,213,219,257,263,285,290,331,337,350,373,393,418,437,470,476,518,650,656,675,737,743,784,829,836,848,982,988,993,1026,1064,1072,1110,1116,1135,1163,1175,1248,1260,1266,1276,1281,1368,1615,1621,1633,1638,1781,1787,1792,1820,1825,1831,1836,1865,1885,1890,1923,1947,1952,1977,1983,1988,1994,1999,2022,2027,2076,2081,2087,2165,2171,2183,2301,2341,2347,2352,2379,2415,2421,2432,2501,2506,2555,2561,2566,2691,2697,2702,2720,2725,2746,2758,2764,2769,2775,2926,2932,2937,3120,3148,3153,3159,3184,3190,3255,3261,3273,3316,3322,3327,3357,3363,3432],{"type":42,"tag":43,"props":44,"children":46},"element","h1",{"id":45},"publishing-deploying-local-network",[47],{"type":48,"value":49},"text","Publishing, Deploying & Local Network",{"type":42,"tag":51,"props":52,"children":53},"blockquote",{},[54],{"type":42,"tag":55,"props":56,"children":57},"p",{},[58,64,66,73],{"type":42,"tag":59,"props":60,"children":61},"strong",{},[62],{"type":48,"value":63},"MCP tool:",{"type":48,"value":65}," When available in your environment, also query the Sui documentation MCP server (",{"type":42,"tag":67,"props":68,"children":70},"code",{"className":69},[],[71],{"type":48,"value":72},"https:\u002F\u002Fsui.mcp.kapa.ai",{"type":48,"value":74},") for up-to-date answers. Use it for verification and for details not covered by these reference files.",{"type":42,"tag":51,"props":76,"children":77},{},[78],{"type":42,"tag":55,"props":79,"children":80},{},[81,86,88,97,99,106],{"type":42,"tag":59,"props":82,"children":83},{},[84],{"type":48,"value":85},"Source constraint:",{"type":48,"value":87}," All information sourced exclusively from ",{"type":42,"tag":89,"props":90,"children":94},"a",{"href":91,"rel":92},"https:\u002F\u002Fdocs.sui.io",[93],"nofollow",[95],{"type":48,"value":96},"docs.sui.io",{"type":48,"value":98}," and ",{"type":42,"tag":89,"props":100,"children":103},{"href":101,"rel":102},"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fsui-stack-hello-world",[93],[104],{"type":48,"value":105},"MystenLabs\u002Fsui-stack-hello-world",{"type":48,"value":107},".",{"type":42,"tag":109,"props":110,"children":112},"h2",{"id":111},"publishing-a-package",[113],{"type":48,"value":114},"Publishing a package",{"type":42,"tag":116,"props":117,"children":119},"h3",{"id":118},"canonical-hello-world-publish-flow",[120],{"type":48,"value":121},"Canonical hello-world publish flow",{"type":42,"tag":55,"props":123,"children":124},{},[125],{"type":48,"value":126},"For the full-stack starter, publish the existing hello-world package only:",{"type":42,"tag":128,"props":129,"children":134},"pre",{"className":130,"code":131,"language":132,"meta":133,"style":133},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","cd sui-stack-hello-world\u002Fmove\u002Fhello-world\nsui move build\nsui client publish\n","bash","",[135],{"type":42,"tag":67,"props":136,"children":137},{"__ignoreMap":133},[138,156,174],{"type":42,"tag":139,"props":140,"children":143},"span",{"class":141,"line":142},"line",1,[144,150],{"type":42,"tag":139,"props":145,"children":147},{"style":146},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[148],{"type":48,"value":149},"cd",{"type":42,"tag":139,"props":151,"children":153},{"style":152},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[154],{"type":48,"value":155}," sui-stack-hello-world\u002Fmove\u002Fhello-world\n",{"type":42,"tag":139,"props":157,"children":158},{"class":141,"line":29},[159,164,169],{"type":42,"tag":139,"props":160,"children":162},{"style":161},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[163],{"type":48,"value":8},{"type":42,"tag":139,"props":165,"children":166},{"style":152},[167],{"type":48,"value":168}," move",{"type":42,"tag":139,"props":170,"children":171},{"style":152},[172],{"type":48,"value":173}," build\n",{"type":42,"tag":139,"props":175,"children":177},{"class":141,"line":176},3,[178,182,187],{"type":42,"tag":139,"props":179,"children":180},{"style":161},[181],{"type":48,"value":8},{"type":42,"tag":139,"props":183,"children":184},{"style":152},[185],{"type":48,"value":186}," client",{"type":42,"tag":139,"props":188,"children":189},{"style":152},[190],{"type":48,"value":191}," publish\n",{"type":42,"tag":55,"props":193,"children":194},{},[195,197,203,205,211],{"type":48,"value":196},"Use the package ID from the publish output to update ",{"type":42,"tag":67,"props":198,"children":200},{"className":199},[],[201],{"type":48,"value":202},"sui-stack-hello-world\u002Fui\u002Fsrc\u002Fconstants.ts",{"type":48,"value":204}," (",{"type":42,"tag":67,"props":206,"children":208},{"className":207},[],[209],{"type":48,"value":210},"TESTNET_HELLO_WORLD_PACKAGE_ID",{"type":48,"value":212},"). Do not publish a separate counter package, and do not create a second project directory.",{"type":42,"tag":116,"props":214,"children":216},{"id":215},"pre-publish-checklist",[217],{"type":48,"value":218},"Pre-publish checklist",{"type":42,"tag":220,"props":221,"children":222},"ol",{},[223,235,246],{"type":42,"tag":224,"props":225,"children":226},"li",{},[227,229],{"type":48,"value":228},"Verify your active environment: ",{"type":42,"tag":67,"props":230,"children":232},{"className":231},[],[233],{"type":48,"value":234},"sui client active-env",{"type":42,"tag":224,"props":236,"children":237},{},[238,240],{"type":48,"value":239},"Verify you have SUI tokens: ",{"type":42,"tag":67,"props":241,"children":243},{"className":242},[],[244],{"type":48,"value":245},"sui client balance",{"type":42,"tag":224,"props":247,"children":248},{},[249,251],{"type":48,"value":250},"Build successfully: ",{"type":42,"tag":67,"props":252,"children":254},{"className":253},[],[255],{"type":48,"value":256},"sui move build",{"type":42,"tag":116,"props":258,"children":260},{"id":259},"publish",[261],{"type":48,"value":262},"Publish",{"type":42,"tag":128,"props":264,"children":266},{"className":130,"code":265,"language":132,"meta":133,"style":133},"sui client publish\n",[267],{"type":42,"tag":67,"props":268,"children":269},{"__ignoreMap":133},[270],{"type":42,"tag":139,"props":271,"children":272},{"class":141,"line":142},[273,277,281],{"type":42,"tag":139,"props":274,"children":275},{"style":161},[276],{"type":48,"value":8},{"type":42,"tag":139,"props":278,"children":279},{"style":152},[280],{"type":48,"value":186},{"type":42,"tag":139,"props":282,"children":283},{"style":152},[284],{"type":48,"value":191},{"type":42,"tag":55,"props":286,"children":287},{},[288],{"type":48,"value":289},"This deploys the package to the active network and returns:",{"type":42,"tag":291,"props":292,"children":293},"ul",{},[294,306,318],{"type":42,"tag":224,"props":295,"children":296},{},[297,299,304],{"type":48,"value":298},"A unique ",{"type":42,"tag":59,"props":300,"children":301},{},[302],{"type":48,"value":303},"package ID",{"type":48,"value":305}," (use this for all future interactions)",{"type":42,"tag":224,"props":307,"children":308},{},[309,311,316],{"type":48,"value":310},"An ",{"type":42,"tag":59,"props":312,"children":313},{},[314],{"type":48,"value":315},"UpgradeCap",{"type":48,"value":317}," object (sent to your address, controls future upgrades)",{"type":42,"tag":224,"props":319,"children":320},{},[321,323,329],{"type":48,"value":322},"Object IDs for anything created during ",{"type":42,"tag":67,"props":324,"children":326},{"className":325},[],[327],{"type":48,"value":328},"init",{"type":48,"value":330}," functions",{"type":42,"tag":116,"props":332,"children":334},{"id":333},"test-publishing-ephemeral-networks",[335],{"type":48,"value":336},"Test publishing (ephemeral networks)",{"type":42,"tag":55,"props":338,"children":339},{},[340,342,348],{"type":48,"value":341},"Use ",{"type":42,"tag":67,"props":343,"children":345},{"className":344},[],[346],{"type":48,"value":347},"sui client test-publish",{"type":48,"value":349}," to publish a package to an ephemeral environment for testing without persisting state to a real network:",{"type":42,"tag":128,"props":351,"children":353},{"className":130,"code":352,"language":132,"meta":133,"style":133},"sui client test-publish\n",[354],{"type":42,"tag":67,"props":355,"children":356},{"__ignoreMap":133},[357],{"type":42,"tag":139,"props":358,"children":359},{"class":141,"line":142},[360,364,368],{"type":42,"tag":139,"props":361,"children":362},{"style":161},[363],{"type":48,"value":8},{"type":42,"tag":139,"props":365,"children":366},{"style":152},[367],{"type":48,"value":186},{"type":42,"tag":139,"props":369,"children":370},{"style":152},[371],{"type":48,"value":372}," test-publish\n",{"type":42,"tag":55,"props":374,"children":375},{},[376,378,383,385,391],{"type":48,"value":377},"This publishes the package, runs ",{"type":42,"tag":67,"props":379,"children":381},{"className":380},[],[382],{"type":48,"value":328},{"type":48,"value":384}," functions, and returns the same output as ",{"type":42,"tag":67,"props":386,"children":388},{"className":387},[],[389],{"type":48,"value":390},"sui client publish",{"type":48,"value":392}," (package ID, UpgradeCap, created objects), but the deployment is not permanent. Use it to:",{"type":42,"tag":291,"props":394,"children":395},{},[396,408,413],{"type":42,"tag":224,"props":397,"children":398},{},[399,401,406],{"type":48,"value":400},"Verify that ",{"type":42,"tag":67,"props":402,"children":404},{"className":403},[],[405],{"type":48,"value":328},{"type":48,"value":407}," functions execute correctly before committing to a real publish",{"type":42,"tag":224,"props":409,"children":410},{},[411],{"type":48,"value":412},"Test publish + upgrade flows in CI without consuming Testnet\u002FDevnet resources",{"type":42,"tag":224,"props":414,"children":415},{},[416],{"type":48,"value":417},"Validate gas costs and object creation before a Mainnet deploy",{"type":42,"tag":55,"props":419,"children":420},{},[421,427,429,435],{"type":42,"tag":67,"props":422,"children":424},{"className":423},[],[425],{"type":48,"value":426},"test-publish",{"type":48,"value":428}," respects ",{"type":42,"tag":67,"props":430,"children":432},{"className":431},[],[433],{"type":48,"value":434},"--build-env",{"type":48,"value":436}," for multi-environment packages:",{"type":42,"tag":128,"props":438,"children":440},{"className":130,"code":439,"language":132,"meta":133,"style":133},"sui client test-publish --build-env testnet\n",[441],{"type":42,"tag":67,"props":442,"children":443},{"__ignoreMap":133},[444],{"type":42,"tag":139,"props":445,"children":446},{"class":141,"line":142},[447,451,455,460,465],{"type":42,"tag":139,"props":448,"children":449},{"style":161},[450],{"type":48,"value":8},{"type":42,"tag":139,"props":452,"children":453},{"style":152},[454],{"type":48,"value":186},{"type":42,"tag":139,"props":456,"children":457},{"style":152},[458],{"type":48,"value":459}," test-publish",{"type":42,"tag":139,"props":461,"children":462},{"style":152},[463],{"type":48,"value":464}," --build-env",{"type":42,"tag":139,"props":466,"children":467},{"style":152},[468],{"type":48,"value":469}," testnet\n",{"type":42,"tag":116,"props":471,"children":473},{"id":472},"after-publishing",[474],{"type":48,"value":475},"After publishing",{"type":42,"tag":55,"props":477,"children":478},{},[479,481,486,488,493,495,500,502,508,510,516],{"type":48,"value":480},"The publish transaction output lists the package ID under the ",{"type":42,"tag":59,"props":482,"children":483},{},[484],{"type":48,"value":485},"created objects",{"type":48,"value":487}," section (alongside the ",{"type":42,"tag":67,"props":489,"children":491},{"className":490},[],[492],{"type":48,"value":315},{"type":48,"value":494}," and any objects created by ",{"type":42,"tag":67,"props":496,"children":498},{"className":497},[],[499],{"type":48,"value":328},{"type":48,"value":501}," functions). The ",{"type":42,"tag":67,"props":503,"children":505},{"className":504},[],[506],{"type":48,"value":507},"published-at",{"type":48,"value":509}," field is also automatically added to your ",{"type":42,"tag":67,"props":511,"children":513},{"className":512},[],[514],{"type":48,"value":515},"Published.toml",{"type":48,"value":517},". To interact with the published package:",{"type":42,"tag":128,"props":519,"children":521},{"className":130,"code":520,"language":132,"meta":133,"style":133},"# Call a function\nsui client call --package \u003CPACKAGE_ID> --module greeting --function new\n\n# Query an object\nsui client object \u003COBJECT_ID>\n",[522],{"type":42,"tag":67,"props":523,"children":524},{"__ignoreMap":133},[525,534,597,606,615],{"type":42,"tag":139,"props":526,"children":527},{"class":141,"line":142},[528],{"type":42,"tag":139,"props":529,"children":531},{"style":530},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[532],{"type":48,"value":533},"# Call a function\n",{"type":42,"tag":139,"props":535,"children":536},{"class":141,"line":29},[537,541,545,550,555,561,566,572,577,582,587,592],{"type":42,"tag":139,"props":538,"children":539},{"style":161},[540],{"type":48,"value":8},{"type":42,"tag":139,"props":542,"children":543},{"style":152},[544],{"type":48,"value":186},{"type":42,"tag":139,"props":546,"children":547},{"style":152},[548],{"type":48,"value":549}," call",{"type":42,"tag":139,"props":551,"children":552},{"style":152},[553],{"type":48,"value":554}," --package",{"type":42,"tag":139,"props":556,"children":558},{"style":557},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[559],{"type":48,"value":560}," \u003C",{"type":42,"tag":139,"props":562,"children":563},{"style":152},[564],{"type":48,"value":565},"PACKAGE_I",{"type":42,"tag":139,"props":567,"children":569},{"style":568},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[570],{"type":48,"value":571},"D",{"type":42,"tag":139,"props":573,"children":574},{"style":557},[575],{"type":48,"value":576},">",{"type":42,"tag":139,"props":578,"children":579},{"style":152},[580],{"type":48,"value":581}," --module",{"type":42,"tag":139,"props":583,"children":584},{"style":152},[585],{"type":48,"value":586}," greeting",{"type":42,"tag":139,"props":588,"children":589},{"style":152},[590],{"type":48,"value":591}," --function",{"type":42,"tag":139,"props":593,"children":594},{"style":152},[595],{"type":48,"value":596}," new\n",{"type":42,"tag":139,"props":598,"children":599},{"class":141,"line":176},[600],{"type":42,"tag":139,"props":601,"children":603},{"emptyLinePlaceholder":602},true,[604],{"type":48,"value":605},"\n",{"type":42,"tag":139,"props":607,"children":609},{"class":141,"line":608},4,[610],{"type":42,"tag":139,"props":611,"children":612},{"style":530},[613],{"type":48,"value":614},"# Query an object\n",{"type":42,"tag":139,"props":616,"children":618},{"class":141,"line":617},5,[619,623,627,632,636,641,645],{"type":42,"tag":139,"props":620,"children":621},{"style":161},[622],{"type":48,"value":8},{"type":42,"tag":139,"props":624,"children":625},{"style":152},[626],{"type":48,"value":186},{"type":42,"tag":139,"props":628,"children":629},{"style":152},[630],{"type":48,"value":631}," object",{"type":42,"tag":139,"props":633,"children":634},{"style":557},[635],{"type":48,"value":560},{"type":42,"tag":139,"props":637,"children":638},{"style":152},[639],{"type":48,"value":640},"OBJECT_I",{"type":42,"tag":139,"props":642,"children":643},{"style":568},[644],{"type":48,"value":571},{"type":42,"tag":139,"props":646,"children":647},{"style":557},[648],{"type":48,"value":649},">\n",{"type":42,"tag":116,"props":651,"children":653},{"id":652},"your-package-is-already-published-error",[654],{"type":48,"value":655},"\"Your package is already published\" error",{"type":42,"tag":55,"props":657,"children":658},{},[659,661,666,668,673],{"type":48,"value":660},"If you see this error when running ",{"type":42,"tag":67,"props":662,"children":664},{"className":663},[],[665],{"type":48,"value":390},{"type":48,"value":667},", it means ",{"type":42,"tag":67,"props":669,"children":671},{"className":670},[],[672],{"type":48,"value":515},{"type":48,"value":674}," already has an entry for your active environment. This happens when iterating on a package during development.",{"type":42,"tag":291,"props":676,"children":677},{},[678,718],{"type":42,"tag":224,"props":679,"children":680},{},[681,683,688,690,696,698,703,705,710,712,717],{"type":48,"value":682},"To ",{"type":42,"tag":59,"props":684,"children":685},{},[686],{"type":48,"value":687},"publish to a different network",{"type":48,"value":689},", switch environments with ",{"type":42,"tag":67,"props":691,"children":693},{"className":692},[],[694],{"type":48,"value":695},"sui client switch --env \u003CENV>",{"type":48,"value":697}," and run ",{"type":42,"tag":67,"props":699,"children":701},{"className":700},[],[702],{"type":48,"value":390},{"type":48,"value":704}," again. The toolchain tracks published addresses per environment in ",{"type":42,"tag":67,"props":706,"children":708},{"className":707},[],[709],{"type":48,"value":515},{"type":48,"value":711}," automatically — do not delete ",{"type":42,"tag":67,"props":713,"children":715},{"className":714},[],[716],{"type":48,"value":515},{"type":48,"value":107},{"type":42,"tag":224,"props":719,"children":720},{},[721,722,727,729,735],{"type":48,"value":682},{"type":42,"tag":59,"props":723,"children":724},{},[725],{"type":48,"value":726},"upgrade",{"type":48,"value":728}," the existing package on the same network, use ",{"type":42,"tag":67,"props":730,"children":732},{"className":731},[],[733],{"type":48,"value":734},"sui client upgrade",{"type":48,"value":736}," (see below).",{"type":42,"tag":116,"props":738,"children":740},{"id":739},"upgrading-a-published-package",[741],{"type":48,"value":742},"Upgrading a published package",{"type":42,"tag":55,"props":744,"children":745},{},[746,748,753,755,760,762,767,769,774,776,782],{"type":48,"value":747},"Published packages are immutable, but you can upgrade by publishing a new version linked to the original. The ",{"type":42,"tag":67,"props":749,"children":751},{"className":750},[],[752],{"type":48,"value":315},{"type":48,"value":754}," object controls upgrade authority. ",{"type":42,"tag":59,"props":756,"children":757},{},[758],{"type":48,"value":759},"Important:",{"type":48,"value":761}," you can restrict the ",{"type":42,"tag":67,"props":763,"children":765},{"className":764},[],[766],{"type":48,"value":315},{"type":48,"value":768}," in the same PTB as the ",{"type":42,"tag":67,"props":770,"children":772},{"className":771},[],[773],{"type":48,"value":259},{"type":48,"value":775}," command — for example, publishing and immediately calling ",{"type":42,"tag":67,"props":777,"children":779},{"className":778},[],[780],{"type":48,"value":781},"sui::package::only_additive_upgrades",{"type":48,"value":783}," in one atomic transaction. You can also destroy it entirely to make the package permanently immutable (see upgrade policies below).",{"type":42,"tag":128,"props":785,"children":787},{"className":130,"code":786,"language":132,"meta":133,"style":133},"sui client upgrade --upgrade-capability \u003CCAP_ID>\n",[788],{"type":42,"tag":67,"props":789,"children":790},{"__ignoreMap":133},[791],{"type":42,"tag":139,"props":792,"children":793},{"class":141,"line":142},[794,798,802,807,812,816,821,825],{"type":42,"tag":139,"props":795,"children":796},{"style":161},[797],{"type":48,"value":8},{"type":42,"tag":139,"props":799,"children":800},{"style":152},[801],{"type":48,"value":186},{"type":42,"tag":139,"props":803,"children":804},{"style":152},[805],{"type":48,"value":806}," upgrade",{"type":42,"tag":139,"props":808,"children":809},{"style":152},[810],{"type":48,"value":811}," --upgrade-capability",{"type":42,"tag":139,"props":813,"children":814},{"style":557},[815],{"type":48,"value":560},{"type":42,"tag":139,"props":817,"children":818},{"style":152},[819],{"type":48,"value":820},"CAP_I",{"type":42,"tag":139,"props":822,"children":823},{"style":568},[824],{"type":48,"value":571},{"type":42,"tag":139,"props":826,"children":827},{"style":557},[828],{"type":48,"value":649},{"type":42,"tag":830,"props":831,"children":833},"h4",{"id":832},"finding-your-upgradecap",[834],{"type":48,"value":835},"Finding your UpgradeCap",{"type":42,"tag":55,"props":837,"children":838},{},[839,841,846],{"type":48,"value":840},"The ",{"type":42,"tag":67,"props":842,"children":844},{"className":843},[],[845],{"type":48,"value":315},{"type":48,"value":847}," object ID is needed for every upgrade. There are several ways to find it:",{"type":42,"tag":220,"props":849,"children":850},{},[851,875,925,949],{"type":42,"tag":224,"props":852,"children":853},{},[854,858,860,865,867,873],{"type":42,"tag":59,"props":855,"children":856},{},[857],{"type":48,"value":515},{"type":48,"value":859}," (preferred): After publishing, the toolchain records the cap ID in ",{"type":42,"tag":67,"props":861,"children":863},{"className":862},[],[864],{"type":48,"value":515},{"type":48,"value":866}," under the ",{"type":42,"tag":67,"props":868,"children":870},{"className":869},[],[871],{"type":48,"value":872},"upgrade-capability",{"type":48,"value":874}," field for each environment.",{"type":42,"tag":224,"props":876,"children":877},{},[878,883,885,890,892],{"type":42,"tag":59,"props":879,"children":880},{},[881],{"type":48,"value":882},"Query owned objects",{"type":48,"value":884},": List all ",{"type":42,"tag":67,"props":886,"children":888},{"className":887},[],[889],{"type":48,"value":315},{"type":48,"value":891}," objects owned by the publish address:\n",{"type":42,"tag":128,"props":893,"children":895},{"className":130,"code":894,"language":132,"meta":133,"style":133},"sui client objects --type 0x2::package::UpgradeCap\n",[896],{"type":42,"tag":67,"props":897,"children":898},{"__ignoreMap":133},[899],{"type":42,"tag":139,"props":900,"children":901},{"class":141,"line":142},[902,906,910,915,920],{"type":42,"tag":139,"props":903,"children":904},{"style":161},[905],{"type":48,"value":8},{"type":42,"tag":139,"props":907,"children":908},{"style":152},[909],{"type":48,"value":186},{"type":42,"tag":139,"props":911,"children":912},{"style":152},[913],{"type":48,"value":914}," objects",{"type":42,"tag":139,"props":916,"children":917},{"style":152},[918],{"type":48,"value":919}," --type",{"type":42,"tag":139,"props":921,"children":922},{"style":152},[923],{"type":48,"value":924}," 0x2::package::UpgradeCap\n",{"type":42,"tag":224,"props":926,"children":927},{},[928,933,935,940,942,947],{"type":42,"tag":59,"props":929,"children":930},{},[931],{"type":48,"value":932},"Publish transaction output",{"type":48,"value":934},": The original ",{"type":42,"tag":67,"props":936,"children":938},{"className":937},[],[939],{"type":48,"value":390},{"type":48,"value":941}," output includes the ",{"type":42,"tag":67,"props":943,"children":945},{"className":944},[],[946],{"type":48,"value":315},{"type":48,"value":948}," object ID in the created objects list.",{"type":42,"tag":224,"props":950,"children":951},{},[952,957,959,965,967,973,975,981],{"type":42,"tag":59,"props":953,"children":954},{},[955],{"type":48,"value":956},"Explorer",{"type":48,"value":958},": Search for your address on SuiVision (",{"type":42,"tag":67,"props":960,"children":962},{"className":961},[],[963],{"type":48,"value":964},"suivision.xyz",{"type":48,"value":966},") or Suiscan (",{"type":42,"tag":67,"props":968,"children":970},{"className":969},[],[971],{"type":48,"value":972},"suiscan.xyz",{"type":48,"value":974},") and filter owned objects by type ",{"type":42,"tag":67,"props":976,"children":978},{"className":977},[],[979],{"type":48,"value":980},"0x2::package::UpgradeCap",{"type":48,"value":107},{"type":42,"tag":830,"props":983,"children":985},{"id":984},"upgrade-policies",[986],{"type":48,"value":987},"Upgrade policies",{"type":42,"tag":55,"props":989,"children":990},{},[991],{"type":48,"value":992},"Upgrade policies restrict what can change:",{"type":42,"tag":291,"props":994,"children":995},{},[996,1006,1016],{"type":42,"tag":224,"props":997,"children":998},{},[999,1004],{"type":42,"tag":59,"props":1000,"children":1001},{},[1002],{"type":48,"value":1003},"Compatible",{"type":48,"value":1005}," (default): The most permissive policy. See detailed rules below.",{"type":42,"tag":224,"props":1007,"children":1008},{},[1009,1014],{"type":42,"tag":59,"props":1010,"children":1011},{},[1012],{"type":48,"value":1013},"Additive:",{"type":48,"value":1015}," New modules can be added, but existing modules cannot change at all.",{"type":42,"tag":224,"props":1017,"children":1018},{},[1019,1024],{"type":42,"tag":59,"props":1020,"children":1021},{},[1022],{"type":48,"value":1023},"Dependency-only:",{"type":48,"value":1025}," Only dependency versions can be updated. No code changes.",{"type":42,"tag":55,"props":1027,"children":1028},{},[1029,1034,1036,1041,1043,1048,1050,1055,1057,1062],{"type":42,"tag":59,"props":1030,"children":1031},{},[1032],{"type":48,"value":1033},"Restricting the UpgradeCap in the same PTB as publish:",{"type":48,"value":1035}," You can restrict the ",{"type":42,"tag":67,"props":1037,"children":1039},{"className":1038},[],[1040],{"type":48,"value":315},{"type":48,"value":1042}," in the same programmable transaction block as the ",{"type":42,"tag":67,"props":1044,"children":1046},{"className":1045},[],[1047],{"type":48,"value":259},{"type":48,"value":1049}," command itself — for example, calling ",{"type":42,"tag":67,"props":1051,"children":1053},{"className":1052},[],[1054],{"type":48,"value":781},{"type":48,"value":1056}," on the ",{"type":42,"tag":67,"props":1058,"children":1060},{"className":1059},[],[1061],{"type":48,"value":315},{"type":48,"value":1063}," immediately after publishing, all within a single atomic transaction. This is the recommended approach for locking down upgrade policy from the start. Once restricted, you cannot widen the policy.",{"type":42,"tag":55,"props":1065,"children":1066},{},[1067],{"type":42,"tag":59,"props":1068,"children":1069},{},[1070],{"type":48,"value":1071},"Other UpgradeCap options:",{"type":42,"tag":291,"props":1073,"children":1074},{},[1075,1085],{"type":42,"tag":224,"props":1076,"children":1077},{},[1078,1083],{"type":42,"tag":59,"props":1079,"children":1080},{},[1081],{"type":48,"value":1082},"Transfer to a multisig address",{"type":48,"value":1084}," for shared upgrade governance.",{"type":42,"tag":224,"props":1086,"children":1087},{},[1088,1093,1095,1101,1103,1108],{"type":42,"tag":59,"props":1089,"children":1090},{},[1091],{"type":48,"value":1092},"Destroy the UpgradeCap",{"type":48,"value":1094}," to make the package permanently immutable. Call ",{"type":42,"tag":67,"props":1096,"children":1098},{"className":1097},[],[1099],{"type":48,"value":1100},"sui::package::make_immutable",{"type":48,"value":1102},", which consumes and destroys the ",{"type":42,"tag":67,"props":1104,"children":1106},{"className":1105},[],[1107],{"type":48,"value":315},{"type":48,"value":1109}," object. Once the cap is destroyed, no one can ever upgrade the package again — this is irreversible.",{"type":42,"tag":830,"props":1111,"children":1113},{"id":1112},"compatible-upgrade-rules-detailed",[1114],{"type":48,"value":1115},"Compatible upgrade rules (detailed)",{"type":42,"tag":55,"props":1117,"children":1118},{},[1119,1121,1126,1128,1133],{"type":48,"value":1120},"Under the ",{"type":42,"tag":59,"props":1122,"children":1123},{},[1124],{"type":48,"value":1125},"compatible",{"type":48,"value":1127}," policy, these changes are ",{"type":42,"tag":59,"props":1129,"children":1130},{},[1131],{"type":48,"value":1132},"allowed",{"type":48,"value":1134},":",{"type":42,"tag":291,"props":1136,"children":1137},{},[1138,1143,1148,1153,1158],{"type":42,"tag":224,"props":1139,"children":1140},{},[1141],{"type":48,"value":1142},"Add new functions (public or private)",{"type":42,"tag":224,"props":1144,"children":1145},{},[1146],{"type":48,"value":1147},"Add new modules",{"type":42,"tag":224,"props":1149,"children":1150},{},[1151],{"type":48,"value":1152},"Change function implementations (body)",{"type":42,"tag":224,"props":1154,"children":1155},{},[1156],{"type":48,"value":1157},"Add new struct types",{"type":42,"tag":224,"props":1159,"children":1160},{},[1161],{"type":48,"value":1162},"Change private\u002Ffriend function signatures",{"type":42,"tag":55,"props":1164,"children":1165},{},[1166,1168,1173],{"type":48,"value":1167},"These changes ",{"type":42,"tag":59,"props":1169,"children":1170},{},[1171],{"type":48,"value":1172},"break compatibility",{"type":48,"value":1174}," and will be rejected:",{"type":42,"tag":291,"props":1176,"children":1177},{},[1178,1183,1188,1193,1198,1203,1238,1243],{"type":42,"tag":224,"props":1179,"children":1180},{},[1181],{"type":48,"value":1182},"Remove or rename an existing module",{"type":42,"tag":224,"props":1184,"children":1185},{},[1186],{"type":48,"value":1187},"Remove or rename a public function",{"type":42,"tag":224,"props":1189,"children":1190},{},[1191],{"type":48,"value":1192},"Change a public function's signature (parameters, return types, type parameters)",{"type":42,"tag":224,"props":1194,"children":1195},{},[1196],{"type":48,"value":1197},"Remove, rename, or reorder struct fields",{"type":42,"tag":224,"props":1199,"children":1200},{},[1201],{"type":48,"value":1202},"Change the type of a struct field",{"type":42,"tag":224,"props":1204,"children":1205},{},[1206,1208,1214,1216,1222,1223,1229,1230,1236],{"type":48,"value":1207},"Add or remove struct abilities (",{"type":42,"tag":67,"props":1209,"children":1211},{"className":1210},[],[1212],{"type":48,"value":1213},"key",{"type":48,"value":1215},", ",{"type":42,"tag":67,"props":1217,"children":1219},{"className":1218},[],[1220],{"type":48,"value":1221},"store",{"type":48,"value":1215},{"type":42,"tag":67,"props":1224,"children":1226},{"className":1225},[],[1227],{"type":48,"value":1228},"copy",{"type":48,"value":1215},{"type":42,"tag":67,"props":1231,"children":1233},{"className":1232},[],[1234],{"type":48,"value":1235},"drop",{"type":48,"value":1237},")",{"type":42,"tag":224,"props":1239,"children":1240},{},[1241],{"type":48,"value":1242},"Remove a struct type entirely",{"type":42,"tag":224,"props":1244,"children":1245},{},[1246],{"type":48,"value":1247},"Change a struct's type parameters",{"type":42,"tag":55,"props":1249,"children":1250},{},[1251,1253,1258],{"type":48,"value":1252},"Before upgrading, review your diff against these rules. The ",{"type":42,"tag":67,"props":1254,"children":1256},{"className":1255},[],[1257],{"type":48,"value":734},{"type":48,"value":1259}," command will reject incompatible changes at build time with a descriptive error.",{"type":42,"tag":116,"props":1261,"children":1263},{"id":1262},"type-anchoring-after-upgrades",[1264],{"type":48,"value":1265},"Type anchoring after upgrades",{"type":42,"tag":55,"props":1267,"children":1268},{},[1269,1274],{"type":42,"tag":59,"props":1270,"children":1271},{},[1272],{"type":48,"value":1273},"Struct types are permanently anchored to the original package ID where they were first published.",{"type":48,"value":1275}," After an upgrade, the new package gets a new ID, but all objects created by the upgraded code still have their type rooted in the original package ID.",{"type":42,"tag":55,"props":1277,"children":1278},{},[1279],{"type":48,"value":1280},"This has critical implications:",{"type":42,"tag":291,"props":1282,"children":1283},{},[1284,1317,1342],{"type":42,"tag":224,"props":1285,"children":1286},{},[1287,1292,1294,1300,1302,1308,1310,1315],{"type":42,"tag":59,"props":1288,"children":1289},{},[1290],{"type":48,"value":1291},"Querying objects by type",{"type":48,"value":1293}," (e.g., ",{"type":42,"tag":67,"props":1295,"children":1297},{"className":1296},[],[1298],{"type":48,"value":1299},"listOwnedObjects",{"type":48,"value":1301}," with a ",{"type":42,"tag":67,"props":1303,"children":1305},{"className":1304},[],[1306],{"type":48,"value":1307},"type",{"type":48,"value":1309}," filter) must use the ",{"type":42,"tag":59,"props":1311,"children":1312},{},[1313],{"type":48,"value":1314},"original",{"type":48,"value":1316}," package ID.",{"type":42,"tag":224,"props":1318,"children":1319},{},[1320,1325,1327,1333,1335,1340],{"type":42,"tag":59,"props":1321,"children":1322},{},[1323],{"type":48,"value":1324},"Calling functions",{"type":48,"value":1326}," via ",{"type":42,"tag":67,"props":1328,"children":1330},{"className":1329},[],[1331],{"type":48,"value":1332},"moveCall",{"type":48,"value":1334}," must use the ",{"type":42,"tag":59,"props":1336,"children":1337},{},[1338],{"type":48,"value":1339},"upgraded",{"type":48,"value":1341}," (latest) package ID.",{"type":42,"tag":224,"props":1343,"children":1344},{},[1345,1350,1352,1358,1360,1366],{"type":42,"tag":59,"props":1346,"children":1347},{},[1348],{"type":48,"value":1349},"Frontend apps",{"type":48,"value":1351}," should maintain both IDs: ",{"type":42,"tag":67,"props":1353,"children":1355},{"className":1354},[],[1356],{"type":48,"value":1357},"ORIGINAL_PACKAGE_ID",{"type":48,"value":1359}," for type queries and ",{"type":42,"tag":67,"props":1361,"children":1363},{"className":1362},[],[1364],{"type":48,"value":1365},"PACKAGE_ID",{"type":48,"value":1367}," for function calls.",{"type":42,"tag":128,"props":1369,"children":1373},{"className":1370,"code":1371,"language":1372,"meta":133,"style":133},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Original publish → package ID 0x1234...\n\u002F\u002F After upgrade  → package ID 0x5678...\n\n\u002F\u002F Query: use ORIGINAL package ID\nclient.core.listOwnedObjects({\n  owner: addr,\n  type: '0x1234...::module::MyObject',  \u002F\u002F ✅ original ID\n});\n\n\u002F\u002F Call: use UPGRADED package ID\ntx.moveCall({\n  target: '0x5678...::module::my_function',  \u002F\u002F ✅ upgraded ID\n});\n","ts",[1374],{"type":42,"tag":67,"props":1375,"children":1376},{"__ignoreMap":133},[1377,1385,1393,1400,1408,1443,1467,1505,1523,1530,1539,1564,1599],{"type":42,"tag":139,"props":1378,"children":1379},{"class":141,"line":142},[1380],{"type":42,"tag":139,"props":1381,"children":1382},{"style":530},[1383],{"type":48,"value":1384},"\u002F\u002F Original publish → package ID 0x1234...\n",{"type":42,"tag":139,"props":1386,"children":1387},{"class":141,"line":29},[1388],{"type":42,"tag":139,"props":1389,"children":1390},{"style":530},[1391],{"type":48,"value":1392},"\u002F\u002F After upgrade  → package ID 0x5678...\n",{"type":42,"tag":139,"props":1394,"children":1395},{"class":141,"line":176},[1396],{"type":42,"tag":139,"props":1397,"children":1398},{"emptyLinePlaceholder":602},[1399],{"type":48,"value":605},{"type":42,"tag":139,"props":1401,"children":1402},{"class":141,"line":608},[1403],{"type":42,"tag":139,"props":1404,"children":1405},{"style":530},[1406],{"type":48,"value":1407},"\u002F\u002F Query: use ORIGINAL package ID\n",{"type":42,"tag":139,"props":1409,"children":1410},{"class":141,"line":617},[1411,1416,1420,1425,1429,1433,1438],{"type":42,"tag":139,"props":1412,"children":1413},{"style":568},[1414],{"type":48,"value":1415},"client",{"type":42,"tag":139,"props":1417,"children":1418},{"style":557},[1419],{"type":48,"value":107},{"type":42,"tag":139,"props":1421,"children":1422},{"style":568},[1423],{"type":48,"value":1424},"core",{"type":42,"tag":139,"props":1426,"children":1427},{"style":557},[1428],{"type":48,"value":107},{"type":42,"tag":139,"props":1430,"children":1431},{"style":146},[1432],{"type":48,"value":1299},{"type":42,"tag":139,"props":1434,"children":1435},{"style":568},[1436],{"type":48,"value":1437},"(",{"type":42,"tag":139,"props":1439,"children":1440},{"style":557},[1441],{"type":48,"value":1442},"{\n",{"type":42,"tag":139,"props":1444,"children":1446},{"class":141,"line":1445},6,[1447,1453,1457,1462],{"type":42,"tag":139,"props":1448,"children":1450},{"style":1449},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[1451],{"type":48,"value":1452},"  owner",{"type":42,"tag":139,"props":1454,"children":1455},{"style":557},[1456],{"type":48,"value":1134},{"type":42,"tag":139,"props":1458,"children":1459},{"style":568},[1460],{"type":48,"value":1461}," addr",{"type":42,"tag":139,"props":1463,"children":1464},{"style":557},[1465],{"type":48,"value":1466},",\n",{"type":42,"tag":139,"props":1468,"children":1470},{"class":141,"line":1469},7,[1471,1476,1480,1485,1490,1495,1500],{"type":42,"tag":139,"props":1472,"children":1473},{"style":1449},[1474],{"type":48,"value":1475},"  type",{"type":42,"tag":139,"props":1477,"children":1478},{"style":557},[1479],{"type":48,"value":1134},{"type":42,"tag":139,"props":1481,"children":1482},{"style":557},[1483],{"type":48,"value":1484}," '",{"type":42,"tag":139,"props":1486,"children":1487},{"style":152},[1488],{"type":48,"value":1489},"0x1234...::module::MyObject",{"type":42,"tag":139,"props":1491,"children":1492},{"style":557},[1493],{"type":48,"value":1494},"'",{"type":42,"tag":139,"props":1496,"children":1497},{"style":557},[1498],{"type":48,"value":1499},",",{"type":42,"tag":139,"props":1501,"children":1502},{"style":530},[1503],{"type":48,"value":1504},"  \u002F\u002F ✅ original ID\n",{"type":42,"tag":139,"props":1506,"children":1508},{"class":141,"line":1507},8,[1509,1514,1518],{"type":42,"tag":139,"props":1510,"children":1511},{"style":557},[1512],{"type":48,"value":1513},"}",{"type":42,"tag":139,"props":1515,"children":1516},{"style":568},[1517],{"type":48,"value":1237},{"type":42,"tag":139,"props":1519,"children":1520},{"style":557},[1521],{"type":48,"value":1522},";\n",{"type":42,"tag":139,"props":1524,"children":1525},{"class":141,"line":25},[1526],{"type":42,"tag":139,"props":1527,"children":1528},{"emptyLinePlaceholder":602},[1529],{"type":48,"value":605},{"type":42,"tag":139,"props":1531,"children":1533},{"class":141,"line":1532},10,[1534],{"type":42,"tag":139,"props":1535,"children":1536},{"style":530},[1537],{"type":48,"value":1538},"\u002F\u002F Call: use UPGRADED package ID\n",{"type":42,"tag":139,"props":1540,"children":1542},{"class":141,"line":1541},11,[1543,1548,1552,1556,1560],{"type":42,"tag":139,"props":1544,"children":1545},{"style":568},[1546],{"type":48,"value":1547},"tx",{"type":42,"tag":139,"props":1549,"children":1550},{"style":557},[1551],{"type":48,"value":107},{"type":42,"tag":139,"props":1553,"children":1554},{"style":146},[1555],{"type":48,"value":1332},{"type":42,"tag":139,"props":1557,"children":1558},{"style":568},[1559],{"type":48,"value":1437},{"type":42,"tag":139,"props":1561,"children":1562},{"style":557},[1563],{"type":48,"value":1442},{"type":42,"tag":139,"props":1565,"children":1567},{"class":141,"line":1566},12,[1568,1573,1577,1581,1586,1590,1594],{"type":42,"tag":139,"props":1569,"children":1570},{"style":1449},[1571],{"type":48,"value":1572},"  target",{"type":42,"tag":139,"props":1574,"children":1575},{"style":557},[1576],{"type":48,"value":1134},{"type":42,"tag":139,"props":1578,"children":1579},{"style":557},[1580],{"type":48,"value":1484},{"type":42,"tag":139,"props":1582,"children":1583},{"style":152},[1584],{"type":48,"value":1585},"0x5678...::module::my_function",{"type":42,"tag":139,"props":1587,"children":1588},{"style":557},[1589],{"type":48,"value":1494},{"type":42,"tag":139,"props":1591,"children":1592},{"style":557},[1593],{"type":48,"value":1499},{"type":42,"tag":139,"props":1595,"children":1596},{"style":530},[1597],{"type":48,"value":1598},"  \u002F\u002F ✅ upgraded ID\n",{"type":42,"tag":139,"props":1600,"children":1602},{"class":141,"line":1601},13,[1603,1607,1611],{"type":42,"tag":139,"props":1604,"children":1605},{"style":557},[1606],{"type":48,"value":1513},{"type":42,"tag":139,"props":1608,"children":1609},{"style":568},[1610],{"type":48,"value":1237},{"type":42,"tag":139,"props":1612,"children":1613},{"style":557},[1614],{"type":48,"value":1522},{"type":42,"tag":116,"props":1616,"children":1618},{"id":1617},"publishing-to-multiple-networks",[1619],{"type":48,"value":1620},"Publishing to multiple networks",{"type":42,"tag":55,"props":1622,"children":1623},{},[1624,1626,1631],{"type":48,"value":1625},"To publish to a different network (for example, from Testnet to Devnet), switch environments and publish again. Each network gives the package a different ID. The ",{"type":42,"tag":67,"props":1627,"children":1629},{"className":1628},[],[1630],{"type":48,"value":515},{"type":48,"value":1632}," file tracks published addresses per environment.",{"type":42,"tag":55,"props":1634,"children":1635},{},[1636],{"type":48,"value":1637},"Before publishing to a new network, ensure you have tokens for that network:",{"type":42,"tag":291,"props":1639,"children":1640},{},[1641,1694,1731,1771],{"type":42,"tag":224,"props":1642,"children":1643},{},[1644,1649,1651,1657,1659,1665,1667,1673,1675,1681,1683],{"type":42,"tag":59,"props":1645,"children":1646},{},[1647],{"type":48,"value":1648},"Testnet:",{"type":48,"value":1650}," Free tokens through the web faucet at ",{"type":42,"tag":67,"props":1652,"children":1654},{"className":1653},[],[1655],{"type":48,"value":1656},"faucet.sui.io",{"type":48,"value":1658},", Discord (",{"type":42,"tag":67,"props":1660,"children":1662},{"className":1661},[],[1663],{"type":48,"value":1664},"!faucet \u003CADDRESS>",{"type":48,"value":1666}," in ",{"type":42,"tag":67,"props":1668,"children":1670},{"className":1669},[],[1671],{"type":48,"value":1672},"#testnet-faucet",{"type":48,"value":1674},"), or the TypeScript SDK (",{"type":42,"tag":67,"props":1676,"children":1678},{"className":1677},[],[1679],{"type":48,"value":1680},"requestSuiFromFaucetV2()",{"type":48,"value":1682},"). ",{"type":42,"tag":59,"props":1684,"children":1685},{},[1686,1692],{"type":42,"tag":67,"props":1687,"children":1689},{"className":1688},[],[1690],{"type":48,"value":1691},"sui client faucet",{"type":48,"value":1693}," does not work on Testnet.",{"type":42,"tag":224,"props":1695,"children":1696},{},[1697,1702,1704,1709,1711,1716,1717,1722,1723,1729],{"type":42,"tag":59,"props":1698,"children":1699},{},[1700],{"type":48,"value":1701},"Devnet:",{"type":48,"value":1703}," Free tokens via ",{"type":42,"tag":67,"props":1705,"children":1707},{"className":1706},[],[1708],{"type":48,"value":1691},{"type":48,"value":1710},", the web faucet at ",{"type":42,"tag":67,"props":1712,"children":1714},{"className":1713},[],[1715],{"type":48,"value":1656},{"type":48,"value":1658},{"type":42,"tag":67,"props":1718,"children":1720},{"className":1719},[],[1721],{"type":48,"value":1664},{"type":48,"value":1666},{"type":42,"tag":67,"props":1724,"children":1726},{"className":1725},[],[1727],{"type":48,"value":1728},"#devnet-faucet",{"type":48,"value":1730},"), or the TypeScript SDK.",{"type":42,"tag":224,"props":1732,"children":1733},{},[1734,1739,1740,1745,1747,1753,1755,1761,1763,1769],{"type":42,"tag":59,"props":1735,"children":1736},{},[1737],{"type":48,"value":1738},"Localnet:",{"type":48,"value":1703},{"type":42,"tag":67,"props":1741,"children":1743},{"className":1742},[],[1744],{"type":48,"value":1691},{"type":48,"value":1746}," or the local faucet at ",{"type":42,"tag":67,"props":1748,"children":1750},{"className":1749},[],[1751],{"type":48,"value":1752},"127.0.0.1:5003\u002Fgas",{"type":48,"value":1754}," or ",{"type":42,"tag":67,"props":1756,"children":1758},{"className":1757},[],[1759],{"type":48,"value":1760},"127.0.0.1:9123\u002Fgas",{"type":48,"value":1762}," (started with ",{"type":42,"tag":67,"props":1764,"children":1766},{"className":1765},[],[1767],{"type":48,"value":1768},"sui start --with-faucet --force-regenesis",{"type":48,"value":1770},").",{"type":42,"tag":224,"props":1772,"children":1773},{},[1774,1779],{"type":42,"tag":59,"props":1775,"children":1776},{},[1777],{"type":48,"value":1778},"Mainnet:",{"type":48,"value":1780}," SUI tokens with real monetary value. Acquire through exchanges or transfers. No faucet available.",{"type":42,"tag":116,"props":1782,"children":1784},{"id":1783},"serializing-for-external-signing",[1785],{"type":48,"value":1786},"Serializing for external signing",{"type":42,"tag":55,"props":1788,"children":1789},{},[1790],{"type":48,"value":1791},"To generate transaction bytes for signing by another party (for example, a multisig):",{"type":42,"tag":128,"props":1793,"children":1795},{"className":130,"code":1794,"language":132,"meta":133,"style":133},"sui client publish --serialize-output\n",[1796],{"type":42,"tag":67,"props":1797,"children":1798},{"__ignoreMap":133},[1799],{"type":42,"tag":139,"props":1800,"children":1801},{"class":141,"line":142},[1802,1806,1810,1815],{"type":42,"tag":139,"props":1803,"children":1804},{"style":161},[1805],{"type":48,"value":8},{"type":42,"tag":139,"props":1807,"children":1808},{"style":152},[1809],{"type":48,"value":186},{"type":42,"tag":139,"props":1811,"children":1812},{"style":152},[1813],{"type":48,"value":1814}," publish",{"type":42,"tag":139,"props":1816,"children":1817},{"style":152},[1818],{"type":48,"value":1819}," --serialize-output\n",{"type":42,"tag":55,"props":1821,"children":1822},{},[1823],{"type":48,"value":1824},"This outputs base64 transaction bytes instead of executing.",{"type":42,"tag":109,"props":1826,"children":1828},{"id":1827},"local-network-localnet",[1829],{"type":48,"value":1830},"Local network (localnet)",{"type":42,"tag":55,"props":1832,"children":1833},{},[1834],{"type":48,"value":1835},"Localnet runs a full Sui network on your machine for offline development and rapid iteration. Start it with:",{"type":42,"tag":128,"props":1837,"children":1839},{"className":130,"code":1838,"language":132,"meta":133,"style":133},"sui start --with-faucet --force-regenesis\n",[1840],{"type":42,"tag":67,"props":1841,"children":1842},{"__ignoreMap":133},[1843],{"type":42,"tag":139,"props":1844,"children":1845},{"class":141,"line":142},[1846,1850,1855,1860],{"type":42,"tag":139,"props":1847,"children":1848},{"style":161},[1849],{"type":48,"value":8},{"type":42,"tag":139,"props":1851,"children":1852},{"style":152},[1853],{"type":48,"value":1854}," start",{"type":42,"tag":139,"props":1856,"children":1857},{"style":152},[1858],{"type":48,"value":1859}," --with-faucet",{"type":42,"tag":139,"props":1861,"children":1862},{"style":152},[1863],{"type":48,"value":1864}," --force-regenesis\n",{"type":42,"tag":55,"props":1866,"children":1867},{},[1868,1869,1875,1877,1883],{"type":48,"value":840},{"type":42,"tag":67,"props":1870,"children":1872},{"className":1871},[],[1873],{"type":48,"value":1874},"--force-regenesis",{"type":48,"value":1876}," flag resets all on-chain state each time the network starts, giving you a clean environment on every restart. The ",{"type":42,"tag":67,"props":1878,"children":1880},{"className":1879},[],[1881],{"type":48,"value":1882},"--with-faucet",{"type":48,"value":1884}," flag starts a local faucet so you can fund addresses.",{"type":42,"tag":55,"props":1886,"children":1887},{},[1888],{"type":48,"value":1889},"To connect the CLI to your localnet:",{"type":42,"tag":128,"props":1891,"children":1893},{"className":130,"code":1892,"language":132,"meta":133,"style":133},"sui client switch --env localnet\n",[1894],{"type":42,"tag":67,"props":1895,"children":1896},{"__ignoreMap":133},[1897],{"type":42,"tag":139,"props":1898,"children":1899},{"class":141,"line":142},[1900,1904,1908,1913,1918],{"type":42,"tag":139,"props":1901,"children":1902},{"style":161},[1903],{"type":48,"value":8},{"type":42,"tag":139,"props":1905,"children":1906},{"style":152},[1907],{"type":48,"value":186},{"type":42,"tag":139,"props":1909,"children":1910},{"style":152},[1911],{"type":48,"value":1912}," switch",{"type":42,"tag":139,"props":1914,"children":1915},{"style":152},[1916],{"type":48,"value":1917}," --env",{"type":42,"tag":139,"props":1919,"children":1920},{"style":152},[1921],{"type":48,"value":1922}," localnet\n",{"type":42,"tag":55,"props":1924,"children":1925},{},[1926,1928,1933,1935,1940,1941,1946],{"type":48,"value":1927},"Get local tokens via ",{"type":42,"tag":67,"props":1929,"children":1931},{"className":1930},[],[1932],{"type":48,"value":1691},{"type":48,"value":1934}," or by hitting the local faucet endpoint directly at ",{"type":42,"tag":67,"props":1936,"children":1938},{"className":1937},[],[1939],{"type":48,"value":1752},{"type":48,"value":1754},{"type":42,"tag":67,"props":1942,"children":1944},{"className":1943},[],[1945],{"type":48,"value":1760},{"type":48,"value":107},{"type":42,"tag":55,"props":1948,"children":1949},{},[1950],{"type":48,"value":1951},"Localnet is useful for:",{"type":42,"tag":291,"props":1953,"children":1954},{},[1955,1960,1965],{"type":42,"tag":224,"props":1956,"children":1957},{},[1958],{"type":48,"value":1959},"Offline development without depending on Testnet\u002FDevnet availability",{"type":42,"tag":224,"props":1961,"children":1962},{},[1963],{"type":48,"value":1964},"Rapid iteration on publish and upgrade flows (reset state with each restart)",{"type":42,"tag":224,"props":1966,"children":1967},{},[1968,1970,1975],{"type":48,"value":1969},"Testing ",{"type":42,"tag":67,"props":1971,"children":1973},{"className":1972},[],[1974],{"type":48,"value":328},{"type":48,"value":1976}," functions and object creation before deploying to a shared network",{"type":42,"tag":109,"props":1978,"children":1980},{"id":1979},"mainnet-launch-checklist",[1981],{"type":48,"value":1982},"Mainnet launch checklist",{"type":42,"tag":55,"props":1984,"children":1985},{},[1986],{"type":48,"value":1987},"Use this checklist when preparing a package for Mainnet publishing. Every item should be verified before executing the publish transaction.",{"type":42,"tag":116,"props":1989,"children":1991},{"id":1990},"_1-tests-and-coverage",[1992],{"type":48,"value":1993},"1. Tests and coverage",{"type":42,"tag":55,"props":1995,"children":1996},{},[1997],{"type":48,"value":1998},"Run the full test suite and confirm all tests pass:",{"type":42,"tag":128,"props":2000,"children":2002},{"className":130,"code":2001,"language":132,"meta":133,"style":133},"sui move test\n",[2003],{"type":42,"tag":67,"props":2004,"children":2005},{"__ignoreMap":133},[2006],{"type":42,"tag":139,"props":2007,"children":2008},{"class":141,"line":142},[2009,2013,2017],{"type":42,"tag":139,"props":2010,"children":2011},{"style":161},[2012],{"type":48,"value":8},{"type":42,"tag":139,"props":2014,"children":2015},{"style":152},[2016],{"type":48,"value":168},{"type":42,"tag":139,"props":2018,"children":2019},{"style":152},[2020],{"type":48,"value":2021}," test\n",{"type":42,"tag":55,"props":2023,"children":2024},{},[2025],{"type":48,"value":2026},"For coverage reporting (if your project requires a threshold):",{"type":42,"tag":128,"props":2028,"children":2030},{"className":130,"code":2029,"language":132,"meta":133,"style":133},"sui move test --coverage\nsui move coverage summary\n",[2031],{"type":42,"tag":67,"props":2032,"children":2033},{"__ignoreMap":133},[2034,2055],{"type":42,"tag":139,"props":2035,"children":2036},{"class":141,"line":142},[2037,2041,2045,2050],{"type":42,"tag":139,"props":2038,"children":2039},{"style":161},[2040],{"type":48,"value":8},{"type":42,"tag":139,"props":2042,"children":2043},{"style":152},[2044],{"type":48,"value":168},{"type":42,"tag":139,"props":2046,"children":2047},{"style":152},[2048],{"type":48,"value":2049}," test",{"type":42,"tag":139,"props":2051,"children":2052},{"style":152},[2053],{"type":48,"value":2054}," --coverage\n",{"type":42,"tag":139,"props":2056,"children":2057},{"class":141,"line":29},[2058,2062,2066,2071],{"type":42,"tag":139,"props":2059,"children":2060},{"style":161},[2061],{"type":48,"value":8},{"type":42,"tag":139,"props":2063,"children":2064},{"style":152},[2065],{"type":48,"value":168},{"type":42,"tag":139,"props":2067,"children":2068},{"style":152},[2069],{"type":48,"value":2070}," coverage",{"type":42,"tag":139,"props":2072,"children":2073},{"style":152},[2074],{"type":48,"value":2075}," summary\n",{"type":42,"tag":55,"props":2077,"children":2078},{},[2079],{"type":48,"value":2080},"Fix any failing tests before proceeding. Do not publish untested code to Mainnet.",{"type":42,"tag":116,"props":2082,"children":2084},{"id":2083},"_2-dependencies-and-addresses",[2085],{"type":48,"value":2086},"2. Dependencies and addresses",{"type":42,"tag":291,"props":2088,"children":2089},{},[2090,2119,2140,2153],{"type":42,"tag":224,"props":2091,"children":2092},{},[2093,2095,2101,2103,2109,2111,2117],{"type":48,"value":2094},"Verify ",{"type":42,"tag":67,"props":2096,"children":2098},{"className":2097},[],[2099],{"type":48,"value":2100},"Move.toml",{"type":48,"value":2102}," uses ",{"type":42,"tag":67,"props":2104,"children":2106},{"className":2105},[],[2107],{"type":48,"value":2108},"edition = \"2024\"",{"type":48,"value":2110}," and has no legacy ",{"type":42,"tag":67,"props":2112,"children":2114},{"className":2113},[],[2115],{"type":48,"value":2116},"[addresses]",{"type":48,"value":2118}," section or git-based Sui framework dependency.",{"type":42,"tag":224,"props":2120,"children":2121},{},[2122,2124,2130,2132,2138],{"type":48,"value":2123},"Confirm ",{"type":42,"tag":67,"props":2125,"children":2127},{"className":2126},[],[2128],{"type":48,"value":2129},"[environments]",{"type":48,"value":2131}," includes a ",{"type":42,"tag":67,"props":2133,"children":2135},{"className":2134},[],[2136],{"type":48,"value":2137},"mainnet",{"type":48,"value":2139}," entry with the correct chain ID.",{"type":42,"tag":224,"props":2141,"children":2142},{},[2143,2145,2151],{"type":48,"value":2144},"If using MVR dependencies (",{"type":42,"tag":67,"props":2146,"children":2148},{"className":2147},[],[2149],{"type":48,"value":2150},"{ r.mvr = \"@org\u002Fpackage\" }",{"type":48,"value":2152},"), verify they resolve on Mainnet.",{"type":42,"tag":224,"props":2154,"children":2155},{},[2156,2158,2163],{"type":48,"value":2157},"Run ",{"type":42,"tag":67,"props":2159,"children":2161},{"className":2160},[],[2162],{"type":48,"value":256},{"type":48,"value":2164}," to confirm clean compilation with no warnings.",{"type":42,"tag":116,"props":2166,"children":2168},{"id":2167},"_3-upgrade-policy-decision",[2169],{"type":48,"value":2170},"3. Upgrade policy decision",{"type":42,"tag":55,"props":2172,"children":2173},{},[2174,2176,2181],{"type":48,"value":2175},"Decide your upgrade policy ",{"type":42,"tag":59,"props":2177,"children":2178},{},[2179],{"type":48,"value":2180},"before",{"type":48,"value":2182}," publishing — you cannot widen it later:",{"type":42,"tag":2184,"props":2185,"children":2186},"table",{},[2187,2211],{"type":42,"tag":2188,"props":2189,"children":2190},"thead",{},[2191],{"type":42,"tag":2192,"props":2193,"children":2194},"tr",{},[2195,2201,2206],{"type":42,"tag":2196,"props":2197,"children":2198},"th",{},[2199],{"type":48,"value":2200},"Policy",{"type":42,"tag":2196,"props":2202,"children":2203},{},[2204],{"type":48,"value":2205},"What you can change",{"type":42,"tag":2196,"props":2207,"children":2208},{},[2209],{"type":48,"value":2210},"When to use",{"type":42,"tag":2212,"props":2213,"children":2214},"tbody",{},[2215,2238,2259,2280],{"type":42,"tag":2192,"props":2216,"children":2217},{},[2218,2228,2233],{"type":42,"tag":2219,"props":2220,"children":2221},"td",{},[2222,2226],{"type":42,"tag":59,"props":2223,"children":2224},{},[2225],{"type":48,"value":1003},{"type":48,"value":2227}," (default)",{"type":42,"tag":2219,"props":2229,"children":2230},{},[2231],{"type":48,"value":2232},"Add functions, add modules, update implementations. Cannot remove functions or change struct layouts.",{"type":42,"tag":2219,"props":2234,"children":2235},{},[2236],{"type":48,"value":2237},"Most packages — gives flexibility for bug fixes while preserving type safety.",{"type":42,"tag":2192,"props":2239,"children":2240},{},[2241,2249,2254],{"type":42,"tag":2219,"props":2242,"children":2243},{},[2244],{"type":42,"tag":59,"props":2245,"children":2246},{},[2247],{"type":48,"value":2248},"Additive",{"type":42,"tag":2219,"props":2250,"children":2251},{},[2252],{"type":48,"value":2253},"Add new modules only. Existing modules are frozen.",{"type":42,"tag":2219,"props":2255,"children":2256},{},[2257],{"type":48,"value":2258},"Packages where you want to extend functionality but guarantee existing code never changes.",{"type":42,"tag":2192,"props":2260,"children":2261},{},[2262,2270,2275],{"type":42,"tag":2219,"props":2263,"children":2264},{},[2265],{"type":42,"tag":59,"props":2266,"children":2267},{},[2268],{"type":48,"value":2269},"Dependency-only",{"type":42,"tag":2219,"props":2271,"children":2272},{},[2273],{"type":48,"value":2274},"Only update dependency versions.",{"type":42,"tag":2219,"props":2276,"children":2277},{},[2278],{"type":48,"value":2279},"Nearly-finalized packages that should only track framework updates.",{"type":42,"tag":2192,"props":2281,"children":2282},{},[2283,2291,2296],{"type":42,"tag":2219,"props":2284,"children":2285},{},[2286],{"type":42,"tag":59,"props":2287,"children":2288},{},[2289],{"type":48,"value":2290},"Immutable",{"type":42,"tag":2219,"props":2292,"children":2293},{},[2294],{"type":48,"value":2295},"Nothing. Package is permanently frozen.",{"type":42,"tag":2219,"props":2297,"children":2298},{},[2299],{"type":48,"value":2300},"Fully audited packages where immutability is a trust guarantee (e.g., token contracts).",{"type":42,"tag":55,"props":2302,"children":2303},{},[2304,2306,2311,2313,2318,2319,2325,2327,2333,2334,2339],{"type":48,"value":2305},"To restrict the policy in the same transaction as publish, include a ",{"type":42,"tag":67,"props":2307,"children":2309},{"className":2308},[],[2310],{"type":48,"value":1332},{"type":48,"value":2312}," to ",{"type":42,"tag":67,"props":2314,"children":2316},{"className":2315},[],[2317],{"type":48,"value":781},{"type":48,"value":1215},{"type":42,"tag":67,"props":2320,"children":2322},{"className":2321},[],[2323],{"type":48,"value":2324},"only_dep_upgrades",{"type":48,"value":2326},", or ",{"type":42,"tag":67,"props":2328,"children":2330},{"className":2329},[],[2331],{"type":48,"value":2332},"make_immutable",{"type":48,"value":1056},{"type":42,"tag":67,"props":2335,"children":2337},{"className":2336},[],[2338],{"type":48,"value":315},{"type":48,"value":2340}," in your publish PTB.",{"type":42,"tag":116,"props":2342,"children":2344},{"id":2343},"_4-gas-estimation",[2345],{"type":48,"value":2346},"4. Gas estimation",{"type":42,"tag":55,"props":2348,"children":2349},{},[2350],{"type":48,"value":2351},"Mainnet SUI has real monetary value. Estimate gas before publishing:",{"type":42,"tag":128,"props":2353,"children":2355},{"className":130,"code":2354,"language":132,"meta":133,"style":133},"sui client publish --dry-run\n",[2356],{"type":42,"tag":67,"props":2357,"children":2358},{"__ignoreMap":133},[2359],{"type":42,"tag":139,"props":2360,"children":2361},{"class":141,"line":142},[2362,2366,2370,2374],{"type":42,"tag":139,"props":2363,"children":2364},{"style":161},[2365],{"type":48,"value":8},{"type":42,"tag":139,"props":2367,"children":2368},{"style":152},[2369],{"type":48,"value":186},{"type":42,"tag":139,"props":2371,"children":2372},{"style":152},[2373],{"type":48,"value":1814},{"type":42,"tag":139,"props":2375,"children":2376},{"style":152},[2377],{"type":48,"value":2378}," --dry-run\n",{"type":42,"tag":55,"props":2380,"children":2381},{},[2382,2384,2390,2391,2397,2399,2405,2407,2413],{"type":48,"value":2383},"The dry-run output includes ",{"type":42,"tag":67,"props":2385,"children":2387},{"className":2386},[],[2388],{"type":48,"value":2389},"computationCost",{"type":48,"value":1215},{"type":42,"tag":67,"props":2392,"children":2394},{"className":2393},[],[2395],{"type":48,"value":2396},"storageCost",{"type":48,"value":2398},", and ",{"type":42,"tag":67,"props":2400,"children":2402},{"className":2401},[],[2403],{"type":48,"value":2404},"storageRebate",{"type":48,"value":2406},". The total gas required is ",{"type":42,"tag":67,"props":2408,"children":2410},{"className":2409},[],[2411],{"type":48,"value":2412},"computationCost + storageCost - storageRebate",{"type":48,"value":2414},". Ensure your address holds enough SUI to cover this amount plus a margin.",{"type":42,"tag":116,"props":2416,"children":2418},{"id":2417},"_5-signer-and-custody-plan",[2419],{"type":48,"value":2420},"5. Signer and custody plan",{"type":42,"tag":55,"props":2422,"children":2423},{},[2424,2426,2431],{"type":48,"value":2425},"Decide who controls the publish address and the ",{"type":42,"tag":67,"props":2427,"children":2429},{"className":2428},[],[2430],{"type":48,"value":315},{"type":48,"value":1134},{"type":42,"tag":291,"props":2433,"children":2434},{},[2435,2452,2477],{"type":42,"tag":224,"props":2436,"children":2437},{},[2438,2443,2445,2450],{"type":42,"tag":59,"props":2439,"children":2440},{},[2441],{"type":48,"value":2442},"Single signer:",{"type":48,"value":2444}," Simplest. One key publishes and holds the ",{"type":42,"tag":67,"props":2446,"children":2448},{"className":2447},[],[2449],{"type":48,"value":315},{"type":48,"value":2451},". Suitable for personal projects or early-stage development.",{"type":42,"tag":224,"props":2453,"children":2454},{},[2455,2460,2462,2468,2470,2475],{"type":42,"tag":59,"props":2456,"children":2457},{},[2458],{"type":48,"value":2459},"Multisig:",{"type":48,"value":2461}," For teams or high-value packages. Create a multisig address, publish using ",{"type":42,"tag":67,"props":2463,"children":2465},{"className":2464},[],[2466],{"type":48,"value":2467},"--serialize-output",{"type":48,"value":2469},", and have the required signers sign offline. Transfer the ",{"type":42,"tag":67,"props":2471,"children":2473},{"className":2472},[],[2474],{"type":48,"value":315},{"type":48,"value":2476}," to the multisig address in the same PTB as publish.",{"type":42,"tag":224,"props":2478,"children":2479},{},[2480,2485,2487,2492,2494,2499],{"type":42,"tag":59,"props":2481,"children":2482},{},[2483],{"type":48,"value":2484},"Immutable on publish:",{"type":48,"value":2486}," If no upgrades will ever be needed, destroy the ",{"type":42,"tag":67,"props":2488,"children":2490},{"className":2489},[],[2491],{"type":48,"value":315},{"type":48,"value":2493}," in the publish PTB (",{"type":42,"tag":67,"props":2495,"children":2497},{"className":2496},[],[2498],{"type":48,"value":1100},{"type":48,"value":2500},"). This removes custody concerns entirely.",{"type":42,"tag":55,"props":2502,"children":2503},{},[2504],{"type":48,"value":2505},"For multisig publishing:",{"type":42,"tag":128,"props":2507,"children":2509},{"className":130,"code":2508,"language":132,"meta":133,"style":133},"# Generate unsigned transaction bytes\nsui client publish --serialize-output\n\n# Each signer signs the bytes, then combine and execute\n",[2510],{"type":42,"tag":67,"props":2511,"children":2512},{"__ignoreMap":133},[2513,2521,2540,2547],{"type":42,"tag":139,"props":2514,"children":2515},{"class":141,"line":142},[2516],{"type":42,"tag":139,"props":2517,"children":2518},{"style":530},[2519],{"type":48,"value":2520},"# Generate unsigned transaction bytes\n",{"type":42,"tag":139,"props":2522,"children":2523},{"class":141,"line":29},[2524,2528,2532,2536],{"type":42,"tag":139,"props":2525,"children":2526},{"style":161},[2527],{"type":48,"value":8},{"type":42,"tag":139,"props":2529,"children":2530},{"style":152},[2531],{"type":48,"value":186},{"type":42,"tag":139,"props":2533,"children":2534},{"style":152},[2535],{"type":48,"value":1814},{"type":42,"tag":139,"props":2537,"children":2538},{"style":152},[2539],{"type":48,"value":1819},{"type":42,"tag":139,"props":2541,"children":2542},{"class":141,"line":176},[2543],{"type":42,"tag":139,"props":2544,"children":2545},{"emptyLinePlaceholder":602},[2546],{"type":48,"value":605},{"type":42,"tag":139,"props":2548,"children":2549},{"class":141,"line":608},[2550],{"type":42,"tag":139,"props":2551,"children":2552},{"style":530},[2553],{"type":48,"value":2554},"# Each signer signs the bytes, then combine and execute\n",{"type":42,"tag":116,"props":2556,"children":2558},{"id":2557},"_6-final-pre-publish-verification",[2559],{"type":48,"value":2560},"6. Final pre-publish verification",{"type":42,"tag":55,"props":2562,"children":2563},{},[2564],{"type":48,"value":2565},"Before executing the publish transaction on Mainnet:",{"type":42,"tag":291,"props":2567,"children":2570},{"className":2568},[2569],"contains-task-list",[2571,2595,2610,2625,2641,2664,2673,2682],{"type":42,"tag":224,"props":2572,"children":2575},{"className":2573},[2574],"task-list-item",[2576,2581,2583,2588,2590],{"type":42,"tag":2577,"props":2578,"children":2580},"input",{"disabled":602,"type":2579},"checkbox",[],{"type":48,"value":2582}," ",{"type":42,"tag":67,"props":2584,"children":2586},{"className":2585},[],[2587],{"type":48,"value":234},{"type":48,"value":2589}," returns ",{"type":42,"tag":67,"props":2591,"children":2593},{"className":2592},[],[2594],{"type":48,"value":2137},{"type":42,"tag":224,"props":2596,"children":2598},{"className":2597},[2574],[2599,2602,2603,2608],{"type":42,"tag":2577,"props":2600,"children":2601},{"disabled":602,"type":2579},[],{"type":48,"value":2582},{"type":42,"tag":67,"props":2604,"children":2606},{"className":2605},[],[2607],{"type":48,"value":245},{"type":48,"value":2609}," shows sufficient SUI for gas (check dry-run estimate)",{"type":42,"tag":224,"props":2611,"children":2613},{"className":2612},[2574],[2614,2617,2618,2623],{"type":42,"tag":2577,"props":2615,"children":2616},{"disabled":602,"type":2579},[],{"type":48,"value":2582},{"type":42,"tag":67,"props":2619,"children":2621},{"className":2620},[],[2622],{"type":48,"value":256},{"type":48,"value":2624}," succeeds with no warnings",{"type":42,"tag":224,"props":2626,"children":2628},{"className":2627},[2574],[2629,2632,2633,2639],{"type":42,"tag":2577,"props":2630,"children":2631},{"disabled":602,"type":2579},[],{"type":48,"value":2582},{"type":42,"tag":67,"props":2634,"children":2636},{"className":2635},[],[2637],{"type":48,"value":2638},"sui move test",{"type":48,"value":2640}," passes with all tests green",{"type":42,"tag":224,"props":2642,"children":2644},{"className":2643},[2574],[2645,2648,2649,2654,2656,2662],{"type":42,"tag":2577,"props":2646,"children":2647},{"disabled":602,"type":2579},[],{"type":48,"value":2582},{"type":42,"tag":67,"props":2650,"children":2652},{"className":2651},[],[2653],{"type":48,"value":2100},{"type":48,"value":2655}," has correct ",{"type":42,"tag":67,"props":2657,"children":2659},{"className":2658},[],[2660],{"type":48,"value":2661},"edition",{"type":48,"value":2663},", no legacy format",{"type":42,"tag":224,"props":2665,"children":2667},{"className":2666},[2574],[2668,2671],{"type":42,"tag":2577,"props":2669,"children":2670},{"disabled":602,"type":2579},[],{"type":48,"value":2672}," Upgrade policy is decided and restriction call is included in the PTB (if applicable)",{"type":42,"tag":224,"props":2674,"children":2676},{"className":2675},[2574],[2677,2680],{"type":42,"tag":2577,"props":2678,"children":2679},{"disabled":602,"type":2579},[],{"type":48,"value":2681}," Signer key or multisig is ready",{"type":42,"tag":224,"props":2683,"children":2685},{"className":2684},[2574],[2686,2689],{"type":42,"tag":2577,"props":2687,"children":2688},{"disabled":602,"type":2579},[],{"type":48,"value":2690}," You have verified the package on Testnet first — same code, same tests, same publish flow",{"type":42,"tag":109,"props":2692,"children":2694},{"id":2693},"dry-runs-and-transaction-debugging",[2695],{"type":48,"value":2696},"Dry runs and transaction debugging",{"type":42,"tag":55,"props":2698,"children":2699},{},[2700],{"type":48,"value":2701},"A dry run simulates a transaction without submitting it to the network. Use dry runs to:",{"type":42,"tag":291,"props":2703,"children":2704},{},[2705,2710,2715],{"type":42,"tag":224,"props":2706,"children":2707},{},[2708],{"type":48,"value":2709},"Estimate gas costs before execution.",{"type":42,"tag":224,"props":2711,"children":2712},{},[2713],{"type":48,"value":2714},"Verify that a transaction succeeds before asking a user to sign.",{"type":42,"tag":224,"props":2716,"children":2717},{},[2718],{"type":48,"value":2719},"Debug failing transactions by inspecting the error before spending gas.",{"type":42,"tag":55,"props":2721,"children":2722},{},[2723],{"type":48,"value":2724},"Wallets (like Slush) automatically perform dry runs before presenting a transaction for signing. If a dry run fails, the wallet shows an error instead of prompting.",{"type":42,"tag":55,"props":2726,"children":2727},{},[2728,2730,2736,2738,2744],{"type":48,"value":2729},"From the TypeScript SDK, use ",{"type":42,"tag":67,"props":2731,"children":2733},{"className":2732},[],[2734],{"type":48,"value":2735},"devInspectTransactionBlock",{"type":48,"value":2737}," to dry-run a transaction programmatically. From the CLI, the ",{"type":42,"tag":67,"props":2739,"children":2741},{"className":2740},[],[2742],{"type":48,"value":2743},"--dry-run",{"type":48,"value":2745}," flag simulates execution.",{"type":42,"tag":55,"props":2747,"children":2748},{},[2749,2751,2756],{"type":48,"value":2750},"When debugging a dry run failure: check that all object IDs are correct, the object versions are current, the sender has sufficient gas, the function arguments match the expected types, and the active environment (",{"type":42,"tag":67,"props":2752,"children":2754},{"className":2753},[],[2755],{"type":48,"value":234},{"type":48,"value":2757},") matches the network where the package is published.",{"type":42,"tag":109,"props":2759,"children":2761},{"id":2760},"production-monitoring",[2762],{"type":48,"value":2763},"Production monitoring",{"type":42,"tag":55,"props":2765,"children":2766},{},[2767],{"type":48,"value":2768},"Sui packages are immutable once published, so monitoring is critical — you cannot hotfix a live contract, only publish an upgrade.",{"type":42,"tag":116,"props":2770,"children":2772},{"id":2771},"what-to-monitor",[2773],{"type":48,"value":2774},"What to monitor",{"type":42,"tag":2184,"props":2776,"children":2777},{},[2778,2799],{"type":42,"tag":2188,"props":2779,"children":2780},{},[2781],{"type":42,"tag":2192,"props":2782,"children":2783},{},[2784,2789,2794],{"type":42,"tag":2196,"props":2785,"children":2786},{},[2787],{"type":48,"value":2788},"Signal",{"type":42,"tag":2196,"props":2790,"children":2791},{},[2792],{"type":48,"value":2793},"How",{"type":42,"tag":2196,"props":2795,"children":2796},{},[2797],{"type":48,"value":2798},"Why",{"type":42,"tag":2212,"props":2800,"children":2801},{},[2802,2820,2846,2872,2890,2908],{"type":42,"tag":2192,"props":2803,"children":2804},{},[2805,2810,2815],{"type":42,"tag":2219,"props":2806,"children":2807},{},[2808],{"type":48,"value":2809},"Failed transactions involving your package",{"type":42,"tag":2219,"props":2811,"children":2812},{},[2813],{"type":48,"value":2814},"Subscribe to transaction effects via gRPC streaming, filter by package ID",{"type":42,"tag":2219,"props":2816,"children":2817},{},[2818],{"type":48,"value":2819},"Detects Move aborts, gas failures, or unexpected reverts in production",{"type":42,"tag":2192,"props":2821,"children":2822},{},[2823,2828,2841],{"type":42,"tag":2219,"props":2824,"children":2825},{},[2826],{"type":48,"value":2827},"Gas spend",{"type":42,"tag":2219,"props":2829,"children":2830},{},[2831,2833,2839],{"type":48,"value":2832},"Track ",{"type":42,"tag":67,"props":2834,"children":2836},{"className":2835},[],[2837],{"type":48,"value":2838},"gasUsed",{"type":48,"value":2840}," from transaction effects",{"type":42,"tag":2219,"props":2842,"children":2843},{},[2844],{"type":48,"value":2845},"Catch unexpectedly expensive operations or gas drain attacks",{"type":42,"tag":2192,"props":2847,"children":2848},{},[2849,2854,2867],{"type":42,"tag":2219,"props":2850,"children":2851},{},[2852],{"type":48,"value":2853},"Event emission",{"type":42,"tag":2219,"props":2855,"children":2856},{},[2857,2859,2865],{"type":48,"value":2858},"Subscribe to events by type (",{"type":42,"tag":67,"props":2860,"children":2862},{"className":2861},[],[2863],{"type":48,"value":2864},"{packageId}::module::EventName",{"type":48,"value":2866},") via gRPC streaming",{"type":42,"tag":2219,"props":2868,"children":2869},{},[2870],{"type":48,"value":2871},"Core business telemetry — mints, transfers, admin actions, deny list changes",{"type":42,"tag":2192,"props":2873,"children":2874},{},[2875,2880,2885],{"type":42,"tag":2219,"props":2876,"children":2877},{},[2878],{"type":48,"value":2879},"Object creation\u002Fdeletion rates",{"type":42,"tag":2219,"props":2881,"children":2882},{},[2883],{"type":48,"value":2884},"Query or subscribe to object changes filtered by your types",{"type":42,"tag":2219,"props":2886,"children":2887},{},[2888],{"type":48,"value":2889},"Detect abnormal activity (mass minting, object spam)",{"type":42,"tag":2192,"props":2891,"children":2892},{},[2893,2898,2903],{"type":42,"tag":2219,"props":2894,"children":2895},{},[2896],{"type":48,"value":2897},"Admin\u002Fcap usage",{"type":42,"tag":2219,"props":2899,"children":2900},{},[2901],{"type":48,"value":2902},"Filter events for capability-gated actions",{"type":42,"tag":2219,"props":2904,"children":2905},{},[2906],{"type":48,"value":2907},"Detect unauthorized or unexpected admin operations",{"type":42,"tag":2192,"props":2909,"children":2910},{},[2911,2916,2921],{"type":42,"tag":2219,"props":2912,"children":2913},{},[2914],{"type":48,"value":2915},"Shared object contention",{"type":42,"tag":2219,"props":2917,"children":2918},{},[2919],{"type":48,"value":2920},"Monitor transaction latency for shared-object transactions",{"type":42,"tag":2219,"props":2922,"children":2923},{},[2924],{"type":48,"value":2925},"High contention degrades UX; may need object sharding",{"type":42,"tag":116,"props":2927,"children":2929},{"id":2928},"implementation",[2930],{"type":48,"value":2931},"Implementation",{"type":42,"tag":55,"props":2933,"children":2934},{},[2935],{"type":48,"value":2936},"Use gRPC streaming subscriptions for real-time monitoring:",{"type":42,"tag":128,"props":2938,"children":2940},{"className":1370,"code":2939,"language":1372,"meta":133,"style":133},"for await (const event of client.subscriptionService.subscribeEvents({\n  filter: { MoveEventModule: { package: PACKAGE_ID, module: 'my_module' } },\n})) {\n  \u002F\u002F Forward to your monitoring stack (Grafana, Datadog, PagerDuty, etc.)\n}\n",[2941],{"type":42,"tag":67,"props":2942,"children":2943},{"__ignoreMap":133},[2944,3008,3088,3104,3112],{"type":42,"tag":139,"props":2945,"children":2946},{"class":141,"line":142},[2947,2953,2958,2962,2968,2973,2978,2982,2986,2991,2995,3000,3004],{"type":42,"tag":139,"props":2948,"children":2950},{"style":2949},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[2951],{"type":48,"value":2952},"for",{"type":42,"tag":139,"props":2954,"children":2955},{"style":2949},[2956],{"type":48,"value":2957}," await",{"type":42,"tag":139,"props":2959,"children":2960},{"style":568},[2961],{"type":48,"value":204},{"type":42,"tag":139,"props":2963,"children":2965},{"style":2964},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[2966],{"type":48,"value":2967},"const",{"type":42,"tag":139,"props":2969,"children":2970},{"style":568},[2971],{"type":48,"value":2972}," event ",{"type":42,"tag":139,"props":2974,"children":2975},{"style":557},[2976],{"type":48,"value":2977},"of",{"type":42,"tag":139,"props":2979,"children":2980},{"style":568},[2981],{"type":48,"value":186},{"type":42,"tag":139,"props":2983,"children":2984},{"style":557},[2985],{"type":48,"value":107},{"type":42,"tag":139,"props":2987,"children":2988},{"style":568},[2989],{"type":48,"value":2990},"subscriptionService",{"type":42,"tag":139,"props":2992,"children":2993},{"style":557},[2994],{"type":48,"value":107},{"type":42,"tag":139,"props":2996,"children":2997},{"style":146},[2998],{"type":48,"value":2999},"subscribeEvents",{"type":42,"tag":139,"props":3001,"children":3002},{"style":568},[3003],{"type":48,"value":1437},{"type":42,"tag":139,"props":3005,"children":3006},{"style":557},[3007],{"type":48,"value":1442},{"type":42,"tag":139,"props":3009,"children":3010},{"class":141,"line":29},[3011,3016,3020,3025,3030,3034,3038,3043,3047,3052,3056,3061,3065,3069,3074,3078,3083],{"type":42,"tag":139,"props":3012,"children":3013},{"style":1449},[3014],{"type":48,"value":3015},"  filter",{"type":42,"tag":139,"props":3017,"children":3018},{"style":557},[3019],{"type":48,"value":1134},{"type":42,"tag":139,"props":3021,"children":3022},{"style":557},[3023],{"type":48,"value":3024}," {",{"type":42,"tag":139,"props":3026,"children":3027},{"style":1449},[3028],{"type":48,"value":3029}," MoveEventModule",{"type":42,"tag":139,"props":3031,"children":3032},{"style":557},[3033],{"type":48,"value":1134},{"type":42,"tag":139,"props":3035,"children":3036},{"style":557},[3037],{"type":48,"value":3024},{"type":42,"tag":139,"props":3039,"children":3040},{"style":1449},[3041],{"type":48,"value":3042}," package",{"type":42,"tag":139,"props":3044,"children":3045},{"style":557},[3046],{"type":48,"value":1134},{"type":42,"tag":139,"props":3048,"children":3049},{"style":568},[3050],{"type":48,"value":3051}," PACKAGE_ID",{"type":42,"tag":139,"props":3053,"children":3054},{"style":557},[3055],{"type":48,"value":1499},{"type":42,"tag":139,"props":3057,"children":3058},{"style":1449},[3059],{"type":48,"value":3060}," module",{"type":42,"tag":139,"props":3062,"children":3063},{"style":557},[3064],{"type":48,"value":1134},{"type":42,"tag":139,"props":3066,"children":3067},{"style":557},[3068],{"type":48,"value":1484},{"type":42,"tag":139,"props":3070,"children":3071},{"style":152},[3072],{"type":48,"value":3073},"my_module",{"type":42,"tag":139,"props":3075,"children":3076},{"style":557},[3077],{"type":48,"value":1494},{"type":42,"tag":139,"props":3079,"children":3080},{"style":557},[3081],{"type":48,"value":3082}," }",{"type":42,"tag":139,"props":3084,"children":3085},{"style":557},[3086],{"type":48,"value":3087}," },\n",{"type":42,"tag":139,"props":3089,"children":3090},{"class":141,"line":176},[3091,3095,3100],{"type":42,"tag":139,"props":3092,"children":3093},{"style":557},[3094],{"type":48,"value":1513},{"type":42,"tag":139,"props":3096,"children":3097},{"style":568},[3098],{"type":48,"value":3099},")) ",{"type":42,"tag":139,"props":3101,"children":3102},{"style":557},[3103],{"type":48,"value":1442},{"type":42,"tag":139,"props":3105,"children":3106},{"class":141,"line":608},[3107],{"type":42,"tag":139,"props":3108,"children":3109},{"style":530},[3110],{"type":48,"value":3111},"  \u002F\u002F Forward to your monitoring stack (Grafana, Datadog, PagerDuty, etc.)\n",{"type":42,"tag":139,"props":3113,"children":3114},{"class":141,"line":617},[3115],{"type":42,"tag":139,"props":3116,"children":3117},{"style":557},[3118],{"type":48,"value":3119},"}\n",{"type":42,"tag":55,"props":3121,"children":3122},{},[3123,3125,3131,3133,3139,3141,3147],{"type":48,"value":3124},"For historical analysis, run a custom indexer (",{"type":42,"tag":67,"props":3126,"children":3128},{"className":3127},[],[3129],{"type":48,"value":3130},"sui-indexer-alt",{"type":48,"value":3132},") that writes relevant events and transaction effects to your own database. See the ",{"type":42,"tag":67,"props":3134,"children":3136},{"className":3135},[],[3137],{"type":48,"value":3138},"accessing-data",{"type":48,"value":3140}," skill's ",{"type":42,"tag":67,"props":3142,"children":3144},{"className":3143},[],[3145],{"type":48,"value":3146},"indexers.md",{"type":48,"value":107},{"type":42,"tag":55,"props":3149,"children":3150},{},[3151],{"type":48,"value":3152},"Emit events for every security-critical action in your Move code — admin changes, configuration updates, deny list modifications, object deletions. Events are the only way offchain systems can observe these actions.",{"type":42,"tag":109,"props":3154,"children":3156},{"id":3155},"rollback-and-incident-response",[3157],{"type":48,"value":3158},"Rollback and incident response",{"type":42,"tag":55,"props":3160,"children":3161},{},[3162,3167,3169,3175,3176,3182],{"type":42,"tag":59,"props":3163,"children":3164},{},[3165],{"type":48,"value":3166},"Sui packages cannot be rolled back.",{"type":48,"value":3168}," Published bytecode is immutable. There is no ",{"type":42,"tag":67,"props":3170,"children":3172},{"className":3171},[],[3173],{"type":48,"value":3174},"revert",{"type":48,"value":1754},{"type":42,"tag":67,"props":3177,"children":3179},{"className":3178},[],[3180],{"type":48,"value":3181},"rollback",{"type":48,"value":3183}," command. Recovery means publishing a forward-fix upgrade.",{"type":42,"tag":116,"props":3185,"children":3187},{"id":3186},"if-a-bad-upgrade-is-published",[3188],{"type":48,"value":3189},"If a bad upgrade is published",{"type":42,"tag":220,"props":3191,"children":3192},{},[3193,3203,3220,3245],{"type":42,"tag":224,"props":3194,"children":3195},{},[3196,3201],{"type":42,"tag":59,"props":3197,"children":3198},{},[3199],{"type":48,"value":3200},"Assess scope.",{"type":48,"value":3202}," Determine which functions are affected. Existing objects created by prior versions are still valid — their types are anchored to the original package ID.",{"type":42,"tag":224,"props":3204,"children":3205},{},[3206,3211,3213,3218],{"type":42,"tag":59,"props":3207,"children":3208},{},[3209],{"type":48,"value":3210},"Publish a fix upgrade immediately.",{"type":48,"value":3212}," Write the corrected code, run tests, dry-run on Testnet, then ",{"type":42,"tag":67,"props":3214,"children":3216},{"className":3215},[],[3217],{"type":48,"value":734},{"type":48,"value":3219}," on Mainnet. The new package ID replaces the old one for all future calls.",{"type":42,"tag":224,"props":3221,"children":3222},{},[3223,3228,3230,3236,3238,3244],{"type":42,"tag":59,"props":3224,"children":3225},{},[3226],{"type":48,"value":3227},"Update frontends.",{"type":48,"value":3229}," Point ",{"type":42,"tag":67,"props":3231,"children":3233},{"className":3232},[],[3234],{"type":48,"value":3235},"PACKAGE_IDS",{"type":48,"value":3237}," to the new (fixed) package ID. Type queries still use ",{"type":42,"tag":67,"props":3239,"children":3241},{"className":3240},[],[3242],{"type":48,"value":3243},"ORIGINAL_PACKAGE_IDS",{"type":48,"value":107},{"type":42,"tag":224,"props":3246,"children":3247},{},[3248,3253],{"type":42,"tag":59,"props":3249,"children":3250},{},[3251],{"type":48,"value":3252},"Communicate.",{"type":48,"value":3254}," If the bug affected user-facing behavior, notify users through your app's channels.",{"type":42,"tag":116,"props":3256,"children":3258},{"id":3257},"if-the-upgradecap-is-compromised",[3259],{"type":48,"value":3260},"If the UpgradeCap is compromised",{"type":42,"tag":55,"props":3262,"children":3263},{},[3264,3266,3271],{"type":48,"value":3265},"An attacker with the ",{"type":42,"tag":67,"props":3267,"children":3269},{"className":3268},[],[3270],{"type":48,"value":315},{"type":48,"value":3272}," can publish arbitrary code under your package. Mitigation:",{"type":42,"tag":291,"props":3274,"children":3275},{},[3276,3299],{"type":42,"tag":224,"props":3277,"children":3278},{},[3279,3284,3286,3291,3292,3297],{"type":42,"tag":59,"props":3280,"children":3281},{},[3282],{"type":48,"value":3283},"If you still hold the cap:",{"type":48,"value":3285}," Immediately restrict it (",{"type":42,"tag":67,"props":3287,"children":3289},{"className":3288},[],[3290],{"type":48,"value":2324},{"type":48,"value":1754},{"type":42,"tag":67,"props":3293,"children":3295},{"className":3294},[],[3296],{"type":48,"value":2332},{"type":48,"value":3298},") to prevent further malicious upgrades.",{"type":42,"tag":224,"props":3300,"children":3301},{},[3302,3307,3309,3314],{"type":42,"tag":59,"props":3303,"children":3304},{},[3305],{"type":48,"value":3306},"If the attacker holds the cap:",{"type":48,"value":3308}," You cannot recover upgrade authority. Publish a new package, migrate users, and communicate the migration. This is why multisig custody of the ",{"type":42,"tag":67,"props":3310,"children":3312},{"className":3311},[],[3313],{"type":48,"value":315},{"type":48,"value":3315}," matters for production packages.",{"type":42,"tag":116,"props":3317,"children":3319},{"id":3318},"if-a-shared-object-is-corrupted",[3320],{"type":48,"value":3321},"If a shared object is corrupted",{"type":42,"tag":55,"props":3323,"children":3324},{},[3325],{"type":48,"value":3326},"A buggy function may write invalid state to a shared object. Since shared objects are mutable by any transaction:",{"type":42,"tag":291,"props":3328,"children":3329},{},[3330,3347],{"type":42,"tag":224,"props":3331,"children":3332},{},[3333,3338,3340,3346],{"type":42,"tag":59,"props":3334,"children":3335},{},[3336],{"type":48,"value":3337},"If you can upgrade:",{"type":48,"value":3339}," Publish an upgrade with a repair function that fixes the corrupted state. Gate it behind an ",{"type":42,"tag":67,"props":3341,"children":3343},{"className":3342},[],[3344],{"type":48,"value":3345},"AdminCap",{"type":48,"value":107},{"type":42,"tag":224,"props":3348,"children":3349},{},[3350,3355],{"type":42,"tag":59,"props":3351,"children":3352},{},[3353],{"type":48,"value":3354},"If the package is immutable:",{"type":48,"value":3356}," The only option is to deploy a new package with a migration function that reads the old object's data (if accessible) and creates corrected objects.",{"type":42,"tag":116,"props":3358,"children":3360},{"id":3359},"prevention-checklist",[3361],{"type":48,"value":3362},"Prevention checklist",{"type":42,"tag":291,"props":3364,"children":3366},{"className":3365},[2569],[3367,3396,3405,3414,3423],{"type":42,"tag":224,"props":3368,"children":3370},{"className":3369},[2574],[3371,3374,3375,3380,3382,3388,3390],{"type":42,"tag":2577,"props":3372,"children":3373},{"disabled":602,"type":2579},[],{"type":48,"value":2582},{"type":42,"tag":67,"props":3376,"children":3378},{"className":3377},[],[3379],{"type":48,"value":315},{"type":48,"value":3381}," held by multisig or restricted to ",{"type":42,"tag":67,"props":3383,"children":3385},{"className":3384},[],[3386],{"type":48,"value":3387},"additive",{"type":48,"value":3389}," \u002F ",{"type":42,"tag":67,"props":3391,"children":3393},{"className":3392},[],[3394],{"type":48,"value":3395},"dep_only",{"type":42,"tag":224,"props":3397,"children":3399},{"className":3398},[2574],[3400,3403],{"type":42,"tag":2577,"props":3401,"children":3402},{"disabled":602,"type":2579},[],{"type":48,"value":3404}," All upgrades tested on Testnet with the same code, same publish flow",{"type":42,"tag":224,"props":3406,"children":3408},{"className":3407},[2574],[3409,3412],{"type":42,"tag":2577,"props":3410,"children":3411},{"disabled":602,"type":2579},[],{"type":48,"value":3413}," Admin actions emit events for monitoring",{"type":42,"tag":224,"props":3415,"children":3417},{"className":3416},[2574],[3418,3421],{"type":42,"tag":2577,"props":3419,"children":3420},{"disabled":602,"type":2579},[],{"type":48,"value":3422}," Critical shared objects have repair functions gated behind capabilities",{"type":42,"tag":224,"props":3424,"children":3426},{"className":3425},[2574],[3427,3430],{"type":42,"tag":2577,"props":3428,"children":3429},{"disabled":602,"type":2579},[],{"type":48,"value":3431}," Frontend can switch package IDs without a redeploy (environment config, not hardcoded)",{"type":42,"tag":3433,"props":3434,"children":3435},"style",{},[3436],{"type":48,"value":3437},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":3439,"total":3541},[3440,3451,3464,3485,3499,3512,3528],{"slug":3138,"name":3138,"fn":3441,"description":3442,"org":3443,"tags":3444,"stars":25,"repoUrl":26,"updatedAt":3450},"read data from the Sui network","How to read data from the Sui network. Use when choosing or implementing a data access strategy — queries for on-chain state, indexing pipelines, historical lookups, event subscriptions, cross-chain reads, or off-chain blob storage. Covers the two live Sui APIs (gRPC and GraphQL RPC), the Archival Store, the General-Purpose Indexer, the `sui-indexer-alt` custom indexing framework, and Walrus for off-chain blobs.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3445,3448,3449],{"name":3446,"slug":3447,"type":15},"Data Analysis","data-analysis",{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-08-01T05:44:32.775598",{"slug":3452,"name":3452,"fn":3453,"description":3454,"org":3455,"tags":3456,"stars":25,"repoUrl":26,"updatedAt":3463},"composable-move-functions","design composable Sui Move functions","Use when writing Move functions on Sui, especially public APIs. Applies to function visibility (public vs entry), parameter ordering, and return patterns. Use whenever designing function signatures or deciding whether functions should transfer objects or return them.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3457,3460,3461,3462],{"name":3458,"slug":3459,"type":15},"API Development","api-development",{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-16T06:02:49.198495",{"slug":3465,"name":3465,"fn":3466,"description":3467,"org":3468,"tags":3469,"stars":25,"repoUrl":26,"updatedAt":3484},"frontend-apps","build Sui dApps with dapp-kit","Sui frontend \u002F dApp development with @mysten\u002Fdapp-kit-react (React) and @mysten\u002Fdapp-kit-core (Vue, vanilla JS, Svelte, Web Components, other frameworks). Use when building browser apps that connect Sui wallets, query on-chain state, or submit transactions. Covers wallet connection, network switching, transaction execution, query patterns with TanStack React Query, and the specific pitfalls of browser + wallet + async-indexer environments. Pair with the `sui-sdks` skill for @mysten\u002Fsui Transaction construction patterns and the `ptbs` skill for PTB semantics.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3470,3473,3476,3477,3480,3483],{"name":3471,"slug":3472,"type":15},"Frontend","frontend",{"name":3474,"slug":3475,"type":15},"React","react",{"name":14,"slug":8,"type":15},{"name":3478,"slug":3479,"type":15},"Svelte","svelte",{"name":3481,"slug":3482,"type":15},"Vue","vue",{"name":17,"slug":18,"type":15},"2026-08-01T05:44:28.958473",{"slug":3486,"name":3486,"fn":3487,"description":3488,"org":3489,"tags":3490,"stars":25,"repoUrl":26,"updatedAt":3498},"generate-sui-agent-config","generate configuration files for Sui projects","Generate a CLAUDE.md or AGENT.md configuration file for Sui projects. Use when setting up a new Sui project, when user mentions \"CLAUDE.md\", \"AGENT.md\", \"agent config\", or when working on a Sui project that does not already have a CLAUDE.md or AGENT.md in the project root.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3491,3494,3497],{"name":3492,"slug":3493,"type":15},"Configuration","configuration",{"name":3495,"slug":3496,"type":15},"Documentation","documentation",{"name":14,"slug":8,"type":15},"2026-07-16T06:00:59.981056",{"slug":3500,"name":3500,"fn":3501,"description":3502,"org":3503,"tags":3504,"stars":25,"repoUrl":26,"updatedAt":3511},"modern-move-syntax","write Move 2024 edition code for Sui","Use when writing Move code on Sui to ensure 2024 edition syntax is used. Applies to method calls, string literals, vector operations, option handling, loops, and struct unpacking. Use whenever writing Move code to avoid legacy function-call syntax patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3505,3508,3509,3510],{"name":3506,"slug":3507,"type":15},"Engineering","engineering",{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-16T06:02:43.277596",{"slug":3513,"name":3513,"fn":3514,"description":3515,"org":3516,"tags":3517,"stars":25,"repoUrl":26,"updatedAt":3527},"move-unit-testing","write unit tests for Sui Move contracts","Use when writing unit tests for Move smart contracts on Sui. Applies to test function naming, assertions, test attributes, context usage, and cleanup patterns. Use whenever user asks to write tests, add tests, or test a Move module.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3518,3521,3522,3523,3526],{"name":3519,"slug":3520,"type":15},"QA","qa",{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":3524,"slug":3525,"type":15},"Testing","testing",{"name":17,"slug":18,"type":15},"2026-08-01T05:44:30.788585",{"slug":3529,"name":3529,"fn":3530,"description":3531,"org":3532,"tags":3533,"stars":25,"repoUrl":26,"updatedAt":3540},"naming-conventions","apply Sui Move naming conventions","Use when writing or reviewing Move smart contracts on Sui. Applies to naming structs, error constants, regular constants, events, getter functions, capability types, hot potato types, and dynamic field keys. Use whenever creating new types, functions, or constants in Move code.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3534,3537,3538,3539],{"name":3535,"slug":3536,"type":15},"Best Practices","best-practices",{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},"2026-07-16T06:02:48.830052",20,{"items":3543,"total":3660},[3544,3558,3567,3577,3592,3610,3616,3623,3632,3638,3645,3653],{"slug":3545,"name":3545,"fn":3546,"description":3547,"org":3548,"tags":3549,"stars":3555,"repoUrl":3556,"updatedAt":3557},"move-bytecode-comprehension","analyze and disassemble Move bytecode","Use when reading or reasoning about compiled Move bytecode or `sui move disassemble` output. Mental model for the binary format, what survives compilation (and what's lost), and how to read disassembly soundly. Trigger on \"what does this package do?\", \"read this .mv module\", \"interpret this disassembly\", or whenever an analysis needs to interpret bytecode faithfully.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3550,3553,3554],{"name":3551,"slug":3552,"type":15},"Code Analysis","code-analysis",{"name":3506,"slug":3507,"type":15},{"name":14,"slug":8,"type":15},7724,"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002Fsui","2026-07-16T05:59:32.904886",{"slug":3559,"name":3559,"fn":3560,"description":3561,"org":3562,"tags":3563,"stars":3555,"repoUrl":3556,"updatedAt":3566},"official-sui-skills","access official Sui development resources","Pointer to the official Mysten Labs skills for building on Sui — language fundamentals, object model, PTBs, SDKs, publishing, upgrades, frontend integration, accessing on-chain data. Maintained upstream at github.com\u002FMystenLabs\u002Fskills; pinned to the same ref the audit catalog derives from (see maintenance\u002FUPSTREAMS.md). Trigger on \"build a contract\", \"publish a package\", \"upgrade a module or package\", \"use the TypeScript SDK\", \"write a PTB\", \"set up a Sui client\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3564,3565],{"name":3495,"slug":3496,"type":15},{"name":14,"slug":8,"type":15},"2026-07-16T06:00:59.641382",{"slug":3568,"name":3568,"fn":3569,"description":3570,"org":3571,"tags":3572,"stars":3555,"repoUrl":3556,"updatedAt":3576},"sui-and-move-tools","disassemble Sui Move bytecode","Use to get bytecode for a deployed Sui package and produce a disassembled working view. One GraphQL call fetches every module's raw bytecode bytes; `sui move disassemble` (already on the system, running `sui prompt`) produces `.asm` files for analysis. Trigger on \"fetch this package's bytecode\", \"get me the .mv for package X\", \"disassemble this package\", or \"I need to read a deployed Sui package\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3573,3574,3575],{"name":3551,"slug":3552,"type":15},{"name":3506,"slug":3507,"type":15},{"name":14,"slug":8,"type":15},"2026-07-16T06:02:25.3633",{"slug":3578,"name":3578,"fn":3579,"description":3580,"org":3581,"tags":3582,"stars":3555,"repoUrl":3556,"updatedAt":3591},"sui-move-security-review","audit Sui Move smart contracts","Use when auditing, reviewing, or hunting for vulnerabilities in Move code on Sui. Applies equally to source code (.move files) and to disassembly of compiled bytecode (on-chain packages). A checklist of invariants whose VIOLATION causes exploitable bugs: access control & capabilities, struct abilities & type safety, object lifecycle & ownership, shared-object and PTB attack surface, dynamic fields & collections, arithmetic & coins, init\u002FOTW\u002Fpackage upgrades, hot-potato composability, time & on-chain randomness, and test-only code leakage. Trigger on \"audit this Move code\", \"find vulnerabilities in this Sui contract\", \"security review\", \"is this package safe?\", \"I suspect there's a bug in X\", \"something is wrong with this contract\", or when reasoning about whether a Move function can be abused.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3583,3586,3589,3590],{"name":3584,"slug":3585,"type":15},"Code Review","code-review",{"name":3587,"slug":3588,"type":15},"Security","security",{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},"2026-07-16T06:02:55.691149",{"slug":3593,"name":3593,"fn":3594,"description":3595,"org":3596,"tags":3597,"stars":3607,"repoUrl":3608,"updatedAt":3609},"memwal","integrate Walrus Memory SDK","Walrus Memory SDK — portable agent memory that works across apps, sessions, and workflows.\n\nUse when users say:\n- \"add memory to my app\"\n- \"portable agent memory\"\n- \"integrate Walrus Memory\"\n- \"AI agent memory\"\n- \"memory across agents\"\n- \"Walrus memory storage\"\n- \"setup Walrus Memory\"\n- \"recall memories\"\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3598,3601,3604],{"name":3599,"slug":3600,"type":15},"Agents","agents",{"name":3602,"slug":3603,"type":15},"Memory","memory",{"name":3605,"slug":3606,"type":15},"SDK","sdk",57,"https:\u002F\u002Fgithub.com\u002FMystenLabs\u002FMemWal","2026-07-16T06:02:39.838395",{"slug":3138,"name":3138,"fn":3441,"description":3442,"org":3611,"tags":3612,"stars":25,"repoUrl":26,"updatedAt":3450},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3613,3614,3615],{"name":3446,"slug":3447,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"slug":3452,"name":3452,"fn":3453,"description":3454,"org":3617,"tags":3618,"stars":25,"repoUrl":26,"updatedAt":3463},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3619,3620,3621,3622],{"name":3458,"slug":3459,"type":15},{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"slug":3465,"name":3465,"fn":3466,"description":3467,"org":3624,"tags":3625,"stars":25,"repoUrl":26,"updatedAt":3484},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3626,3627,3628,3629,3630,3631],{"name":3471,"slug":3472,"type":15},{"name":3474,"slug":3475,"type":15},{"name":14,"slug":8,"type":15},{"name":3478,"slug":3479,"type":15},{"name":3481,"slug":3482,"type":15},{"name":17,"slug":18,"type":15},{"slug":3486,"name":3486,"fn":3487,"description":3488,"org":3633,"tags":3634,"stars":25,"repoUrl":26,"updatedAt":3498},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3635,3636,3637],{"name":3492,"slug":3493,"type":15},{"name":3495,"slug":3496,"type":15},{"name":14,"slug":8,"type":15},{"slug":3500,"name":3500,"fn":3501,"description":3502,"org":3639,"tags":3640,"stars":25,"repoUrl":26,"updatedAt":3511},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3641,3642,3643,3644],{"name":3506,"slug":3507,"type":15},{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},{"slug":3513,"name":3513,"fn":3514,"description":3515,"org":3646,"tags":3647,"stars":25,"repoUrl":26,"updatedAt":3527},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3648,3649,3650,3651,3652],{"name":3519,"slug":3520,"type":15},{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":3524,"slug":3525,"type":15},{"name":17,"slug":18,"type":15},{"slug":3529,"name":3529,"fn":3530,"description":3531,"org":3654,"tags":3655,"stars":25,"repoUrl":26,"updatedAt":3540},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3656,3657,3658,3659],{"name":3535,"slug":3536,"type":15},{"name":23,"slug":24,"type":15},{"name":14,"slug":8,"type":15},{"name":17,"slug":18,"type":15},37]