Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c93b5b4
feat(console): support for raw canister (proof of concept)
peterpeterparker Jan 6, 2026
932f1fe
Merge branch 'main' into feat/raw-canister
peterpeterparker Jan 6, 2026
8d939a3
feat: use new functions
peterpeterparker Jan 6, 2026
ea3c432
feat: finish support for create canister
peterpeterparker Jan 6, 2026
8d01ec1
feat: finish support for create canister
peterpeterparker Jan 6, 2026
982267c
fix: export and impl missing
peterpeterparker Jan 6, 2026
9a4369e
feat: generate did
peterpeterparker Jan 6, 2026
5af1f36
feat: upgrade state
peterpeterparker Jan 6, 2026
c0aa3de
chore: no dev
peterpeterparker Jan 6, 2026
b61aac5
Merge branch 'main' into feat/raw-canister
peterpeterparker Jan 6, 2026
77efb49
Merge branch 'main' into feat/raw-canister
peterpeterparker Jan 6, 2026
1fa08eb
fix: upgrade
peterpeterparker Jan 6, 2026
bcef1fd
feat: create canister
peterpeterparker Jan 6, 2026
e4cfa18
Merge branch 'main' into feat/raw-canister
peterpeterparker Jan 6, 2026
00e72d5
feat: canister id schema
peterpeterparker Jan 6, 2026
8643017
Merge branch 'main' into feat/raw-canister
peterpeterparker Jan 6, 2026
2f98e89
feat: create canister with optional name
peterpeterparker Jan 6, 2026
5826761
feat: canister overview
peterpeterparker Jan 6, 2026
8e7576e
fix: load list of canister
peterpeterparker Jan 6, 2026
7018b0e
fix: few cast issues
peterpeterparker Jan 6, 2026
dbf7496
feat: canister settings
peterpeterparker Jan 6, 2026
d151785
feat: menu for showcase
peterpeterparker Jan 6, 2026
16f07d0
chore: fmt
peterpeterparker Jan 6, 2026
504805c
chore: merge main
peterpeterparker Apr 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/console/src/api/factory.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::factory::canister::create_canister;
use crate::factory::mission_control::create_mission_control as create_mission_control_console;
use crate::factory::orbiter::create_orbiter as create_orbiter_console;
use crate::factory::satellite::create_satellite as create_satellite_console;
Expand All @@ -6,7 +7,7 @@ use ic_cdk_macros::update;
use junobuild_shared::ic::api::caller;
use junobuild_shared::ic::UnwrapOrTrap;
use junobuild_shared::types::interface::{
CreateMissionControlArgs, CreateOrbiterArgs, CreateSatelliteArgs,
CreateMissionControlArgs, CreateOrbiterArgs, CreateSatelliteArgs, CreateSegmentArgs,
};

#[update]
Expand All @@ -33,3 +34,19 @@ async fn create_orbiter(args: CreateOrbiterArgs) -> Principal {

create_orbiter_console(caller, args).await.unwrap_or_trap()
}

#[update]
async fn create_segment(args: CreateSegmentArgs) -> Principal {
let caller = caller();

let result = match args {
CreateSegmentArgs::Satellite(args) => create_satellite_console(caller, args).await,
CreateSegmentArgs::MissionControl(args) => {
create_mission_control_console(caller, args).await
}
CreateSegmentArgs::Orbiter(args) => create_orbiter_console(caller, args).await,
CreateSegmentArgs::Canister(args) => create_canister(caller, args).await,
};

result.unwrap_or_trap()
}
1 change: 1 addition & 0 deletions src/console/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub const SATELLITE_CREATION_FEE_CYCLES: CyclesTokens = CyclesTokens::from_e12s(
pub const ORBITER_CREATION_FEE_CYCLES: CyclesTokens = CyclesTokens::from_e12s(3_000_000_000_000);
pub const MISSION_CONTROL_CREATION_FEE_CYCLES: CyclesTokens =
CyclesTokens::from_e12s(3_000_000_000_000);
pub const CANISTER_CREATION_FEE_CYCLES: CyclesTokens = CyclesTokens::from_e12s(3_000_000_000_000);

// 1 ICP but also the default credit - i.e. a mission control starts with one credit.
// A credit which can be used to start one satellite or one orbiter.
Expand Down
83 changes: 83 additions & 0 deletions src/console/src/factory/canister.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::accounts::get_existing_account;
use crate::constants::FREEZING_THRESHOLD_ONE_YEAR;
use crate::factory::orchestrator::create_segment_with_account;
use crate::factory::services::payment::{process_payment_cycles, refund_payment_cycles};
use crate::factory::types::CanisterCreator;
use crate::factory::utils::controllers::update_mission_control_controllers;
use crate::fees::get_factory_fee;
use crate::rates::increment_canister_rate;
use crate::segments::add_segment as add_segment_store;
use crate::types::ledger::Fee;
use crate::types::state::{Segment, SegmentKey, StorableSegmentKind};
use candid::{Nat, Principal};
use junobuild_shared::constants::shared::CREATE_CANISTER_CYCLES;
use junobuild_shared::ic::api::id;
use junobuild_shared::mgmt::cmc::create_canister_with_cmc;
use junobuild_shared::mgmt::ic::create_canister_with_ic_mgmt;
use junobuild_shared::mgmt::types::cmc::SubnetId;
use junobuild_shared::mgmt::types::ic::CreateCanisterInitSettingsArg;
use junobuild_shared::types::interface::CreateCanisterArgs;
use junobuild_shared::types::state::{SegmentKind, UserId};

pub async fn create_canister(
caller: Principal,
args: CreateCanisterArgs,
) -> Result<Principal, String> {
let account = get_existing_account(&caller)?;

let name = args.name.clone();
let creator: CanisterCreator = CanisterCreator::User((account.owner, None));

let fee = get_factory_fee(&SegmentKind::Canister)?.fee_cycles;

let canister_id = create_segment_with_account(
create_raw_canister,
process_payment_cycles,
refund_payment_cycles,
&increment_canister_rate,
Fee::Cycles(fee),
&account,
creator,
args.into(),
)
.await?;

add_segment(&account.owner, &canister_id, &name);

Ok(canister_id)
}

async fn create_raw_canister(
creator: CanisterCreator,
subnet_id: Option<SubnetId>,
) -> Result<Principal, String> {
let CanisterCreator::User((user_id, _)) = creator else {
return Err("Mission Control cannot create a raw canister".to_string());
};

// We temporarily use the Console as a controller to create the canister but
// remove it as soon as it is spin.
let temporary_init_controllers = Vec::from([id(), user_id]);

let create_settings_arg = CreateCanisterInitSettingsArg {
controllers: temporary_init_controllers,
freezing_threshold: Nat::from(FREEZING_THRESHOLD_ONE_YEAR),
};

let mission_control_id = if let Some(subnet_id) = subnet_id {
create_canister_with_cmc(&create_settings_arg, CREATE_CANISTER_CYCLES, &subnet_id).await
} else {
create_canister_with_ic_mgmt(&create_settings_arg, CREATE_CANISTER_CYCLES).await
}?;

update_mission_control_controllers(&mission_control_id, &user_id).await?;

Ok(mission_control_id)
}

fn add_segment(user: &UserId, canister_id: &Principal, name: &Option<String>) {
let metadata = Segment::init_metadata(name);
let canister = Segment::new(canister_id, Some(metadata));
let key = SegmentKey::from(user, canister_id, StorableSegmentKind::Canister);
add_segment_store(&key, &canister)
}
13 changes: 12 additions & 1 deletion src/console/src/factory/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::factory::types::CanisterCreator;
use crate::factory::types::CreateSegmentArgs;
use candid::Principal;
use junobuild_shared::types::interface::{
CreateMissionControlArgs, CreateOrbiterArgs, CreateSatelliteArgs,
CreateCanisterArgs, CreateMissionControlArgs, CreateOrbiterArgs, CreateSatelliteArgs,
};
use junobuild_shared::types::state::{AccessKeyId, UserId};

Expand Down Expand Up @@ -63,3 +63,14 @@ impl From<CreateMissionControlArgs> for CreateSegmentArgs {
}
}
}

impl From<CreateCanisterArgs> for CreateSegmentArgs {
fn from(args: CreateCanisterArgs) -> Self {
Self {
// Unlike Satellite and Orbiter, or same as Mission Control, Canister can only be
// spin using credits or ICRC-2 transfer from.
block_index: None,
subnet_id: args.subnet_id,
}
}
}
1 change: 1 addition & 0 deletions src/console/src/factory/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod canister;
mod impls;
pub mod mission_control;
pub mod orbiter;
Expand Down
12 changes: 10 additions & 2 deletions src/console/src/fees/init.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::constants::{
MISSION_CONTROL_CREATION_FEE_CYCLES, ORBITER_CREATION_FEE_CYCLES, ORBITER_CREATION_FEE_ICP,
SATELLITE_CREATION_FEE_CYCLES, SATELLITE_CREATION_FEE_ICP,
CANISTER_CREATION_FEE_CYCLES, MISSION_CONTROL_CREATION_FEE_CYCLES, ORBITER_CREATION_FEE_CYCLES,
ORBITER_CREATION_FEE_ICP, SATELLITE_CREATION_FEE_CYCLES, SATELLITE_CREATION_FEE_ICP,
};
use crate::types::state::{FactoryFee, FactoryFees};
use ic_cdk::api::time;
Expand Down Expand Up @@ -35,5 +35,13 @@ pub fn init_factory_fees() -> FactoryFees {
updated_at: now,
},
),
(
SegmentKind::Canister,
FactoryFee {
fee_cycles: CANISTER_CREATION_FEE_CYCLES,
fee_icp: None,
updated_at: now,
},
),
])
}
1 change: 1 addition & 0 deletions src/console/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ use junobuild_shared::types::domain::CustomDomains;
use junobuild_shared::types::interface::CreateMissionControlArgs;
use junobuild_shared::types::interface::CreateOrbiterArgs;
use junobuild_shared::types::interface::CreateSatelliteArgs;
use junobuild_shared::types::interface::CreateSegmentArgs;
use junobuild_shared::types::interface::{
AssertMissionControlCenterArgs, DeleteControllersArgs, GetCreateCanisterFeeArgs,
SetControllersArgs,
Expand Down
7 changes: 7 additions & 0 deletions src/console/src/rates/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,12 @@ pub fn init_factory_rates() -> FactoryRates {
tokens: tokens.clone(),
},
),
(
SegmentKind::Canister,
FactoryRate {
config: DEFAULT_RATE_CONFIG,
tokens: tokens.clone(),
},
),
])
}
4 changes: 4 additions & 0 deletions src/console/src/rates/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ pub fn increment_mission_controls_rate() -> Result<(), String> {
pub fn increment_orbiters_rate() -> Result<(), String> {
increment_rate(&SegmentKind::Orbiter)
}

pub fn increment_canister_rate() -> Result<(), String> {
increment_rate(&SegmentKind::Canister)
}
2 changes: 1 addition & 1 deletion src/console/src/segments/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ fn filter_segments_range(
let end_key = SegmentKey {
user: *user,
// Fallback to last enum
segment_kind: segment_kind.clone().unwrap_or(StorableSegmentKind::Orbiter),
segment_kind: segment_kind.clone().unwrap_or(StorableSegmentKind::Canister),
segment_id: segment_id.unwrap_or(PRINCIPAL_MAX),
};

Expand Down
1 change: 1 addition & 0 deletions src/console/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ pub mod state {
// For historical reasons, MissionControl is not stored in the segments stable tree
// but within the Account structure
Orbiter,
Canister,
}

// On Apr. 4, 2026, someone exploited the free tier to spin up free canisters.
Expand Down
13 changes: 13 additions & 0 deletions src/declarations/console/console.factory.certified.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ export const idlFactory = ({ IDL }) => {
name: IDL.Opt(IDL.Text),
user: IDL.Principal
});
const CreateCanisterArgs = IDL.Record({
subnet_id: IDL.Opt(IDL.Principal),
name: IDL.Opt(IDL.Text)
});
const CreateSegmentArgs = IDL.Variant({
Orbiter: CreateOrbiterArgs,
MissionControl: CreateMissionControlArgs,
Canister: CreateCanisterArgs,
Satellite: CreateSatelliteArgs
});
const DeleteControllersArgs = IDL.Record({
controllers: IDL.Vec(IDL.Principal)
});
Expand Down Expand Up @@ -232,6 +242,7 @@ export const idlFactory = ({ IDL }) => {
const SegmentKind = IDL.Variant({
Orbiter: IDL.Null,
MissionControl: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const CyclesTokens = IDL.Record({ e12s: IDL.Nat64 });
Expand Down Expand Up @@ -440,6 +451,7 @@ export const idlFactory = ({ IDL }) => {
});
const StorableSegmentKind = IDL.Variant({
Orbiter: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const ListSegmentsArgs = IDL.Record({
Expand Down Expand Up @@ -528,6 +540,7 @@ export const idlFactory = ({ IDL }) => {
create_mission_control: IDL.Func([CreateMissionControlArgs], [IDL.Principal], []),
create_orbiter: IDL.Func([CreateOrbiterArgs], [IDL.Principal], []),
create_satellite: IDL.Func([CreateSatelliteArgs], [IDL.Principal], []),
create_segment: IDL.Func([CreateSegmentArgs], [IDL.Principal], []),
del_controllers: IDL.Func([DeleteControllersArgs], [], []),
del_custom_domain: IDL.Func([IDL.Text], [], []),
delete_proposal_assets: IDL.Func([DeleteProposalAssets], [], []),
Expand Down
13 changes: 13 additions & 0 deletions src/declarations/console/console.factory.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ export const idlFactory = ({ IDL }) => {
name: IDL.Opt(IDL.Text),
user: IDL.Principal
});
const CreateCanisterArgs = IDL.Record({
subnet_id: IDL.Opt(IDL.Principal),
name: IDL.Opt(IDL.Text)
});
const CreateSegmentArgs = IDL.Variant({
Orbiter: CreateOrbiterArgs,
MissionControl: CreateMissionControlArgs,
Canister: CreateCanisterArgs,
Satellite: CreateSatelliteArgs
});
const DeleteControllersArgs = IDL.Record({
controllers: IDL.Vec(IDL.Principal)
});
Expand Down Expand Up @@ -232,6 +242,7 @@ export const idlFactory = ({ IDL }) => {
const SegmentKind = IDL.Variant({
Orbiter: IDL.Null,
MissionControl: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const CyclesTokens = IDL.Record({ e12s: IDL.Nat64 });
Expand Down Expand Up @@ -440,6 +451,7 @@ export const idlFactory = ({ IDL }) => {
});
const StorableSegmentKind = IDL.Variant({
Orbiter: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const ListSegmentsArgs = IDL.Record({
Expand Down Expand Up @@ -528,6 +540,7 @@ export const idlFactory = ({ IDL }) => {
create_mission_control: IDL.Func([CreateMissionControlArgs], [IDL.Principal], []),
create_orbiter: IDL.Func([CreateOrbiterArgs], [IDL.Principal], []),
create_satellite: IDL.Func([CreateSatelliteArgs], [IDL.Principal], []),
create_segment: IDL.Func([CreateSegmentArgs], [IDL.Principal], []),
del_controllers: IDL.Func([DeleteControllersArgs], [], []),
del_custom_domain: IDL.Func([IDL.Text], [], []),
delete_proposal_assets: IDL.Func([DeleteProposalAssets], [], []),
Expand Down
13 changes: 13 additions & 0 deletions src/declarations/console/console.factory.did.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ export const idlFactory = ({ IDL }) => {
name: IDL.Opt(IDL.Text),
user: IDL.Principal
});
const CreateCanisterArgs = IDL.Record({
subnet_id: IDL.Opt(IDL.Principal),
name: IDL.Opt(IDL.Text)
});
const CreateSegmentArgs = IDL.Variant({
Orbiter: CreateOrbiterArgs,
MissionControl: CreateMissionControlArgs,
Canister: CreateCanisterArgs,
Satellite: CreateSatelliteArgs
});
const DeleteControllersArgs = IDL.Record({
controllers: IDL.Vec(IDL.Principal)
});
Expand Down Expand Up @@ -232,6 +242,7 @@ export const idlFactory = ({ IDL }) => {
const SegmentKind = IDL.Variant({
Orbiter: IDL.Null,
MissionControl: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const CyclesTokens = IDL.Record({ e12s: IDL.Nat64 });
Expand Down Expand Up @@ -440,6 +451,7 @@ export const idlFactory = ({ IDL }) => {
});
const StorableSegmentKind = IDL.Variant({
Orbiter: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const ListSegmentsArgs = IDL.Record({
Expand Down Expand Up @@ -528,6 +540,7 @@ export const idlFactory = ({ IDL }) => {
create_mission_control: IDL.Func([CreateMissionControlArgs], [IDL.Principal], []),
create_orbiter: IDL.Func([CreateOrbiterArgs], [IDL.Principal], []),
create_satellite: IDL.Func([CreateSatelliteArgs], [IDL.Principal], []),
create_segment: IDL.Func([CreateSegmentArgs], [IDL.Principal], []),
del_controllers: IDL.Func([DeleteControllersArgs], [], []),
del_custom_domain: IDL.Func([IDL.Text], [], []),
delete_proposal_assets: IDL.Func([DeleteProposalAssets], [], []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const idlFactory = ({ IDL }) => {
const SegmentKind = IDL.Variant({
Orbiter: IDL.Null,
MissionControl: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const Segment = IDL.Record({
Expand Down
1 change: 1 addition & 0 deletions src/declarations/observatory/observatory.factory.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const idlFactory = ({ IDL }) => {
const SegmentKind = IDL.Variant({
Orbiter: IDL.Null,
MissionControl: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const Segment = IDL.Record({
Expand Down
1 change: 1 addition & 0 deletions src/declarations/observatory/observatory.factory.did.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const idlFactory = ({ IDL }) => {
const SegmentKind = IDL.Variant({
Orbiter: IDL.Null,
MissionControl: IDL.Null,
Canister: IDL.Null,
Satellite: IDL.Null
});
const Segment = IDL.Record({
Expand Down
6 changes: 6 additions & 0 deletions src/frontend/src/lib/api/console.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
}): Promise<ConsoleDid.FactoryFee> =>
await getFee({ identity, segmentKind: { MissionControl: null } });

export const getCanisterFee = async ({
identity
}: {
identity: OptionIdentity;

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (3, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (8, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (4, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (5, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (1, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (6, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (7, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (2, 9)

Cannot find name 'OptionIdentity'.

Check failure on line 61 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (9, 9)

Cannot find name 'OptionIdentity'.
}): Promise<ConsoleDid.FactoryFee> => await getFee({ identity, segmentKind: { Canister: null } });

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (3, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (8, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (4, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (5, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (1, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (6, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (7, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (2, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

Check failure on line 62 in src/frontend/src/lib/api/console.api.ts

View workflow job for this annotation

GitHub Actions / tests (9, 9)

Object literal may only specify known properties, and 'Canister' does not exist in type 'SegmentKind'.

const getFee = async ({
identity,
segmentKind
Expand Down
Loading
Loading