
Research
/Security News
jscrambler npm Package Compromised in Supply Chain Attack
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.
@inferenco/nova-wallet-adapter
Advanced tools
Wallet adapter for connecting Cedra dApps to Nova Desk and Nova Wallet.
Supports the AIP-62 wallet-standard and plugin-style integration.
This adapter allows Cedra dApps to connect to two Nova products:
localhost:21984. No external services required.Both connections are handled transparently — the adapter detects the environment and uses the right transport automatically.
NovaWallet) and AIP-62 wallet-standard (registerNovaWallet)window.inferenco, window.nova, and branded aliasesinferenco:// URI scheme for wallet handoff on desktop and mobilenpm install @inferenco/nova-wallet-adapter
yarn add @inferenco/nova-wallet-adapter
pnpm add @inferenco/nova-wallet-adapter
The simplest way to integrate — auto-register Nova as a wallet-standard wallet:
// Side-effect import — registers Nova wallet automatically
import "@inferenco/nova-wallet-adapter/auto-register";
Or register manually with options:
import { registerNovaWallet } from "@inferenco/nova-wallet-adapter/aip62";
registerNovaWallet({
forceRegistration: true, // Register even without injected provider
});
For dApps using plugin-style adapters:
import { NovaWallet } from "@inferenco/nova-wallet-adapter";
const wallet = new NovaWallet();
// Connect
const account = await wallet.connect();
console.log(account.address);
// Sign a message
const response = await wallet.signMessage({
message: "Hello Nova!",
nonce: "unique-nonce-123",
});
// Sign and submit a transaction
const result = await wallet.signAndSubmitTransaction({
data: {
function: "0x1::coin::transfer",
typeArguments: ["0x1::aptos_coin::AptosCoin"],
functionArguments: ["0xrecipient", 1000],
},
});
// Disconnect
await wallet.disconnect();
For full control over the connection lifecycle:
import { NovaClient } from "@inferenco/nova-wallet-adapter";
const client = new NovaClient({
bridgeBaseUrl: "http://127.0.0.1:21984",
detectAliases: true,
});
const { account, network } = await client.connect();
const signed = await client.signTransaction(rawTransaction);
const result = await client.signAndSubmitTransaction(transactionPayload);
If your dApp uses Cedra WalletCore, call the resume helper during provider bootstrap:
import {
NOVA_CONNECT_NAME,
tryResumeNovaWalletConnection,
} from "@inferenco/nova-wallet-adapter";
await tryResumeNovaWalletConnection(walletCore);
This resumes pending mobile callback state after browser reloads and reconnects through stored sessions without app-specific bridge logic.
The adapter provides two dApp integration surfaces backed by a shared NovaClient, which connects to Nova Desk or Nova Wallet depending on the environment:
┌─────────────────────────────────────────────────────────┐
│ Your dApp │
│ │
│ NovaWallet (plugin) ─┐ │
│ ├──▶ NovaClient (core logic) │
│ AIP-62 Bridge ────────┘ │ │
└───────────────────────────────────┼─────────────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Injected │ │ Nova Desk │ │ Nova Wallet │
│ Provider │ │ (desktop) │ │ (mobile) │
│ │ │ │ │ │
│ window.nova │ │ localhost │ │ nova-service │
│ window. │ │ :21984 │ │ + deeplink │
│ inferenco │ │ HTTP bridge │ │ E2E encrypt │
└──────────────┘ └──────────────┘ └──────────────┘
Desktop — Nova Desk: The adapter connects to Nova Desk's local HTTP bridge at http://127.0.0.1:21984. Requests are initiated, then polled until the user approves in the Nova Desk UI. Sessions persist across page reloads.
Mobile — Nova Wallet: The adapter creates an encrypted pairing through nova-service, then launches an inferenco:// deeplink to hand off to Nova Wallet. The user approves in the app, and the result is returned through the relay. All communication is end-to-end encrypted.
Injected provider: When a Nova extension is installed, the adapter calls it directly — no bridge or relay needed.
window.inferenco / window.nova (instant, direct)inferenco://login handoff when Nova Desk is not runningNova Desk and nova-service are independent. Nova Desk works without nova-service, and Nova Wallet works without Nova Desk.
For more detail, see Architecture docs.
NovaWalletThe plugin adapter class, compatible with plugin-style wallet consumers.
| Method | Returns | Description |
|---|---|---|
connect() | Promise<AccountInfo> | Connect to Nova Desk or Nova Wallet |
account() | Promise<AccountInfo> | Get current account info |
disconnect() | Promise<void> | Disconnect and clear session |
signMessage(input) | Promise<CedraSignMessageOutput> | Sign an arbitrary message |
signTransaction(tx, opts?) | Promise<Uint8Array | { authenticator, rawTransaction?: AnyRawTransaction }> | Sign a transaction without submitting |
signAndSubmitTransaction(tx, opts?) | Promise<CedraSignAndSubmitTransactionOutput> | Sign and submit a transaction |
signAndSubmitBCSTransaction(tx, opts?) | Promise<CedraSignAndSubmitTransactionOutput> | Sign and submit (BCS variant) |
onAccountChange(cb) | Promise<void> | Subscribe to account changes |
onNetworkChange(cb) | Promise<void> | Subscribe to network changes |
deeplinkProvider(url?) | string | Generate a deeplink URL |
signTransaction accepts prebuilt SDK transactions and Cedra wallet-standard v1.1
inputs, including secondarySigners and fee payer fields. When the wallet returns
a signed multi-agent transaction, the adapter preserves the SDK AnyRawTransaction
wrapper so secondary signer and fee payer metadata remains available for submission.
Properties:
| Property | Type | Description |
|---|---|---|
name | "Nova Connect" | Wallet display name |
url | string | Wallet website URL |
icon | string | Base64 SVG icon |
readyState | NovaWalletReadyState | Current detection state |
connecting | boolean | Connection in progress |
connected | boolean | Currently connected |
publicAccount | NovaAccountKeys | Cached public key info |
network | NovaNetworkInfo | Current network info |
registerNovaWallet(options?)Registers Nova as an AIP-62 wallet-standard wallet. Implements all Cedra standard features:
cedra:connect, cedra:disconnect, cedra:account, cedra:networkcedra:signMessage, cedra:signTransaction, cedra:signAndSubmitTransactioncedra:onAccountChange, cedra:onNetworkChangecedra:openInMobileAppNovaClientThe core client powering both adapter surfaces. Use directly for advanced control.
| Method | Returns | Description |
|---|---|---|
connect() | Promise<{ account, network }> | Connect to Nova Desk or Nova Wallet |
disconnect() | Promise<void> | Disconnect and revoke session |
getAccount() | Promise<AccountInfo> | Fetch account from provider or session |
getNetwork() | Promise<NetworkInfo> | Fetch current network |
signMessage(input) | Promise<CedraSignMessageOutput> | Sign message via active transport |
signMessageAndVerify(input) | Promise<boolean> | Sign and verify locally |
signTransaction(tx, opts?) | Promise<NovaSignTransactionResult> | Sign transaction |
signAndSubmitTransaction(tx, opts?) | Promise<CedraSignAndSubmitTransactionOutput> | Sign and submit |
hasProvider() | boolean | Check for injected provider |
hasExternalSession() | boolean | Check for stored Nova Desk or Nova Wallet session |
For the complete type reference, see API Reference docs.
All options are optional with sensible defaults:
const wallet = new NovaWallet({
// Identity & deeplinks
deeplinkBaseUrl: "inferenco://connect?callback=",
deeplinkScheme: "inferenco",
websiteUrl: "https://inferenco.com/nova-desk",
// Registration behavior
forceRegistration: false, // Register even without injected provider
desktopRegistration: true, // Register on desktop browsers
detectAliases: true, // Check window.cedra / window.aptos
// Network
networkOverride: undefined, // Force specific network
fullnodeUrl: undefined, // Custom fullnode for SDK operations
// Nova Desk (desktop bridge)
bridgeBaseUrl: "http://127.0.0.1:21984",
bridgeConnectTimeoutMs: 1200,
bridgePollIntervalMs: 250,
bridgePollTimeoutMs: 120000,
// Nova Wallet (mobile relay via nova-service)
relayBaseUrl: "https://nova-service-....run.app",
websocketBaseUrl: "wss://nova-service-....run.app/v1/ws",
mobilePollIntervalMs: 1000,
mobileRequestTimeoutMs: 180000,
mobileSocketTimeoutMs: 15000,
});
See Configuration docs for detailed descriptions of each option.
All adapter errors are instances of NovaAdapterError with a typed error code:
import { NovaAdapterError, NovaErrorCode } from "@inferenco/nova-wallet-adapter";
try {
await wallet.connect();
} catch (error) {
if (error instanceof NovaAdapterError) {
switch (error.code) {
case NovaErrorCode.UserRejected:
console.log("User rejected the request");
break;
case NovaErrorCode.ConnectionTimeout:
console.log("Connection timed out");
break;
case NovaErrorCode.NotInstalled:
console.log("Nova Wallet not found");
break;
}
}
}
| Error Code | Value | Description |
|---|---|---|
UserRejected | USER_REJECTED | User declined the request |
Unauthorized | UNAUTHORIZED | Session expired or invalid |
Unsupported | UNSUPPORTED | Operation not supported by provider |
NotInstalled | NOT_INSTALLED | No provider or bridge found |
ConnectionTimeout | CONNECTION_TIMEOUT | Bridge/relay connection timed out |
InvalidParams | INVALID_PARAMS | Invalid parameters provided |
InvalidNetwork | INVALID_NETWORK | Network mismatch or unavailable |
InternalError | INTERNAL_ERROR | Unexpected internal error |
The adapter detects Nova providers in this priority order:
window.inferenco — primary namespacewindow.nova — secondary namespacewindow.cedra — only if isNovaWallet === true (branded)window.aptos — only if isNovaWallet === true (branded)Unbranded providers on window.cedra / window.aptos are never wrapped. Alias detection can be disabled with detectAliases: false.
Sessions are persisted in localStorage under the key inferenco:nova-session and automatically validated on reconnect:
/session/{id} endpointCommunication between the dApp and Nova Wallet through nova-service is end-to-end encrypted:
| Layer | Algorithm | Purpose |
|---|---|---|
| Key exchange | X25519 (ECDH) | Derive shared secret between dApp and wallet |
| Key derivation | HKDF-SHA256 | Deterministic key from shared secret with "nova-connect-relay" info |
| Encryption | XChaCha20-Poly1305 | Authenticated encryption of all request/response payloads |
| Nonce | 24 random bytes | Per-message nonce prevents replay attacks |
The relay server (nova-service) never sees plaintext request or response data.
The package ships three entry points:
| Entry Point | Import Path | Contents |
|---|---|---|
| Main | @inferenco/nova-wallet-adapter | NovaWallet, NovaClient, types, utilities, errors |
| AIP-62 | @inferenco/nova-wallet-adapter/aip62 | createNovaAIP62Wallet, registerNovaWallet |
| Auto-register | @inferenco/nova-wallet-adapter/auto-register | Side-effect registration (import-only) |
Both ESM and CommonJS builds are included with full TypeScript declarations.
When Nova Desk is running locally, the adapter communicates via HTTP:
| Endpoint | Method | Description |
|---|---|---|
/connect | GET | Initiate connection request |
/sign-message | POST | Sign message request |
/sign-transaction | POST | Sign transaction request |
/transaction | POST | Sign and submit transaction |
/request/{requestId} | GET | Poll for request status |
/session/{sessionId} | GET | Validate existing session |
/connection | DELETE | Revoke connection |
/session/{sessionId} | DELETE | Revoke session |
All operations use a poll-based flow: initiate a request, receive a requestId, then poll until the user approves or rejects in Nova Desk.
# Install dependencies
npm install
# Build (ESM + CJS + declarations)
npm run build
# Run tests
npm test
# Watch tests
npm run test:watch
# Type check
npm run typecheck
| Document | Description |
|---|---|
| Architecture | Transport mechanisms, connection flows, and system design |
| API Reference | Complete type and method documentation |
| Configuration | All options with defaults and examples |
| Mobile Relay Protocol | Nova Wallet end-to-end encrypted communication |
| Changelog | Version history and release notes |
| Package | Purpose |
|---|---|
@cedra-labs/ts-sdk | Transaction building, network utilities, SDK operations |
@cedra-labs/wallet-standard | AIP-62 wallet-standard types and registration |
@noble/curves | X25519 ECDH key exchange (Nova Wallet relay) |
@noble/hashes | SHA256, HKDF key derivation (Nova Wallet relay) |
@noble/ciphers | XChaCha20-Poly1305 authenticated encryption (Nova Wallet relay) |
eventemitter3 | Event emission for account/network change subscriptions |
FAQs
Standalone Nova wallet adapter for Cedra dapps
We found that @inferenco/nova-wallet-adapter demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.

Research
/Security News
A malicious .NET package is typosquatting the Braintree SDK to steal live payment card data, merchant API keys, and host secrets from production apps.

Security News
/Research
Compromised Injective SDK npm version 1.20.21 exfiltrates wallet private keys and mnemonics through fake telemetry functionality.