@acta-team/did-stellar
v0.1.0
Published
Official TypeScript SDK for the did:stellar v0.1 method. DIF did-resolver compatible, prepare/submit XDR helpers, and W3C-compliant DID Document construction.
Readme
@acta-team/did-stellar
Official TypeScript SDK for the did:stellar v0.1 method.
| | |
|---|---|
| DID method | did:stellar |
| Networks | mainnet, testnet |
| Testnet registry | CB7ATU7SF5QUKJMSULJDJVWJZVDXC23HTZX6NFUDTSFPVT6MA575NNZJ |
| Spec | v0.1 |
| DIF compatibility | Drop-in driver for did-resolver |
What's inside
- Resolver —
resolveDidStellar(did)reads the on-chainDidRecordvia Stellar RPC and returns a W3C DID Document. - DIF driver —
getResolver()plugs straight intonew Resolver({...})fromdid-resolver. - Prepare / submit — four mutation helpers
(
prepareRegisterDidXdr,prepareUpdateDidXdr,prepareTransferControllerXdr,prepareDeactivateDidXdr) that build unsigned XDRs, plussubmitSignedXdrto deliver them. - Proof of control — JCS-canonicalised challenges,
buildChallenge,verifyProofOfControl(Ed25519, ±5 min replay window). - Optional HTTP client —
ActaDidClientfor integrators that prefer talking todid-stellar-apirather than wiring a Stellar RPC themselves. - React hook —
useDid()(subpath@acta-team/did-stellar/hooks) for browser apps. - Typed errors — every failure is a
DidErrorwith a stablecodestring (did_not_found,version_mismatch,signature_invalid, …).
The SDK has zero ACTA-hosted dependencies in its hot path. You can
resolve any did:stellar:... with just a Stellar RPC URL.
Install
npm install @acta-team/did-stellar
# peer (only if you use the ./hooks entrypoint):
npm install reactQuickstart — resolve
import { resolveDidStellar } from '@acta-team/did-stellar';
const { didDocument, didDocumentMetadata } = await resolveDidStellar(
'did:stellar:testnet:aaaqeayeaudaocajbifqydiob4'
);
console.log(didDocument);Defaults: SDF public RPC (https://soroban-testnet.stellar.org) + the
canonical registry contract ID. Override either via { rpcUrl,
registryContractId }.
Quickstart — DIF driver
import { Resolver } from 'did-resolver';
import { getResolver } from '@acta-team/did-stellar/resolver';
const resolver = new Resolver({ ...getResolver() });
const result = await resolver.resolve('did:stellar:testnet:aaaqeayeaudaocajbifqydiob4');Quickstart — register a DID
import {
generateDidId,
buildDidStellar,
prepareRegisterDidXdr,
submitSignedXdr,
} from '@acta-team/did-stellar';
const didId = generateDidId();
const did = buildDidStellar('testnet', didId);
const prepared = await prepareRegisterDidXdr({
did,
sourcePublicKey: 'G...',
record: {
controller: 'G...',
authentication: [{ publicKeyMultibase: 'z6Mk...' }],
assertionMethod: [{ publicKeyMultibase: 'z6Mk...' }],
keyAgreement: [],
services: [],
},
});
// Sign with Freighter / Albedo / Hana / server-side key ...
const signedXdr = await signWithWallet(prepared.xdr, {
networkPassphrase: prepared.networkPassphrase,
});
const { txId } = await submitSignedXdr({
signedXdr,
network: prepared.network,
});Quickstart — proof of control
import {
buildChallenge,
generateNonce,
jcsCanonicalize,
resolveDidStellar,
verifyProofOfControl,
} from '@acta-team/did-stellar';
// Verifier issues the challenge:
const challenge = buildChallenge({
did: 'did:stellar:testnet:aaaqeayeaudaocajbifqydiob4',
domain: 'verifier.example.com',
nonce: generateNonce(),
});
const message = jcsCanonicalize(challenge);
// → present `challenge` + `message` to the wallet for Ed25519 signing.
// Wallet returns signature (base64url, no padding):
const signature = '...';
// Verifier:
const { didDocument } = await resolveDidStellar(challenge.did);
const result = await verifyProofOfControl({
challenge,
signature,
didDocument: didDocument!,
expectedDomain: 'verifier.example.com',
isNonceFresh: (nonce, did) => myRedis.setnx(`pc:${did}:${nonce}`, '1', 'EX', 300),
});
if (!result.valid) throw result.reason;Error handling
Every SDK function rejects with DidError. Branch on code:
import { DidError } from '@acta-team/did-stellar';
try {
await prepareUpdateDidXdr({ ... });
} catch (err) {
if (DidError.is(err) && err.code === 'version_mismatch') {
// re-read the record, rebuild, retry
} else {
throw err;
}
}See src/errors.ts for the full DidErrorCode union.
Spec conformance
The package ships vectors A.1–A.3 from
the spec and pnpm test verifies the DID Document builder produces
bit-identical output. Adding new functionality without updating the
spec is intentionally a CI failure surface.
License
MIT
