@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 +9 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +29 -7
- package/dist/types.d.ts +6 -1
- package/package.json +2 -2
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({
|
|
18
|
+
const client = createLdgrClient({ network: "testnet" });
|
|
19
19
|
const payment = await client.payments.verifyTransfer(transactionHash, {
|
|
20
20
|
to: merchantAddress,
|
|
21
|
-
asset: "
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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",
|