Skip to content

docs: Solana chain fusion guide#96

Merged
marc0olo merged 2 commits into
mainfrom
docs/guides-chain-fusion-solana
Apr 16, 2026
Merged

docs: Solana chain fusion guide#96
marc0olo merged 2 commits into
mainfrom
docs/guides-chain-fusion-solana

Conversation

@marc0olo
Copy link
Copy Markdown
Member

Summary

  • How the integration works: HTTPS outcalls + threshold Ed25519
  • SOL RPC canister (2xib7-jqaaa-aaaar-qai6q-cai): providers, request flow, Candid interface
  • Querying Solana: getBalance with Rust and Motoko examples
  • Threshold Ed25519 signing: schnorr_public_key and sign_with_schnorr with Rust and Motoko examples
  • Key ID table (test_key_1 vs key_1), cycle costs table
  • Complete transaction example linking to basic_solana reference
  • Current limitations: no SPL helpers, no ckSOL, manual transaction construction

Note: stub renamed from .md to .mdx to support language-tab components.

Sync recommendation

informed by dfinity/portal — docs/developer-docs/multi-chain/solana/

Adds docs/guides/chain-fusion/solana.mdx covering the SOL RPC canister
for querying Solana via JSON-RPC and threshold Ed25519 for signing
transactions. Includes Rust and Motoko examples for getBalance, public
key derivation, and message signing. Documents current status and
limitations of the integration.

Renames stub solana.md to solana.mdx (tabs require MDX).
@marc0olo
Copy link
Copy Markdown
Member Author

Review: Solana Integration

Must fix

  • Tab order (Rust → Motoko) violates project convention: CLAUDE.md requires tab order "Motoko → Rust → others" for all <Tabs syncKey="lang"> blocks. All three tab groups in this page (get balance, get public key, sign message) have Rust first. The tabs must be reordered to Motoko first, Rust second.

  • Wrong NNS link at line 30: The page says the SOL RPC canister "is controlled by the Network Nervous System". The URL points to an article about Subnet Creation, not NNS governance. This is a misleading link. Replace with a relevant NNS governance link or explain inline without an external URL.

  • Unresolved human verification flag (line 293): The Motoko sign_with_schnorr block contains {/* Needs human verification: Motoko cycle attachment for sign_with_schnorr uses a fixed 30B cycles based on the cdk-rs SIGN_WITH_SCHNORR_FEE constant. ... */}. The actual SIGN_WITH_SCHNORR_FEE in .sources/cdk-rs/ic-cdk/src/api/management_canister/schnorr/mod.rs is 26_153_846_153 (~26.15B cycles), not 30B. The Motoko code hardcodes 30B as a buffer — the excess is refunded in practice. The flag must be resolved before merge: either update the value to 26_153_846_153 for accuracy, or replace the comment with a note explaining that 30B is an intentional buffer above the ~26.15B fee, since unused cycles are refunded.

Suggestions

  • Cycle cost table precision (line 327): The table says "~26B cycles" for sign_with_schnorr. The exact fee from cdk-rs is 26_153_846_153 (~26.15B). Changing to "~26.15B cycles" would be more precise and would help readers reconcile the difference between the Rust (auto-attached exact fee) and Motoko (hardcoded 30B buffer) examples.

  • max_response_bytes context missing in "Other common queries" section (lines 122–141): The intro says "adjust max_response_bytes for the expected response size" but the code examples show only JSON payloads without wrapping them in the request call. A reader copying the snippet would not know to pass max_response_bytes as the second argument. A brief note clarifying that these JSON strings are used as the first argument, with max_response_bytes as the second, would reduce confusion.

  • Base58 address derivation not shown: Lines 151–153 and 222 tell the reader to "base58-encode these 32 bytes" to get a Solana address, but no code is provided. Given that this is a required step before submitting any transaction, adding a pointer to a specific file in the basic_solana example (e.g., the exact function in the repo) would lower friction.

  • Local testing limitation not prominent enough: The key table note at line 307 says "dfx_test_key is not available for Ed25519". The practical implication — that there is no local equivalent and developers must use ICP mainnet for all testing — deserves a slightly more explicit callout to prevent wasted debugging time.

Verified

  • All internal links resolve: ../../concepts/chain-fusion.md exists; ../backends/https-outcalls.md resolves to https-outcalls.mdx (Astro .md.mdx resolution, valid per project rules); bitcoin.mdbitcoin.mdx; ethereum.mdethereum.mdx.
  • Rust API types verified against .sources/cdk-rs/ic-management-canister-types/src/lib.rs: SchnorrPublicKeyArgs, SignWithSchnorrArgs, SchnorrKeyId, SchnorrAlgorithm, SchnorrAlgorithm::Ed25519, and all field names (canister_id, derivation_path, key_id, message, aux, public_key, signature) confirmed correct.
  • schnorr_public_key and sign_with_schnorr function signatures correct in .sources/cdk-rs/ic-cdk/src/management_canister.rs: both take &args, return types handled correctly.
  • Call::unbounded_wait, .with_args, .with_cycles, .candid_tuple all confirmed valid in .sources/cdk-rs/ic-cdk/src/call.rs.
  • ic_cdk::update macro confirmed exported via ic_cdk/src/macros.rs.
  • Motoko Runtime.trap confirmed in .sources/motoko-core/src/Runtime.mo with correct signature.
  • Motoko (with cycles = N) expr syntax confirmed valid in .sources/motoko/doc/md/core/Cycles.md.
  • mo:core/Runtime, mo:core/Principal, mo:core/Blob imports are correct mo:core modules (not the banned mo:base).
  • SOL RPC canister ID 2xib7-jqaaa-aaaar-qai6q-cai matches .sources/portal/docs/building-apps/chain-fusion/solana/overview.mdx.
  • RPC provider list (Helius, Alchemy, Ankr, dRPC, Public Node) matches portal source exactly.
  • <\!-- Upstream: --> comment present at end of file, listing correct source repos.
  • Frontmatter completetitle, description, sidebar.order all present, no contradictions.
  • No dfx references and no mo:base imports found.
  • Key ID table (test_key_1 / key_1) is accurate and matches ICP documentation conventions.

- Fix NNS link (was pointing to Subnet Creation article, now links to internal governance page)
- Reorder all three Tabs blocks to Motoko → Rust per project convention
- Resolve human-verification comment on sign_with_schnorr cycles: replace with note explaining 30B is an intentional buffer above the 26.15B fee, unused cycles are refunded
- Update cycle cost table: ~26B → ~26.15B to match cdk-rs SIGN_WITH_SCHNORR_FEE constant
- Clarify max_response_bytes as second argument to request() in "Other common queries"
- Add base58 address derivation pointer to basic_solana solana_helpers.rs
- Expand local testing limitation note: explicitly state no local replica support for Ed25519 signing
@marc0olo
Copy link
Copy Markdown
Member Author

PR #96 Feedback Fix Summary — docs/guides/chain-fusion/solana.mdx

Changes applied

Must-fix items (all 3 applied):

  1. Tab order corrected — all three <Tabs syncKey="lang"> blocks (get balance, get public key, sign message) were reordered from Rust → Motoko to Motoko → Rust, per the CLAUDE.md project convention.

  2. NNS link fixed — replaced the incorrect link pointing to the "Subnet Creation" Learn Hub article (https://learn.internetcomputer.org/hc/en-us/articles/34209955782420-Subnet-Creation) with the internal governance concepts page (../../concepts/governance.md). The portal source links to https://internetcomputer.org/nns, but per project rules we link internally when an internal page exists.

  3. Human verification comment resolved — the {/* Needs human verification: ... */} comment on the Motoko sign_with_schnorr block was replaced with a factual note: "30B cycles is an intentional buffer above the ~26.15B fee (26_153_846_153 cycles, per cdk-rs SIGN_WITH_SCHNORR_FEE). Unused cycles are refunded. The Rust cdk-rs attaches the exact fee automatically; Motoko requires an explicit with cycles attachment." The fee value was verified against .sources/cdk-rs/ic-cdk/src/api/management_canister/schnorr/mod.rs.

Suggestions (4 of 4 applied):

  1. Cycle cost table precision — updated ~26B cycles to ~26.15B cycles for sign_with_schnorr to match the exact cdk-rs constant (26_153_846_153).

  2. max_response_bytes context — updated the "Other common queries" intro from "replace the JSON payload and adjust max_response_bytes" to explicitly state: "pass the JSON payload as the first argument to request and set the second argument (max_response_bytes) to the expected response size. Larger values cost more cycles; set it to the minimum needed."

  3. Base58 address derivation pointer — added a link to solana_helpers.rs in the basic_solana example immediately after the "base58-encode these 32 bytes" mention, giving readers a concrete reference for implementing this step.

  4. Local testing limitation callout — expanded the key table note from "dfx_test_key is not available for Ed25519" to explicitly state: "Ed25519 does not have a local development key — unlike ECDSA (which has dfx_test_key for local replica testing), there is no Ed25519 equivalent. All Ed25519 signing must be tested on ICP mainnet using test_key_1. Plan your test workflow accordingly: local replica development is not possible for the signing steps."

Items skipped

None. All must-fix items and all 4 suggestions were applied. All feedback items were factually correct and improve the page.

Verification

  • Build passes: npm run build completed successfully (86 pages built, 0 errors)
  • Committed to branch docs/guides-chain-fusion-solana

@marc0olo marc0olo merged commit 4d2b433 into main Apr 16, 2026
1 check passed
@marc0olo marc0olo deleted the docs/guides-chain-fusion-solana branch April 16, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant