Signing & Credentials
The CRYPTO_WALLET vault credential, accepted key formats, and which operations need it
6 operations require a credential:
transaction/sendNative,
token/createAta, token/transfer, staking/delegate,
wallet/signMessage, and wallet/getPublicKey. Every other operation on this
node is a free read that needs no credential at all.
Setting Up the Credential
Set credentialID on the node to a vault entry of type CRYPTO_WALLET. Its secret-key field must contain one of two accepted formats:
| Format | Source | Shape |
|---|---|---|
| Base58 string | solana-keygen or Phantom "export private key" | The full 64-byte keypair (32-byte seed + 32-byte public key), base58-encoded as one string. |
| JSON byte array | solana-keygen keyfile (e.g. id.json) |
A JSON array of exactly 64 integers, each 0–255, e.g. [12,45,201,...] (64 elements). |
Invalid key material: Anything that isn't a valid 64-byte base58 string or a 64-element
JSON integer array throws
SolanaInvalidKeyMaterialException — "Configured signing
credential is neither a valid base58 secret key nor a 64-byte JSON array. Expected the
solana-keygen/Phantom base58 export or a solana-keygen JSON keyfile array." A 32-byte seed alone
(not the full 64-byte expanded key) is a common mistake and will fail this check.
How Resolution Works
- The node reads
credentialIDfrom its config (auto-wired via the platform's standard credential registration). - At execution time, the secret key is resolved once per execution from the vault via
ReadCredentialValuePrimaryAsync— the same generic single-secret-value slot Ethereum's wallet resolution, SMTP's password, and Slack's bot token all reuse. - For a
CRYPTO_WALLET-type credential this resolves toCryptoWalletRecord.PrivateKey. - The raw key material is parsed into a signing keypair by
SolanaAccountFactory.FromSecretKey, then used to sign the operation's transaction/message.
Never stored, never logged: The secret key is never a node config field, never
included in output data (
ToDictionary()), and never echoed back in a response —
only the derived public address ever appears in output (e.g. wallet/getPublicKey's
address field). The platform's SensitiveDataScrubber also redacts any config
key containing "private" as defense in depth, though no signing key ever reaches config in the first
place.
Missing Credential Behavior
If credentialID is unset, or resolves to an empty/whitespace value, every signing
operation returns the same clean error rather than an unhandled exception:
"No signing credential configured. Set 'credentialID' on this node to a vault entry
containing the wallet secret key."
This check happens before any network call — a missing credential never wastes an RPC round-trip.
Which Operations Need It
| Operation | What the key is used for |
|---|---|
transaction/sendNative | Signs the native SOL transfer transaction. |
token/createAta | Signs and pays the rent for the Associated Token Account creation transaction. |
token/transfer | Signs the SPL token transfer from the wallet's own ATA. |
staking/delegate | Signs as the stake account's authority to delegate it. |
wallet/signMessage | Signs an arbitrary message — no network call, pure local cryptography. |
wallet/getPublicKey | Read-only use — derives the address without signing or broadcasting anything. |