Importing a Stellar secret key gives an application full control of the associated wallet and funds. Treat an imported key as highly sensitive from the moment the user enters it until it is removed from memory or secure storage.
The PocketPay SDK can use a key supplied by a consuming application, but the consuming application is responsible for how that key is collected, stored, and passed to the SDK. The SDK does not make insecure application storage safe.
- Never log a secret key. Do not include it in console output, structured logs, error messages, stack-trace context, or debugging snapshots.
- Never send a secret key to an external server. This includes an app's own backend, analytics tools, crash reporters, monitoring services, support tools, and third-party APIs.
- Keep signing local to the user's device. Pass the key only to the PocketPay SDK operation that requires it, and do not include it in network request payloads.
- Do not store secret keys in plain-text preferences, unencrypted databases, files, browser storage, source code, or environment/configuration files bundled with the mobile app.
If a PocketPay mobile app accepts imported keys, the app must protect them using secure local storage appropriate to its platform, such as an operating system keychain, keystore, or equivalent hardware-backed secure storage where available. Access should be limited to the app, and device authentication should be required when appropriate for the product's threat model.
The app is also responsible for:
- ensuring backups and device migrations do not expose the key;
- clearing the key when the wallet is removed or the user signs out;
- preventing the key from appearing in screenshots, clipboard history, UI state persistence, diagnostic reports, or analytics events;
- reviewing dependencies and error-handling paths for accidental disclosure;
- documenting whether and how an imported wallet can be recovered.
- Collect the key in a dedicated, masked input that disables autocorrect and avoids persisting form state.
- Validate the key locally, store it immediately in platform secure storage, and clear the input state as soon as practical.
- Read the key only when a local signing operation needs it, pass it directly to the relevant PocketPay SDK call, and release references afterward.
- Log only non-secret values such as the wallet's public key, transaction hash, or a sanitized error code.
- Redact fields named
secretKey,seed, or similar at the logging and crash reporting boundaries as defense in depth.
// The secure storage implementation is owned by the mobile app.
const secretKey = await secureStorage.get('wallet-secret-key');
try {
await pocketPay.sendPayment({ secretKey, destination, amount });
logger.info('Payment submitted', { publicKey, destination });
} finally {
// Do not retain the key in component, navigation, or persisted app state.
}JavaScript strings cannot be reliably zeroed from memory, so minimize how long the key is referenced and never rely on manual clearing as a substitute for secure storage and careful data flow.
// Unsafe: secrets can reach device logs and log aggregation services.
console.log('Imported wallet', { secretKey });
// Unsafe: imported keys must not leave the device.
await api.post('/wallets/import', { secretKey });
analytics.track('wallet_imported', { secretKey });
crashReporter.setAttribute('secretKey', secretKey);
// Unsafe: ordinary app storage is not suitable for wallet secrets.
await preferences.set('wallet-secret-key', secretKey);Do not send a secret key to customer support or ask a user to paste one into a support ticket. Diagnose wallet-import problems with public keys, sanitized error codes, and non-sensitive device or transaction metadata.
When importing secret keys, the SDK performs strict local validation prior to any key derivation or SDK operations:
- Type Check: Non-string values throw
PocketPayErrorwith validation reasonnot_a_string. - Presence Check: Empty or whitespace-only strings throw
PocketPayErrorwith validation reasonmissing. - Prefix Check: Keys must start with
'S'. Non-matching values throwPocketPayErrorwith validation reasoninvalid_prefix. - Length Check: Keys must be exactly 56 characters. Incorrect lengths throw
PocketPayErrorwith validation reasoninvalid_length. - Format Check: Keys with invalid strkey payloads or checksums throw
PocketPayErrorwith validation reasoninvalid_format.
Secret key inputs are never attached to error.validation.value or raw error messages. Sanitized error messages give clear guidance without echoing key material.
In addition to importWallet(secretKey), the SDK provides non-throwing and enriched wrappers:
import { safeImportWallet, enhancedImportWallet } from '@axionvera/pocketpay-sdk';
// 1. Non-throwing result wrapper
const result = safeImportWallet(userInputKey);
if (result.ok) {
console.log('Wallet imported:', result.value.publicKey);
} else {
console.error('Import failed [code]:', result.error.code);
}
// 2. Enhanced wrapper with recovery hints
const enhanced = enhancedImportWallet(userInputKey);
if (!enhanced.ok) {
enhanced.recoveryHints?.forEach(hint => {
console.log('Recovery action:', hint.action, hint.message);
});
}- Secret keys never appear in logs, errors, analytics, or crash reports.
- Secret keys never leave the user's device.
- Imported keys are stored only in platform secure storage.
- Signing occurs locally through the PocketPay SDK.
- UI, clipboard, backup, logout, and wallet-removal flows are reviewed for secret retention.
- Tests and debugging tools use dedicated test accounts, never user keys.