Skip to content

The Settings account stores configuration for Range verification. Each admin creates their own Settings account, enabling multi-tenant deployments.

Range uses a multi-tenant architecture where each admin has their own isolated Settings:

Benefits:

  • Each project/admin has independent configuration
  • No shared state or conflicts between tenants
  • Different window_size values for different use cases
  • Separate range_signer keys for isolated backends
pub struct Settings {
pub bump: u8,
pub admin: Pubkey,
pub window_size: u64,
pub range_signer: Pubkey,
}
FieldTypeDescription
bumpu8PDA bump seed for deterministic derivation
adminPubkeyCurrent owner who can modify settings
window_sizeu64Time window (seconds) for timestamp validation
range_signerPubkeyPublic key of the trusted backend signer

Settings accounts are Program Derived Addresses (PDAs) derived from the admin’s public key:

const [settingsPda, bump] = PublicKey.findProgramAddressSync(
[Buffer.from("settings"), adminPubkey.toBuffer()],
RANGE_PROGRAM_ID
);

Seeds: ["settings", admin_pubkey]

Any user can create a Settings account by calling initialize_settings:

import { buildInitializeSettingsInstruction } from './codama-ts-range-custom';
const instruction = await buildInitializeSettingsInstruction({
admin: walletPublicKey, // You become the admin
rangeSigner: backendPublicKey, // Your backend's signing key
windowSize: 60n, // 60 second validity window
});

Once created, you are the admin of this Settings account.

Only the current admin can update window_size and range_signer:

import { buildUpdateSettingsInstruction } from './codama-ts-range-custom';
const instruction = await buildUpdateSettingsInstruction({
admin: walletPublicKey,
windowSize: 120n, // Optional: new window size
rangeSigner: newBackendPublicKey, // Optional: new trusted signer
});

Admin ownership can be transferred to another pubkey:

import { buildTransferAdminInstruction } from './codama-ts-range-custom';
const instruction = await buildTransferAdminInstruction({
admin: currentAdminPublicKey,
newAdmin: newAdminPublicKey,
});

Important:

  • Only the current admin can transfer ownership
  • The PDA address stays the same (derived from original admin)
  • The admin field in the account changes to the new admin
  • Old admin immediately loses all control

The window_size determines how long a backend signature remains valid:

ValueUse CaseTrade-offs
30sHigh-security, fast networksLess tolerance for latency
60sRecommended defaultGood balance of security and usability
120sSlower networks, batch operationsWider replay attack window
300s+Very slow networks, offline signingHigher risk, not recommended

When calling verify_range, you must specify which Settings to use:

const instruction = await buildVerifyRangeInstruction({
signer: userPublicKey,
admin: settingsAdminPubkey, // Points to the Settings to use
signature: signature,
message: message,
});

The admin parameter determines which Settings account’s range_signer and window_size are used for verification.

  1. Secure your admin keypair - It controls your Settings
  2. Rotate range_signer periodically - Update via update_settings if your backend key is compromised
  3. Use smallest practical window_size - Minimize replay attack window
  4. Monitor Settings changes - Log update_settings and transfer_admin events
  5. Test on devnet first - Verify your configuration before mainnet