@ldgr/client 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,14 +15,21 @@ manager or HSM integration; never log it or send it to LDGR.
15
15
  ```ts
16
16
  import { createLdgrClient } from "@ldgr/client";
17
17
 
18
- const client = createLdgrClient({ apiBase: "https://tst.ldgr.ltd" });
18
+ const client = createLdgrClient({ network: "testnet" });
19
19
  const payment = await client.payments.verifyTransfer(transactionHash, {
20
20
  to: merchantAddress,
21
- asset: "dng",
21
+ asset: "t0",
22
22
  amount: "2.50",
23
23
  });
24
24
  ```
25
25
 
26
+ Pass `network: "testnet" | "mainnet"` or the matching ledger id (`0` / `1`).
27
+ The client selects `https://tst.ldgr.ltd` or `https://ldgr.ltd` by default; pass
28
+ `apiBase` alongside `network` for a local deployment or proxy. Use public native
29
+ asset id `t0` on testnet and `t1` on mainnet. Legacy `dng` remains accepted for
30
+ compatibility, while raw authoritative transactions retain their signed wire
31
+ code `dng`.
32
+
26
33
  Only fulfil an order after `payment.status === "confirmed"`, and store the
27
34
  transaction hash as the idempotency key. AMM quotes are estimates: pass an
28
35
  explicit minimum output in the signed swap payload and re-quote immediately
package/dist/index.d.ts CHANGED
@@ -69,6 +69,6 @@ export declare function createLdgrClient(options: LdgrClientOptions): {
69
69
  }>(path: string, signed: SignedSubmission) => Promise<T>;
70
70
  };
71
71
  export { LdgrClientError } from "./types";
72
- export type { LdgrClientOptions, LdgrTransaction, PaymentExpectation, PaymentVerification, SignedSubmission } from "./types";
72
+ export type { LdgrClientOptions, LdgrNetwork, LdgrTransaction, PaymentExpectation, PaymentVerification, SignedSubmission } from "./types";
73
73
  export { createWebCryptoSigner, generateLocalWallet } from "./signer";
74
74
  export type { LdgrSigner, LocalLdgrWallet } from "./signer";
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ // src/client.ts
2
+ import { resolveLdgrNetwork } from "@ldgr/protocol";
3
+
1
4
  // src/types.ts
2
5
  class LdgrClientError extends Error {
3
6
  status;
@@ -17,6 +20,13 @@ function normalizeApiBase(apiBase) {
17
20
  throw new TypeError("apiBase must be an absolute HTTP(S) URL");
18
21
  return normalized;
19
22
  }
23
+ function apiBaseForOptions(options) {
24
+ if (options.apiBase !== undefined)
25
+ return normalizeApiBase(options.apiBase);
26
+ if (options.network === undefined)
27
+ throw new TypeError("apiBase is required when network is not provided");
28
+ return resolveLdgrNetwork(options.network) === 0 ? "https://tst.ldgr.ltd" : "https://ldgr.ltd";
29
+ }
20
30
  function assertApiPath(path) {
21
31
  if (!path.startsWith("/api/v1/") || path.includes("//") || path.includes("..")) {
22
32
  throw new TypeError("path must be an /api/v1/ relative path");
@@ -37,7 +47,7 @@ async function parseJson(response) {
37
47
  return body;
38
48
  }
39
49
  function createTransport(options) {
40
- const apiBase = normalizeApiBase(options.apiBase);
50
+ const apiBase = apiBaseForOptions(options);
41
51
  const request = options.fetch ?? globalThis.fetch;
42
52
  if (typeof request !== "function")
43
53
  throw new TypeError("fetch is required");
@@ -66,6 +76,9 @@ function queryPath(path, query) {
66
76
  const encoded = search.toString();
67
77
  return encoded ? `${path}?${encoded}` : path;
68
78
  }
79
+
80
+ // src/index.ts
81
+ import { resolveLdgrNetwork as resolveLdgrNetwork2, resolvePublicAssetCode } from "@ldgr/protocol";
69
82
  // src/signer.ts
70
83
  import {
71
84
  deriveAddress,
@@ -136,6 +149,15 @@ function transactionFields(transaction) {
136
149
  }
137
150
  function createLdgrClient(options) {
138
151
  const transport = createTransport(options);
152
+ const ledgerId = options.network === undefined ? undefined : resolveLdgrNetwork2(options.network);
153
+ const resolveAsset = (asset) => {
154
+ if (ledgerId !== undefined)
155
+ return resolvePublicAssetCode(asset, ledgerId);
156
+ if (/^t[01]$/i.test(asset.trim())) {
157
+ throw new TypeError("network is required when using public native asset ids t0 or t1");
158
+ }
159
+ return asset;
160
+ };
139
161
  return {
140
162
  ledger: {
141
163
  get: () => transport.get("/api/v1/ledger"),
@@ -143,8 +165,8 @@ function createLdgrClient(options) {
143
165
  },
144
166
  accounts: {
145
167
  listBalances: (address) => transport.get(`/api/v1/balances/${encodePathSegment(address)}`),
146
- getBalance: (address, asset) => transport.get(`/api/v1/balances/${encodePathSegment(address)}/${encodePathSegment(asset)}`),
147
- getNextNonce: (address, asset) => transport.get(`/api/v1/nonces/${encodePathSegment(address)}/${encodePathSegment(asset)}`)
168
+ getBalance: (address, asset) => transport.get(`/api/v1/balances/${encodePathSegment(address)}/${encodePathSegment(resolveAsset(asset))}`),
169
+ getNextNonce: (address, asset) => transport.get(`/api/v1/nonces/${encodePathSegment(address)}/${encodePathSegment(resolveAsset(asset))}`)
148
170
  },
149
171
  transactions: {
150
172
  get: (transactionHash) => transport.get(`/api/v1/transactions/${normalizedHash(transactionHash)}`)
@@ -152,9 +174,9 @@ function createLdgrClient(options) {
152
174
  amm: {
153
175
  listPools: () => transport.get("/api/v1/amm/pools"),
154
176
  getPool: (poolId) => transport.get(`/api/v1/amm/pools/${encodePathSegment(poolId)}`),
155
- getPoolByPair: (assetA, assetB) => transport.get(`/api/v1/amm/pools/by-pair/${encodePathSegment(assetA)}/${encodePathSegment(assetB)}`),
156
- quoteSwap: (poolId, assetIn, amountIn) => transport.get(queryPath(`/api/v1/amm/pools/${encodePathSegment(poolId)}/quote`, { assetIn, amountIn })),
157
- quoteRoute: (assetIn, assetOut, amountIn, maxHops) => transport.get(queryPath("/api/v1/amm/routes/quote", { assetIn, assetOut, amountIn, maxHops }))
177
+ getPoolByPair: (assetA, assetB) => transport.get(`/api/v1/amm/pools/by-pair/${encodePathSegment(resolveAsset(assetA))}/${encodePathSegment(resolveAsset(assetB))}`),
178
+ quoteSwap: (poolId, assetIn, amountIn) => transport.get(queryPath(`/api/v1/amm/pools/${encodePathSegment(poolId)}/quote`, { assetIn: resolveAsset(assetIn), amountIn })),
179
+ quoteRoute: (assetIn, assetOut, amountIn, maxHops) => transport.get(queryPath("/api/v1/amm/routes/quote", { assetIn: resolveAsset(assetIn), assetOut: resolveAsset(assetOut), amountIn, maxHops }))
158
180
  },
159
181
  subscriptions: {
160
182
  getPlan: (planId) => transport.get(`/api/v1/subscription-plans/${encodePathSegment(planId)}`),
@@ -189,6 +211,7 @@ function createLdgrClient(options) {
189
211
  payments: {
190
212
  async verifyTransfer(transactionHash, expected) {
191
213
  const hash = normalizedHash(transactionHash);
214
+ const expectedAsset = resolveAsset((expected.asset ?? "dng").trim() || "dng");
192
215
  let transaction;
193
216
  try {
194
217
  transaction = await transport.get(`/api/v1/payments/v0.1/transactions/${hash}`);
@@ -198,7 +221,6 @@ function createLdgrClient(options) {
198
221
  throw error;
199
222
  }
200
223
  const fields = transactionFields(transaction);
201
- const expectedAsset = (expected.asset ?? "dng").trim() || "dng";
202
224
  if (transaction.action !== "transfer" || fields === null || fields.to !== expected.to || fields.asset !== expectedAsset || !sameDecimalAmount(fields.amount, expected.amount) || expected.reference !== undefined && paymentReference(transaction.metadata) !== expected.reference) {
203
225
  return { status: "mismatch", transactionHash: hash };
204
226
  }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import type { LdgrNetwork } from "@ldgr/protocol";
1
2
  export type LedgerId = 0 | 1;
3
+ export type { LdgrNetwork } from "@ldgr/protocol";
2
4
  export type LdgrTransaction = {
3
5
  readonly action: string;
4
6
  readonly from?: string;
@@ -33,7 +35,10 @@ export type SignedSubmission = {
33
35
  readonly feeSponsor?: unknown;
34
36
  };
35
37
  export type LdgrClientOptions = {
36
- readonly apiBase: string;
38
+ /** `testnet` / `0` or `mainnet` / `1`; required to use public native ids `t0` / `t1`. */
39
+ readonly network?: LdgrNetwork;
40
+ /** Defaults to the canonical public origin when `network` is supplied. */
41
+ readonly apiBase?: string;
37
42
  readonly fetch?: typeof globalThis.fetch;
38
43
  };
39
44
  export type LdgrClientErrorBody = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ldgr/client",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -17,7 +17,7 @@
17
17
  "node": ">=20.19.0"
18
18
  },
19
19
  "dependencies": {
20
- "@ldgr/protocol": "^0.1.0"
20
+ "@ldgr/protocol": "^0.1.1"
21
21
  },
22
22
  "scripts": {
23
23
  "build": "rm -rf dist && bun build src/index.ts --outdir dist --target node --format esm --packages external && tsc -p tsconfig.build.json",