TypeScript Client
Pre-Alpha Disclaimer: This is an early pre-alpha release for exploring the SDK and starting development only. There is no real MPC signing — all signatures are generated by a single mock signer, not a distributed network. Do not submit any real transactions for signing or rely on any security guarantees. The dWallet keys, trust model, and signing protocol are not final; do not rely on any key material until mainnet. All interfaces, APIs, and data formats are subject to change without notice. The Solana program and all on-chain data will be wiped periodically and everything will be deleted when we transition to Ika Alpha 1. This software is provided “as is” without warranty of any kind; use is entirely at your own risk and dWallet Labs assumes no liability for any damages arising from its use.
The @ika.xyz/pre-alpha-solana-client package provides a TypeScript client for interacting with the dWallet program on Solana. Built on @solana/kit (web3.js v2).
Installation
bun add @ika.xyz/pre-alpha-solana-client @solana/kit
Or with npm:
npm install @ika.xyz/pre-alpha-solana-client @solana/kit
Quick Start
import {
address,
createSolanaRpc,
createSolanaRpcSubscriptions,
generateKeyPairSigner,
pipe,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
} from "@solana/kit";
const RPC_URL = "https://api.devnet.solana.com";
const WS_URL = "wss://api.devnet.solana.com";
const DWALLET_PROGRAM = address("TODO: program ID after deployment");
const rpc = createSolanaRpc(RPC_URL);
const rpcSubscriptions = createSolanaRpcSubscriptions(WS_URL);
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
Building Transactions
Approve Message
Build an ApproveMessage instruction to authorize the Ika network to sign a message:
import { getAddressEncoder, getProgramDerivedAddress, getUtf8Encoder } from "@solana/kit";
const utf8 = getUtf8Encoder();
const addressEncoder = getAddressEncoder();
// Derive MessageApproval PDA
const [messageApprovalPda, messageApprovalBump] = await getProgramDerivedAddress({
seeds: [
utf8.encode("message_approval"),
addressEncoder.encode(dwalletAddress),
messageHash, // Uint8Array(32)
],
programAddress: DWALLET_PROGRAM,
});
// Build instruction data: disc(1) + bump(1) + message_hash(32) + user_pubkey(32) + scheme(1) = 67
const data = new Uint8Array(67);
data[0] = 8; // IX_APPROVE_MESSAGE discriminator
data[1] = messageApprovalBump;
data.set(messageHash, 2);
data.set(userPubkey, 34);
data[66] = 0; // signature_scheme: 0=Ed25519
const approveMessageIx = {
programAddress: DWALLET_PROGRAM,
accounts: [
{ address: messageApprovalPda, role: AccountRole.WRITABLE },
{ address: dwalletAddress, role: AccountRole.READONLY },
{ address: authority, role: AccountRole.READONLY_SIGNER },
{ address: payer, role: AccountRole.WRITABLE_SIGNER },
{ address: SYSTEM_PROGRAM, role: AccountRole.READONLY },
],
data,
};
Transfer dWallet Authority
const data = new Uint8Array(33);
data[0] = 24; // IX_TRANSFER_DWALLET discriminator
data.set(newAuthorityBytes, 1);
const transferIx = {
programAddress: DWALLET_PROGRAM,
accounts: [
{ address: currentAuthority, role: AccountRole.READONLY_SIGNER },
{ address: dwalletAddress, role: AccountRole.WRITABLE },
],
data,
};
Send Transaction
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const tx = pipe(
createTransactionMessage({ version: 0 }),
(msg) => setTransactionMessageFeePayerSigner(payer, msg),
(msg) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, msg),
(msg) => appendTransactionMessageInstruction(approveMessageIx, msg),
);
const signedTx = await signTransactionMessageWithSigners(tx);
await sendAndConfirm(signedTx, { commitment: "confirmed" });
Reading Accounts
Read dWallet
const account = await rpc.getAccountInfo(dwalletAddress, { encoding: "base64" }).send();
const data = Buffer.from(account.value.data[0], "base64");
// Field offsets (after 2-byte disc+version prefix):
const authority = data.subarray(2, 34); // [u8; 32]
const curve = data[34]; // u8
const state = data[35]; // u8: 0=DKGInProgress, 1=Active, 2=Frozen
const publicKeyLen = data[36]; // u8
const publicKey = data.subarray(37, 37 + publicKeyLen);
Read MessageApproval
const data = Buffer.from(account.value.data[0], "base64");
const dwallet = data.subarray(2, 34);
const messageHash = data.subarray(34, 66);
const approver = data.subarray(66, 98);
const status = data[139]; // 0=Pending, 1=Signed
const signatureLen = data.readUInt16LE(140);
const signature = data.subarray(142, 142 + signatureLen);
gRPC Client
For submitting dWallet operations (DKG, Sign, Presign) via gRPC:
// The gRPC client uses BCS-serialized request/response types.
// See the gRPC API section for details on SubmitTransaction.
// Connect to the pre-alpha dWallet gRPC service
const GRPC_URL = "pre-alpha-dev-1.ika.ika-network.net:443";
// gRPC types are defined in proto/ika_dwallet.proto
// Use a gRPC client library (e.g., @grpc/grpc-js or connectrpc) to call:
// DWalletService.SubmitTransaction(UserSignedRequest) -> TransactionResponse
Instruction Discriminators
| Discriminator | Instruction |
|---|---|
| 8 | ApproveMessage |
| 24 | TransferDWallet |
| 31 | CommitDWallet |
| 33 | CommitFutureSign |
| 34 | CommitEncryptedUserSecretKeyShare |
| 35 | CommitPublicUserSecretKeyShare |
| 36 | CreateDeposit |
| 37 | TopUp |
| 38 | SettleGas |
| 42 | TransferFutureSign |
| 43 | CommitSignature |
| 44 | RequestWithdraw |
| 45 | Withdraw |
| 46 | Initialize |
PDA Seeds
| Account | Seeds |
|---|---|
| DWalletCoordinator | ["dwallet_coordinator"] |
| DWallet | ["dwallet", curve_byte, public_key_bytes] |
| MessageApproval | ["message_approval", dwallet_pubkey, message_hash] |
| GasDeposit | ["gas_deposit", user_pubkey] |
| NetworkEncryptionKey | ["network_encryption_key", noa_public_key] |
| CPI Authority | ["__ika_cpi_authority"] (derived per calling program) |
Framework Comparison
| Pinocchio | Native | Anchor | TypeScript | |
|---|---|---|---|---|
| Language | Rust (no_std) | Rust (std) | Rust (std) | TypeScript |
| Runs | On-chain | On-chain | On-chain | Off-chain |
| Use case | Program CPI | Program CPI | Program CPI | Client transactions |
| Account types | AccountView | AccountInfo | Account/UncheckedAccount | Address + raw bytes |
| Best for | Max performance | Existing codebases | Rapid development | dApps, scripts, bots |