Skip to content

Commit 8934b33

Browse files
committed
fix(anchor-sdk): add missing LICENSE/README, align version for first publish
package.json declared "files": ["dist", "README.md", "LICENSE"] but neither file existed on disk - the next release tag would have published this package with no license text. Added the canonical repo-wide MIT LICENSE (identical text to every other package) and a real README documenting the SEP-1/10/12/24/31 clients this package actually implements. Also aligned version 0.2.0 -> 0.1.0: this package has never been published, so 0.2.0 implied a 0.1.0 predecessor that never existed. Matches the rest of the workspace's first-publish convention.
1 parent b972e76 commit 8934b33

3 files changed

Lines changed: 139 additions & 1 deletion

File tree

packages/anchor-sdk/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 Orbital Contributors
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.

packages/anchor-sdk/README.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# @orbital-stellar/anchor-sdk
2+
3+
**Typed clients for talking to Stellar anchors.** Discovery, SEP-10 authentication, SEP-12 KYC, SEP-24 interactive deposit/withdraw, and SEP-31 cross-border payments - each with a validated request/response shape instead of hand-rolled `fetch` calls.
4+
5+
```bash
6+
pnpm add @orbital-stellar/anchor-sdk
7+
```
8+
9+
## What it does
10+
11+
`anchor-sdk` is the client side of the SEP anchor protocols. You point it at an anchor's home domain, it discovers the endpoints from `stellar.toml`, authenticates, and drives the deposit/withdraw or cross-border payment flow - each response validated against a `zod` schema so a malformed anchor reply throws instead of silently propagating `undefined`.
12+
13+
It never holds a Stellar secret key. Every flow that needs a signature takes a caller-supplied signing callback, so the key can live in a hardware wallet, a KMS, or wherever the consumer already keeps it - the SDK only ever sees signed XDR.
14+
15+
## SEP-1 - discovery
16+
17+
```ts
18+
import { discoverAnchor } from "@orbital-stellar/anchor-sdk";
19+
20+
const toml = await discoverAnchor("anchor.example.com");
21+
// toml.WEB_AUTH_ENDPOINT, toml.TRANSFER_SERVER_SEP0024, toml.SIGNING_KEY, ...
22+
```
23+
24+
`discoverAnchor` fetches `https://{homeDomain}/.well-known/stellar.toml`, caps the response at 100 KB, and parses only the top-level keys this SDK understands. A response that isn't reachable, isn't valid, or exceeds the size cap throws `Sep1DiscoveryError`.
25+
26+
## SEP-10 - authentication
27+
28+
```ts
29+
import { discoverAnchor, Sep10Client } from "@orbital-stellar/anchor-sdk";
30+
import { Keypair } from "@stellar/stellar-sdk";
31+
32+
const toml = await discoverAnchor("anchor.example.com");
33+
const client = Sep10Client.fromToml(toml, "anchor.example.com");
34+
35+
const keypair = Keypair.fromSecret(process.env.STELLAR_SECRET!);
36+
37+
const token = await client.authenticate({
38+
account: keypair.publicKey(),
39+
sign: async (challenge) => {
40+
// Sign with whatever holds your key - here, an in-process Keypair.
41+
const tx = /* build a Transaction from challenge.transaction */;
42+
tx.sign(keypair);
43+
return tx.toXDR();
44+
},
45+
});
46+
```
47+
48+
Every challenge is validated against the anchor's `SIGNING_KEY`, network passphrase, home domain, and `web_auth_domain` **before** it reaches your `sign` callback - a hostile or compromised anchor cannot get an arbitrary transaction signed by handing you a "challenge" that is actually a payment or a `set_options` adding a signer. `Sep10Client.fromToml` is the preferred constructor: it's the path that cannot forget to pass `SIGNING_KEY`, without which no challenge can be attributed to the anchor.
49+
50+
## SEP-12 - KYC
51+
52+
```ts
53+
import { Sep12Client } from "@orbital-stellar/anchor-sdk";
54+
55+
const kyc = new Sep12Client(toml.KYC_SERVER!);
56+
const info = await kyc.getCustomer({ account: keypair.publicKey() }, token);
57+
58+
if (info.status === "NEEDS_INFO") {
59+
const form = new FormData();
60+
form.set("first_name", "Jane");
61+
form.set("last_name", "Doe");
62+
await kyc.putCustomer(form, token);
63+
}
64+
```
65+
66+
## SEP-24 - interactive deposit / withdraw
67+
68+
```ts
69+
import { Sep24Client, Sep24StatusMachine } from "@orbital-stellar/anchor-sdk";
70+
71+
const transfer = new Sep24Client(toml.TRANSFER_SERVER_SEP0024!);
72+
73+
const { url, id } = await transfer.initiateDeposit(
74+
{ asset_code: "USDC" },
75+
token,
76+
);
77+
// Open `url` in a webview so the user completes the anchor's flow.
78+
79+
const machine = new Sep24StatusMachine();
80+
const { status } = await transfer.transaction(id, token);
81+
machine.transitionTo(status); // throws InvalidSep24TransitionError on an illegal jump
82+
```
83+
84+
`Sep24StatusMachine` tracks one transaction's lifecycle and rejects transitions the spec doesn't allow (e.g. leaving a terminal status), so a buggy poll loop can't silently mark a refunded deposit as completed. Re-applying the same status is a no-op, since anchors commonly re-report an unchanged status on every poll.
85+
86+
## SEP-31 - cross-border payments
87+
88+
```ts
89+
import { Sep31Client } from "@orbital-stellar/anchor-sdk";
90+
91+
const sep31 = new Sep31Client(toml.DIRECT_PAYMENT_SERVER!);
92+
const info = await sep31.info();
93+
94+
const { id, stellar_account_id, stellar_memo } = await sep31.initiateTransaction(
95+
{ asset_code: "USDC", receiver_id: "..." },
96+
token,
97+
);
98+
// Pay stellar_account_id with memo stellar_memo, then poll:
99+
const tx = await sep31.pollStatus(id, token);
100+
```
101+
102+
`sep31.sep12` is a bound `Sep12Client` for the same anchor, for when a SEP-31 flow needs sender/receiver KYC. `initiateTransaction` throws `MissingFieldsError` or `CustomerInfoNeededError` when the anchor needs more information before it will proceed.
103+
104+
## Normalizing anchor events
105+
106+
```ts
107+
import { normalizeAnchorEvent } from "@orbital-stellar/anchor-sdk";
108+
109+
const event = normalizeAnchorEvent(sep24Transaction);
110+
// event.type is one of the `anchor.*` lifecycle events from @orbital-stellar/pulse-core
111+
```
112+
113+
Maps a SEP-24 or SEP-31 transaction onto the `anchor.*` taxonomy in `@orbital-stellar/pulse-core`. The anchor's own status is always preserved verbatim in `protocolStatus` - the normalized `type` is a convenience layer, never a replacement, so a compliance consumer can still see exactly what the anchor said. `settlementTxHash` is only ever a hash the anchor actually published; it is `null` rather than guessed when the anchor doesn't expose one.
114+
115+
## License
116+
117+
MIT, see [LICENSE](./LICENSE).

packages/anchor-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@orbital-stellar/anchor-sdk",
3-
"version": "0.2.0",
3+
"version": "0.1.0",
44
"description": "SDK for interacting with Stellar Anchors (SEP-12, SEP-24, SEP-31).",
55
"license": "MIT",
66
"engines": {

0 commit comments

Comments
 (0)