Use Liquidium without the app
Check, repay, and withdraw Advanced positions directly from the canisters if the app is unavailable.
Your Advanced positions live in Liquidium's canisters (smart contracts) on the Internet Computer, not on Liquidium's servers. If app.liquidium.fi is unavailable, you can still read your position, repay debt, and, if you sign in with a Bitcoin or Ethereum wallet, withdraw collateral by calling the canisters directly.
This page is for technical users. The examples use dfx with --network ic. Read-only queries can use --identity anonymous. Transfers and withdrawals need a dfx identity that holds the funds or can submit the call. If you can use the app, use the app.
Sending the wrong asset, using the wrong subaccount, or calling the wrong canister can lose funds. Test with a small amount first and double-check every canister ID against the table below.
Mainnet canister IDs
Canister | ID | Role |
|---|---|---|
Lending Canister | | Profiles, positions, health factor, withdrawals, borrows, liquidations |
BTC Pool | | BTC liquidity (held as ckBTC) |
ETH Pool | | ETH liquidity (held as ckETH) |
USDC Pool | | USDC liquidity (held as ckUSDC) |
USDT Pool | | USDT liquidity (held as ckUSDT) |
ICP Pool | | Native ICP liquidity |
Deposit Accounts | | Ethereum deposit and repay addresses |
Simple Loans | | Accountless Simple Loans |
Identity Anchor | | Internet Identity origin for Liquidium |
The pools use these ledgers and minters, run by the Internet Computer:
Asset | Ledger | Minter |
|---|---|---|
ckBTC | | |
ckETH | | |
ckUSDC | | |
ckUSDT | | |
ICP | | None |
You can also call these methods from the Candid UI on the ICP dashboard.
1. Find your profile
Every Advanced account is a profile principal. Look it up with a wallet address you signed in with:
dfx canister call --network ic --identity anonymous --query \
hyk4r-jqaaa-aaaar-qb4ca-cai get_wallet_profile '("bc1q...your-address")'The result is opt principal "...". Enter the address exactly as your wallet shows it. Ethereum addresses are matched case-sensitively, so if you get null, try the checksummed (mixed-case) form.
To list every wallet linked to a profile, call get_profile_wallets '(principal "<profile>")'.
2. Read your position
Health factor and totals for the whole profile:
dfx canister call --network ic --identity anonymous --query \
hyk4r-jqaaa-aaaar-qb4ca-cai get_health_factor '(principal "<profile>")'- The first value is the health factor with three decimals:
1000means 1.0. Below1000the position can be liquidated. collateralanddebtare values in USDT terms with 27 decimals. With no debt, the health factor is the maximumnatvalue.get_profile_stats '(principal "<profile>")'returns the same totals without the health factor.
One pool at a time:
dfx canister call --network ic --identity anonymous --query \
hyk4r-jqaaa-aaaar-qb4ca-cai get_position '(principal "<profile>", principal "<pool-id>")'deposited_native_now is your supply and debt_native_now is your current debt, both in the asset's smallest unit: sats for BTC, wei for ETH, 6 decimals for USDC and USDT, and e8s for ICP.
3. Repay
Repayments are transfers into a repay subaccount that belongs to your profile on the borrowed asset's pool. The subaccount is derived from your profile, so it never changes. Get it from the pool:
dfx canister call --network ic --identity anonymous --query \
hnnn4-iyaaa-aaaar-qb4bq-cai get_inflow_subaccount '(variant { Repayment = principal "<profile>" })'Use the pool of the asset you borrowed. The reply is a 32-byte blob. Use Deposit instead of Repayment only if you want to supply collateral.
ckBTC, ckETH, ckUSDC, ckUSDT
Send the ck version of the borrowed asset with an ICRC-1 transfer to the pool and your repay subaccount. The pool scans its ledger about once a minute and credits the repayment on its own.
dfx canister call --network ic <ledger-id> icrc1_transfer '(record {
to = record { owner = principal "<pool-id>"; subaccount = opt blob "<repay-subaccount>" };
amount = <amount-in-smallest-unit>;
})'Native ICP
Make the same ICRC-1 transfer on the ICP ledger to the ICP Pool. The ICP Pool does not scan for new transfers by itself. After the transfer, ask it to process your subaccount:
dfx canister call --network ic r2pk3-4yaaa-aaaar-qb7zq-cai check_subaccount '(blob "<repay-subaccount>")'Native BTC
Your BTC repay address is a ckBTC deposit address owned by the BTC Pool. It is the same address the app shows. To get it without the app, call the ckBTC minter:
dfx canister call --network ic mqygn-kiaaa-aaaar-qaadq-cai get_btc_address '(record {
owner = opt principal "hkmli-faaaa-aaaar-qb4ba-cai";
subaccount = opt blob "<repay-subaccount>";
})'Send BTC to that address. After the ckBTC minter's required confirmations (currently 4), call update_balance with the same owner and subaccount to mint the ckBTC. The BTC Pool then picks it up like a ckBTC repayment. The minter deducts its own fee.
Native ETH, USDC, USDT
The Ethereum repay addresses shown in the app are processed with help from Liquidium's backend. If the app is down, repay with the matching ck asset over ICP instead (see above).
Check debt_native_now right before you send. Interest keeps accruing, so a full repayment needs slightly more. Excess above the pool's refund minimum (overpay_refund_min in get_pool) is parked in a recovery balance for your profile, and smaller excess is kept as a fee. Nothing is sent back to the sending address. Contact support to recover an overpayment.
4. Withdraw
If you signed in with a Bitcoin or Ethereum wallet, a withdrawal is a message signed by that wallet and sent straight to the Lending Canister. Liquidium holds no key that can sign it for you.
The easiest way is the public Liquidium SDK. client.lending.withdraw(...) builds the message, asks your wallet to sign it, and submits it to the canister. See the SDK docs.
To do it by hand:
- Read your wallet's nonce:
get_nonce '("<wallet-address>")'on the Lending Canister. - Build this exact message, with Unix-seconds expiry no more than 5 minutes ahead:
Liquidium: Withdraw Assets
Action: Withdraw from pool
Pool ID: <pool-id>
Amount: <amount-in-smallest-unit>
Address:<destination-address>
Expires: <unix-seconds>
Nonce: <nonce>- Sign it with your wallet. Bitcoin wallets can use BIP-322 or legacy message signing. Ethereum wallets use
personal_sign(EIP-191). Encode the signature as hex without a0xprefix. Bitcoin wallets often return base64, so convert it. - Call
withdrawon the Lending Canister with exactly the values you signed:
dfx canister call --network ic hyk4r-jqaaa-aaaar-qb4ca-cai withdraw '(principal "<profile>", record {
data = record {
pool_id = principal "<pool-id>";
amount = <amount-in-smallest-unit>;
account = variant { External = "<destination-address>" };
expiry_timestamp = <unix-seconds>;
};
signature_info = variant { Wallet = record {
signature = "<hex-signature>";
chain = variant { BTC };
account = "<wallet-address>";
} };
})'Use chain = variant { ETH } for an Ethereum wallet. External sends the native asset to a Bitcoin or Ethereum address. To receive the ck asset on ICP instead, use account = variant { Native = principal "<principal>" } and the message line Principal:<principal>. The ICP Pool does not take External; use Native, Icrc, or AccountIdentifier (message lines Principal:..., Icrc:..., AccountId:...). For Bitcoin or Ethereum destinations, withdraw at least 5,000 sats, 0.005 ETH, or 1 USDC or USDT; smaller amounts can get stuck. The withdrawal must keep your health factor at or above 1.0, and it fails while the pool is frozen or prices are stale. See Security, governance & risk.
Internet Identity
Internet Identity profiles live in the same canisters, and Liquidium holds no key that can act for you. You can check your position and repay with the steps above, as long as you know your profile principal. Linking a Bitcoin or Ethereum wallet to your profile lets you look it up with get_wallet_profile.
Withdrawing currently depends on the website. Internet Identity only gives you your Liquidium identity on websites approved by Liquidium's Identity Anchor canister cicgv-7yaaa-aaaar-qca2a-cai. Today the only approved origin is https://app.liquidium.fi, and adding another website needs the Liquidium multisig. If you want to be able to withdraw without the app, link a supported Bitcoin or Ethereum wallet to your profile.
Simple Loans
Simple Loans work differently. Each loan's position sits in the Lending Canister, but it is controlled by the Simple Loans canister, which signs for the loan with its own key. Liquidium's service tells that canister when a deposit or full repayment has landed, and the canister then opens the loan or returns the collateral. You cannot release Simple Loan collateral with your own wallet. Keep your Loan ID and receipt, and contact support if a Simple Loan looks stuck.