Skip to Content

Ika dWallet Instructions

Veil integrates Ika’s dWallet infrastructure  to allow native Bitcoin and Ethereum to be used as collateral on Solana without bridging. A dWallet is a programmable cross-chain wallet governed jointly by the user and Ika’s decentralised MPC network.

How it works:

  1. User creates a dWallet on the Ika network (via Ika SDK or the Veil frontend wizard)
  2. User transfers the dWallet’s authority to Veil’s CPI PDA
  3. User calls IkaRegister — Veil verifies authority and creates an IkaDwalletPosition
  4. The dWallet can now only sign Bitcoin/Ethereum transactions if Veil approves (via IkaSign)
  5. When the user wants to exit, IkaRelease transfers authority back and closes the position

Veil CPI Authority PDA: seeds ["__ika_cpi_authority"] on the Veil program ID

Ika Program ID: 87W54kGYFQ1rgWqMeu4XTPHWXWmXSQCcjm8vCTfiq1oY


IkaDwalletPosition Account

Discriminator: VEILIKA! · Size: 128 bytes

OffsetSizeFieldDescription
08discriminatorVEILIKA!
832ownerUser wallet
4032poolAssociated lending pool
7232dwalletIka dWallet account address
1048usd_valueCollateral value at registration (USD cents, u64)
1122curveCurve type (see below)
1142signature_schemeSigning scheme (see below)
1161status0 = Active, 1 = Released, 2 = Liquidated
1171bumpPDA bump
11810_pad

PDA: seeds ["ika_pos", pool, user]

Curve Types

ValueConstantChain
0SECP256K1Bitcoin, Ethereum
1SECP256R1WebAuthn
2CURVE25519Solana, Ed25519
3RISTRETTOSubstrate / sr25519

Signature Schemes

ValueConstantUse Case
0ECDSA_KECCAK256Ethereum transactions
1ECDSA_SHA256Bitcoin legacy, WebAuthn
2ECDSA_DOUBLE_SHA256Bitcoin BIP143
3TAPROOT_SHA256Bitcoin Taproot
4ECDSA_BLAKE2B256Zcash
5EDDSA_SHA512Ed25519 (Solana native)
6SCHNORRKEL_MERLINSubstrate sr25519

IkaRegister

Discriminator: 0x11 (17)

Register a dWallet as collateral. Verifies that the dWallet’s authority has been transferred to Veil’s CPI PDA, then creates an IkaDwalletPosition.

The dWallet authority must already be the Veil CPI PDA before this instruction is called. Use the Ika SDK’s transferDWalletAuthority (or the Veil frontend wizard) to perform this transfer first.

Accounts

#NameFlagsDescription
0usersigner, writableMust match dWallet’s previous authority transfer initiator
1poolreadonlyLending pool the position will be linked to
2dwalletreadonlyIka dWallet account (owned by Ika program)
3ika_positionwritableNew IkaDwalletPosition PDA — seeds: ["ika_pos", pool, user]
4cpi_authorityreadonlyVeil CPI authority PDA — seeds: ["__ika_cpi_authority"]
5system_programreadonly

Instruction Data

OffsetSizeFieldDescription
01discriminator0x11
18usd_valueDeclared collateral value in USD cents (u64 LE)
92curvedWallet curve type (u16 LE)
112signature_schemeSigning scheme (u16 LE)
131position_bumpBump for the IkaDwalletPosition PDA
141cpi_authority_bumpBump for the CPI authority PDA

Validation

The instruction verifies:

  1. dwallet.discriminator == 2 (Ika account type = dWallet)
  2. dwallet.state == 1 (Active — DKG complete)
  3. dwallet.authority == cpi_authority — Veil already controls this dWallet

Example

import { ikaRegisterIx } from './lib/ika/instructions'; import { findCpiAuthority, findIkaPosition } from './lib/ika/pda'; import { DWalletCurve, SignatureScheme } from './lib/ika/types'; import { PROGRAM_ID } from './lib/veil/constants'; const [cpiAuthority, cpiAuthorityBump] = await findCpiAuthority(PROGRAM_ID); const [ikaPosition, positionBump] = await findIkaPosition(pool, user, PROGRAM_ID); const ix = ikaRegisterIx( user, pool, dwalletAddress, ikaPosition, cpiAuthority, 1_200_000n, // $12,000.00 in cents DWalletCurve.SECP256K1, SignatureScheme.ECDSA_SHA256, positionBump, cpiAuthorityBump, );

IkaRelease

Discriminator: 0x12 (18)

Release a registered dWallet. CPIs transfer_dwallet on the Ika program to return authority to the user, then marks the position as Released.

Accounts

#NameFlagsDescription
0usersigner, writableMust be ika_position.owner
1poolreadonly
2dwalletwritableIka dWallet account
3ika_positionwritable
4caller_programreadonlyVeil program ID
5cpi_authorityreadonly
6ika_programreadonly87W54kGYFQ1rgWqMeu4XTPHWXWmXSQCcjm8vCTfiq1oY

Instruction Data

OffsetSizeFieldDescription
01discriminator0x12
11cpi_authority_bumpNeeded to sign the Ika CPI

Example

import { ikaReleaseIx } from './lib/ika/instructions'; import { PROGRAM_ID } from './lib/veil/constants'; import { IKA_PROGRAM_ID } from './lib/ika/types'; const ix = ikaReleaseIx( user, pool, dwalletAddress, ikaPosition, PROGRAM_ID, cpiAuthority, cpiAuthorityBump, );

IkaSign

Discriminator: 0x13 (19)

Approve a cross-chain message for signing by the Ika MPC network. CPIs approve_message on the Ika program, which creates a MessageApproval account that the Ika nodes observe and sign.

This is used for on-chain governance of Bitcoin/Ethereum transactions: only Veil can approve messages for a registered dWallet, so the MPC network won’t sign any transaction unless Veil’s program logic permits it.

Accounts

#NameFlagsDescription
0usersigner, writableMust be ika_position.owner
1coordinatorreadonlyIka DWalletCoordinator PDA
2message_approvalwritableNew Ika MessageApproval PDA (created by this instruction)
3dwalletreadonly
4ika_positionreadonlyMust be Active
5caller_programreadonlyVeil program ID
6cpi_authorityreadonly
7system_programreadonly
8ika_programreadonly

Instruction Data

OffsetSizeFieldDescription
01discriminator0x13
132message_digestSHA-256 hash of the message to sign
3332message_metadata_digestMetadata digest (zero-fill if unused)
6532user_pubkeyUser’s 32-byte public key
972signature_schemeSigning scheme (u16 LE)
991msg_approval_bumpBump for the MessageApproval PDA
1001cpi_authority_bump

Total instruction data: 101 bytes

Example

import { ikaSignIx } from './lib/ika/instructions'; import { findCoordinator, findMessageApproval } from './lib/ika/pda'; import { SignatureScheme } from './lib/ika/types'; import { PROGRAM_ID } from './lib/veil/constants'; const messageDigest = sha256(bitcoinTransaction); // 32 bytes const metadataDigest = new Uint8Array(32); // zeros if unused const [coordinator] = await findCoordinator(); const [messageApproval, msgApprovalBump] = await findMessageApproval( dwalletAddress, messageDigest, metadataDigest, SignatureScheme.ECDSA_SHA256, ); const ix = ikaSignIx( user, coordinator, messageApproval, dwalletAddress, ikaPosition, PROGRAM_ID, cpiAuthority, messageDigest, metadataDigest, user.toBytes(), SignatureScheme.ECDSA_SHA256, msgApprovalBump, cpiAuthorityBump, );
Last updated on