Ink SDK / Integration guide

Developer integration guide.

The Ink SDK is a chain-agnostic signing client for Ika-backed execution. It adds SDK-native EVM dWallet creation, the Ink CLI, SDK-side policies, Solana ED25519 dWallet creation/signing, and Sui ED25519 intent signing while keeping non-EVM execution honest through explicit submit hooks.

EVM helpers
Policy gates
Solana dWallets
Sui signatures

How it works

When you call ink.call(), the SDK resolves the chain adapter, checks configured policies, builds the native payload, sends the exact bytes to your configured Ika connector, attaches the returned signature, and uses the adapter to submit or return the signed result.

Execution lifecycle

Every call progresses through tracked statuses: builtsigningsignedbroadcastexecuted. On failure: sign_failed or broadcast_failed. Each transition emits an action:status event and persists to storage if configured.

Capability map

EVM

Production-ready signing path

ABI calldata, ethers RPC helpers, Ika secp256k1 signing, sign-only mode, optional broadcast, and receipts.

Solana

ED25519 dWallet signing

Ika can create/import Solana dWallets and sign serialized solana-message payloads. Execution still needs real send/confirm hooks.

Sui

ED25519 dWallet signing

Ika can create/import Sui dWallets and return Sui intent-aware serialized signatures for transaction bytes. Execution still needs submit/wait hooks.

Policies

Pre-signing guardrails

Reject unsafe chain, target, function, value, or non-idempotent requests before a signature is requested.

01 / Install

Add the package.

terminal
npm install @ink-sdk/sdk @ink-sdk/evm

Chain adapters

Built-in adapters for EVM (ethers), Solana, and Sui. Each handles chain-specific build, sign, submit, and confirm.

dWallet signing

Use Ika EVM signing, Solana ED25519 dWallets, or Sui ED25519 intent signatures through connector classes.

Receipts & events

Typed receipts with action IDs, transaction hashes, policy failures, and lifecycle events for reconciliation.

02 / Quick starts

Start with the right chain path.

The SDK keeps one developer workflow across Monad, Solana, and Sui: build a native payload, send the exact bytes to your Ika connector, attach the returned signature, and persist a receipt.

Monad (EVM-compatible)

Reference snippet

Use the EVM adapter for Monad workflows with Ika secp256k1 signing, ABI-aware calldata, and receipts.

ts
import { createInkClient, IkaEvmSigningConnector } from "@ink-sdk/sdk";
import { createEthersEvmAdapter } from "@ink-sdk/evm";
const ink = createInkClient({
mode: "production",
ika: {
connector: new IkaEvmSigningConnector({ env: process.env }),
network: "testnet",
},
chains: [{ type: "evm", chainId: 10143, rpcUrl: process.env.MONAD_RPC_URL }],
adapters: [createEthersEvmAdapter({
chain: { type: "evm", chainId: 10143 },
rpcUrl: process.env.MONAD_RPC_URL,
signerAddress: process.env.IKA_ETH_ADDRESS,
broadcast: false,
})],
});

Sui

Reference snippet

Register a Sui dWallet and sign transaction bytes with the Sui connector, then submit them with your own confirmation hook.

ts
import { createInkClient } from "@ink-sdk/sdk";
import { IkaSuiDWalletConnector } from "@ink-sdk/sdk";
const ink = createInkClient({
mode: "production",
ika: { connector: new IkaSuiDWalletConnector({ env: process.env }) },
chains: [{ type: "sui", network: "testnet" }],
});

Solana

Reference snippet

Create or import a Solana dWallet and sign serialized Solana messages through the connector before broadcasting.

ts
import { createInkClient } from "@ink-sdk/sdk";
import { IkaSolanaDWalletConnector } from "@ink-sdk/sdk";
const ink = createInkClient({
mode: "production",
ika: { connector: new IkaSolanaDWalletConnector({ env: process.env }) },
chains: [{ type: "solana", cluster: "devnet" }],
});

03 / Configuration

Create a client.

ts
import { createEthersEvmAdapter } from "@ink-sdk/evm";
import { createInkClient, createJsonFileStorage, IkaEvmSigningConnector } from "@ink-sdk/sdk";
export const ink = createInkClient({
mode: "production",
ika: {
connector: new IkaEvmSigningConnector({ env: process.env }),
network: "testnet",
},
chains: [{ type: "evm", chainId: 10143, rpcUrl: process.env.MONAD_RPC_URL }],
adapters: [
createEthersEvmAdapter({
chain: { type: "evm", chainId: 10143 },
rpcUrl: process.env.MONAD_RPC_URL,
signerAddress: process.env.IKA_ETH_ADDRESS,
broadcast: false,
}),
],
policies: {
allowedChains: [{ type: "evm", chainId: 10143 }],
allowedFunctions: ["transfer", "deposit", "crossBorrow"],
requireIdempotencyKey: true,
},
storage: await createJsonFileStorage(".ink/receipts.json"),
});
mode"development" | "production"

Production mode requires a real Ika connector and refuses in-memory defaults.

ika.connectorIkaConnector

Use IkaEvmSigningConnector, IkaSolanaDWalletConnector, or IkaSuiDWalletConnector for production signing.

ika.networkstring | undefined

Optional network identifier passed through to the Ika connector for routing.

chainsInkChain[]

Allowed EVM, Solana, and Sui targets. Calls outside this list are rejected.

adaptersChainAdapter[]

Optional custom adapters for RPC, gas, broadcast, confirmation, and chain-specific behavior.

policiesInkPolicyConfig

Optional pre-signing controls for allowed chains, contracts, programs, packages, functions, value, and idempotency.

storageInkStorage

Persistent receipts, statuses, dWallet metadata, and idempotency mappings. Ships createJsonFileStorage().

04 / Wallet setup

Connect a signer.

Create an EVM dWallet through the Ika EVM connector, or use the Solana and Sui Ika connectors for ED25519 wallets. The connector owns the cryptographic signing path; the adapter owns chain submission and confirmation.

ts
const dwallet = await ink.dwallet.create({
name: "user-wallet",
chains: [{ type: "evm", chainId: 10143, rpcUrl: process.env.MONAD_RPC_URL }],
config: { purpose: "app_execution" },
});
console.info("Ready", dwallet.id, dwallet.addresses.evm);
ts
import { IkaSolanaDWalletConnector, IkaSuiDWalletConnector } from "@ink-sdk/sdk";
const solanaInk = createInkClient({
mode: "production",
ika: { connector: new IkaSolanaDWalletConnector({ env: process.env }) },
chains: [{ type: "solana", cluster: "devnet" }],
});
const suiInk = createInkClient({
mode: "production",
ika: { connector: new IkaSuiDWalletConnector({ env: process.env }) },
chains: [{ type: "sui", network: "testnet" }],
});

05 / CLI

Create Ika dWallets from the terminal.

ink-cli create

The CLI runs the same live Ika creation path used by the SDK. It submits the Ika DKG transaction through Sui, waits for the dWallet to become active, derives the EVM address, creates a presign, and can write the resulting object IDs back into your env file for app use.

terminal
ink-cli create \
--env-file .env \
--network testnet \
--write-env \
--json

Command flags

--env-file <path>

Load Ika, Sui, RPC, and coin object config from a specific env file instead of the default .env.

--network <name>

Select the Ika/Sui network, for example testnet.

--rpc <url>

Override the Sui RPC endpoint used for live wallet creation.

--ika-coin <id>

Use a specific IKA coin object for the DKG transaction.

--sui-coin <id>

Use a specific SUI coin object for transaction payment or object routing.

--gas-coin <id>

Use a specific SUI gas coin object for the wallet creation transaction.

--fresh / --reuse

Force new object discovery or reuse configured env object IDs when available.

--write-env / --no-write-env

Choose whether generated wallet IDs are written back into the env file.

--json

Return machine-readable output for scripts, CI, or app setup flows.

--timeout <ms>

Control how long the command waits for Ika/Sui transaction completion.

Required env

IKA_SUI_PRIVATE_KEY

Sui private key that submits the Ika DKG transaction and pays gas on testnet.

IKA_COIN_ID

IKA coin object used for Ika protocol fees. Can also be passed with --ika-coin.

IKA_SUI_COIN_ID

SUI coin object used by the Ika flow. Can also be passed with --sui-coin.

IKA_NETWORK

Network name such as testnet. Can also be passed with --network.

IKA_SUI_RPC

Sui RPC endpoint. Can also be passed with --rpc.

Use --no-write-env for CI or one-off scripts that should print the object IDs without modifying local files.

06 / Signing requests

Submit typed payloads.

ts
const receipt = await ink.call({
targetChain: { type: "evm", chainId: 10143 },
target: {
contract: "0xae13...a7cd",
abi,
functionName: "crossBorrow",
args: ["1000000000", 10143, "0x742d...44e"],
value: "0",
},
signing: { provider: "ika", dWalletId: dwallet.id },
execution: {
waitForReceipt: true,
returnExplorerUrl: true,
idempotencyKey: crypto.randomUUID(),
},
});
console.info(receipt.status, receipt.transaction?.hash);

07 / SDK reference

Core methods.

createInkClient(config)

Creates a typed open SDK client with production guardrails, adapters, storage, and raw signing.

createEthersEvmAdapter(config)

Adds ethers-powered nonce, gas, sign-only, broadcast, and receipt handling for EVM calls.

ink.dwallet.importExisting(input)

Registers an existing Ika dWallet and its chain addresses for app execution.

ink.dwallet.create(input)

Creates real Ika dWallets through the configured EVM, Solana, or Sui connector.

ink.call(input)

Builds a native transaction payload, asks Ika to sign it, attaches the signature, submits through the adapter, and returns a receipt.

ink.estimate(input)

Asks the selected adapter for gas, fees, or compute units before execution.

ink.getStatus(actionId)

Reads the latest lifecycle status for an action.

ink.getReceipt(actionId)

Reads a stored receipt for audit trails, retries, and reconciliation.

08 / Errors

Handle failures directly.

Treat SDK errors as structured signals. Most issues come from missing connector configuration, a chain not on the allowlist, or a policy rejection before a signature is requested.

INK_CONFIG_INVALID

A required configuration field is missing or malformed.

INK_SIGNER_REQUIRED

Production mode was started without an Ika connector. Provide one via ika.connector.

INK_CHAIN_NOT_CONFIGURED

The target chain is not in the configured chain allowlist.

INK_POLICY_REJECTED

A configured policy blocked the chain, target, function, value, or missing idempotency key before signing.

INK_TARGET_INVALID

The contract, program, Move call, ABI, or arguments failed adapter validation.

INK_SIGNATURE_FAILED

The Ika connector could not produce a signature for the signing payload.

INK_BROADCAST_FAILED

The signed transaction could not be submitted or confirmed on the target chain.

Troubleshooting playbook

No signer available

Production mode was started without an Ika connector.

Provide ika.connector and ensure the dWallet is imported or created before calling ink.call().

Unknown chain

The target chain is not in the allowlist.

Add the chain to chains and allowedChains, and verify the RPC URL and network name.

Signature rejected

A policy blocked the action before signing.

Check the allowed chain, target, function, or package list, and add an idempotency key.

Broadcast or confirmation failed

The signature was produced but submission did not complete.

Confirm the RPC endpoint, wallet funding, and whether broadcast was disabled for the adapter.

09 / Events

Listen in-app.

ts
ink.on("action:status", ({ actionId, status }) => {
console.info("[ink]", actionId, status);
});
ink.on("action:receipt", ({ receipt }) => {
finalizeAction(receipt.actionId, receipt.transaction?.hash);
});

10 / Launch checklist

Before production.

  • Use testnet mode during development.
  • Set idempotency keys for all signing requests.
  • Configure policies before exposing automated signing to users or agents.
  • Show the exact payload summary before calling ink.call.
  • Handle timeout, rejected, and cancelled states separately.
  • Use broadcast: false for EVM signing proofs until the signer address is funded.
  • Provide real Solana/Sui submit hooks before marking non-EVM actions executed.
  • Subscribe to SDK events for async request completion.
INSTALL OPEN SDK