PageSourceSearch

https://cosmwasm.github.io/assets/js/106aeb73.f42930a5.js

js cosmwasm.github.io collected 2026-10-03 08:50:48 UTC 22,202 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkcosmwasm_documentation=self.webpackChunkcosmwasm_documentation||[]).push([["4169"],{2373(e,n,t){t.r(n),t.d(n,{metadata:()=>a,default:()=>l,frontMatter:()=>o,contentTitle:()=>d,toc:()=>c,assets:()=>i});var a=JSON.parse('{"id":"tutorial/platform/sudo-msg","title":"First sudo message","description":"The Cosmos way to manage your smart contract.","source":"@site/docs/tutorial/platform/17-sudo-msg.md","sourceDirName":"tutorial/platform","slug":"/tutorial/platform/sudo-msg","permalink":"/tutorial/platform/sudo-msg","draft":false,"unlisted":false,"tags":[],"version":"current","lastUpdatedAt":1763729090000,"sidebarPosition":17,"frontMatter":{"title":"First sudo message","description":"The Cosmos way to manage your smart contract."},"sidebar":"tutorialSidebar","previous":{"title":"Proper funds handling","permalink":"/tutorial/platform/fund-handling"},"next":{"title":"First migration","permalink":"/tutorial/platform/migration"}}'),s=t(4848),r=t(8453);let o={title:"First sudo message",description:"The Cosmos way to manage your smart contract."},d="First sudo message",i={},c=[{value:"The mechanism",id:"the-mechanism",level:2},{value:"The use-case",id:"the-use-case",level:2},{value:"Add the payment params query",id:"add-the-payment-params-query",level:2},{value:"The sudo message",id:"the-sudo-message",level:2},{value:"Sudo handling",id:"sudo-handling",level:2},{value:"Adjust instantiate for good measure",id:"adjust-instantiate-for-good-measure",level:2},{value:"Unit tests",id:"unit-tests",level:2},{value:"Mocked app tests",id:"mocked-app-tests",level:2},{value:"Conclusion",id:"conclusion",level:2}];function m(e){let n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"first-sudo-message",children:"First sudo message"})}),"\n",(0,s.jsxs)(n.p,{children:["Your ",(0,s.jsx)(n.em,{children:"collection manager"})," smart contract can now impose a payment when minting a new name."]}),"\n",(0,s.jsx)(n.p,{children:":::info Exercise progression"}),"\n",(0,s.jsx)(n.p,{children:"If you skipped the previous section, you can just switch:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"my-nameservice"})," project to its ",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-nameservice/tree/execute-return-data",children:(0,s.jsx)(n.code,{children:"execute-return-data"})})," branch."]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"my-collection-manager"})," project to its ",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-collection-manager/tree/proper-fund-handling",children:(0,s.jsx)(n.code,{children:"proper-fund-handling"})})," branch."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"And take it from there."}),"\n",(0,s.jsx)(n.p,{children:":::"}),"\n",(0,s.jsxs)(n.p,{children:["What if you want to change the price or the beneficiary? You could add a new ",(0,s.jsx)(n.code,{children:"ExecuteMsg"})," variant,\nand gateway it with some parameters. Perhaps you may want to have a vote on it.\nAll this sounds a lot like a governance proposal as it can be implemented on a Cosmos app-chain.\nWhat if you could create a governance proposal whose execution is deterministically executed by your smart contract?"]}),"\n",(0,s.jsxs)(n.p,{children:["That's one of the purposes of ",(0,s.jsx)(n.strong,{children:"sudo"})," messages. A sudo message is one that comes from the underlying app-chain.\nThis is not a user-generated message coming with a transaction."]}),"\n",(0,s.jsx)(n.h2,{id:"the-mechanism",children:"The mechanism"}),"\n",(0,s.jsxs)(n.p,{children:["When running ",(0,s.jsx)(n.code,{children:"wasmd"})," or your own app chain you can launch a governance proposal by using the command:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",children:"wasmd tx gov submit-proposal sudo-contract --help\n"})}),"\n",(0,s.jsxs)(n.p,{children:["This creates a ",(0,s.jsx)(n.a,{href:"https://github.com/CosmWasm/wasmd/blob/v0.53.0/proto/cosmwasm/wasm/v1/tx.proto#L314-L328",children:(0,s.jsx)(n.code,{children:"MsgSudoContract"})}),"\nthat very much looks like ",(0,s.jsx)(n.a,{href:"https://github.com/CosmWasm/cw-multi-test/blob/v1.2.0/src/wasm.rs#L45-L53",children:(0,s.jsx)(n.code,{children:"WasmSudo"})}),"\nthat you use in the mocked app tests below."]}),"\n",(0,s.jsxs)(n.p,{children:["When the proposal is voted in, your smart contract gets called with the ",(0,s.jsx)(n.code,{children:"bytes msg"})," part."]}),"\n",(0,s.jsx)(n.h2,{id:"the-use-case",children:"The use-case"}),"\n",(0,s.jsx)(n.p,{children:"You implement a sudo message that lets the app-chain change the payment parameters."}),"\n",(0,s.jsx)(n.h2,{id:"add-the-payment-params-query",children:"Add the payment params query"}),"\n",(0,s.jsx)(n.p,{children:"As it is going to be useful, add a query to get the current payment parameters.\nIn a previous section, you saw in detail how to do that, so here we add them without many explanations:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="src/msg.rs"',children:"// diff-del\n- use cosmwasm_schema::cw_serde;\n// diff-add\n+ use cosmwasm_schema::{cw_serde, QueryResponses};\n  use cosmwasm_std::{Addr, Coin, Empty, Uint128};\n  ...\n  pub struct NameServiceExecuteMsgResponse {\n      pub num_tokens: u64,\n  }\n// diff-add-start\n+\n+ #[cw_serde]\n+ #[derive(QueryResponses)]\n+ pub enum QueryMsg {\n+     #[returns(GetPaymentParam
1sResponse)]\n+     GetPaymentParams,\n+ }\n+\n+ #[cw_serde]\n+ pub struct GetPaymentParamsResponse {\n+     pub payment_params: PaymentParams,\n+ }\n// diff-add-end\n"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="src/contract.rs"',children:'  use crate::{\n      error::ContractError,\n      msg::{\n// diff-del-start\n-         CollectionExecuteMsg, CollectionQueryMsg, ExecuteMsg, InstantiateMsg,\n-         NameServiceExecuteMsgResponse,\n// diff-del-end\n// diff-add-start\n+         CollectionExecuteMsg, CollectionQueryMsg, ExecuteMsg, GetPaymentParamsResponse,\n+         InstantiateMsg, NameServiceExecuteMsgResponse, QueryMsg,\n// diff-add-end\n      },\n      state::PAYMENT_PARAMS,\n  };\n  ...\n  use cosmwasm_std::{\n// diff-del-start\n-     from_json, to_json_binary, BankMsg, Coin, CosmosMsg, DepsMut, Empty, Env, Event, MessageInfo,\n-     QueryRequest, Reply, ReplyOn, Response, StdError, SubMsg, Uint128, WasmMsg, WasmQuery,\n// diff-del-end\n// diff-add-start\n+     from_json, to_json_binary, BankMsg, Coin, CosmosMsg, Deps, DepsMut, Empty, Env, Event,\n+     MessageInfo, QueryRequest, QueryResponse, Reply, ReplyOn, Response, StdError, SubMsg, Uint128,\n+     WasmMsg, WasmQuery,\n// diff-add-end\n  };\n  ...\n  fn reply_pass_through(...) -> ContractResult {\n      ...\n  }\n\n// diff-add-start\n+ #[cfg_attr(not(feature = "library"), entry_point)]\n+ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result<QueryResponse, ContractError> {\n+     match msg {\n+         QueryMsg::GetPaymentParams {} => Ok(to_json_binary(&GetPaymentParamsResponse {\n+             payment_params: PAYMENT_PARAMS.load(deps.storage)?,\n+         })?),\n+     }\n+ }\n// diff-add-end\n  ...\n'})}),"\n",(0,s.jsx)(n.p,{children:"Take this opportunity to replace your dummy query lambda, used in the mocked app test, with the real function:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="test/contract.rs"',children:'// diff-del\n- use cosmwasm_std::{to_json_binary, Addr, Coin, Empty, Event, Uint128};\n// diff-add\n+ use cosmwasm_std::{Addr, Coin, Empty, Event, Uint128};\n  ...\n  use cw_my_collection_manager::{\n// diff-del\n-     contract::{execute, instantiate, reply},\n// diff-add\n+     contract::{execute, instantiate, query, reply},\n      msg::{ExecuteMsg, InstantiateMsg, PaymentParams},\n  };\n  ...\n  fn instantiate_collection_manager(\n      ...\n  ) -> (u64, Addr) {\n// diff-del-start\n-     let code = Box::new(\n-         ContractWrapper::new(execute, instantiate, |_, _, _: ()| {\n-             to_json_binary("mocked_manager_query")\n-         })\n-         .with_reply(reply),\n-     );\n// diff-del-end\n// diff-add\n+     let code = Box::new(ContractWrapper::new(execute, instantiate, query).with_reply(reply));\n      let manager_code_id = mock_app.store_code(code);\n      ...\n  }\n  ...\n'})}),"\n",(0,s.jsx)(n.p,{children:":::info Exercise progression"}),"\n",(0,s.jsxs)(n.p,{children:["At this intermediate stage the ",(0,s.jsx)(n.code,{children:"my-collection-manager"})," project should have something similar to the\n",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-collection-manager/tree/payment-params-query",children:(0,s.jsx)(n.code,{children:"payment-params-query"})})," branch,\nwith ",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-collection-manager/compare/proper-fund-handling..payment-params-query",children:"this"})," as the diff."]}),"\n",(0,s.jsx)(n.p,{children:":::"}),"\n",(0,s.jsx)(n.h2,{id:"the-sudo-message",children:"The sudo message"}),"\n",(0,s.jsxs)(n.p,{children:["You define your own sudo messages separately from the others.\nThey are not a subset of, say, ",(0,s.jsx)(n.code,{children:"ExecuteMsg"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="src/msg.rs"',children:"  ...\n  pub struct GetPaymentParamsResponse {\n      pub payment_params: PaymentParams,\n  }\n// diff-add-start\n+\n+  #[cw_serde]\n+  pub enum SudoMsg {\n+      UpdatePaymentParams(PaymentParam
1s),\n+  }\n// diff-add-end\n"})}),"\n",(0,s.jsx)(n.h2,{id:"sudo-handling",children:"Sudo handling"}),"\n",(0,s.jsxs)(n.p,{children:["To handle sudo messages, you need to add the ",(0,s.jsx)(n.code,{children:"sudo"})," entry point. This is the one that the CosmWasm module\nwill invoke when the system instructs it to handle a sudo message. Here too, the ",(0,s.jsx)(n.code,{children:"sudo"})," function only matches\nthe variant and then invokes a specialized sudo function:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="src/contract.rs"',children:'  use crate::{\n      msg::{\n          CollectionExecuteMsg, CollectionQueryMsg, ExecuteMsg, GetPaymentParamsResponse,\n// diff-del\n-         InstantiateMsg, NameServiceExecuteMsgResponse, QueryMsg,\n// diff-add\n+         InstantiateMsg, NameServiceExecuteMsgResponse, PaymentParams, QueryMsg, SudoMsg,\n      },\n  }\n  ...\n// diff-add-start\n+ #[cfg_attr(not(feature = "library"), entry_point)]\n+ pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> ContractResult {\n+     match msg {\n+         SudoMsg::UpdatePaymentParams(payment_params) => {\n+             sudo_update_payment_params(deps, payment_params)\n+         }\n+     }\n+ }\n+ \n+ fn sudo_update_payment_params(deps: DepsMut, payment_params: PaymentParams) -> ContractResult {\n+     payment_params.validate()?;\n+     PAYMENT_PARAMS.save(deps.storage, &payment_params)?;\n+     let sudo_event = Event::new("my-collection-manager");\n+     let sudo_event = append_payment_params_attributes(sudo_event, payment_params);\n+     Ok(Response::default().add_event(sudo_event))\n+ }\n// diff-add-end\n\n// diff-add-start\n+ fn append_payment_params_attributes(my_event: Event, payment_params: PaymentParams) -> Event {\n+     let my_event = my_event.add_attribute(\n+         "update-payment-params-beneficiary",\n+         payment_params.beneficiary,\n+     );\n+     match payment_params.mint_price {\n+         None => my_event.add_attribute("update-payment-params-mint-price", "none"),\n+         Some(mint_price) => my_event\n+             .add_attribute("update-payment-params-mint-price-denom", mint_price.denom)\n+             .add_attribute(\n+                 "update-payment-params-mint-price-amount",\n+                 mint_price.amount.to_string(),\n+             ),\n+     }\n+ }\n// diff-add-end\n\n  #[cfg(test)]\n  mod tests...\n'})}),"\n",(0,s.jsx)(n.p,{children:"Note that:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Just as in instantiate, it verifies that the new parameters are valid."}),"\n",(0,s.jsx)(n.li,{children:"Just as in execute, it emits an event to inform on the change."}),"\n",(0,s.jsx)(n.li,{children:"The new function that appends values to the event can be reused."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"adjust-instantiate-for-good-measure",children:"Adjust instantiate for good measure"}),"\n",(0,s.jsxs)(n.p,{children:["Now that the payment parameters can change, and with a goal of symmetry, you can adjust the ",(0,s.jsx)(n.code,{children:"instantiate"})," function\nto also emit an event. This has the added benefit that the history of the payment parameters value\ncan be reconstructed from the events alone."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="src/contract.rs"',children:'  ..\n  #[cfg_attr(not(feature = "library"), entry_point)]\n  pub fn instantiate(deps: DepsMut, _: Env, _: MessageInfo, msg: InstantiateMsg) -> ContractResult {\n      msg.payment_params.validate()?;\n      PAYMENT_PARAMS.save(deps.storage, &msg.payment_params)?;\n// diff-add-start\n+     let instantiate_event = Event::new("my-collection-manager");\n+     let instantiate_event = append_payment_params_attributes(instantiate_event, msg.payment_params);\n// diff-add-end\n// diff-del\n-     Ok(Response::default())\n// diff-add\n+     Ok(Response::default().add_event(instantiate_event))\n  }\n  ...\n'})}),"\n",(0,s.jsx)(n.h2,{id:"unit-tests",children:"Unit tests"}),"\n",(0,s.jsx)(n.p,{children:"It is worth adding a unit test that calls the function in isolation and confirms it returns as expected."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="src/contract.rs"',children:'  ...\n  mod tests {\n      use crate::{\n          contract::ReplyCode,\n          msg::{\n              CollectionExecuteMsg, CollectionQueryMsg, ExecuteMsg, InstantiateMsg,\n// diff-del\n-             NameServiceExecuteMsgResponse, PaymentParam
1s,\n// diff-add\n+             NameServiceExecuteMsgResponse, PaymentParams, SudoMsg,\n          },\n// diff-add\n+         state::PAYMENT_PARAMS,\n      };\n      ...\n      fn test_reply_pass_through() {\n          ...\n      }\n// diff-add-start\n+ \n+     #[test]\n+     fn test_sudo_update_payment_params() {\n+         // Arrange\n+         let mut mocked_deps_mut = testing::mock_dependencies();\n+         let mocked_env = testing::mock_env();\n+         let beneficiary = Addr::unchecked("beneficiary");\n+         let new_payment_params = PaymentParams {\n+             beneficiary: beneficiary.to_owned(),\n+             mint_price: Some(Coin {\n+                 denom: "silver".to_owned(),\n+                 amount: Uint128::one(),\n+             }),\n+         };\n+         let sudo_msg = SudoMsg::UpdatePaymentParams(new_payment_params.to_owned());\n+\n+         // Act\n+         let contract_result = super::sudo(mocked_deps_mut.as_mut(), mocked_env, sudo_msg);\n+\n+         // Assert\n+         assert!(contract_result.is_ok(), "Failed to sudo");\n+         let received_response = contract_result.unwrap();\n+         let expected_response = Response::default().add_event(\n+             Event::new("my-collection-manager")\n+                 .add_attribute("update-payment-params-beneficiary", beneficiary)\n+                 .add_attribute("update-payment-params-mint-price-denom", "silver")\n+                 .add_attribute("update-payment-params-mint-price-amount", "1"),\n+         );\n+         assert_eq!(received_response, expected_response);\n+         let payment_params = PAYMENT_PARAMS\n+             .load(&mocked_deps_mut.storage)\n+             .expect("Failed to load payment params");\n+         assert_eq!(payment_params, new_payment_params);\n+     }\n// diff-add-end\n  }\n'})}),"\n",(0,s.jsx)(n.p,{children:"Note that:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"It is not strictly necessary to first call the instantiate as the test only writes to storage."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"mocked-app-tests",children:"Mocked app tests"}),"\n",(0,s.jsxs)(n.p,{children:["You can instruct the mocked app to pass a sudo msg to your ",(0,s.jsx)(n.em,{children:"compiled"})," smart contract,\nas long as you compiled it with the ",(0,s.jsx)(n.code,{children:"sudo"})," function."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-rust",metastring:'title="tests/contract.rs"',children:'  ...\n  use cw721::msg::{Cw721ExecuteMsg, Cw721QueryMsg, OwnerOfResponse};\n// diff-del\n- use cw_multi_test::{App, AppBuilder, ContractWrapper, Executor};\n// diff-add\n+ use cw_multi_test::{App, AppBuilder, ContractWrapper, Executor, WasmSudo};\n  use cw_my_collection_manager::{\n// diff-del-start\n-     contract::{execute, instantiate, query, reply},\n-     msg::{ExecuteMsg, InstantiateMsg, PaymentParams},\n// diff-del-end\n// diff-add-start\n+     contract::{execute, instantiate, query, reply, sudo},\n+     msg::{ExecuteMsg, GetPaymentParamsResponse, InstantiateMsg, PaymentParams, QueryMsg, SudoMsg},\n// diff-add-end\n  };\n  ...\n  fn instantiate_collection_manager(\n      ...\n  ) -> (u64, Addr) {\n      let code = Box::new(\n          ContractWrapper::new(execute, instantiate, query)\n// diff-del\n-             .with_reply(reply),\n// diff-add-start\n+             .with_reply(reply)\n+             .with_sudo(sudo),\n// diff-add-end\n      );\n      ...\n  }\n  ...\n// diff-add-start\n+ #[test]\n+ fn test_sudo_update_payment_params() {\n+     // Arrange\n+     let mut mock_app = App::default();\n+     let beneficiary_addr = Addr::unchecked("beneficiary");\n+     let (_, addr_manager) = instantiate_collection_manager(\n+         &mut mock_app,\n+         PaymentParams {\n+             beneficiary: beneficiary_addr.to_owned(),\n+             mint_price: None,\n+         },\n+     );\n+     let new_payment_params = PaymentParams {\n+         beneficiary: beneficiary_addr.to_owned(),\n+         mint_price: Some(Coin {\n+             denom: "silver".to_owned(),\n+             amount: Uint128::from(23u16),\n+         }),\n+     };
1\n+     let update_sudo_msg = SudoMsg::UpdatePaymentParams(new_payment_params.to_owned());\n+     let sudo_msg = cw_multi_test::SudoMsg::Wasm(\n+         WasmSudo::new(&addr_manager, &update_sudo_msg).expect("Failed to serialize sudo message"),\n+     );\n+\n+     // Act\n+     let result = mock_app.sudo(sudo_msg);\n+\n+     // Assert\n+     assert!(result.is_ok(), "Failed to pass through the message");\n+     let result = result.unwrap();\n+     let expected_sudo_event = Event::new("wasm-my-collection-manager")\n+         .add_attribute("_contract_address", addr_manager.to_owned())\n+         .add_attribute("update-payment-params-beneficiary", beneficiary_addr)\n+         .add_attribute("update-payment-params-mint-price-denom", "silver")\n+         .add_attribute("update-payment-params-mint-price-amount", "23");\n+     result.assert_event(&expected_sudo_event);\n+     let result = mock_app\n+         .wrap()\n+         .query_wasm_smart::<GetPaymentParamsResponse>(&addr_manager, &QueryMsg::GetPaymentParams);\n+     assert!(result.is_ok(), "Failed to query payment params");\n+     assert_eq!(\n+         result.unwrap(),\n+         GetPaymentParamsResponse {\n+             payment_params: new_payment_params\n+         }\n+     );\n+ }\n// diff-add-end\n'})}),"\n",(0,s.jsx)(n.p,{children:"Note that:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Note that your smart contract's sudo message is first wrapped into the testing frameworks sudo message."}),"\n",(0,s.jsx)(n.li,{children:"The mocked app tests only test that the contract handles a sudo message coming from the app.\nIt does not test that, given a properly formed governance proposal, the smart contract is called on sudo.\nTesting that would be like testing a mocked app feature."}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,s.jsx)(n.p,{children:"Now your smart contract is able to receive instructions from the underlying app chain to update the payment parameters.\nBy leveraging the Cosmos SDK's governance module, you only have to code the effect of successful proposals."}),"\n",(0,s.jsx)(n.p,{children:":::info Exercise progression"}),"\n",(0,s.jsx)(n.p,{children:"At this stage:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"my-nameservice"})," project should still have something similar to the\n",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-nameservice/tree/execute-return-data",children:(0,s.jsx)(n.code,{children:"execute-return-data"})})," branch."]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"my-collection-manager"})," project should have something similar to the\n",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-collection-manager/tree/sudo-message",children:(0,s.jsx)(n.code,{children:"sudo-message"})})," branch,\nwith ",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-collection-manager/compare/payment-params-query..sudo-message",children:"this"}),"\nas the diff from the payment params query and ",(0,s.jsx)(n.a,{href:"https://github.com/b9lab/cw-my-collection-manager/compare/proper-fund-handling..sudo-message",children:"this"}),"\nas the larger diff from the previous section."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:":::"})]})}function l(e={}){let{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(m,{...e})}):m(e)}},8453(e,n,t){t.d(n,{R:()=>o,x:()=>d});var a=t(6540);let s={},r=a.createContext(s);function o(e){let n=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.