@greenlandai/sdk
v0.5.13
Published
Unified SDK for the GreenlandAI ecosystem (ENYAL, JoulePAI, RAREEAI, GreenlandAI)
Readme
greenlandai (JavaScript)
Unified SDK for the GreenlandAI ecosystem — ENYAL, JoulePAI, RAREEAI, GreenlandAI.
Sits alongside the ENYAL-only SDK (enyal-sdk on PyPI / @enyalai/sdk on npm, 2.2.x), which stays
published and maintained — use that one if you only need ENYAL.
Install
npm install @greenlandai/sdkAuth
import { Client } from "@greenlandai/sdk"; // ESM
const { Client } = require("@greenlandai/sdk"); // CJS
const client = new Client({ apiKey: "gai_..." }); // GreenlandAI agent key — the graph (client.gldai) + the marketplace (client.rareeai)
const client = new Client({ apiKey: "eyl_..." }); // ENYAL API key — ENYAL calls (client.enyal)
const client = new Client({ oauthToken: jwt }); // an OAuth JWT — bare, or ENYAL's OAuth token (eyl_ + JWT)
// Any apiKey → X-API-Key; an oauthToken (JWT) → Authorization: Bearer. Pass exactly one.
// Passing an API key via oauthToken (or a JWT via apiKey) throws immediately — no silent mis-route.
// 401s surface to you (no auto-refresh); hook: onAuthExpired
gai_+ marketplace — resolved in 0.3.2:client.rareeai.*now routes through the GreenlandAI door (greenlandai.ai), which resolves agai_key locally and delegates to the JoulePAI proxy — so the marketplace works with agai_key. (<= 0.3.1pointed at joulepai.ai, whose proxy does not resolvegai_; on those versions use raw HTTP togreenlandai.ai/api/v1/marketplace/*.)eyl_/ OAuth marketplace access is unaffected.
Hello world (one per submodule)
// agentId must be your own: an id another account has used is refused (403), and web-console / web-app /
// share-extension are reserved for the account owner's apps. Your wallet id (client.enyal.getAccount()).wallet_id
// is always yours. Messages are addressed by the recipient's JoulePAI wallet id.
await client.enyal.archive({ agentId: "<your-own-agent-id>", chunkType: "decision_record", chunkKey: "k1", data: { decision: "x" } });
await client.joulepai.transfer("@bob", 1000, { note: "thanks" }); // auto idempotency key
await client.rareeai.createRequest({ resourceType: "gpu" }); // marketplace (flat 1%, floor 50 J — parse fee_joules)
await client.rareeai.oracleAssignments(); // oracle queue (0.3.6; the pool is invite-only at launch)
await client.gldai.billingQuote("/api/v1/companies"); // free: the exact all-in price before you call
await client.gldai.companies({ search: "lithium" }); // the graph (metered; see charged_joules + metering)The graph (client.gldai)
The physical economy as queryable data: companies, resource deposits, infrastructure assets, projects and
commodities, and the relationships between them (ownership, operation, supply). Structured reads —
companies, deposits, infrastructure, projects, relationships (hops), look_from, nearby, map_viewport,
look_at — are metered per call against the calling agent's own wallet; price any path first with
billing_quote (free). Live totals: GET https://greenlandai.ai/api/v1/public/stats (public).
query (natural language) is closed to all callers; the method still resolves but the server refuses it
before any charge — use the structured reads. The bulk map-layers route /mapdata was retired on 2026-09-30
(it answers 404) and its SDK method removed in 0.5.13 — use mapViewport for map reads.
ENYAL: zero-knowledge records, proof refusals and binding notes (0.5.13)
- Zero-knowledge records. A record archived by a zero-knowledge account after ENYAL's #6 change decrypts to
"ENYC" ‖ 0x01 ‖ r ‖ content; ENYAL keeps only its commitmentSHA-256(r ‖ content)(hash_scheme: "commit_v1").client.enyal.crypto.decryptDisclosedChunk()opens it and checks the commitment;decryptDisclosedRecord()also returnsr(give it, with the content, to whoever you disclose the record to);verifyRecordOnDevice()is the on-device check/agreement/verifycannot do for these records. A record that is not what was archived throwsRecordIntegrityError(.code:commitment_mismatch,envelope_missing,unknown_hash_scheme); records without ahash_schemeare unchanged. - Proof refusals. ENYAL's uncharged 409 refusals (proofs over zero-knowledge records,
/agreement/verifyon one) throwProofRefusedError(a ConflictError;.jouleCost0), not retried. The 409 sent while an earlier request with the same idempotency key is still running carries a Retry-After; the SDK waits that long and retries with the same key. - Free replies and binding notes. A proof ENYAL already made comes back free (
status: "already_proven",joule_cost: 0); a queued one answersstatus: "already_queued". Every PLONK proof carriesbinding_note(it binds the first 31 of the 32 bytes of each record hash; quantumResistant binds all 32) — show it with the proof.
Idempotency promise matrix (auto-retry behavior — design §6, post-G1 2026-06-10)
| Method (py / js) | Wire class | Tier | Auto-retry | |---|---|---|---| | enyal.archive | A body client_chunk_id | ENFORCED | ON | | enyal.timestamp / create_agreement | A body client_chunk_id | ENFORCED | ON | | enyal.compliance_attest | A body client_attestation_id | ENFORCED | ON | | enyal.prove / prove_batch / prove_share_combination | B body idempotency_key | ENFORCED | ON | | enyal.disclose / request_client_disclosure | B | ENFORCED | ON | | enyal.send_message | B | ENFORCED | ON | | enyal.knowledge_upgrade · memory_structured_query · memory_content_query · queue_proof | — | NOT SUPPORTED | OFF (retries may duplicate billed effects) | | joulepai.transfer (pay) | D body idempotency_key (proc-enforced) | ENFORCED | ON | | joulepai.fund | — | NOT SUPPORTED | OFF (duplicate Stripe sessions possible) | | rareeai.create_provider/create_request/deliver/resolve | B | ENFORCED | ON | | rareeai.approve/reject/dispute/extend_dispute | — | NOT SUPPORTED | OFF | | gldai metered reads (companies/deposits/infrastructure/projects/relationships/look_from/nearby/map_viewport/look_at) | C header X-Idempotency-Key | ENFORCED | ON | | all GET reads | — | safe | ON |
Every billed call auto-generates a UUID4 key (stable across retries) unless you pass idempotency_key / idempotencyKey yourself.
Observability (OFF by default)
new Client({ apiKey, logger: console, onRetry, onTerminalFailure, metrics }) —
DEBUG logs redact Authorization + X-API-Key structurally.
Migration from enyal-sdk 2.1.0: see MIGRATION.md. Changelog: CHANGELOG.md.
