ika-move
Guide for integrating Ika dWallet 2PC-MPC protocol into Sui Move contracts. Use when building Move contracts that need cross-chain signing, dWallet creation, presigning, signing, future signing, key importing, or any Ika on-chain integration. Triggers on Move/Sui contract tasks involving dWallets, cross-chain signing, or Ika protocol operations.
What this skill does
# Ika Move Integration
Build Sui Move contracts integrating Ika dWallet 2PC-MPC for programmable cross-chain signing.
## References (detailed patterns and complete code)
- `references/protocols-detailed.md` - All coordinator function signatures with full parameter lists
- `references/patterns.md` - Complete integration patterns: treasury, DAO governance, imported key wallet, presign pool, events, enums
- `references/typescript-integration.md` - Full TypeScript SDK flows: DKG prep, signing, key import, polling, IkaTransaction API
## Setup
### Move.toml
```toml
[package]
name = "my_project"
edition = "2024.beta"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }
ika_dwallet_2pc_mpc = { git = "https://github.com/dwallet-labs/ika.git", subdir = "deployed_contracts/testnet/ika_dwallet_2pc_mpc", rev = "main" }
ika = { git = "https://github.com/dwallet-labs/ika.git", subdir = "deployed_contracts/testnet/ika", rev = "main" }
[addresses]
my_project = "0x0"
```
For mainnet: change `testnet` to `mainnet` in paths.
### TypeScript SDK
```bash
pnpm add @ika.xyz/sdk
```
```typescript
import { getNetworkConfig, IkaClient } from '@ika.xyz/sdk';
import { getJsonRpcFullnodeUrl, SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
const suiClient = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('testnet'), network: 'testnet' });
const ikaClient = new IkaClient({ suiClient, config: getNetworkConfig('testnet'), cache: true });
await ikaClient.initialize();
```
## Crypto Constants
### Curves
- `0` = SECP256K1 (Bitcoin, Ethereum)
- `1` = SECP256R1 (WebAuthn)
- `2` = ED25519 (Solana, Substrate)
- `3` = RISTRETTO (Privacy)
### Signature Algorithms (relative to curve)
- SECP256K1: `0`=ECDSA, `1`=Taproot
- SECP256R1: `0`=ECDSA
- ED25519: `0`=EdDSA
- RISTRETTO: `0`=Schnorrkel
### Hash Schemes (relative to curve+algo)
- SECP256K1+ECDSA: `0`=KECCAK256(Ethereum), `1`=SHA256, `2`=DoubleSHA256(Bitcoin)
- SECP256K1+Taproot: `0`=SHA256
- SECP256R1+ECDSA: `0`=SHA256
- ED25519+EdDSA: `0`=SHA512
- RISTRETTO+Schnorrkel: `0`=Merlin
## Core Imports
```rust
use ika::ika::IKA;
use ika_dwallet_2pc_mpc::{
coordinator::DWalletCoordinator,
coordinator_inner::{
DWalletCap, ImportedKeyDWalletCap,
UnverifiedPresignCap, VerifiedPresignCap,
UnverifiedPartialUserSignatureCap, VerifiedPartialUserSignatureCap,
MessageApproval, ImportedKeyMessageApproval
},
sessions_manager::SessionIdentifier
};
use sui::{balance::Balance, coin::Coin, sui::SUI};
```
## Contract Template
```rust
public struct MyContract has key, store {
id: UID,
dwallet_cap: DWalletCap,
presigns: vector<UnverifiedPresignCap>,
ika_balance: Balance<IKA>,
sui_balance: Balance<SUI>,
dwallet_network_encryption_key_id: ID,
}
```
### Required Helpers
```rust
fun random_session(coordinator: &mut DWalletCoordinator, ctx: &mut TxContext): SessionIdentifier {
coordinator.register_session_identifier(ctx.fresh_object_address().to_bytes(), ctx)
}
fun withdraw_payment_coins(self: &mut MyContract, ctx: &mut TxContext): (Coin<IKA>, Coin<SUI>) {
let ika = self.ika_balance.withdraw_all().into_coin(ctx);
let sui = self.sui_balance.withdraw_all().into_coin(ctx);
(ika, sui)
}
fun return_payment_coins(self: &mut MyContract, ika: Coin<IKA>, sui: Coin<SUI>) {
self.ika_balance.join(ika.into_balance());
self.sui_balance.join(sui.into_balance());
}
public fun add_ika_balance(self: &mut MyContract, coin: Coin<IKA>) {
self.ika_balance.join(coin.into_balance());
}
public fun add_sui_balance(self: &mut MyContract, coin: Coin<SUI>) {
self.sui_balance.join(coin.into_balance());
}
```
## DWalletCoordinator
Central shared object for all operations. Pass as `&mut DWalletCoordinator` for mutations, `&DWalletCoordinator` for reads.
Get ID in TypeScript: `ikaClient.ikaConfig.objects.ikaDWalletCoordinator.objectID`
## Capabilities
| Capability | Purpose | Created By |
|---|---|---|
| `DWalletCap` | Authorize signing | DKG |
| `ImportedKeyDWalletCap` | Authorize imported key signing | Import verification |
| `UnverifiedPresignCap` | Presign reference (needs verify) | Presign request |
| `VerifiedPresignCap` | Ready for signing | `verify_presign_cap()` |
| `UnverifiedPartialUserSignatureCap` | Partial sig (needs verify) | Future sign |
| `VerifiedPartialUserSignatureCap` | Ready for completion | `verify_partial_user_signature_cap()` |
| `MessageApproval` | Auth to sign specific message | `approve_message()` |
| `ImportedKeyMessageApproval` | Auth for imported keys | `approve_imported_key_message()` |
## SessionIdentifier
Every protocol op needs a unique `SessionIdentifier`. Create via:
```rust
let session = coordinator.register_session_identifier(ctx.fresh_object_address().to_bytes(), ctx);
```
Rules: create just before use, never reuse, one per operation.
## Payment Pattern
All ops require IKA+SUI fees. Pattern: withdraw all -> perform ops (fees auto-deducted from `&mut Coin`) -> return remainder.
## Protocol: DKG (Create dWallet)
### Shared dWallet (recommended for contracts)
Public user share, network signs without user interaction.
```rust
let (dwallet_cap, _) = coordinator.request_dwallet_dkg_with_public_user_secret_key_share(
dwallet_network_encryption_key_id, curve,
centralized_public_key_share_and_proof, user_public_output, public_user_secret_key_share,
option::none(), // sign_during_dkg_request
session, &mut ika, &mut sui, ctx,
);
```
### Zero-Trust dWallet
Encrypted user share, user must participate in every signature.
```rust
let (dwallet_cap, _) = coordinator.request_dwallet_dkg(
dwallet_network_encryption_key_id, curve,
centralized_public_key_share_and_proof, encrypted_centralized_secret_share_and_proof,
encryption_key_address, user_public_output, signer_public_key,
option::none(), session, &mut ika, &mut sui, ctx,
);
```
**Important:** After zero-trust DKG (or key import), the dWallet is in `AwaitingKeyHolderSignature` state. The user must call `acceptEncryptedUserShare` to transition the dWallet to `Active` state before it can be used for signing:
```typescript
// Wait for DKG to complete and dWallet to reach AwaitingKeyHolderSignature state
const awaitingDWallet = await ikaClient.getDWalletInParticularState(dwalletId, 'AwaitingKeyHolderSignature');
// The encrypted user secret key share ID comes from the DKG transaction event,
// NOT from the dWallet ID.
const encryptedShare = await ikaClient.getEncryptedUserSecretKeyShare(encryptedUserSecretKeyShareId);
const tx = new Transaction();
const ikaTx = new IkaTransaction({ ikaClient, transaction: tx, userShareEncryptionKeys: keys });
await ikaTx.acceptEncryptedUserShare({
dWallet: awaitingDWallet,
encryptedUserSecretKeyShareId: encryptedShare.id,
userPublicOutput: new Uint8Array(dkgData.userPublicOutput),
});
await suiClient.core.signAndExecuteTransaction({ transaction: tx, signer: keypair });
// dWallet is now Active and ready for signing
const activeDWallet = await ikaClient.getDWalletInParticularState(dwalletId, 'Active');
```
This step is NOT needed for shared dWallets (created with `request_dwallet_dkg_with_public_user_secret_key_share`).
### TypeScript DKG Prep
```typescript
import { prepareDKGAsync, UserShareEncryptionKeys, Curve, createRandomSessionIdentifier } from '@ika.xyz/sdk';
const keys = await UserShareEncryptionKeys.fromRootSeedKey(seed, Curve.SECP256K1);
const bytesToHash = createRandomSessionIdentifier(); // bytes hashed to derive the session identifier
const dkgData = await prepareDKGAsync(ikaClient, Curve.SECP256K1, keys, bytesToHash, signerAddress);
const networkKey = await ikaClient.getLatestNetworkEncryptionKey();
// dkgData has: userDKGMessage, userPublicOutput, encryptedUserShareAndProof, userSecretKeyShare
```
### Sign During DKG (optional)
Pass existing presign to get signature during DKG:
```rust
lRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.