Research Preview — The SDK is under active development.
Compute module
The ComputeModule provides geospatial operations designed to run in a trusted execution environment, so the computation can be verified independently. Each operation returns a signed result (a delegated attestation that can be submitted to EAS). Note that the TEE makes the computation verifiable, not the input locations truthful, and continuous attested operation is not yet funded — see the trust model .
import { AstralSDK } from '@decentralized-geo/astral-sdk' ;
const astral = new AstralSDK ({
chainId: 84532 ,
signer: wallet ,
apiUrl: 'https://staging-api.astral.global'
});
// Access via astral.compute
astral . compute . distance ( from , to , options );
astral . compute . area ( geometry , options );
astral . compute . length ( geometry , options );
astral . compute . contains ( container , containee , options );
astral . compute . within ( geometry , target , radius , options );
astral . compute . intersects ( a , b , options );
astral . compute . submit ( input );
astral . compute . estimate ( attestation );
astral . compute . health ();
All compute methods accept flexible input types:
type Input =
| string // Onchain attestation UID
| GeoJSON . Geometry // Raw GeoJSON geometry
| { uid : string } // Onchain reference
| { uid : string ; uri : string } // Offchain reference
| { verifiedProof : VerifiedLocationProof } // Verified proof input
Examples
// Using attestation UID
const result = await astral . compute . distance (
'0x1234...abcd' ,
'0x5678...efgh' ,
options
);
// Using raw GeoJSON
const result = await astral . compute . distance (
{ type: 'Point' , coordinates: [ 2.2945 , 48.8584 ] },
{ type: 'Point' , coordinates: [ - 0.1276 , 51.5074 ] },
options
);
// Mixing UIDs and GeoJSON
const result = await astral . compute . contains (
boundaryUID ,
{ type: 'Point' , coordinates: [ lon , lat ] },
options
);
Raw GeoJSON is not verified for authenticity. The inputRefs will contain a keccak256 hash of the geometry rather than a UID.
Compute options
All spatial methods require options:
interface ComputeOptions {
schema : string ; // Required: EAS schema UID for the result
recipient ?: string ; // Optional: recipient address (defaults to zero address)
}
Schema requirements
Use the correct schema type — Compute operations encode data differently than location attestations. Using the wrong schema UID causes a data/schema mismatch where the attestation is stored but cannot be decoded correctly.
Operation Required schema type distance, area, lengthNumericPolicyAttestation contains, within, intersectsBooleanPolicyAttestation
// CORRECT: Boolean operation with boolean schema
await compute . within ( point , target , 500 , {
schema: BOOLEAN_POLICY_SCHEMA_UID
});
// WRONG: Boolean operation with location schema
await compute . within ( point , target , 500 , {
schema: LOCATION_SCHEMA_UID
});
// The attestation is created but data is unreadable!
See Schemas for schema definitions and default UIDs.
Numeric operations
distance()
Calculate the geodesic distance between two geometries.
astral . compute . distance (
from : Input ,
to : Input ,
options : ComputeOptions
): Promise < NumericComputeResult >
const result = await astral . compute . distance (
userLocationUID ,
landmarkUID ,
{ schema: SCHEMA_UID }
);
console . log ( result . result ); // 523.45
console . log ( result . units ); // 'meters'
console . log ( result . operation ); // 'distance'
area()
Calculate the area of a polygon.
astral . compute . area (
geometry : Input ,
options : ComputeOptions
): Promise < NumericComputeResult >
const result = await astral . compute . area (
propertyBoundaryUID ,
{ schema: SCHEMA_UID }
);
console . log ( result . result ); // 5432.10
console . log ( result . units ); // 'square_meters'
length()
Calculate the length of a LineString.
astral . compute . length (
geometry : Input ,
options : ComputeOptions
): Promise < NumericComputeResult >
const result = await astral . compute . length (
routeUID ,
{ schema: SCHEMA_UID }
);
console . log ( result . result ); // 2345.67
console . log ( result . units ); // 'meters'
Boolean operations
contains()
Check if a container geometry contains another geometry.
astral . compute . contains (
container : Input ,
containee : Input ,
options : ComputeOptions
): Promise < BooleanComputeResult >
const result = await astral . compute . contains (
geofencePolygonUID ,
userLocationUID ,
{ schema: SCHEMA_UID }
);
if ( result . result ) {
console . log ( 'User is inside the geofence!' );
await astral . compute . submit ( result . delegatedAttestation );
}
within()
Check if a geometry is within a specified radius of a target.
astral . compute . within (
geometry : Input ,
target : Input ,
radius : number , // meters
options : ComputeOptions
): Promise < BooleanComputeResult >
const result = await astral . compute . within (
userLocationUID ,
landmarkUID ,
500 ,
{ schema: SCHEMA_UID , recipient: userAddress }
);
if ( result . result ) {
console . log ( 'User is within 500m of the landmark!' );
await astral . compute . submit ( result . delegatedAttestation );
}
intersects()
Check if two geometries intersect.
astral . compute . intersects (
a : Input ,
b : Input ,
options : ComputeOptions
): Promise < BooleanComputeResult >
const result = await astral . compute . intersects (
territory1UID ,
territory2UID ,
{ schema: SCHEMA_UID }
);
console . log ( 'Territories overlap:' , result . result );
Submission methods
submit()
Submit a delegated attestation to EAS. Accepts two input formats:
// Format 1: DelegatedAttestation directly
astral . compute . submit (
attestation : DelegatedAttestation
): Promise < AttestationResult >
// Format 2: Object with both attestation types
astral . compute . submit (
input : {
attestation: AttestationObject ;
delegatedAttestation : DelegatedAttestationObject ;
}
): Promise < AttestationResult >
const result = await astral . compute . within (
userLocationUID , landmarkUID , 500 , { schema: SCHEMA_UID }
);
if ( result . result ) {
const submission = await astral . compute . submit ( result . delegatedAttestation );
console . log ( 'Attestation UID:' , submission . uid );
}
estimate()
Estimate gas for attestation submission.
astral . compute . estimate (
attestation : DelegatedAttestation
): Promise < bigint >
const gas = await astral . compute . estimate ( result . delegatedAttestation );
console . log ( 'Estimated gas:' , gas . toString ());
if ( gas < 200000 n ) {
await astral . compute . submit ( result . delegatedAttestation );
}
health()
Check the compute service health status.
astral . compute . health (): Promise < HealthStatus >
const status = await astral . compute . health ();
console . log ( 'Service status:' , status . status );
console . log ( 'Database status:' , status . database );
Return types
NumericComputeResult
interface NumericComputeResult {
result : number ;
units : string ; // 'meters' or 'square_meters'
operation : string ; // 'distance', 'area', or 'length'
timestamp : number ;
inputRefs : string []; // UIDs or hashes of inputs
attestation : AttestationObject ;
delegatedAttestation : DelegatedAttestationObject ;
proofInputs ?: ProofInputContext []; // When using VerifiedLocationProof inputs
}
BooleanComputeResult
interface BooleanComputeResult {
result : boolean ;
operation : string ; // 'contains', 'within', or 'intersects'
timestamp : number ;
inputRefs : string [];
attestation : AttestationObject ;
delegatedAttestation : DelegatedAttestationObject ;
proofInputs ?: ProofInputContext [];
}
DelegatedAttestation
interface DelegatedAttestation {
message : {
schema : string ;
recipient : string ;
expirationTime : bigint ;
revocable : boolean ;
refUID : string ;
data : string ;
value : bigint ;
nonce : bigint ;
deadline : bigint ;
};
signature : {
v : number ;
r : string ;
s : string ;
};
attester : string ;
}
How delegated attestations work
Step Who Does what 1 Developer Calls compute.within() or other method 2 Astral API Runs computation in TEE, signs attestation 3 Developer Receives signed delegatedAttestation 4 Developer Calls compute.submit() (pays gas) 5 EAS Verifies signature, records Astral as attester 6 Resolver Checks attestation.attester == astralSigner
This pattern means:
Astral does not need to pay gas for every computation
Developers control when/whether to submit onchain
Smart contracts can verify attestations came from Astral
Signature expiry
Delegated attestation signatures have a deadline:
const result = await astral . compute . within ( uid1 , uid2 , 500 , options );
const deadline = result . delegatedAttestation . message . deadline ;
const now = BigInt ( Math . floor ( Date . now () / 1000 ));
if ( now < deadline ) {
await astral . compute . submit ( result . delegatedAttestation );
} else {
// Signature expired — request new computation
const newResult = await astral . compute . within ( uid1 , uid2 , 500 , options );
await astral . compute . submit ( newResult . delegatedAttestation );
}
Complete example
import { AstralSDK } from '@decentralized-geo/astral-sdk' ;
import { ethers } from 'ethers' ;
const provider = new ethers . JsonRpcProvider ( 'https://sepolia.base.org' );
const wallet = new ethers . Wallet ( process . env . PRIVATE_KEY , provider );
const astral = new AstralSDK ({
chainId: 84532 ,
signer: wallet ,
apiUrl: 'https://staging-api.astral.global'
});
// Create a location attestation
const location = await astral . location . onchain . create ({
location: { type: 'Point' , coordinates: [ 2.2951 , 48.8580 ] },
memo: 'Near Eiffel Tower'
});
// Check proximity to a landmark
const LANDMARK_UID = '0x...' ;
const SCHEMA_UID = '0x...' ;
const result = await astral . compute . within (
location . uid ,
LANDMARK_UID ,
500 ,
{ schema: SCHEMA_UID , recipient: wallet . address }
);
console . log ( 'Within 500m:' , result . result );
// Estimate gas and submit if check passed
if ( result . result ) {
const gas = await astral . compute . estimate ( result . delegatedAttestation );
console . log ( 'Estimated gas:' , gas . toString ());
const submission = await astral . compute . submit ( result . delegatedAttestation );
console . log ( 'Attestation submitted:' , submission . uid );
}
Next: EAS integration Learn how the SDK integrates with EAS