Skip to main content
Research preview — The stamps module is under active development.

Stamps module

The StampsModule orchestrates evidence collection, stamp creation, signing, and verification across registered plugins. Each stamp represents evidence from a single proof-of-location system.
import { AstralSDK } from '@decentralized-geo/astral-sdk';

const astral = new AstralSDK({
  chainId: 84532,
  signer: wallet,
  apiUrl: 'https://api.astral.global'
});

// Access via astral.stamps
astral.stamps.collect(options);
astral.stamps.create(options, signals);
astral.stamps.sign(options, stamp, signer);
astral.stamps.verify(stamp, options);
For conceptual background, see Location Proofs.

stamps.collect()

Collect raw signals from registered plugins.
astral.stamps.collect(
  options?: StampsCollectOptions
): Promise<RawSignals[]>
Returns an array of RawSignals — one per plugin that implements collect(). Not all plugins support collection; ProofMode, for example, collects on-device via its mobile app rather than through the SDK.

Parameters

ParameterTypeRequiredDescription
options.pluginsstring[]NoSubset of registered plugins to collect from. Omit to collect from all that implement collect().
options.timeoutnumberNoCollection timeout in milliseconds
options.signalsstring[]NoSpecific signals to request (plugin-dependent)

Example

// Collect from all plugins that support it
const allSignals = await astral.stamps.collect();
// Returns: [{ plugin: 'mock', timestamp: ..., data: {...} }, ...]

// Collect from specific plugins
const signals = await astral.stamps.collect({
  plugins: ['mock'],
  timeout: 5000
});

stamps.create()

Process raw signals into an unsigned stamp using a specific plugin.
astral.stamps.create(
  options: StampsCreateOptions,
  signals: RawSignals
): Promise<UnsignedLocationStamp>

Parameters

ParameterTypeRequiredDescription
options.pluginstringYesName of the plugin to use for stamp creation
signalsRawSignalsYesRaw signals from collect() or external source

Example

const signals = (await astral.stamps.collect({ plugins: ['mock'] }))[0];

const unsigned = await astral.stamps.create(
  { plugin: 'mock' },
  signals
);

console.log(unsigned.location);          // GeoJSON Point
console.log(unsigned.temporalFootprint); // { start, end }
console.log(unsigned.plugin);            // 'mock'

stamps.sign()

Sign an unsigned stamp with a key.
astral.stamps.sign(
  options: StampsSignOptions,
  stamp: UnsignedLocationStamp,
  signer: StampSigner
): Promise<LocationStamp>

Parameters

ParameterTypeRequiredDescription
options.pluginstringYesName of the plugin
stampUnsignedLocationStampYesOutput from create()
signerStampSignerYesSigning key

StampSigner

interface StampSigner {
  algorithm: string;           // e.g., "secp256k1", "ed25519"
  signer: SubjectIdentifier;   // { scheme, value }
  sign(data: string): Promise<string>;
}

Example

const stamp = await astral.stamps.sign(
  { plugin: 'mock' },
  unsigned,
  {
    algorithm: 'secp256k1',
    signer: { scheme: 'eth-address', value: wallet.address },
    sign: (data) => wallet.signMessage(data)
  }
);
// stamp now has a signatures array and is ready for proofs

stamps.verify()

Verify a stamp’s internal validity.
astral.stamps.verify(
  stamp: LocationStamp,
  options?: { hosted?: boolean }
): Promise<StampVerificationResult>

Parameters

ParameterTypeRequiredDescription
stampLocationStampYesThe stamp to verify
options.hostedbooleanNoIf true, send to Astral API for verification. Default: local verification via plugin.

Example

// Local verification (delegates to the stamp's plugin)
const result = await astral.stamps.verify(stamp);

console.log(result.valid);              // true
console.log(result.signaturesValid);    // true
console.log(result.structureValid);     // true
console.log(result.signalsConsistent);  // true
console.log(result.details);            // plugin-specific details

// Hosted verification
const hosted = await astral.stamps.verify(stamp, { hosted: true });

Types

RawSignals

interface RawSignals {
  plugin: string;              // Plugin that produced these signals
  timestamp: number;           // Unix seconds
  data: Record<string, unknown>;  // Plugin-specific signal data
}

UnsignedLocationStamp

interface UnsignedLocationStamp {
  lpVersion: string;           // e.g., "0.2"
  locationType: string;        // e.g., "geojson-point"
  location: LocationData;      // GeoJSON geometry or string
  srs: string;                 // Spatial reference system (e.g., "EPSG:4326")
  temporalFootprint: TimeBounds; // { start, end } — Unix seconds
  plugin: string;              // Plugin name
  pluginVersion: string;       // Semver
  signals: Record<string, unknown>; // Plugin-specific data
}

LocationStamp

interface LocationStamp extends UnsignedLocationStamp {
  signatures: Signature[];     // One or more signatures
}

interface Signature {
  signer: SubjectIdentifier;   // { scheme, value }
  algorithm: string;           // e.g., "secp256k1", "pgp"
  value: string;               // Hex or base64 encoded
  timestamp: number;           // Unix seconds
}

StampVerificationResult

interface StampVerificationResult {
  valid: boolean;
  signaturesValid: boolean;
  structureValid: boolean;
  signalsConsistent: boolean;
  details: Record<string, unknown>;  // Plugin-specific verification details
}

StampsCollectOptions

interface StampsCollectOptions {
  plugins?: string[];          // Subset of plugins, or all
  timeout?: number;            // Milliseconds
  signals?: string[];          // Specific signals to request
}

StampsCreateOptions

interface StampsCreateOptions {
  plugin: string;              // Which plugin to use
}

StampsSignOptions

interface StampsSignOptions {
  plugin: string;              // Which plugin to use
}

Complete example

import { AstralSDK, MockPlugin } from '@decentralized-geo/astral-sdk';
import { ethers } from 'ethers';

// Setup
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY);

const astral = new AstralSDK({
  chainId: 84532,
  signer: wallet,
  apiUrl: 'https://api.astral.global'
});

// Register a plugin
astral.plugins.register(new MockPlugin({
  lat: 37.7749,
  lon: -122.4194,
  accuracy: 10
}));

// 1. Collect signals
const signals = (await astral.stamps.collect({ plugins: ['mock'] }))[0];

// 2. Create unsigned stamp
const unsigned = await astral.stamps.create({ plugin: 'mock' }, signals);

// 3. Sign the stamp
const stamp = await astral.stamps.sign(
  { plugin: 'mock' },
  unsigned,
  {
    algorithm: 'secp256k1',
    signer: { scheme: 'eth-address', value: wallet.address },
    sign: (data) => wallet.signMessage(data)
  }
);

// 4. Verify
const result = await astral.stamps.verify(stamp);
console.log('Valid:', result.valid);

// stamp is now ready to include in a location proof

Next: Location proofs

Bundle stamps into proofs and verify with CredibilityVector