Bursa is a programmatic Cardano wallet and CLI tool
10K+
Programmatic Cardano Wallet
Bursa is two things that share one set of keys:
bursa command. That is what the rest of this README covers.ui/ and has
its own README.Bursa implements the following Cardano Improvement Proposals:
Start a Bursa wallet and interact with it using the Bursa API.
# Clone the Bursa repository
git clone [email protected]:blinklabs-io/bursa.git
cd bursa
# Start the Bursa API server
go run ./cmd/bursa api
Access API Swagger documentation on the default loopback listener: http://localhost:8080/swagger/index.html.
Signer replicas must share one PostgreSQL watermark database to preserve the
payload and operational-certificate counter guards across replicas. Configure
every replica with the same database and keep mode: enforce:
signer:
watermark:
type: postgres
mode: enforce
dsn_env: BURSA_SIGNER_WATERMARK_POSTGRES_DSN
Set the named environment variable to a pgx/libpq connection string. Remote connections should require server identity verification, for example:
postgres://[email protected]/bursa?sslmode=verify-full&sslrootcert=/etc/bursa/postgres-ca.pem
Supply the password through the process environment or another pgx-supported credential mechanism; do not store credentials in the YAML file. The database role needs permission to create the two watermark tables on first startup and to read and write them thereafter.
PostgreSQL replication and failover are external to Bursa. A failover endpoint
must preserve all committed rows and continue to present one authoritative
database; routing replicas to independent databases defeats the HA signing
guards. Bursa reports the signer unready while the database is unavailable and
signing in enforce mode fails closed.
Bursa does not automatically import watermark history from the in-memory or SQLite stores. Do not cut an active signer over to an empty PostgreSQL database: preserve or import both the payload and counter watermark rows during a controlled outage, or enable PostgreSQL before the affected keys sign for the first time.
The API listens on 127.0.0.1 by default. Set API_LISTEN_ADDRESS to an
explicit address such as 0.0.0.0 only when remote access is intended and
protected by TLS and JWT authentication. A non-loopback listener refuses to
start unless API_TLS_CERT_FILE / api.tls_cert_file and
API_TLS_KEY_FILE / api.tls_key_file identify a server certificate and
private key, and exactly one of these API trust sources is configured:
API_JWT_SECRET / api.jwt_secret: an HS256 secret of at least 32 bytes;
keep it in a deployment secret, not a committed config file.API_JWKS_URL / api.jwks_url: an HTTPS JWKS endpoint (plain HTTP is only
accepted for loopback development).API_JWT_ISSUER / api.jwt_issuer and API_JWT_AUDIENCE /
api.jwt_audience optionally constrain accepted bearer tokens. The secret,
signing, and mnemonic/address-derivation endpoints require an
Authorization: Bearer <JWT> header whenever API authentication is configured.
When Google Secret Manager persistence is enabled, the wallet
list, get, update, and delete endpoints use the same authentication
requirement and additionally require a subject listed in
API_JWT_ADMIN_SUBJECTS / api.jwt_admin_subjects. This is an explicit
global-administrator model; wallet names are not caller ownership boundaries.
Wallet creation is POST /api/wallet/create; wallet responses are marked
Cache-Control: no-store. A remote Swagger URL uses the same HTTPS listener,
for example https://wallet.example.com:8080/swagger/index.html. Plain HTTP
remains available only for loopback development when no TLS files are set.
api:
address: 0.0.0.0
port: 8080
tls_cert_file: /run/secrets/bursa-api-cert.pem
tls_key_file: /run/secrets/bursa-api-key.pem
jwks_url: https://identity.example.com/.well-known/jwks.json
jwt_issuer: https://identity.example.com
jwt_audience: bursa-api
jwt_admin_subjects:
- wallet-service-admin
The Bursa container listens on loopback by default. A Kubernetes Service must
set API_LISTEN_ADDRESS to the pod address (normally 0.0.0.0) and preserve
the API and metrics container/Service ports of 8080 and 8081. When Google
Secret Manager persistence is enabled, the deployment must inject
GOOGLE_PROJECT, GCP_KMS_RESOURCE_ID, and GCP_SECRET_PREFIX, provide
API_JWT_SECRET or API_JWKS_URL, provide at least one
API_JWT_ADMIN_SUBJECTS value, and mount the matching TLS certificate and key
as API_TLS_CERT_FILE and API_TLS_KEY_FILE. The API refuses a non-loopback
listener without both TLS files and authentication. These values belong in
the chart's secret/config wiring; do not place credentials in chart defaults.
For more information about Bursa CLI
go run ./cmd/bursa
Usage:
bursa [command]
Available Commands:
address Address utility commands
api Runs the api
cert Certificate generation commands
help Help about any command
key Key derivation commands
script Script commands for multi-signature operations
wallet Wallet commands
Flags:
-h, --help help for bursa
Use "bursa [command] --help" for more information about a command.
Derive individual keys from a BIP-39 mnemonic:
bursa key root --mnemonic "..." # Root extended private key
bursa key account --mnemonic "..." # Account key (CIP-1852)
bursa key payment --mnemonic "..." # Payment key (CIP-1852)
bursa key stake --mnemonic "..." # Stake key (CIP-1852)
bursa key policy --mnemonic "..." # Forging policy key (CIP-1855)
bursa key pool-cold --mnemonic "..." # Pool cold key (CIP-1853)
bursa key drep --mnemonic "..." # DRep key (CIP-0105)
bursa key committee-cold --mnemonic "..." # Committee cold key (CIP-0105)
bursa key committee-hot --mnemonic "..." # Committee hot key (CIP-0105)
bursa key vrf --mnemonic "..." # VRF key pair for block production
bursa key kes --mnemonic "..." # KES key pair for block production
Generate the Dijkstra-era BLS stake-pool key used by Leios and Peras. The
signing key is never printed. The signing and verification files use
cardano-cli-compatible BlsSigningKey_bls12-381-BLS-Signature-Minimal-Signature-Size
and BlsVerificationKey_bls12-381-BLS-Signature-Minimal-Signature-Size envelopes;
the JSON output contains the 96-byte public key and 48-byte proof of
possession required for pool registration.
bursa key bls --signing-key-file bls.skey \
--verification-key-file bls.vkey --output-file bls-registration.json
Back up the signing key like other pool credentials and plan rotation with the Dijkstra-era registration policy. Leios and Peras rotation policy remains protocol-dependent.
Mnemonic-derived keys are output in bech32 format with appropriate prefixes
(root_xsk, acct_xsk, addr_xsk, stake_xsk, policy_xsk, pool_xsk,
drep_xsk, cc_cold_xsk, cc_hot_xsk, vrf_sk, kes_sk).
Inspect Cardano addresses and display their components:
bursa address info <address> # Display address type, network, credentials, etc.
Supports all CIP-0019 address types including base, enterprise, pointer, reward, and legacy Byron addresses.
Generate certificates for stake pool operations and block production:
bursa cert op-cert --kes-vkey kes.vkey --cold-skey cold.skey \
--counter 0 --kes-period 200 --out node.cert # Operational certificate for block production
Operational certificates link KES keys to stake pool cold keys for secure block production.
Bursa generates key files that are fully compatible with cardano-cli. Use bursa wallet create or bursa wallet restore to generate key files, then use them directly with cardano-cli commands:
# Create a wallet with Bursa
bursa wallet create --name mywallet
# Use the generated keys with cardano-cli
cardano-cli address build \
--payment-verification-key-file mywallet/payment.vkey \
--stake-verification-key-file mywallet/stake.vkey \
--mainnet
This enables Bursa as a drop-in replacement for key generation while maintaining full compatibility with the Cardano ecosystem.
Keys derived through a Cardano HD path retain their existing public identity
when exported. Bursa therefore writes payment, stake, governance, policy,
multi-signature, Calidus, account, and root signing files as extended
Ed25519-BIP32 envelopes. The paired verification files remain the canonical
32-byte public identities used by addresses, credentials, and key hashes.
cardano-cli key verification-key emits an extended verification envelope for
an extended signing key; its first 32 bytes are the same paired public identity.
Pool-cold keys are the deliberate exception. Their canonical signing file is a standard, non-extended Ed25519 seed envelope, matching the pool verification key and pool ID. The optional extended pool-cold envelope expands that same seed and therefore implies the same pool identity. Bursa continues to accept valid non-extended envelopes produced from genuine Ed25519 seeds.
Signing files generated by older Bursa versions may declare a non-extended
type while containing the first 32 bytes of an HD key. Such a file does not
imply the verification key, address, credential, or pool identity that was
exported beside it. Do not fix one by changing only its type field. Regenerate
the signing and verification files together from the original mnemonic, then
compare the resulting address or key hash with the identity already in use
before signing. Bursa does not rewrite previously exported files or persisted
wallet items automatically.
Content type
Image
Digest
sha256:eaa76dbe3…
Size
47.6 MB
Last updated
14 days ago
docker pull blinklabs/bursa