diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/assets.rs b/code/xcvm/cosmwasm/contracts/gateway/src/assets.rs index 582bb7ebcfe..5c7ca15c9a1 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/assets.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/assets.rs @@ -1,5 +1,6 @@ use crate::{ auth, + batch::BatchResponse, error::{ContractError, Result}, events::make_event, prelude::*, @@ -8,17 +9,17 @@ use crate::{ assets::{ASSETS, LOCAL_ASSETS}, }, }; -use cosmwasm_std::{Deps, DepsMut, Response}; +use cosmwasm_std::{Deps, DepsMut}; use xc_core::{AssetId, NetworkId}; /// Adds a new asset to the registry; errors out if asset already exists. -pub(crate) fn force_asset(_: auth::Admin, deps: DepsMut, msg: AssetItem) -> Result { +pub(crate) fn force_asset(_: auth::Admin, deps: DepsMut, msg: AssetItem) -> Result { let config = crate::state::load(deps.storage)?; ASSETS.save(deps.storage, msg.asset_id, &msg)?; if msg.network_id == config.network_id { LOCAL_ASSETS.save(deps.storage, msg.local.clone(), &msg)?; } - Ok(Response::new().add_event( + Ok(BatchResponse::new().add_event( make_event("assets.forced") .add_attribute("asset_id", msg.asset_id.to_string()) .add_attribute("denom", msg.denom()), @@ -46,14 +47,14 @@ pub(crate) fn force_remove_asset( _: auth::Auth, deps: DepsMut<'_>, asset_id: AssetId, -) -> std::result::Result { +) -> std::result::Result { let config = crate::state::load(deps.storage)?; let asset = ASSETS.load(deps.storage, asset_id)?; ASSETS.remove(deps.storage, asset_id); if asset.network_id == config.network_id { LOCAL_ASSETS.remove(deps.storage, asset.local); } - Ok(Response::new() + Ok(BatchResponse::new() .add_event(make_event("assets.removed").add_attribute("asset_id", asset_id.to_string()))) } @@ -63,9 +64,9 @@ pub(crate) fn force_asset_to_network_map( this_asset: AssetId, other_network: NetworkId, other_asset: AssetId, -) -> Result { +) -> Result { state::assets::NETWORK_ASSET.save(deps.storage, (this_asset, other_network), &other_asset)?; - Ok(Response::new().add_event( + Ok(BatchResponse::new().add_event( make_event("assets.forced_asset_to_network_map") .add_attribute("this_asset", this_asset.to_string()) .add_attribute("other_asset", other_asset.to_string()), diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/auth.rs b/code/xcvm/cosmwasm/contracts/gateway/src/auth.rs index 14da0956f43..d768145dbb4 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/auth.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/auth.rs @@ -17,6 +17,7 @@ use xc_core::{gateway::OtherNetworkItem, NetworkId}; /// /// For convenience, type aliases are provided for the different /// authorisation levels: [`Contract`], [`Interpreter`] and [`Admin`]. +#[derive(Clone, Copy)] pub(crate) struct Auth(core::marker::PhantomData); /// Authorisation token for messages which can only be sent from the @@ -113,8 +114,10 @@ impl Auth { } pub(crate) mod policy { + #[derive(Clone, Copy)] pub(crate) enum Contract {} pub(crate) enum Interpreter {} + #[derive(Clone, Copy)] pub(crate) enum Admin {} pub(crate) enum WasmHook {} } diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/batch.rs b/code/xcvm/cosmwasm/contracts/gateway/src/batch.rs new file mode 100644 index 00000000000..49567d1120b --- /dev/null +++ b/code/xcvm/cosmwasm/contracts/gateway/src/batch.rs @@ -0,0 +1,41 @@ +use cosmwasm_std::{CosmosMsg, Event, Response, SubMsg}; + +#[derive(Debug, Clone, Default)] +pub struct BatchResponse { + pub messages: Vec, + pub events: Vec, +} + +impl BatchResponse { + pub fn new() -> Self { + <_>::default() + } + pub fn add_message(mut self, msg: impl Into) -> Self { + self.messages.push(SubMsg::new(msg)); + self + } + + pub fn add_submessage(mut self, msg: SubMsg) -> Self { + self.messages.push(msg); + self + } + + pub fn add_event(mut self, event: Event) -> Self { + self.events.push(event); + self + } + + pub fn merge(&mut self, mut other: Self) { + self.messages.append(&mut other.messages); + self.events.append(&mut other.events); + } +} + +impl From for Response { + fn from(resp: BatchResponse) -> Self { + let mut result = Self::new(); + result.messages = resp.messages; + result.events = resp.events; + result + } +} diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/contract/execute.rs b/code/xcvm/cosmwasm/contracts/gateway/src/contract/execute.rs index 8362809c300..8109e2cd2ba 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/contract/execute.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/contract/execute.rs @@ -1,5 +1,6 @@ use crate::{ assets, auth, + batch::BatchResponse, error::{ContractError, Result}, events::make_event, interpreter, msg, @@ -28,7 +29,7 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: msg::ExecuteMsg) match msg { ExecuteMsg::Config(msg) => { let auth = auth::Admin::authorise(deps.as_ref(), &info)?; - handle_config_msg(auth, deps, msg, env) + handle_config_msg(auth, deps, msg, &env).map(Into::into) }, msg::ExecuteMsg::ExecuteProgram { execute_program, tip } => @@ -60,7 +61,12 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: msg::ExecuteMsg) } } -fn handle_config_msg(auth: auth::Admin, deps: DepsMut, msg: ConfigSubMsg, env: Env) -> Result { +fn handle_config_msg( + auth: auth::Admin, + mut deps: DepsMut, + msg: ConfigSubMsg, + env: &Env, +) -> Result { deps.api.debug(serde_json_wasm::to_string(&msg)?.as_str()); match msg { ConfigSubMsg::ForceNetworkToNetwork(msg) => @@ -71,8 +77,21 @@ fn handle_config_msg(auth: auth::Admin, deps: DepsMut, msg: ConfigSubMsg, env: E ConfigSubMsg::ForceAssetToNetworkMap { this_asset, other_network, other_asset } => assets::force_asset_to_network_map(auth, deps, this_asset, other_network, other_asset), ConfigSubMsg::ForceNetwork(msg) => network::force_network(auth, deps, msg), - ConfigSubMsg::ForceInstantiate { user_origin, salt } => - interpreter::force_instantiate(auth, env.contract.address, deps, user_origin, salt), + ConfigSubMsg::ForceInstantiate { user_origin, salt } => interpreter::force_instantiate( + auth, + env.contract.address.clone(), + deps, + user_origin, + salt, + ), + ConfigSubMsg::Force(msgs) => { + let mut aggregated = BatchResponse::new(); + for msg in msgs { + let response = handle_config_msg(auth, deps.branch(), msg, env)?; + aggregated.merge(response); + } + Ok(aggregated) + }, } } diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/error.rs b/code/xcvm/cosmwasm/contracts/gateway/src/error.rs index e5107c173f3..202c86c8bda 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/error.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/error.rs @@ -76,6 +76,9 @@ pub enum ContractError { GatewayForNetworkNotFound(NetworkId), #[error("Anonymous calls can do only limitet set of actions")] AnonymousCallsCanDoOnlyLimitedSetOfActions, + /// use events attributes to return data + #[error("Batched calls cannot return data")] + BatchedCallsCannotReturnData, } impl From for ContractError { diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/interpreter.rs b/code/xcvm/cosmwasm/contracts/gateway/src/interpreter.rs index c79bb6aa6eb..9c15d74bf44 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/interpreter.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/interpreter.rs @@ -1,4 +1,5 @@ use crate::{ + batch::BatchResponse, contract::INSTANTIATE_INTERPRETER_REPLY_ID, error::{ContractError, Result}, events::make_event, @@ -21,7 +22,7 @@ pub(crate) fn force_instantiate( deps: DepsMut, user_origin: Addr, salt: String, -) -> Result { +) -> Result { let config = load_this(deps.storage)?; let interpreter_code_id = match config.gateway.expect("expected setup") { GatewayId::CosmWasm { interpreter_code_id, .. } => interpreter_code_id, @@ -32,7 +33,10 @@ pub(crate) fn force_instantiate( let interpreter_origin = InterpreterOrigin { user_origin: call_origin.user(config.network_id), salt: salt.clone() }; let msg = instantiate(deps.as_ref(), gateway, interpreter_code_id, &interpreter_origin, salt)?; - Ok(Response::new().add_submessage(msg).add_event(make_event("interpreter.forced"))) + Ok(BatchResponse::new().add_submessage(msg).add_event( + make_event("interpreter.forced") + .add_attribute("interpreter_origin", interpreter_origin.to_string()), + )) } pub fn instantiate( diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/lib.rs b/code/xcvm/cosmwasm/contracts/gateway/src/lib.rs index 798d57c19d9..3f536c82689 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/lib.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/lib.rs @@ -5,6 +5,7 @@ pub use xc_core::gateway as msg; pub mod assets; pub mod auth; +pub mod batch; pub mod contract; pub mod error; mod events; diff --git a/code/xcvm/cosmwasm/contracts/gateway/src/network.rs b/code/xcvm/cosmwasm/contracts/gateway/src/network.rs index a0f9292264f..2146b13703a 100644 --- a/code/xcvm/cosmwasm/contracts/gateway/src/network.rs +++ b/code/xcvm/cosmwasm/contracts/gateway/src/network.rs @@ -1,5 +1,7 @@ -use crate::{events::make_event, prelude::*, state::xcvm::IBC_CHANNEL_NETWORK}; -use cosmwasm_std::{Response, Storage}; +use crate::{ + batch::BatchResponse, events::make_event, prelude::*, state::xcvm::IBC_CHANNEL_NETWORK, +}; +use cosmwasm_std::{DepsMut, Storage}; use xc_core::{gateway::NetworkItem, NetworkId}; use crate::state::{self, NETWORK, NETWORK_TO_NETWORK}; @@ -28,25 +30,28 @@ pub fn load_other(storage: &dyn Storage, other: NetworkId) -> Result, - deps: cosmwasm_std::DepsMut, + deps: DepsMut, msg: xc_core::gateway::ForceNetworkToNetworkMsg, -) -> std::result::Result { +) -> std::result::Result { NETWORK_TO_NETWORK.save(deps.storage, (msg.from, msg.to), &msg.other)?; if let Some(ibc) = msg.other.xcvm_channel { IBC_CHANNEL_NETWORK.save(deps.storage, ibc.id.to_string(), &msg.to)?; } - Ok(Response::new() - .add_event(make_event("network_to_network.forced").add_attribute("to", msg.to.to_string())) - .add_attribute("from", msg.from.to_string())) + Ok(BatchResponse::new().add_event( + make_event("network_to_network.forced") + .add_attribute("to", msg.to.to_string()) + .add_attribute("from", msg.from.to_string()) + .add_attribute("ics_20", msg.other.ics_20.is_some().to_string()), + )) } pub(crate) fn force_network( _auth: crate::auth::Auth, - deps: cosmwasm_std::DepsMut, + deps: DepsMut, msg: NetworkItem, -) -> std::result::Result { +) -> crate::error::Result { NETWORK.save(deps.storage, msg.network_id, &msg)?; - Ok(Response::new().add_event( + Ok(BatchResponse::new().add_event( make_event("network.forced").add_attribute("network_id", msg.network_id.to_string()), )) } diff --git a/code/xcvm/lib/core/schema/raw/execute.json b/code/xcvm/lib/core/schema/raw/execute.json index 90fdc7d2b70..26073d82cb3 100644 --- a/code/xcvm/lib/core/schema/raw/execute.json +++ b/code/xcvm/lib/core/schema/raw/execute.json @@ -156,14 +156,15 @@ "type": "object", "required": [ "asset_id", - "from_network_id", - "local" + "local", + "network_id" ], "properties": { "asset_id": { "$ref": "#/definitions/AssetId" }, "bridged": { + "description": "if asset was bridged, it would have way to identify bridge/source/channel", "anyOf": [ { "$ref": "#/definitions/BridgeAsset" @@ -173,11 +174,16 @@ } ] }, - "from_network_id": { - "$ref": "#/definitions/NetworkId" - }, "local": { "$ref": "#/definitions/AssetReference" + }, + "network_id": { + "description": "network id on which this asset id can be used locally", + "allOf": [ + { + "$ref": "#/definitions/NetworkId" + } + ] } } }, @@ -513,6 +519,22 @@ }, "additionalProperties": false }, + { + "description": "short cut to rollout config faster", + "type": "object", + "required": [ + "force" + ], + "properties": { + "force": { + "type": "array", + "items": { + "$ref": "#/definitions/ConfigSubMsg" + } + } + }, + "additionalProperties": false + }, { "description": "instantiates default interpreter on behalf of user `salt` - human string, converted to hex or base64 depending on implementation", "type": "object", @@ -527,10 +549,7 @@ ], "properties": { "salt": { - "type": [ - "string", - "null" - ] + "type": "string" }, "user_origin": { "$ref": "#/definitions/Addr" @@ -1243,6 +1262,7 @@ ] }, "RelativeTimeout": { + "description": "relative timeout to CW/IBC-rs time. very small, assumed messages are arriving fast enough, like less than hours", "oneOf": [ { "description": "Timeout is relative to the current block timestamp of counter party", diff --git a/code/xcvm/lib/core/schema/raw/instantiate.json b/code/xcvm/lib/core/schema/raw/instantiate.json index 75f93e86788..4cfaced8ecb 100644 --- a/code/xcvm/lib/core/schema/raw/instantiate.json +++ b/code/xcvm/lib/core/schema/raw/instantiate.json @@ -15,7 +15,7 @@ "type": "object", "required": [ "admin", - "here_id" + "network_id" ], "properties": { "admin": { @@ -26,8 +26,8 @@ } ] }, - "here_id": { - "description": "Network ID of this network", + "network_id": { + "description": "Network ID of this network where contract is deployed", "allOf": [ { "$ref": "#/definitions/NetworkId" diff --git a/code/xcvm/lib/core/schema/raw/response_to_get_asset_by_id.json b/code/xcvm/lib/core/schema/raw/response_to_get_asset_by_id.json index aade0feb1be..5bb68d62451 100644 --- a/code/xcvm/lib/core/schema/raw/response_to_get_asset_by_id.json +++ b/code/xcvm/lib/core/schema/raw/response_to_get_asset_by_id.json @@ -27,14 +27,15 @@ "type": "object", "required": [ "asset_id", - "from_network_id", - "local" + "local", + "network_id" ], "properties": { "asset_id": { "$ref": "#/definitions/AssetId" }, "bridged": { + "description": "if asset was bridged, it would have way to identify bridge/source/channel", "anyOf": [ { "$ref": "#/definitions/BridgeAsset" @@ -44,11 +45,16 @@ } ] }, - "from_network_id": { - "$ref": "#/definitions/NetworkId" - }, "local": { "$ref": "#/definitions/AssetReference" + }, + "network_id": { + "description": "network id on which this asset id can be used locally", + "allOf": [ + { + "$ref": "#/definitions/NetworkId" + } + ] } } }, diff --git a/code/xcvm/lib/core/schema/raw/response_to_get_ibc_ics20_route.json b/code/xcvm/lib/core/schema/raw/response_to_get_ibc_ics20_route.json index 19d40b17533..d76ccfc3239 100644 --- a/code/xcvm/lib/core/schema/raw/response_to_get_ibc_ics20_route.json +++ b/code/xcvm/lib/core/schema/raw/response_to_get_ibc_ics20_route.json @@ -56,7 +56,12 @@ "$ref": "#/definitions/NetworkId" }, "gateway_to_send_to": { - "$ref": "#/definitions/Addr" + "description": "the contract address of the gateway to send to assets", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] }, "ibc_ics_20_sender": { "$ref": "#/definitions/IbcIcs20Sender" @@ -102,6 +107,7 @@ "minimum": 0.0 }, "RelativeTimeout": { + "description": "relative timeout to CW/IBC-rs time. very small, assumed messages are arriving fast enough, like less than hours", "oneOf": [ { "description": "Timeout is relative to the current block timestamp of counter party", diff --git a/code/xcvm/lib/core/schema/raw/response_to_get_local_asset_by_reference.json b/code/xcvm/lib/core/schema/raw/response_to_get_local_asset_by_reference.json index aade0feb1be..5bb68d62451 100644 --- a/code/xcvm/lib/core/schema/raw/response_to_get_local_asset_by_reference.json +++ b/code/xcvm/lib/core/schema/raw/response_to_get_local_asset_by_reference.json @@ -27,14 +27,15 @@ "type": "object", "required": [ "asset_id", - "from_network_id", - "local" + "local", + "network_id" ], "properties": { "asset_id": { "$ref": "#/definitions/AssetId" }, "bridged": { + "description": "if asset was bridged, it would have way to identify bridge/source/channel", "anyOf": [ { "$ref": "#/definitions/BridgeAsset" @@ -44,11 +45,16 @@ } ] }, - "from_network_id": { - "$ref": "#/definitions/NetworkId" - }, "local": { "$ref": "#/definitions/AssetReference" + }, + "network_id": { + "description": "network id on which this asset id can be used locally", + "allOf": [ + { + "$ref": "#/definitions/NetworkId" + } + ] } } }, diff --git a/code/xcvm/lib/core/schema/xc-core.json b/code/xcvm/lib/core/schema/xc-core.json index c4ddd22ecad..7db2ae081c5 100644 --- a/code/xcvm/lib/core/schema/xc-core.json +++ b/code/xcvm/lib/core/schema/xc-core.json @@ -19,7 +19,7 @@ "type": "object", "required": [ "admin", - "here_id" + "network_id" ], "properties": { "admin": { @@ -30,8 +30,8 @@ } ] }, - "here_id": { - "description": "Network ID of this network", + "network_id": { + "description": "Network ID of this network where contract is deployed", "allOf": [ { "$ref": "#/definitions/NetworkId" @@ -206,14 +206,15 @@ "type": "object", "required": [ "asset_id", - "from_network_id", - "local" + "local", + "network_id" ], "properties": { "asset_id": { "$ref": "#/definitions/AssetId" }, "bridged": { + "description": "if asset was bridged, it would have way to identify bridge/source/channel", "anyOf": [ { "$ref": "#/definitions/BridgeAsset" @@ -223,11 +224,16 @@ } ] }, - "from_network_id": { - "$ref": "#/definitions/NetworkId" - }, "local": { "$ref": "#/definitions/AssetReference" + }, + "network_id": { + "description": "network id on which this asset id can be used locally", + "allOf": [ + { + "$ref": "#/definitions/NetworkId" + } + ] } } }, @@ -563,6 +569,22 @@ }, "additionalProperties": false }, + { + "description": "short cut to rollout config faster", + "type": "object", + "required": [ + "force" + ], + "properties": { + "force": { + "type": "array", + "items": { + "$ref": "#/definitions/ConfigSubMsg" + } + } + }, + "additionalProperties": false + }, { "description": "instantiates default interpreter on behalf of user `salt` - human string, converted to hex or base64 depending on implementation", "type": "object", @@ -577,10 +599,7 @@ ], "properties": { "salt": { - "type": [ - "string", - "null" - ] + "type": "string" }, "user_origin": { "$ref": "#/definitions/Addr" @@ -1293,6 +1312,7 @@ ] }, "RelativeTimeout": { + "description": "relative timeout to CW/IBC-rs time. very small, assumed messages are arriving fast enough, like less than hours", "oneOf": [ { "description": "Timeout is relative to the current block timestamp of counter party", @@ -1588,14 +1608,15 @@ "type": "object", "required": [ "asset_id", - "from_network_id", - "local" + "local", + "network_id" ], "properties": { "asset_id": { "$ref": "#/definitions/AssetId" }, "bridged": { + "description": "if asset was bridged, it would have way to identify bridge/source/channel", "anyOf": [ { "$ref": "#/definitions/BridgeAsset" @@ -1605,11 +1626,16 @@ } ] }, - "from_network_id": { - "$ref": "#/definitions/NetworkId" - }, "local": { "$ref": "#/definitions/AssetReference" + }, + "network_id": { + "description": "network id on which this asset id can be used locally", + "allOf": [ + { + "$ref": "#/definitions/NetworkId" + } + ] } } }, @@ -1775,7 +1801,12 @@ "$ref": "#/definitions/NetworkId" }, "gateway_to_send_to": { - "$ref": "#/definitions/Addr" + "description": "the contract address of the gateway to send to assets", + "allOf": [ + { + "$ref": "#/definitions/Addr" + } + ] }, "ibc_ics_20_sender": { "$ref": "#/definitions/IbcIcs20Sender" @@ -1821,6 +1852,7 @@ "minimum": 0.0 }, "RelativeTimeout": { + "description": "relative timeout to CW/IBC-rs time. very small, assumed messages are arriving fast enough, like less than hours", "oneOf": [ { "description": "Timeout is relative to the current block timestamp of counter party", @@ -1870,14 +1902,15 @@ "type": "object", "required": [ "asset_id", - "from_network_id", - "local" + "local", + "network_id" ], "properties": { "asset_id": { "$ref": "#/definitions/AssetId" }, "bridged": { + "description": "if asset was bridged, it would have way to identify bridge/source/channel", "anyOf": [ { "$ref": "#/definitions/BridgeAsset" @@ -1887,11 +1920,16 @@ } ] }, - "from_network_id": { - "$ref": "#/definitions/NetworkId" - }, "local": { "$ref": "#/definitions/AssetReference" + }, + "network_id": { + "description": "network id on which this asset id can be used locally", + "allOf": [ + { + "$ref": "#/definitions/NetworkId" + } + ] } } }, diff --git a/code/xcvm/lib/core/src/gateway/config.rs b/code/xcvm/lib/core/src/gateway/config.rs index 3380265803b..75f8a6b39fa 100644 --- a/code/xcvm/lib/core/src/gateway/config.rs +++ b/code/xcvm/lib/core/src/gateway/config.rs @@ -189,6 +189,10 @@ pub enum ConfigSubMsg { asset_id: AssetId, }, + // https://github.com/CosmWasm/cosmwasm/discussions/1814 + /// short cut to rollout config faster + Force(Vec), + /// instantiates default interpreter on behalf of user /// `salt` - human string, converted to hex or base64 depending on implementation ForceInstantiate { diff --git a/flake/release.nix b/flake/release.nix index 4c20d4b38fb..5faedbb163a 100644 --- a/flake/release.nix +++ b/flake/release.nix @@ -97,6 +97,11 @@ subwasm-version packages.composable-testfast-runtime }.wasm + + # XCVM + cp ${packages.cw-xc-gateway}/lib/cw_xc_gateway.wasm release-artifacts/to-upload/cw_xc_gateway.wasm + cp ${packages.cw-xc-interpreter}/lib/cw_xc_interpreter.wasm release-artifacts/to-upload/cw_xc_interpreter.wasm + echo "Generate node packages" cp ${ make-bundle "toRPM" packages.composable-node @@ -131,6 +136,7 @@ make-bundle "toDEB" packages.ccw }/*.deb release-artifacts/to-upload/ccw_${packages.ccw.version}-1_amd64.deb + # Checksum everything cd release-artifacts/to-upload sha256sum ./* > checksums.txt diff --git a/terraform/github.com/config.tf b/terraform/github.com/config.tf index dd1216a4e9e..2e2487bf651 100644 --- a/terraform/github.com/config.tf +++ b/terraform/github.com/config.tf @@ -13,6 +13,10 @@ variable "CI_COSMOS_MNEMONIC" { sensitive = true } +variable "CACHIX_AUTH_TOKEN" { + type = string + sensitive = true +} data "github_repository" "self" { full_name = "ComposibleFi/composable"