Skip to content

Commit 5d47737

Browse files
authored
Merge pull request #1 from HerodotusDev/feat/atlantic-sdk
feat: atlantic sdk
2 parents 053002e + 166c11c commit 5d47737

38 files changed

Lines changed: 2411 additions & 1 deletion

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,5 @@ dist
111111

112112
# TernJS port file
113113
.tern-port
114+
115+
/docs

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Herodotus Dev Ltd
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,183 @@
1-
# atlantic-sdk
1+
# Atlantic SDK
2+
3+
TypeScript SDK and CLI for the Herodotus Atlantic API.
4+
5+
This package provides two surfaces:
6+
7+
- A typed SDK for direct Atlantic API calls and higher-level workflow helpers.
8+
- A JSON-first CLI that delegates to the SDK so terminal usage and library usage share behavior.
9+
10+
## Installation
11+
12+
```bash
13+
bun add @herodotus_dev/atlantic-sdk
14+
```
15+
16+
```bash
17+
npm install @herodotus_dev/atlantic-sdk
18+
```
19+
20+
Install the CLI globally:
21+
22+
```bash
23+
npm install -g @herodotus_dev/atlantic-sdk
24+
```
25+
26+
## SDK quickstart
27+
28+
```ts
29+
import { AtlanticClient, submitAndWait } from '@herodotus_dev/atlantic-sdk';
30+
31+
const client = new AtlanticClient({
32+
apiKey: process.env.ATLANTIC_API_KEY,
33+
});
34+
35+
const result = await submitAndWait(client, {
36+
declaredJobSize: 'S',
37+
pieFile: './pie.zip',
38+
});
39+
40+
console.log(result.atlanticQuery.id, result.atlanticQuery.status);
41+
```
42+
43+
## Direct API usage
44+
45+
```ts
46+
import { AtlanticClient } from '@herodotus_dev/atlantic-sdk';
47+
48+
const client = new AtlanticClient({
49+
apiKey: process.env.ATLANTIC_API_KEY,
50+
});
51+
52+
const submitted = await client.submitQuery({
53+
declaredJobSize: 'S',
54+
pieFile: './pie.zip',
55+
layout: 'dynamic',
56+
});
57+
58+
const details = await client.getQuery(submitted.atlanticQueryId);
59+
60+
console.log(details.atlanticQuery.status, details.metadataUrls);
61+
```
62+
63+
## CLI quickstart
64+
65+
```bash
66+
ATLANTIC_API_KEY=... bunx atlantic submit-query \
67+
--pie-file ./pie.zip \
68+
--declared-job-size S
69+
```
70+
71+
Every CLI command prints JSON so agents and shell scripts can chain outputs without scraping prose.
72+
73+
Common commands:
74+
75+
```bash
76+
atlantic get-query-details <query-id>
77+
atlantic get-my-queries --limit 20 --offset 0
78+
atlantic retry-if-retriable <query-id>
79+
atlantic list-buckets
80+
atlantic create-bucket --aggregator-version STONE
81+
atlantic close-bucket <bucket-id>
82+
```
83+
84+
## SDK reference
85+
86+
### Client
87+
88+
- `new AtlanticClient(options)`: Creates a typed Atlantic API client. Configure `baseUrl`, `apiKey`, optional `fetch`, and optional x402 `paymentAdapter`.
89+
- `healthCheck()`: Checks whether Atlantic is reachable. Returns `{ alive }`.
90+
- `submitQuery(input, options)`: Submits a proving query. Accepts program/input/PIE/proof files, Cairo options, result target, declared job size, dedup/external IDs, and bucket fields. Returns the durable `atlanticQueryId` and optional x402 settlement data.
91+
- `getQuery(atlanticQueryId)`: Fetches query details plus metadata URLs.
92+
- `getQueryByDedupId(dedupId)`: Fetches a query by dedup ID. Use API-key flow; anonymous x402 does not support dedup IDs.
93+
- `listQueries({ limit, offset })`: Lists submitted queries with pagination.
94+
- `getQueryStats()`: Fetches query statistics for the configured API key.
95+
- `getQueryJobs(atlanticQueryId)`: Fetches job lifecycle details for a query.
96+
- `retryQuery(atlanticQueryId)`: Requests an API retry for a failed query. Branch on structured errors for wrong state, max retries, not found, and forbidden outcomes.
97+
- `listBuckets({ limit, offset })`: Lists Applicative Recursion buckets.
98+
- `createBucket(input)`: Creates an Applicative Recursion bucket.
99+
- `getBucket(bucketId)`: Fetches a bucket and associated queries.
100+
- `closeBucket(bucketId)`: Closes a bucket.
101+
102+
### Workflow helpers
103+
104+
- `submitAndReturnId(client, input)`: Submit and return the query ID immediately.
105+
- `waitForQuery(client, atlanticQueryId, options)`: Poll until terminal status or timeout. Returns observed statuses and final query details.
106+
- `submitAndWait(client, input, options)`: Submit and wait in one helper while preserving the original submit result.
107+
- `retryIfRetriable(client, atlanticQueryId)`: Fetches current query details and retries only when the query is failed and retriable.
108+
- `getQueryWithJobs(client, atlanticQueryId)`: Fetches query details and query jobs together.
109+
- `submitToBucket(client, input)`: Submits a query into an existing bucket with explicit job index.
110+
- `createBucketAndSubmit(client, input)`: Creates a bucket and submits indexed queries into it.
111+
112+
## x402
113+
114+
The SDK supports Atlantic's x402 flow through a caller-provided payment adapter. It waits for a real `402` challenge, signs the server-provided payment requirement, retries the original submit request with `PAYMENT-SIGNATURE`, and parses `PAYMENT-RESPONSE`.
115+
116+
### Private-key adapter
117+
118+
For server-side scripts, CI, or agents with a dedicated payment key, use the built-in private-key adapter:
119+
120+
```ts
121+
import { AtlanticClient, createPrivateKeyPaymentAdapter } from '@herodotus_dev/atlantic-sdk';
122+
123+
const paymentAdapter = createPrivateKeyPaymentAdapter({
124+
privateKey: process.env.WALLET_PRIVATE_KEY as `0x${string}`,
125+
});
126+
127+
const client = new AtlanticClient({
128+
apiKey: process.env.ATLANTIC_API_KEY,
129+
paymentAdapter,
130+
});
131+
132+
const result = await client.submitQuery({
133+
declaredJobSize: 'S',
134+
pieFile: './pie.zip',
135+
});
136+
137+
console.log(result.atlanticQueryId, result.payment);
138+
```
139+
140+
The adapter reads the x402 requirement returned by Atlantic, verifies that `accepts[].network` is Base mainnet (`eip155:8453`) and `accepts[].extra.name` is `USD Coin`, signs an EIP-3009 `transferWithAuthorization`, and returns the `PAYMENT-SIGNATURE` payload.
141+
142+
### Custom wallet adapter
143+
144+
Use a custom adapter when signing should happen through another wallet, custody service, browser wallet, or agent wallet.
145+
146+
```ts
147+
import {
148+
AtlanticClient,
149+
type X402PaymentAdapter,
150+
type X402PaymentPayload,
151+
} from '@herodotus_dev/atlantic-sdk';
152+
153+
const paymentAdapter: X402PaymentAdapter = {
154+
async createPayment({ requirement }): Promise<X402PaymentPayload> {
155+
const authorization = {
156+
from: '0xYourWallet',
157+
to: requirement.payTo,
158+
value: requirement.amount,
159+
validAfter: '0',
160+
validBefore: String(Math.floor(Date.now() / 1000) + (requirement.maxTimeoutSeconds ?? 300)),
161+
nonce: '0x...32-bytes',
162+
};
163+
164+
const signature = await signTransferWithAuthorization({
165+
requirement,
166+
authorization,
167+
});
168+
169+
return {
170+
x402Version: 2,
171+
accepted: requirement,
172+
payload: {
173+
signature,
174+
authorization,
175+
},
176+
};
177+
},
178+
};
179+
180+
const client = new AtlanticClient({ paymentAdapter });
181+
```
182+
183+
Preserve the `requirement` object from `accepts[]` verbatim. Atlantic currently accepts USD Coin on Base mainnet; do not hardcode `payTo`, `asset`, `network`, or `amount`, because Atlantic may rotate the receiver or change the required payment amount.

bun.lock

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/buckets.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { AtlanticClient, createBucketAndSubmit } from '../src';
2+
3+
const client = new AtlanticClient(
4+
process.env.ATLANTIC_API_KEY ? { apiKey: process.env.ATLANTIC_API_KEY } : {},
5+
);
6+
7+
const result = await createBucketAndSubmit(client, {
8+
bucket: {
9+
aggregatorVersion: 'STONE',
10+
},
11+
queries: [
12+
{
13+
declaredJobSize: 'S',
14+
pieFile: './pie-0.zip',
15+
},
16+
{
17+
declaredJobSize: 'S',
18+
pieFile: './pie-1.zip',
19+
},
20+
],
21+
});
22+
23+
console.log(result.bucket.atlanticBucket.id, result.submissions.map((submission) => submission.atlanticQueryId));

examples/submit-and-wait.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { AtlanticClient, submitAndWait } from '../src';
2+
3+
const client = new AtlanticClient(
4+
process.env.ATLANTIC_API_KEY ? { apiKey: process.env.ATLANTIC_API_KEY } : {},
5+
);
6+
7+
const result = await submitAndWait(
8+
client,
9+
{
10+
declaredJobSize: 'S',
11+
pieFile: './pie.zip',
12+
},
13+
{
14+
intervalMs: 5_000,
15+
timeoutMs: 10 * 60_000,
16+
},
17+
);
18+
19+
console.log(result.atlanticQuery.id, result.atlanticQuery.status);

examples/submit-query.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { AtlanticClient } from '../src';
2+
3+
const client = new AtlanticClient(
4+
process.env.ATLANTIC_API_KEY ? { apiKey: process.env.ATLANTIC_API_KEY } : {},
5+
);
6+
7+
const result = await client.submitQuery({
8+
declaredJobSize: 'S',
9+
pieFile: './pie.zip',
10+
layout: 'dynamic',
11+
});
12+
13+
console.log(result.atlanticQueryId);

examples/x402-submit.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { AtlanticClient, type X402PaymentAdapter } from '../src';
2+
3+
const paymentAdapter: X402PaymentAdapter = {
4+
async createPayment({ requirement }) {
5+
// Sign EIP-3009 using your wallet implementation. The requirement is Atlantic-provided
6+
// and must be preserved verbatim: do not hardcode payTo, asset, network, or amount.
7+
throw new Error(`Connect a wallet signer for ${requirement.network}`);
8+
},
9+
};
10+
11+
const client = new AtlanticClient({ paymentAdapter });
12+
13+
const result = await client.submitQuery(
14+
{
15+
declaredJobSize: 'S',
16+
pieFile: './pie.zip',
17+
},
18+
{
19+
anonymousPayment: true,
20+
},
21+
);
22+
23+
console.log(result.atlanticQueryId, result.payment);

0 commit comments

Comments
 (0)