@settlemint/dalp-sdk 3.1.25 → 3.1.26-main.37116470199
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 +239 -172
- package/dist/auth/client.d.ts +103 -0
- package/dist/auth/invite-step-up.d.ts +2 -0
- package/dist/auth/live.d.ts +47 -0
- package/dist/auth/native-passkey.d.ts +9 -0
- package/dist/{auth-permissions.d.ts → auth/permissions.d.ts} +0 -8
- package/dist/{auth-wallet-plugins.d.ts → auth/wallet-plugins.d.ts} +68 -6
- package/dist/auth-surface.d.ts +2 -0
- package/dist/auth.d.ts +8 -115
- package/dist/auth.js +525 -0
- package/dist/chunk-4f4kjtt0.js +149 -0
- package/dist/chunk-b03ycwb7.js +68 -0
- package/dist/chunk-ghgcmyhk.js +5 -0
- package/dist/chunk-h241xecg.js +1625 -0
- package/dist/chunk-hqz56e6q.js +4 -0
- package/dist/chunk-k3ntysxx.js +57 -0
- package/dist/chunk-pjjrxre1.js +36 -0
- package/dist/chunk-qvtjb3dz.js +102 -0
- package/dist/chunk-v54k7mgr.js +271 -0
- package/dist/chunk-w361dpdk.js +5 -0
- package/dist/client/conditional-request.d.ts +8 -0
- package/dist/client/factory.d.ts +4 -0
- package/dist/client/query-serializer.d.ts +1 -0
- package/dist/client/request-compression.d.ts +12 -0
- package/dist/client/ssr-fetch.d.ts +10 -0
- package/dist/client/step-up-challenge.d.ts +10 -0
- package/dist/effect.d.ts +38 -0
- package/dist/effect.js +87 -0
- package/dist/errors/api-error.d.ts +35 -0
- package/dist/errors/error-codes.d.ts +21 -0
- package/dist/errors/find-current-error.d.ts +2 -0
- package/dist/errors/sdk-error.d.ts +52 -0
- package/dist/errors/sdk-error.js +8 -0
- package/dist/generated/api-types.d.ts +69961 -0
- package/dist/generated/console-routes.d.ts +12 -0
- package/dist/generated/error-catalog.d.ts +9 -0
- package/dist/generated/error-codes.d.ts +9 -0
- package/dist/generated/response-scalars.d.ts +9 -0
- package/dist/generated/response-schemas.d.ts +9 -0
- package/dist/generated/route-error-codes.d.ts +9 -0
- package/dist/generated/routes.d.ts +12 -0
- package/dist/index.d.ts +28 -45
- package/dist/index.js +150 -96216
- package/dist/proxy/builder.d.ts +17 -0
- package/dist/proxy/client-core.d.ts +28 -0
- package/dist/proxy/client.d.ts +5 -0
- package/dist/proxy/fetch-executor.d.ts +6 -0
- package/dist/proxy/flat-args.d.ts +24 -0
- package/dist/proxy/response-decode.d.ts +37 -0
- package/dist/proxy/sse.d.ts +11 -0
- package/dist/proxy/step-up-challenge.d.ts +4 -0
- package/dist/proxy/tanstack.d.ts +6 -0
- package/dist/proxy/transport.d.ts +63 -0
- package/dist/react-query.d.ts +2 -0
- package/dist/react-query.js +12 -0
- package/dist/readonly-deep.d.ts +3 -0
- package/dist/routes/console.d.ts +14 -0
- package/dist/routes/console.js +25 -0
- package/dist/routes/index.d.ts +4 -0
- package/dist/routes/index.js +10 -0
- package/dist/routes/types.d.ts +72 -0
- package/dist/runtime-exports.d.ts +4 -0
- package/dist/runtime-exports.js +16 -0
- package/dist/runtime.d.ts +11 -0
- package/dist/scalars/big-decimal.d.ts +4 -0
- package/dist/scalars/ethereum-address.d.ts +5 -0
- package/dist/scalars/exchange-rates.d.ts +13 -0
- package/dist/scalars/index.d.ts +10 -0
- package/dist/scalars/index.js +102 -0
- package/dist/scalars/organization-id.d.ts +5 -0
- package/dist/scalars/token-decimals.d.ts +4 -0
- package/dist/secret.d.ts +12 -0
- package/dist/sign-webhook-receipt.d.ts +16 -0
- package/dist/sign-webhook-receipt.js +26 -0
- package/dist/transport/cookie-store.d.ts +9 -0
- package/dist/transport/sse-lifecycle.d.ts +24 -0
- package/dist/types.d.ts +37 -114
- package/dist/url.d.ts +0 -1
- package/dist/verify-webhook.d.ts +17 -28
- package/dist/verify-webhook.js +8 -0
- package/dist/version.d.ts +0 -3
- package/dist/wait-for-transaction.d.ts +44 -86
- package/dist/wait-for-transaction.js +151 -0
- package/dist/webhook-events.d.ts +543 -33
- package/package.json +110 -34
- package/dist/api-types.generated.d.ts +0 -14160
- package/dist/api-types.generated.d.ts.map +0 -1
- package/dist/auth-permissions.d.ts.map +0 -1
- package/dist/auth-wallet-plugins.d.ts.map +0 -1
- package/dist/auth.d.ts.map +0 -1
- package/dist/bundler.d.ts +0 -217
- package/dist/bundler.d.ts.map +0 -1
- package/dist/chunk-xm8h1dzh.js +0 -33
- package/dist/client.d.ts +0 -19
- package/dist/client.d.ts.map +0 -1
- package/dist/contract-errors.d.ts +0 -4156
- package/dist/contract-errors.d.ts.map +0 -1
- package/dist/contract.d.ts +0 -22
- package/dist/contract.d.ts.map +0 -1
- package/dist/cookie-store.d.ts +0 -10
- package/dist/cookie-store.d.ts.map +0 -1
- package/dist/dapi-errors.d.ts +0 -654
- package/dist/dapi-errors.d.ts.map +0 -1
- package/dist/errors.d.ts +0 -637
- package/dist/errors.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/platform.d.ts +0 -41
- package/dist/platform.d.ts.map +0 -1
- package/dist/plugins/index.d.ts +0 -13
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -10
- package/dist/sdk-error.d.ts +0 -74
- package/dist/sdk-error.d.ts.map +0 -1
- package/dist/serializers.d.ts +0 -41
- package/dist/serializers.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/url.d.ts.map +0 -1
- package/dist/verify-webhook.d.ts.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.generated.d.ts +0 -8
- package/dist/version.generated.d.ts.map +0 -1
- package/dist/wait-for-transaction.d.ts.map +0 -1
- package/dist/webhook-events.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,206 +1,273 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<a href="https://www.npmjs.com/package/@settlemint/dalp-sdk" rel="nofollow"><img src="https://img.shields.io/npm/v/@settlemint/dalp-sdk" alt="npm version"></a>
|
|
13
|
-
<a href="https://www.npmjs.com/package/@settlemint/dalp-sdk" rel="nofollow"><img src="https://img.shields.io/npm/dw/@settlemint/dalp-sdk" alt="npm downloads"></a>
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<div align="center">
|
|
17
|
-
<a href="https://settlemint.com">Website</a>
|
|
18
|
-
<span> • </span>
|
|
19
|
-
<a href="https://www.npmjs.com/package/@settlemint/dalp-sdk">NPM</a>
|
|
20
|
-
<span> • </span>
|
|
21
|
-
<a href="mailto:support@settlemint.com">Support</a>
|
|
22
|
-
<br />
|
|
23
|
-
</div>
|
|
24
|
-
|
|
25
|
-
## About
|
|
26
|
-
|
|
27
|
-
The DALP SDK provides a fully typed client for the Digital Asset Lifecycle Platform API. Built on [oRPC](https://orpc.unnoq.com/) with contract-first types, it gives you auto-complete for every API namespace — tokens, identities, compliance, transactions, and more.
|
|
28
|
-
|
|
29
|
-
## Installation
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# npm
|
|
33
|
-
npm install @settlemint/dalp-sdk
|
|
34
|
-
|
|
35
|
-
# bun
|
|
36
|
-
bun add @settlemint/dalp-sdk
|
|
37
|
-
```
|
|
1
|
+
# DALP SDK
|
|
2
|
+
|
|
3
|
+
One typed client for the Platform API v2, derived from the platform's own route
|
|
4
|
+
declaration. Calls are namespaced (`dalp.api.token.transfer(...)`), a queue
|
|
5
|
+
backed write resolves once the chain has settled, and TanStack Query factories
|
|
6
|
+
sit on the same nodes as the calls. The package ships no runtime schema
|
|
7
|
+
library: the types are compile time only.
|
|
8
|
+
|
|
9
|
+
Two interpreters over one route table. The package root returns promises. The
|
|
10
|
+
`./effect` subpath returns Effect values with a typed failure channel. Neither
|
|
11
|
+
pulls the other in, and a build gate keeps the root free of Effect.
|
|
38
12
|
|
|
39
|
-
##
|
|
13
|
+
## Client
|
|
40
14
|
|
|
41
|
-
```
|
|
15
|
+
```ts
|
|
42
16
|
import { createDalpClient } from "@settlemint/dalp-sdk";
|
|
43
17
|
|
|
44
18
|
const dalp = createDalpClient({
|
|
45
|
-
|
|
19
|
+
baseUrl: "https://dalp.example.com",
|
|
46
20
|
apiKey: "sm_dalp_...",
|
|
47
|
-
organizationId: "org_...", // optional, for multi-org setups
|
|
48
21
|
});
|
|
49
22
|
|
|
50
|
-
|
|
51
|
-
const tokens = await dalp.token.list({ query: {} });
|
|
52
|
-
const system = await dalp.system.read({});
|
|
23
|
+
const tokens = await dalp.api.token.list({ page: { limit: 25 } }, { signal });
|
|
53
24
|
```
|
|
54
25
|
|
|
55
|
-
|
|
26
|
+
A call takes one flat object. The route table says which of its keys are path
|
|
27
|
+
parameters and which are query or body fields, so a call site names what it
|
|
28
|
+
means and never restates the transport. The build refuses any route whose path
|
|
29
|
+
parameter would collide with a body or query key, which is what makes the
|
|
30
|
+
merge safe.
|
|
31
|
+
|
|
32
|
+
`createDalpClient` owns the shared transport policy once: the credential
|
|
33
|
+
mechanism, the acting-context headers (`organizationId`, `participant`,
|
|
34
|
+
`executor`, `chainId`, `selectedSigners`, `idempotencyKey`), conditional
|
|
35
|
+
`If-None-Match` reuse, custom fetch injection, the settlement bound, and abort
|
|
36
|
+
propagation.
|
|
37
|
+
|
|
38
|
+
**An API key cannot reach a browser or an app.** `createDalpClient` and
|
|
39
|
+
`createDalpAuthClient` throw at construction when a key is passed with
|
|
40
|
+
`runtime: "browser"` or `runtime: "react-native"`, rather than at the first
|
|
41
|
+
request. A key carries the
|
|
42
|
+
full authority of the identity it belongs to, and anything bundled into a web
|
|
43
|
+
page or an app ships to every user. There the client authenticates with the
|
|
44
|
+
session cookie instead.
|
|
45
|
+
|
|
46
|
+
### Dispatch by route id
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const token = await dalp.execute("token/read", { assetId });
|
|
50
|
+
```
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
`execute` is typed against the id through the `DalpRouteTypes` registry, so a
|
|
53
|
+
command surface built from route ids keeps the same request and response types
|
|
54
|
+
the namespaced tree gives a call site. The CLI, the end-to-end harness, and the
|
|
55
|
+
demo scripts are all built on it.
|
|
56
|
+
|
|
57
|
+
### Settlement
|
|
58
|
+
|
|
59
|
+
A queue-backed write carries a `Prefer` header derived from
|
|
60
|
+
`settlementTimeoutMs`: undefined asks for `wait=15`, zero or less asks for
|
|
61
|
+
`respond-async`, anything else asks for `wait=<seconds>`, clamped to the
|
|
62
|
+
platform's 5 to 99 second range. `settlementTimeoutMs` sets that bound per
|
|
63
|
+
client, and a call may override it.
|
|
64
|
+
|
|
65
|
+
The platform does the waiting, not the client. When the write settles inside
|
|
66
|
+
the wait, the call returns the route's HTTP 200 resource. When it does not, the
|
|
67
|
+
call returns the declared HTTP 202 handle unchanged: a transaction write's
|
|
68
|
+
`{ transactionId, status, statusUrl }`, or a custody write's `{ requestId,
|
|
69
|
+
state, statusUrl }`. The client never polls a status URL on your behalf.
|
|
70
|
+
|
|
71
|
+
Pass a transaction id to `waitForTransaction` to follow it to a terminal
|
|
72
|
+
state. A write the funding gate parks on an operator payment reads as still
|
|
73
|
+
queued for as long as the ask is open: the status row carries it as
|
|
74
|
+
`activeRequirement`, and `waitForTransaction` restarts its own timeout on every
|
|
75
|
+
status that reports one, so the wait it runs outlasts the pause. A caller that
|
|
76
|
+
cannot wait that long ends the wait through `signal`, or passes
|
|
77
|
+
`holdWhilePaused: false` to end on the first parked status instead. A custody
|
|
78
|
+
handle has no equivalent helper: follow `statusUrl` yourself.
|
|
79
|
+
|
|
80
|
+
### Conditional requests and ETags
|
|
81
|
+
|
|
82
|
+
The client reuses a held body when the server answers a matching ETag with 304.
|
|
83
|
+
Server ETags must be **strong content digests** computed **after
|
|
84
|
+
authorization** inside the requester's partition. Version-stamp ETags
|
|
85
|
+
(generation counters, watermarks, table versions) are forbidden for conditional
|
|
86
|
+
request adopters: a stamp can collide across tenants or lag a body change.
|
|
87
|
+
|
|
88
|
+
Identity changes that do not ride this client (browser sign-out, organization
|
|
89
|
+
switch) must clear the held bodies, so a later GET cannot send another
|
|
90
|
+
session's `If-None-Match`.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
dalp.conditionalRequests.clear();
|
|
94
|
+
```
|
|
59
95
|
|
|
60
|
-
|
|
61
|
-
import { createDalpAuthClient } from "@settlemint/dalp-sdk";
|
|
96
|
+
## Effect
|
|
62
97
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
apiKey: "sm_dalp_...",
|
|
66
|
-
organizationId: "org_...",
|
|
67
|
-
});
|
|
98
|
+
```ts
|
|
99
|
+
import { createDalpEffectClient } from "@settlemint/dalp-sdk/effect";
|
|
68
100
|
|
|
69
|
-
const
|
|
101
|
+
const dalp = createDalpEffectClient({ baseUrl, apiKey });
|
|
102
|
+
const tokens = yield * dalp.api.token.list({ page: { limit: 25 } });
|
|
70
103
|
```
|
|
71
104
|
|
|
72
|
-
|
|
73
|
-
|
|
105
|
+
The same routes, returning `Effect` values that fail with `DalpRequestError`
|
|
106
|
+
rather than throwing. `execute` is typed by route id here too.
|
|
74
107
|
|
|
75
|
-
|
|
76
|
-
import { createDalpPlatformClient } from "@settlemint/dalp-sdk";
|
|
108
|
+
## The route table
|
|
77
109
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
110
|
+
```ts
|
|
111
|
+
import { routeIds, routeTable } from "@settlemint/dalp-sdk/routes";
|
|
112
|
+
```
|
|
81
113
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
});
|
|
114
|
+
`./routes` publishes the generated table both interpreters dispatch through:
|
|
115
|
+
every v2 route's id, method, path template, statuses, and traits. It carries no
|
|
116
|
+
client and no Effect, so a tool that only needs to know what the platform
|
|
117
|
+
serves loads this rather than a client.
|
|
87
118
|
|
|
88
|
-
|
|
89
|
-
```
|
|
119
|
+
## TanStack Query
|
|
90
120
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
| Namespace | Operations | Description |
|
|
96
|
-
| --------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
97
|
-
| `signIn` | `email` | Sign in with email and password |
|
|
98
|
-
| `signUp` | `email` | Register a new account |
|
|
99
|
-
| `getSession` | — | Fetch the current session |
|
|
100
|
-
| `listSessions` | — | List all active sessions |
|
|
101
|
-
| `revokeSession` | — | Revoke a specific session |
|
|
102
|
-
| `revokeOtherSessions` | — | Revoke all sessions except the current one |
|
|
103
|
-
| `apiKey` | `create`, `list`, `delete` | Manage API keys |
|
|
104
|
-
| `organization` | `create`, `list`, `setActive`, `inviteMember`, `acceptInvitation`, `listMembers`, `addMember`, `removeMember` | Manage organizations and membership |
|
|
105
|
-
| `admin` | `listUsers`, `createUser`, `removeUser`, `setRole` | Administrative user management |
|
|
106
|
-
| `device` | `code`, `token`, `approve`, `deny` | Device authorization flow |
|
|
107
|
-
| `twoFactor` | `enable`, `disable`, `verifyTotp`, `verifyBackupCode`, `generateBackupCodes` | Account-level TOTP two-factor authentication |
|
|
108
|
-
| `wallet.pincode` | `enable`, `disable`, `update`, `reset` | Wallet pincode protection |
|
|
109
|
-
| `wallet.twoFactor` | `enable`, `disable`, `verify` | Wallet two-factor verification |
|
|
110
|
-
| `wallet.secretCodes` | `generate`, `confirm` | Wallet secret (recovery) codes |
|
|
111
|
-
| `passkey` | — | Account-level passkey registration (browser/WebAuthn only) |
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
// Enable account-level 2FA and verify a TOTP code
|
|
115
|
-
await auth.twoFactor.enable({ password: "..." });
|
|
116
|
-
await auth.twoFactor.verifyTotp({ code: "123456" });
|
|
121
|
+
```ts
|
|
122
|
+
const options = dalp.api.token.list.queryOptions({ page: { limit: 25 } });
|
|
123
|
+
const transfer = dalp.api.token.transfer.mutationOptions();
|
|
117
124
|
```
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
Every read node carries `queryOptions`; every write node carries
|
|
127
|
+
`mutationOptions`. They are plain objects in the shapes TanStack
|
|
128
|
+
Query expects, so nothing forces you into that library and nothing stops you
|
|
129
|
+
using something else.
|
|
130
|
+
|
|
131
|
+
Cache keys are derived from route identity plus canonicalized input, so two
|
|
132
|
+
callers passing the same parameters in a different key order share one entry.
|
|
133
|
+
`./react-query` exports `queryKeyFor` and `canonicalize` for building a
|
|
134
|
+
matching invalidation filter, and `UI_SETTLEMENT_TIMEOUT_MS`, the bound the
|
|
135
|
+
mutation factories default to.
|
|
136
|
+
|
|
137
|
+
## Scalars
|
|
138
|
+
|
|
139
|
+
Custom wire formats (BigDecimal amounts, EVM addresses, and the
|
|
140
|
+
`OrganizationId` entity brand) are not expressed structurally in the generated
|
|
141
|
+
OpenAPI document, so `./scalars` carries a decoder for each:
|
|
142
|
+
`decodeBigDecimal`, `decodeEthereumAddress`, `decodeOrganizationId`, and the
|
|
143
|
+
exchange-rate response transformer. The route table names which fields carry a
|
|
144
|
+
scalar, keyed by dotted path, so a consumer applies a decoder where the
|
|
145
|
+
declaration says one lives rather than guessing from a field name.
|
|
146
|
+
`OrganizationId` is the only entity id branded end to end across the platform;
|
|
147
|
+
every other identifier crossing this boundary is a plain string.
|
|
148
|
+
|
|
149
|
+
## Auth
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { createDalpAuthClient } from "@settlemint/dalp-sdk/auth";
|
|
122
153
|
```
|
|
123
154
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
155
|
+
The route surface already carries every auth REST route. `./auth` covers what a
|
|
156
|
+
REST call cannot express: the session and cookie state machine, plugin actions
|
|
157
|
+
that must run on the device (`passkeyClient` drives the WebAuthn ceremony
|
|
158
|
+
through `navigator.credentials`, or through the `passkey` ceremony a React
|
|
159
|
+
Native app passes), and the access-control model that evaluates a
|
|
160
|
+
permission locally instead of round-tripping. It sits off the package root
|
|
161
|
+
because it costs roughly 70 KiB of Better Auth that a consumer who only calls
|
|
162
|
+
routes should not pay.
|
|
163
|
+
|
|
164
|
+
Better Auth's client types reference zod, so `zod` is an optional peer
|
|
165
|
+
dependency: install it if you use `./auth`, skip it otherwise. No code in this
|
|
166
|
+
package imports zod at runtime.
|
|
167
|
+
|
|
168
|
+
An API key works on 8 auth routes only. Each of them is a read:
|
|
169
|
+
|
|
170
|
+
- `GET /get-session`
|
|
171
|
+
- `GET /organization/list`
|
|
172
|
+
- `GET /organization/get-full-organization`
|
|
173
|
+
- `GET /organization/list-members`
|
|
174
|
+
- `POST /organization/has-permission`
|
|
175
|
+
- `GET /api-key/list`
|
|
176
|
+
- `GET /api-key/get`
|
|
177
|
+
- `GET /passkey/list-user-passkeys`
|
|
178
|
+
|
|
179
|
+
Every other auth route answers a request that carries a key with HTTP 403 and
|
|
180
|
+
the code `API_KEY_NOT_SUPPORTED_ON_ROUTE`. Use a session cookie for those
|
|
181
|
+
routes. The API key guide in the DALP API reference has the details.
|
|
182
|
+
|
|
183
|
+
## React Native
|
|
184
|
+
|
|
185
|
+
Supported: Expo SDK 57 (React Native 0.86, React 19.2), with `fetch` from
|
|
186
|
+
`expo/fetch` passed to both clients. The SDK detects React Native from
|
|
187
|
+
`navigator.product` and then keeps the session in its own cookie store, sends
|
|
188
|
+
`credentials: "omit"`, refuses an API key, and sends the platform's origin as
|
|
189
|
+
`Origin` on every call.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { createCookieStoreFetch, createDalpClient, makeCookieStore } from "@settlemint/dalp-sdk";
|
|
193
|
+
import { createDalpAuthClient } from "@settlemint/dalp-sdk/auth";
|
|
194
|
+
import { fetch } from "expo/fetch";
|
|
195
|
+
|
|
196
|
+
const cookieStore = makeCookieStore((await SecureStore.getItemAsync("dalp.session")) ?? "");
|
|
197
|
+
const auth = await createDalpAuthClient({ url, cookieStore, fetch, passkey: ceremony });
|
|
198
|
+
const dalp = createDalpClient({ baseUrl: url, fetch: createCookieStoreFetch(cookieStore, fetch) });
|
|
144
199
|
```
|
|
145
200
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
The
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
201
|
+
- React Native's built-in `fetch` works for calls but cannot read a stream; a
|
|
202
|
+
stream on it fails with `sdk.stream.UNREADABLE_BODY` before the request is
|
|
203
|
+
sent. Use `expo/fetch`.
|
|
204
|
+
- React Native has no WebAuthn. Pass a `passkey` ceremony (`DalpPasskeyCeremony`:
|
|
205
|
+
`authenticate` and `register`, each taking the platform's options JSON and
|
|
206
|
+
returning the credential JSON) backed by a native passkey module.
|
|
207
|
+
- Persist `cookieStore.header()` in secure storage yourself; the SDK holds it in
|
|
208
|
+
memory only.
|
|
209
|
+
|
|
210
|
+
The SDK's tests run this wiring headless on the fetch and abort polyfills React
|
|
211
|
+
Native ships and a model of `expo/fetch`. They do not run on Hermes, a
|
|
212
|
+
simulator, or a device.
|
|
213
|
+
|
|
214
|
+
## Bundler and paymaster
|
|
215
|
+
|
|
216
|
+
Use JSON-RPC 2.0 over `POST https://dalp.example.com/bundler/{chainId}` for
|
|
217
|
+
account-abstraction calls. `{chainId}` is the decimal EVM chain ID; this is
|
|
218
|
+
not an `/api/v2` REST route and is not exposed through `dalp.api` or a separate
|
|
219
|
+
SDK bundler client. From a server, send a write-capable API key in `x-api-key`;
|
|
220
|
+
the key's active organization selects the tenant. Never put the key in browser
|
|
221
|
+
code.
|
|
222
|
+
|
|
223
|
+
The mount serves these standard methods:
|
|
224
|
+
|
|
225
|
+
| Method | Params |
|
|
226
|
+
| ------------------------------ | ----------------------------------------------- |
|
|
227
|
+
| `eth_chainId` | `[]` |
|
|
228
|
+
| `eth_sendUserOperation` | `[userOperation, entryPoint]` |
|
|
229
|
+
| `eth_estimateUserOperationGas` | `[userOperation, entryPoint]` |
|
|
230
|
+
| `eth_getUserOperationByHash` | `[userOperationHash]` |
|
|
231
|
+
| `eth_getUserOperationReceipt` | `[userOperationHash]` |
|
|
232
|
+
| `eth_supportedEntryPoints` | `[]` |
|
|
233
|
+
| `pm_getPaymasterData` | `[userOperation, entryPoint, chainId, context]` |
|
|
234
|
+
| `pm_getPaymasterStubData` | `[userOperation, entryPoint, chainId, context]` |
|
|
235
|
+
|
|
236
|
+
The UserOperation must be signed by your account-abstraction stack before
|
|
237
|
+
`eth_sendUserOperation`. The mount accepts EntryPoint v0.7 UserOperations and
|
|
238
|
+
returns JSON-RPC `result` or `error` envelopes, not REST `{ data, links }`
|
|
239
|
+
resources. `eth_chainId` reports the chain selected by the URL. Consult the platform's bundler
|
|
240
|
+
method policy before depending on a method being enabled for your credential.
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
const response = await fetch("https://dalp.example.com/bundler/1", {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers: {
|
|
246
|
+
"content-type": "application/json",
|
|
247
|
+
"x-api-key": apiKey,
|
|
248
|
+
},
|
|
249
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_supportedEntryPoints", params: [] }),
|
|
250
|
+
});
|
|
251
|
+
const answer = await response.json(); // { jsonrpc: "2.0", id: 1, result: [...] } or { error: ... }
|
|
190
252
|
```
|
|
191
253
|
|
|
192
|
-
##
|
|
254
|
+
## Webhooks and transaction wait
|
|
193
255
|
|
|
194
|
-
-
|
|
195
|
-
-
|
|
196
|
-
-
|
|
197
|
-
|
|
256
|
+
- `./verify-webhook` verifies an inbound webhook signature.
|
|
257
|
+
- `./sign-webhook-receipt` signs a webhook delivery receipt (Node only).
|
|
258
|
+
- `./wait-for-transaction` is a bounded poll to a terminal state, for a
|
|
259
|
+
transaction id from any source, including the 202 handle a client write
|
|
260
|
+
returns when the platform's wait runs out.
|
|
198
261
|
|
|
199
|
-
##
|
|
262
|
+
## Package root
|
|
200
263
|
|
|
201
|
-
|
|
202
|
-
|
|
264
|
+
The root stays small: the client factory, its options and errors, cookie-store
|
|
265
|
+
transport, and the version constants. A consumer who only
|
|
266
|
+
calls routes never pays for auth, TanStack Query, or webhook code.
|
|
203
267
|
|
|
204
|
-
##
|
|
268
|
+
## Documentation
|
|
205
269
|
|
|
206
|
-
|
|
270
|
+
The integrator guide lives under Developer reference in the platform docs:
|
|
271
|
+
install and credentials, calling routes, mutations and settlement, streaming,
|
|
272
|
+
TanStack Query, server rendering in TanStack Start and Next.js, React Native,
|
|
273
|
+
and the Effect surface.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { DalpFetch } from "../client/ssr-fetch.ts";
|
|
2
|
+
import type { DalpAuthSurface } from "../auth-surface.ts";
|
|
3
|
+
import type { AuthGetApiKeyListResponse, AuthGetOrganizationListResponse, AuthPostApiKeyCreateData, AuthPostApiKeyCreateResponse, AuthPostApiKeyDeleteData, AuthPostApiKeyDeleteResponse, AuthPostOrganizationCreateData, AuthPostOrganizationCreateResponse, AuthPostOrganizationRemoveMemberData, AuthPostOrganizationRemoveMemberResponse, AuthPostRevokeOtherSessionsResponse, AuthPostRevokeSessionData, AuthPostRevokeSessionResponse, AuthPostTwoFactorDisableData, AuthPostTwoFactorDisableResponse, AuthPostTwoFactorEnableData, AuthPostTwoFactorEnableResponse, AuthPostTwoFactorVerifyBackupCodeData, AuthPostTwoFactorVerifyBackupCodeResponse, AuthPostTwoFactorVerifyTotpData, AuthPostTwoFactorVerifyTotpResponse, CreateOrganizationInvitationData, CreateOrganizationInvitationResponse, GetSessionResponse, ListUserSessionsResponse, Member, SetActiveOrganizationData, SetActiveOrganizationResponse } from "../generated/api-types.d.ts";
|
|
4
|
+
import { Secret } from "../secret.ts";
|
|
5
|
+
import type { CookieStoreShape } from "../transport/cookie-store.ts";
|
|
6
|
+
import type { DalpRuntime } from "../runtime.ts";
|
|
7
|
+
import type { DalpPasskeyCeremony } from "./native-passkey.ts";
|
|
8
|
+
export interface DalpAuthClientConfig {
|
|
9
|
+
readonly url: string;
|
|
10
|
+
readonly apiKey?: string;
|
|
11
|
+
readonly cookie?: string;
|
|
12
|
+
readonly cookieStore?: CookieStoreShape;
|
|
13
|
+
readonly organizationId?: string;
|
|
14
|
+
readonly authSurface?: DalpAuthSurface;
|
|
15
|
+
readonly headers?: Record<string, string>;
|
|
16
|
+
readonly fetch?: DalpFetch;
|
|
17
|
+
readonly runtime?: DalpRuntime;
|
|
18
|
+
readonly passkey?: DalpPasskeyCeremony;
|
|
19
|
+
}
|
|
20
|
+
export interface DecodedDalpAuthClientConfig extends Omit<DalpAuthClientConfig, "apiKey" | "cookie"> {
|
|
21
|
+
readonly apiKey?: Secret;
|
|
22
|
+
readonly cookie?: Secret;
|
|
23
|
+
}
|
|
24
|
+
export interface DalpAuthError {
|
|
25
|
+
readonly code?: string;
|
|
26
|
+
readonly message?: string;
|
|
27
|
+
readonly status?: number;
|
|
28
|
+
readonly statusText?: string;
|
|
29
|
+
readonly [key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
export interface DalpAuthResult<TData = unknown, TError = DalpAuthError> {
|
|
32
|
+
readonly data: TData | null;
|
|
33
|
+
readonly error: TError | null;
|
|
34
|
+
}
|
|
35
|
+
export type DalpAuthOperation<TInput, TData = unknown> = (input?: TInput, options?: unknown) => Promise<DalpAuthResult<TData>>;
|
|
36
|
+
export type DalpRequiredAuthOperation<TInput, TData> = (input: TInput, options?: unknown) => Promise<DalpAuthResult<TData>>;
|
|
37
|
+
export type DalpNoInputAuthOperation<TData> = (options?: unknown) => Promise<DalpAuthResult<TData>>;
|
|
38
|
+
export type RequestBody<TData> = TData;
|
|
39
|
+
export interface DalpOrganizationMember extends Member {
|
|
40
|
+
readonly user: {
|
|
41
|
+
readonly id: string;
|
|
42
|
+
readonly email: string;
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly image?: string;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface DalpOrganizationMembersQuery {
|
|
48
|
+
readonly limit?: string | number;
|
|
49
|
+
readonly offset?: string | number;
|
|
50
|
+
readonly sortBy?: string;
|
|
51
|
+
readonly sortDirection?: "asc" | "desc";
|
|
52
|
+
readonly filterField?: string;
|
|
53
|
+
readonly filterValue?: string | number | boolean | ReadonlyArray<string> | ReadonlyArray<number>;
|
|
54
|
+
readonly filterOperator?: "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "not_in" | "contains" | "starts_with" | "ends_with";
|
|
55
|
+
readonly organizationId?: string;
|
|
56
|
+
readonly organizationSlug?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface DalpOrganizationInvitation {
|
|
59
|
+
readonly id: string;
|
|
60
|
+
readonly organizationId: string;
|
|
61
|
+
readonly email: string;
|
|
62
|
+
readonly role?: string;
|
|
63
|
+
readonly status: string;
|
|
64
|
+
readonly expiresAt: string | Date;
|
|
65
|
+
}
|
|
66
|
+
export interface DalpOrganizationInvitationsQuery {
|
|
67
|
+
readonly organizationId?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface DalpCliAuthClient {
|
|
70
|
+
readonly getSession: DalpNoInputAuthOperation<GetSessionResponse>;
|
|
71
|
+
readonly listSessions: DalpNoInputAuthOperation<ListUserSessionsResponse>;
|
|
72
|
+
readonly revokeSession: DalpRequiredAuthOperation<RequestBody<AuthPostRevokeSessionData>, AuthPostRevokeSessionResponse>;
|
|
73
|
+
readonly revokeOtherSessions: DalpNoInputAuthOperation<AuthPostRevokeOtherSessionsResponse>;
|
|
74
|
+
readonly apiKey: {
|
|
75
|
+
readonly list: DalpNoInputAuthOperation<AuthGetApiKeyListResponse>;
|
|
76
|
+
readonly create: DalpRequiredAuthOperation<RequestBody<AuthPostApiKeyCreateData>, AuthPostApiKeyCreateResponse>;
|
|
77
|
+
readonly delete: DalpRequiredAuthOperation<RequestBody<AuthPostApiKeyDeleteData>, AuthPostApiKeyDeleteResponse>;
|
|
78
|
+
};
|
|
79
|
+
readonly organization: {
|
|
80
|
+
readonly list: DalpNoInputAuthOperation<AuthGetOrganizationListResponse>;
|
|
81
|
+
readonly setActive: DalpRequiredAuthOperation<RequestBody<SetActiveOrganizationData>, SetActiveOrganizationResponse>;
|
|
82
|
+
readonly create: DalpRequiredAuthOperation<RequestBody<AuthPostOrganizationCreateData>, AuthPostOrganizationCreateResponse>;
|
|
83
|
+
readonly inviteMember: DalpRequiredAuthOperation<RequestBody<CreateOrganizationInvitationData>, CreateOrganizationInvitationResponse>;
|
|
84
|
+
readonly removeMember: DalpRequiredAuthOperation<RequestBody<AuthPostOrganizationRemoveMemberData>, AuthPostOrganizationRemoveMemberResponse>;
|
|
85
|
+
readonly listMembers: DalpRequiredAuthOperation<{
|
|
86
|
+
readonly query?: DalpOrganizationMembersQuery;
|
|
87
|
+
}, {
|
|
88
|
+
readonly members: ReadonlyArray<DalpOrganizationMember>;
|
|
89
|
+
readonly total: number;
|
|
90
|
+
}>;
|
|
91
|
+
readonly listInvitations: DalpAuthOperation<{
|
|
92
|
+
readonly query?: DalpOrganizationInvitationsQuery;
|
|
93
|
+
}, ReadonlyArray<DalpOrganizationInvitation>>;
|
|
94
|
+
readonly listUserInvitations: DalpNoInputAuthOperation<ReadonlyArray<DalpOrganizationInvitation>>;
|
|
95
|
+
};
|
|
96
|
+
readonly twoFactor: {
|
|
97
|
+
readonly enable: DalpRequiredAuthOperation<RequestBody<AuthPostTwoFactorEnableData>, AuthPostTwoFactorEnableResponse>;
|
|
98
|
+
readonly disable: DalpRequiredAuthOperation<RequestBody<AuthPostTwoFactorDisableData>, AuthPostTwoFactorDisableResponse>;
|
|
99
|
+
readonly verifyTotp: DalpRequiredAuthOperation<RequestBody<AuthPostTwoFactorVerifyTotpData>, AuthPostTwoFactorVerifyTotpResponse>;
|
|
100
|
+
readonly verifyBackupCode: DalpRequiredAuthOperation<RequestBody<AuthPostTwoFactorVerifyBackupCodeData>, AuthPostTwoFactorVerifyBackupCodeResponse>;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export declare function decodeDalpAuthClientConfig(input: DalpAuthClientConfig): Promise<DecodedDalpAuthClientConfig>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { apiKeyClient } from "@better-auth/api-key/client";
|
|
2
|
+
import { passkeyClient } from "@better-auth/passkey/client";
|
|
3
|
+
import { type AuthClient, type BetterAuthClientOptions } from "better-auth/client";
|
|
4
|
+
import { adminClient, customSessionClient, deviceAuthorizationClient, inferAdditionalFields, organizationClient, twoFactorClient } from "better-auth/client/plugins";
|
|
5
|
+
import { type DalpAuthClientConfig, type DalpCliAuthClient } from "./client.ts";
|
|
6
|
+
import { type DalpWalletAuthClient, walletPincodeClient, walletSecretCodesClient, walletTwoFactorClient } from "./wallet-plugins.ts";
|
|
7
|
+
declare const adminPluginOptions: {
|
|
8
|
+
ac: import("better-auth/client").AccessControl;
|
|
9
|
+
roles: {
|
|
10
|
+
admin: import("better-auth/client").Role;
|
|
11
|
+
owner: import("better-auth/client").Role;
|
|
12
|
+
member: import("better-auth/client").Role;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
declare const organizationPluginOptions: {
|
|
16
|
+
ac: import("better-auth/client").AccessControl;
|
|
17
|
+
roles: {
|
|
18
|
+
owner: import("better-auth/client").Role;
|
|
19
|
+
member: import("better-auth/client").Role;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
type ConfiguredBetterAuthPluginTuple = [
|
|
23
|
+
ReturnType<typeof customSessionClient>,
|
|
24
|
+
ReturnType<typeof inferAdditionalFields>,
|
|
25
|
+
ReturnType<typeof adminClient<typeof adminPluginOptions>>,
|
|
26
|
+
ReturnType<typeof apiKeyClient>,
|
|
27
|
+
ReturnType<typeof passkeyClient>,
|
|
28
|
+
ReturnType<typeof walletPincodeClient>,
|
|
29
|
+
ReturnType<typeof walletTwoFactorClient>,
|
|
30
|
+
ReturnType<typeof walletSecretCodesClient>,
|
|
31
|
+
ReturnType<typeof twoFactorClient>,
|
|
32
|
+
ReturnType<typeof deviceAuthorizationClient>,
|
|
33
|
+
ReturnType<typeof organizationClient<typeof organizationPluginOptions>>
|
|
34
|
+
];
|
|
35
|
+
type ConfiguredBetterAuthClientOptions = Omit<BetterAuthClientOptions, "plugins"> & {
|
|
36
|
+
plugins: ConfiguredBetterAuthPluginTuple;
|
|
37
|
+
};
|
|
38
|
+
export type InferredBetterAuthClient = AuthClient<ConfiguredBetterAuthClientOptions>;
|
|
39
|
+
type UnservedAuthClientMembers = "deleteUser" | "revokeSessions" | "sendVerificationEmail";
|
|
40
|
+
interface DalpDeviceAuthClient {
|
|
41
|
+
readonly device: Omit<InferredBetterAuthClient["device"], "approve" | "deny">;
|
|
42
|
+
readonly passkey: Omit<InferredBetterAuthClient["passkey"], "updatePasskey">;
|
|
43
|
+
}
|
|
44
|
+
export type DalpAuthClient = Omit<InferredBetterAuthClient, keyof DalpCliAuthClient | keyof DalpWalletAuthClient | keyof DalpDeviceAuthClient | UnservedAuthClientMembers> & DalpDeviceAuthClient & DalpCliAuthClient & DalpWalletAuthClient;
|
|
45
|
+
export declare function createDalpAuthClient(input: DalpAuthClientConfig): Promise<DalpAuthClient>;
|
|
46
|
+
export declare const makeDalpAuthClient: typeof createDalpAuthClient;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { passkeyClient, type AuthenticationResponseJSON, type PublicKeyCredentialCreationOptionsJSON, type PublicKeyCredentialRequestOptionsJSON, type RegistrationResponseJSON } from "@better-auth/passkey/client";
|
|
2
|
+
export interface DalpPasskeyCeremony {
|
|
3
|
+
readonly authenticate: (options: PublicKeyCredentialRequestOptionsJSON) => Promise<AuthenticationResponseJSON>;
|
|
4
|
+
readonly register: (options: PublicKeyCredentialCreationOptionsJSON) => Promise<RegistrationResponseJSON>;
|
|
5
|
+
}
|
|
6
|
+
type PasskeyClientPlugin = ReturnType<typeof passkeyClient>;
|
|
7
|
+
/** @internal */
|
|
8
|
+
export declare function ceremonyPasskeyClient(ceremony: DalpPasskeyCeremony): PasskeyClientPlugin;
|
|
9
|
+
export {};
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Client-side Better Auth access-control metadata for DALP auth clients.
|
|
3
|
-
*
|
|
4
|
-
* Related: packages/dalp/auth/src/utils/permissions.ts, kit/sdk/src/auth.ts
|
|
5
|
-
*
|
|
6
|
-
* @module
|
|
7
|
-
*/
|
|
8
1
|
import { type AccessControl, type Role } from "better-auth/plugins/access";
|
|
9
2
|
export declare const accessControl: AccessControl;
|
|
10
3
|
export declare const adminRole: Role;
|
|
11
4
|
export declare const ownerRole: Role;
|
|
12
5
|
export declare const memberRole: Role;
|
|
13
|
-
//# sourceMappingURL=auth-permissions.d.ts.map
|