Mysten Incubation
Reference

CLI Signer API

HTTP API for signing transactions using the local sui CLI keystore. Private keys never leave the sui binary — only transaction bytes are sent for signing.

This API is served by the dev wallet's standalone server (npx @mysten-incubation/dev-wallet serve). The endpoints are implemented as middleware that can be mounted on any HTTP server.

Endpoints

GET /api/v1/accounts

List all accounts available in the Sui CLI keystore.

Request:

GET /api/v1/accounts HTTP/1.1
Authorization: Bearer <token>

Response (200):

{
	"accounts": [
		{
			"suiAddress": "0x1234567890abcdef...",
			"publicBase64Key": "AO3a1234...",
			"keyScheme": "ed25519",
			"alias": "my-account"
		}
	]
}
FieldTypeDescription
suiAddressstringHex address with 0x prefix
publicBase64KeystringBase64-encoded public key with flag byte prefix
keySchemestringed25519, secp256k1, or secp256r1
aliasstring | nullHuman-friendly account name, if set

POST /api/v1/sign-transaction

Sign BCS-serialized TransactionData using the sui CLI. Calls sui keytool sign under the hood.

Request:

POST /api/v1/sign-transaction HTTP/1.1
Authorization: Bearer <token>
Content-Type: application/json

{
  "address": "0x1234567890abcdef...",
  "txBytes": "oEJ..."
}
FieldTypeValidationDescription
addressstringValid Sui address (isValidSuiAddress)Sui address to sign with
txBytesstringNon-empty base64, max ~1M charsBCS-serialized transaction data

Response (200):

{
	"suiSignature": "AKjTrX9...",
	"digest": "7f9a2c1b..."
}
FieldTypeDescription
suiSignaturestringSui signature (includes scheme flag)
digeststringTransaction digest

Personal message signing is not supportedsui keytool sign only accepts TransactionData.

Error Responses

All errors return JSON with an error field:

{ "error": "description of what went wrong" }
StatusWhen
400Invalid JSON body, bad address format, or invalid txBytes
401Missing or invalid authentication token
403Request not from localhost
404Address not found in keystore
413Request body exceeds 2 MB (based on content-length)
500sui CLI not found or signing failure

Authentication

The API uses a token-in-URL approach (same pattern as Jupyter notebooks):

  1. On server start, a 256-bit random token is generated
  2. The token is printed to the terminal as part of the URL: http://localhost:5174/?token=<token>
  3. Opening that URL stores the token in localStorage
  4. All API requests require the token in the Authorization: Bearer <token> header
  5. Token comparison uses timingSafeEqual() to prevent timing attacks

Client Integration

The RemoteCliAdapter from @mysten-incubation/dev-wallet/adapters implements the browser-side client for this API. See Remote CLI Adapter for usage.

import { RemoteCliAdapter } from '@mysten-incubation/dev-wallet/adapters';

const adapter = new RemoteCliAdapter({
	serverOrigin: 'http://localhost:5174',
	token: '<token>',
});
await adapter.initialize();

// List accounts available on the server (not yet imported)
const available = await adapter.listAvailableAccounts();

// Import a specific account for use in the wallet
await adapter.importAccount({ address: '0x...' });

On this page