@cfxdevkit/signer-session
Headless signer session factory — create a ready Signer pair (eSpace + Core) from any backend without browser UI.
Install
pnpm
pnpm add @cfxdevkit/signer-sessionHeadless signer session factory. Create a ready { eSpace, core? } Signer pair from any backend — no browser UI, no devnode-server required.
Backends
Memory (dev / test)
import { createSignerSession } from '@cfxdevkit/signer-session';
const s = await createSignerSession({
kind: 'memory',
privateKey: '0x…',
});
const sig = await s.eSpace.signMessage('Hello Conflux');
const coreSig = await s.core!.signMessage('Hello Core');
await s.dispose(); // no-op for memoryFile keystore (CI / scripts)
const s = await createSignerSession({
kind: 'file-keystore',
path: '~/.cfxdevkit/keystore.json', // or set CFX_KEYSTORE_PATH
passphrase: process.env.MY_PASS, // or set CFX_PASSPHRASE
ref: { service: 'cfxdevkit', account: 'deployer' },
accountIndex: 0,
});
const sig = await s.eSpace.signMessage('Hello');
await s.dispose();Environment variables (all optional when passed explicitly):
| Variable | Purpose | Default |
|---|---|---|
CFX_KEYSTORE_PATH | Keystore file path | (required if not passed) |
CFX_PASSPHRASE | Decryption passphrase | (required if not passed) |
CFX_KEYSTORE_SERVICE | ref.service | "cfxdevkit" |
CFX_KEYSTORE_ACCOUNT | ref.account | "default" |
OneKey hardware (Node.js / Electron)
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
await HardwareSDK.init({ debug: false });
const devicesRes = await HardwareSDK.searchDevices();
const { connectId } = devicesRes.payload[0];
const { deviceId } = (await HardwareSDK.getFeatures(connectId)).payload;
const s = await createSignerSession({
kind: 'onekey',
sdk: HardwareSDK,
connectId,
deviceId,
});Ledger hardware (Node.js HID)
import { createNodeHidLedgerTransport } from '@cfxdevkit/wallet/hardware/ledger';
const transport = await createNodeHidLedgerTransport();
const s = await createSignerSession({
kind: 'ledger',
transport,
});
await s.eSpace.signMessage('Hello');
await s.dispose(); // closes HID transportCLI — cdk sign
# Sign a message from env-var keystore
CFX_KEYSTORE_PATH=~/.cfxdevkit/keystore.json CFX_PASSPHRASE=secret \
cdk sign message "Hello Conflux"
# Core Space
cdk sign message "Hello Core" --space core
# Typed data
cdk sign typed-data ./payload.json --space espace --json
# With explicit keystore flags
cdk sign message "Hello" --keystore ./my.json --account deployerMCP offline mode
When devnode-server is not running, cfxdevkit_wallet_sign_message automatically falls
back to createSignerSession({ kind: 'file-keystore' }) if CFX_PASSPHRASE and
CFX_KEYSTORE_PATH are set. The response includes a "note" field indicating offline mode.
Signer Configuration File (.cfxdevkit/signer.json)
For projects using the full developer toolchain, configure a persistent signer:
# Interactive setup wizard
cdk signer setup
# Check current config
cdk signer status
# List all configured signers
cdk signer list
# Switch the active signer
cdk signer use hardware.cfxdevkit/signer.json format:
{
"defaultSigner": "dev-wallet",
"signers": {
"dev-wallet": {
"kind": "file-keystore",
"path": ".cfxdevkit/keystore.json",
"service": "cfxdevkit",
"account": "deployer",
"accountIndex": 0
},
"quick": { "kind": "memory" },
"hardware": { "kind": "onekey" }
}
}The file is automatically gitignored by the setup wizard.
CFX_SIGNER_NAME — override the active signer name without editing the file.
cdk sign reads signer config automatically when CFX_KEYSTORE_PATH is not set.
Usage
import { createSignerSession } from '@cfxdevkit/signer-session';
// Memory signer (ephemeral)
const mem = await createSignerSession({
kind: 'memory',
privateKey: '0x…',
});
// File keystore signer (CI / scripts)
const file = await createSignerSession({
kind: 'file-keystore',
path: process.env.CFX_KEYSTORE_PATH!,
passphrase: process.env.CFX_PASSPHRASE!,
ref: { service: 'myapp', account: 'deployer' },
accountIndex: 0,
});
// Hardware signer (OneKey)
const hw = await createSignerSession({
kind: 'onekey',
sdk: HardwareSDK,
connectId,
deviceId,
});
// Sign messages
const sig = await mem.eSpace.signMessage('Hello');
const coreSig = await mem.core!.signMessage('Hello Core');API Reference
See API.md for the full public surface.
Tier
Tier 0 — framework — Must not runtime-import from any higher tier.
API Reference
.
// Represents a file-based keystore input for initializing a signer session.
export { FileKeystoreSignerInput }
// Represents a Ledger hardware wallet input for initializing a signer session.
export { LedgerSignerInput }
// Represents an in-memory (ephemeral) input for initializing a signer session.
export { MemorySignerInput }
// Represents a OneKey hardware wallet input for initializing a signer session.
export { OneKeySignerInput }
// A session object encapsulating both eSpace and Core signer instances, ready for use.
export { SignerSession }
// Input configuration object used to create a `SignerSession`.
export { SignerSessionInput }
// Enum indicating the type of signer being used (e.g., file, ledger, memory, onekey).
export { SignerSessionKind }
// A file-based keystore entry, containing metadata and path info for a keystore file.
export { FileKeystoreSignerEntry }
// A Ledger hardware wallet entry, containing metadata for ledger device interaction.
export { LedgerSignerEntry }
// An in-memory (ephemeral) entry, representing a temporary signer instance.
export { MemorySignerEntry }
// A OneKey hardware wallet entry, containing metadata for OneKey device interaction.
export { OneKeySignerEntry }
// Configuration object for a signer, including options like derivation path and network.
export { SignerConfig }
// Union type representing any valid signer entry (file, ledger, memory, onekey).
export { SignerEntry }
// Enum indicating the kind of signer (e.g., 'file', 'ledger', 'memory', 'onekey').
export { SignerKind }
// Default configuration for a signer session, used when no explicit config is provided.
export { defaultSignerConfig }
// Ensures that a signer JSON config file is present and git-ignored for security.
export { ensureSignerJsonGitignored }
// Reads and parses a signer configuration file from disk.
export { readSignerConfig }
// Resolves a `SignerEntry` from a given input or configuration.
export { resolveSignerEntry }
// Returns the default path where signer configuration files are stored.
export { signerConfigPath }
// Writes a signer configuration object to disk.
export { writeSignerConfig }
// Creates a `SignerSession` from a `SignerSessionInput`, supporting all signer types.
export declare function createSignerSession(input: SignerSessionInput): Promise<SignerSession>;
// Creates a `SignerSession` by loading a named configuration from disk (or default if none).
// Optionally specify a custom working directory (`cwd`) for config resolution.
export declare function createSignerSessionFromConfig(name?: string | null, cwd?: string): Promise<SignerSession>;
// Warning message displayed when using an ephemeral (in-memory) signer.
export declare const EPHEMERAL_WARNING = "\u26A0 ephemeral memory signer \u2014 key exists only for this session. Use `cdk signer setup` to configure a persistent signer.";Usage
import { createSignerSession } from '@cfxdevkit/signer-session';
// Create a session using an in-memory signer (ephemeral)
const session = await createSignerSession({ kind: 'memory' });
// Or load from a named config file (e.g., `~/.cdk/signer-config.json`)
const sessionFromConfig = await createSignerSessionFromConfig('my-signer');