@xkova/sdk 0.1.0-alpha.1 → 0.1.0-alpha.10
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 +324 -32
- package/dist/abi.d.ts +40 -0
- package/dist/abi.js +25 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.js +62 -3
- package/dist/generated/types.d.ts +8629 -5182
- package/dist/held-approval.d.ts +41 -0
- package/dist/held-approval.js +33 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/member-action-intents.js +2 -2
- package/dist/member-bff.d.ts +60 -21
- package/dist/member-bff.js +81 -79
- package/dist/member-resources.d.ts +67 -1
- package/dist/member-resources.js +9 -5
- package/dist/request-signing.js +6 -0
- package/dist/resources/account-holders.d.ts +131 -1
- package/dist/resources/account-holders.js +44 -9
- package/dist/resources/branding.d.ts +10 -0
- package/dist/resources/branding.js +2 -0
- package/dist/resources/contacts.d.ts +2 -2
- package/dist/resources/contacts.js +3 -3
- package/dist/resources/escrows.d.ts +3 -0
- package/dist/resources/payment-requests.d.ts +4 -0
- package/dist/resources/payments.d.ts +13 -0
- package/dist/resources/payments.js +7 -0
- package/dist/resources/ramps.d.ts +73 -64
- package/dist/resources/ramps.js +2 -2
- package/dist/resources/rwa.d.ts +9 -9
- package/dist/resources/tenant.d.ts +15 -0
- package/dist/resources/tenant.js +6 -1
- package/dist/resources/tokenization.d.ts +30 -11
- package/dist/resources/tokenization.js +10 -10
- package/dist/resources/treasury.d.ts +404 -0
- package/dist/resources/treasury.js +115 -0
- package/dist/resources/wallets.d.ts +2 -0
- package/dist/resources/webhooks.d.ts +1 -1
- package/dist/resources/webhooks.js +2 -2
- package/dist/resources/workflows.d.ts +7 -6
- package/dist/resources/workflows.js +87 -24
- package/dist/resources/workforce-wallets.d.ts +34 -0
- package/dist/resources/workforce-wallets.js +19 -0
- package/dist/url.d.ts +1 -0
- package/dist/url.js +4 -0
- package/dist/webhook.js +1 -1
- package/dist/workforce-bff.d.ts +202 -0
- package/dist/workforce-bff.js +462 -0
- package/examples/postgres-checkpoint-store.mjs +116 -0
- package/examples/postgres-checkpoints.sql +9 -0
- package/llms.txt +29 -9
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ holders, wallets, payments, tokenization, and other customer resources.
|
|
|
6
6
|
## Install
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
npm install @xkova/sdk@
|
|
9
|
+
npm install @xkova/sdk@alpha
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Requires Node.js 22 or newer. Keep this package and your API keys on the server.
|
|
@@ -93,6 +93,83 @@ one live successor; either key can be revoked immediately.
|
|
|
93
93
|
|
|
94
94
|
## Typed resources
|
|
95
95
|
|
|
96
|
+
### Customer workforce applications
|
|
97
|
+
|
|
98
|
+
Use `@xkova/sdk/workforce-bff` on a confidential server for an institution's
|
|
99
|
+
staff application. It is separate from member login and Console operator
|
|
100
|
+
sessions. The Console administrator first registers an exact issuer, audience,
|
|
101
|
+
JWKS endpoint, application origins/callbacks and dedicated workspace API
|
|
102
|
+
principal. They explicitly admit each immutable provider subject to an existing
|
|
103
|
+
staff membership with narrowed roles and assigned resources. Email and provider
|
|
104
|
+
groups never grant authority. A transport key cannot admit its own users.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { XKOVAWorkforceBffClient } from '@xkova/sdk/workforce-bff';
|
|
108
|
+
|
|
109
|
+
const workforce = new XKOVAWorkforceBffClient({
|
|
110
|
+
baseUrl: 'https://sandbox-api.xkova.com',
|
|
111
|
+
apiKey: process.env.XKOVA_WORKFORCE_API_KEY!,
|
|
112
|
+
workforceKey: process.env.XKOVA_WORKFORCE_KEY!,
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use separate encrypted durable transaction/session stores implementing
|
|
117
|
+
`XKOVAWorkforceStore`. Each write must commit independently of a later callback
|
|
118
|
+
error. Serialize each reference across replicas, and make `replace` fail when
|
|
119
|
+
the record is absent. The included PostgreSQL adapter demonstrates this contract.
|
|
120
|
+
Use a distinct namespace from member sessions. Keep session material, provider
|
|
121
|
+
proofs, PKCE verifiers and refresh attempts on the server.
|
|
122
|
+
|
|
123
|
+
`beginAuthorization` returns the registered provider endpoint, audience, nonce,
|
|
124
|
+
PKCE challenge and policy. Use a short-lived HttpOnly flow cookie for its state.
|
|
125
|
+
Your BFF exchanges the real provider code and verifies its signature, issuer,
|
|
126
|
+
audience, nonce and PKCE through `completeAuthorizationCallback`. XKOVA performs
|
|
127
|
+
its own registered-provider verification before issuing the workforce session.
|
|
128
|
+
An uncertain provider exchange cannot redeem the code again. A staged proof can
|
|
129
|
+
recover the same API exchange attempt. A provider token's actual expiry bounds
|
|
130
|
+
the session; refreshing XKOVA credentials does not refresh upstream identity.
|
|
131
|
+
|
|
132
|
+
Read only `projectXKOVAWorkforceSession` into browser UI. Resolve resource access
|
|
133
|
+
per request with `resolveResources({ reference, sessionStore, browserOrigin })`.
|
|
134
|
+
The browser's Origin and session-bound CSRF proof must be checked before writes.
|
|
135
|
+
The BFF pins its registered origin, workforce application and resolved human
|
|
136
|
+
session. Roles/scopes/resources are intersected by the API, never combined with
|
|
137
|
+
the transport principal's authority. A member credential cannot supply workforce
|
|
138
|
+
authority, and workforce sessions cannot enter Console operator routes.
|
|
139
|
+
|
|
140
|
+
For `human_authorization_required`, preserve the exact request, body, origin and
|
|
141
|
+
idempotency key in a private review record. Use `inspectAction` and
|
|
142
|
+
`beginActionProof` for its exact `authorization_token`. Show the returned review
|
|
143
|
+
before starting real fresh provider authentication with the returned nonce and
|
|
144
|
+
qualified assurance policy. Validate the provider callback's own state, PKCE,
|
|
145
|
+
issuer, audience, nonce and current subject; require fresh authentication rather
|
|
146
|
+
than accepting a cached login. Submit the real token with `completeActionProof`.
|
|
147
|
+
Keep its short-lived grant server-side and pass it as `actionGrant` to
|
|
148
|
+
`resolveResources` for only the unchanged frozen request. A grant never approves
|
|
149
|
+
another request or replaces independent Safe signatures/quorum. These methods
|
|
150
|
+
do not automatically retry an action or an uncertain proof completion.
|
|
151
|
+
|
|
152
|
+
`logoutSession` durably blocks the local session before retiring it at XKOVA.
|
|
153
|
+
Retry only that same logout if the network result is uncertain. It does not
|
|
154
|
+
promise a global logout at the external provider. No request may fall back to a
|
|
155
|
+
machine principal after workforce authentication fails.
|
|
156
|
+
|
|
157
|
+
The resolved `wallets` resource supports `list`, `provision`, `register` and
|
|
158
|
+
`signingBootstrap`. Provisioning and signing need the exact one-use human grant.
|
|
159
|
+
Register only after signing the API's returned enrollment typed data. Signing
|
|
160
|
+
bootstrap requires the existing proposal ID, its frozen Safe digest and nonce.
|
|
161
|
+
Use `@xkova/browser/wallet` for the isolated browser ceremony, with a fresh
|
|
162
|
+
purpose-bound admission and the expected wallet address. Keep the BFF key,
|
|
163
|
+
provider proofs and workforce session credentials on the server. Provider
|
|
164
|
+
admission does not replace wallet possession, current signer eligibility,
|
|
165
|
+
independent-person quorum or confirmed chain settlement.
|
|
166
|
+
|
|
167
|
+
Workforce session staff IDs and assigned treasury/token IDs use the API's
|
|
168
|
+
canonical 22-character base62 bodies (`stf_`, `vlt_`, `ctk_`). Preserve these
|
|
169
|
+
opaque values exactly. Server SDK alpha.9 fixes alpha.8's incorrect rejection
|
|
170
|
+
of these API responses. The separate enrollment typed-data UUID strings must
|
|
171
|
+
also remain unchanged; they are not the session's public resource IDs.
|
|
172
|
+
|
|
96
173
|
Call resource methods with typed inputs:
|
|
97
174
|
|
|
98
175
|
```ts
|
|
@@ -113,6 +190,48 @@ const paymentRequests = await xkova.paymentRequests.list({ limit: 25 });
|
|
|
113
190
|
|
|
114
191
|
Writes accept an optional caller-provided `idempotencyKey`. Reuse the same key when retrying the same logical request. If omitted, the SDK generates a new key for that individual call.
|
|
115
192
|
|
|
193
|
+
Optional mutation queries follow the existing mutation options. For contact
|
|
194
|
+
search, pass the returned cursor to fetch another page; each page is a distinct
|
|
195
|
+
request, so use a new idempotency key or leave the options undefined:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
const matches = await xkova.contacts.search(
|
|
199
|
+
{ account_holder_id: holderId, email: contactEmail },
|
|
200
|
+
undefined,
|
|
201
|
+
{ cursor: nextCursor, limit: 25 },
|
|
202
|
+
);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Signer removal accepts its explicit acknowledgement as the fourth argument:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
await xkova.treasury.deleteSigner(
|
|
209
|
+
vaultId,
|
|
210
|
+
signerStaffId,
|
|
211
|
+
{ idempotencyKey: crypto.randomUUID() },
|
|
212
|
+
{ acknowledged_unsafe: true },
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Set that flag only after reviewing the reduced lost-key safety buffer. Omission
|
|
217
|
+
keeps the API's normal safety check; the SDK never selects acknowledgement.
|
|
218
|
+
The API's minimum threshold, human authorization, current signer authority and
|
|
219
|
+
other controls still apply.
|
|
220
|
+
|
|
221
|
+
Optional bodies for webhook secret rotation, token pause/unpause and access
|
|
222
|
+
registry disable follow the existing mutation options as a third argument:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
await xkova.webhooks.rotateSecret(
|
|
226
|
+
endpointId,
|
|
227
|
+
{ idempotencyKey: crypto.randomUUID() },
|
|
228
|
+
{ overlap_sec: 120 },
|
|
229
|
+
);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Omitting that body keeps the API's default behavior. If a token operation's
|
|
233
|
+
body includes `idempotencyKey`, keep it equal to the mutation option's key.
|
|
234
|
+
|
|
116
235
|
Account-holder `self` methods require a member session and its application's
|
|
117
236
|
publishable key. Load both from your BFF's session store. These methods act on
|
|
118
237
|
the signed-in account holder; browser input cannot select a different person:
|
|
@@ -124,6 +243,10 @@ const balance = await xkova.accountHolders.selfBalance({
|
|
|
124
243
|
});
|
|
125
244
|
```
|
|
126
245
|
|
|
246
|
+
`selfBalance` can return a partial answer. A chain not known right now has no
|
|
247
|
+
entries in `balances` and a null `through_block` in `data_freshness`, so check
|
|
248
|
+
that before treating a missing token as zero or adding balances together.
|
|
249
|
+
|
|
127
250
|
## Register a Hosted Auth application
|
|
128
251
|
|
|
129
252
|
Hosted Auth provides an optional XKOVA-hosted sign-in flow. Register an
|
|
@@ -197,26 +320,17 @@ For your own OIDC provider, use `beginAuthorization` and
|
|
|
197
320
|
code unless your integration explicitly assigns that exchange to XKOVA. Both
|
|
198
321
|
sign-in paths use the same XKOVA session and store contracts.
|
|
199
322
|
|
|
200
|
-
###
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
`
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
Keep the same pending reservation and transaction after an ambiguous admission
|
|
213
|
-
failure. Repeating the method uses the same idempotency key and recovers the
|
|
214
|
-
same demo account reservation. The method never retries automatically.
|
|
215
|
-
`isDefinitiveXKOVASandboxDemoAdmissionFailure(error)` identifies confirmed
|
|
216
|
-
rejection before an account was reserved; network, malformed-response, and
|
|
217
|
-
unknown server failures can leave the reservation outcome uncertain.
|
|
218
|
-
API errors retain their status, correlation ID, and Retry-After. Both admission
|
|
219
|
-
and session requests reject HTTP redirects.
|
|
323
|
+
### Local development
|
|
324
|
+
|
|
325
|
+
The SDK accepts HTTP API URLs, browser origins, callbacks, and storage URLs on
|
|
326
|
+
`localhost` and `127.0.0.1`. Remote hosts require HTTPS. Register each origin
|
|
327
|
+
and callback with its exact scheme, host, port, and path. These two local hosts
|
|
328
|
+
are distinct origins; cookies and browser storage are not shared between them.
|
|
329
|
+
|
|
330
|
+
For local passkeys, serve the authentication page on `localhost` and use
|
|
331
|
+
`localhost` as its relying-party ID. An IP address cannot be a passkey
|
|
332
|
+
relying-party ID. Keep API keys and member sessions in your BFF, including
|
|
333
|
+
during local development.
|
|
220
334
|
|
|
221
335
|
### Stores and callback recovery
|
|
222
336
|
|
|
@@ -225,6 +339,26 @@ proofs, and manages session refresh and logout. Implement its session,
|
|
|
225
339
|
authorization-transaction, and direct proof-exchange store contracts in your
|
|
226
340
|
own database. It does not include a web framework or database adapter.
|
|
227
341
|
|
|
342
|
+
`runExclusive` is an exclusivity boundary, not an all-or-nothing SQL
|
|
343
|
+
transaction. Every awaited `put`, `replace` and `delete` must commit before
|
|
344
|
+
returning, and remain committed if later callback work throws. Wrapping the
|
|
345
|
+
whole callback in a rollback transaction can erase a staged proof after its
|
|
346
|
+
one-time provider code was consumed. The same rule protects refresh-attempt
|
|
347
|
+
checkpoints. Reconcile an uncertain write acknowledgement using the exact
|
|
348
|
+
record and attempt identity, rather than starting a new operation.
|
|
349
|
+
|
|
350
|
+
The package includes [a PostgreSQL checkpoint-store example](examples/postgres-checkpoint-store.mjs)
|
|
351
|
+
and its [application-owned table definition](examples/postgres-checkpoints.sql).
|
|
352
|
+
Install `pg` in your backend and apply the table definition through your own
|
|
353
|
+
migration process. Instantiate separate stores with namespaces such as
|
|
354
|
+
`authorization`, `sessions` and `exchange`, one shared pool and an existing
|
|
355
|
+
32-byte application encryption key. The example uses session advisory locks
|
|
356
|
+
across replicas, independent autocommit checkpoints, authenticated encryption
|
|
357
|
+
bound to namespace/reference, exact replacement without upsert, and connection
|
|
358
|
+
discard when lock release is uncertain. Do not use a transaction-pooling proxy
|
|
359
|
+
for session locks. Own key rotation, pool deadlines and expired-record cleanup
|
|
360
|
+
in your application; do not log records or encryption material.
|
|
361
|
+
|
|
228
362
|
Authorization, Account Center, and action transactions expire within ten
|
|
229
363
|
minutes of starting the request, or at the server's expiry if sooner. Late,
|
|
230
364
|
expired, or excessively long-lived responses are rejected. Keep your BFF's
|
|
@@ -255,8 +389,60 @@ To exchange a proof without a browser callback, call `establishSession` with an
|
|
|
255
389
|
`exchangeId`. Persist that ID before the first attempt and reuse it on retries.
|
|
256
390
|
The store serializes attempts and preserves the exchange and session references.
|
|
257
391
|
|
|
392
|
+
### Enroll an external identity-provider member
|
|
393
|
+
|
|
394
|
+
For a registered OIDC connection, the confidential backend can call
|
|
395
|
+
`memberAuth.enrollExternalMember({ externalSub, applicationConfigVersion,
|
|
396
|
+
idempotencyKey })`. Use the exact opaque subject from a fully verified provider
|
|
397
|
+
proof, the final read-back application configuration version, and one persisted
|
|
398
|
+
operation key. Never link by email. The API derives issuer namespace, tenant,
|
|
399
|
+
workspace and application from the registered connection and its bound
|
|
400
|
+
`member_auth` API principal. The header selector and body selector must match.
|
|
401
|
+
An existing issuer/subject membership is returned without replacing its identity,
|
|
402
|
+
status or wallet bindings. A held or closed member remains held or closed.
|
|
403
|
+
|
|
404
|
+
Enrollment creates or finds a membership, not an authenticated session or wallet.
|
|
405
|
+
The normal nonce-bound provider-proof exchange remains required. For callback
|
|
406
|
+
flows use `completeAuthorizationCallback`'s optional `ensureMemberEnrollment`
|
|
407
|
+
hook. It runs after the one-time provider proof is durably staged, with a stable
|
|
408
|
+
`idempotencyKey` preserved across retries. Verify the staged proof's signature,
|
|
409
|
+
issuer, audience, algorithm, expiry and nonce, then call `enrollExternalMember`
|
|
410
|
+
with its exact `sub`. Return that result from the hook. The helper checks that
|
|
411
|
+
the resulting authenticated session resolves to the enrolled account holder.
|
|
412
|
+
Do not put a fallible enrollment call inside `exchangeProviderCode`, before
|
|
413
|
+
the provider result has been staged. A version conflict requires reviewing the
|
|
414
|
+
changed registration and starting a new authorization flow, not blind retries.
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
const completion = await memberAuth.completeAuthorizationCallback({
|
|
418
|
+
...callbackInput,
|
|
419
|
+
ensureMemberEnrollment: async ({ proofToken, idempotencyKey }) => {
|
|
420
|
+
// This application function performs full JOSE and exact nonce validation.
|
|
421
|
+
const verified = await verifyRegisteredProviderProof(proofToken);
|
|
422
|
+
return memberAuth.enrollExternalMember({
|
|
423
|
+
externalSub: verified.sub,
|
|
424
|
+
applicationConfigVersion: registration.config_version,
|
|
425
|
+
idempotencyKey,
|
|
426
|
+
});
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
The verifier and `registration` are application prerequisites in this example,
|
|
432
|
+
not SDK-provided provider validation or discovery functions. The public endpoint
|
|
433
|
+
is `POST /v1/member-auth/enrollments`; it accepts no caller-selected account
|
|
434
|
+
holder, tenant, issuer namespace, email or permissions. Enrollment alone never
|
|
435
|
+
qualifies fresh action assurance, signing authority or settlement.
|
|
436
|
+
|
|
258
437
|
### Account Center and action callbacks
|
|
259
438
|
|
|
439
|
+
Direct Account Center starts accept `security`, `sessions`, or
|
|
440
|
+
`wallet_readiness`. Resource-bound actions start through the member action
|
|
441
|
+
flow; their shared callback result may contain the `action` intent. Refresh
|
|
442
|
+
preserves the session ID, account holder, and provider subject. A changed
|
|
443
|
+
identity is rejected before replacing stored credentials, including when
|
|
444
|
+
separate session validation is disabled for an immediate business request.
|
|
445
|
+
|
|
260
446
|
Account Center accepts a same-origin `applicationReturnUri` and preserves it
|
|
261
447
|
through successful callback recovery. Member actions separately accept
|
|
262
448
|
`applicationReviewUri` for cancellation or expiry and `applicationReturnUri`
|
|
@@ -344,6 +530,10 @@ Business requests use `no-store` and reject redirects so credentials cannot
|
|
|
344
530
|
follow a redirect. Network failures preserve the application session. Reuse the
|
|
345
531
|
original idempotency key when reconciling an uncertain write.
|
|
346
532
|
|
|
533
|
+
`resolved.resources.self.profile()` returns the current member's profile,
|
|
534
|
+
including email and name. These fields are display metadata, not authentication
|
|
535
|
+
proof. Read the profile when displaying it instead of caching it in the session.
|
|
536
|
+
|
|
347
537
|
`resolved.resources.self.verification()` returns the member's verification
|
|
348
538
|
requirements and sessions through the public self-verification operation.
|
|
349
539
|
`resolved.resources.self.uploadAvatar(image)` performs presign, object upload,
|
|
@@ -351,7 +541,7 @@ confirmation, and refreshed avatar lookup. Pass a nonempty PNG, JPEG, WebP, or G
|
|
|
351
541
|
`Blob` of at most 5 MiB. Storage receives only the image bytes and their content
|
|
352
542
|
headers, never bearer credentials, request signatures, member context, or cookies.
|
|
353
543
|
The helper rejects redirects, expired capabilities, URL credentials, and non-HTTPS
|
|
354
|
-
storage URLs (localhost
|
|
544
|
+
storage URLs (HTTP on `localhost` or `127.0.0.1` is permitted for local development). It does not
|
|
355
545
|
retry an upload. `XKOVAUploadError` identifies the object-storage stage without
|
|
356
546
|
exposing the signed URL; API failures retain `XKOVAApiError` metadata.
|
|
357
547
|
|
|
@@ -371,7 +561,44 @@ Durable application cookies use the host-only `__Host-` prefix, `Secure`, `HttpO
|
|
|
371
561
|
|
|
372
562
|
The publishable key is a non-secret application registration identifier. It grants no member or tenant authority by itself. The registered application pins tenant, workspace, environment, provider kind, issuer, audience, origins, redirects, and session policy, and must also match the authenticated workspace principal.
|
|
373
563
|
|
|
374
|
-
|
|
564
|
+
### Recover an existing member payment
|
|
565
|
+
|
|
566
|
+
Read recovery state through the resolved member resources:
|
|
567
|
+
|
|
568
|
+
```ts
|
|
569
|
+
const recovery = await resolved.resources.payments.recovery(paymentId);
|
|
570
|
+
// Call only after the member confirms cancellation in your app.
|
|
571
|
+
if (recovery.can_cancel) {
|
|
572
|
+
await resolved.resources.payments.cancelForMember(paymentId);
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
The API permits reads by the sender or recipient. Only the sender can cancel
|
|
577
|
+
or continue. The API principal needs `payment.read` and `payment.cancel`
|
|
578
|
+
permissions for these operations. Your BFF must validate the session, exact
|
|
579
|
+
Origin, and CSRF token before cancellation. Cancellation does not require a
|
|
580
|
+
passkey because it sends no value.
|
|
581
|
+
|
|
582
|
+
When `can_continue` is true, use `beginMemberAction()` with
|
|
583
|
+
`resourceType: 'payment'`, the existing `resourceId`, and `action: 'sign'`.
|
|
584
|
+
Complete fresh authorization through the registered provider. Keep the original
|
|
585
|
+
amount, recipient, fees, and deadline. Do not create a second payment or reuse
|
|
586
|
+
an expired signing credential. Recovery uses the payment ID, so a new valid
|
|
587
|
+
session for the same member can recover it without the original form draft.
|
|
588
|
+
|
|
589
|
+
`approval_expired` means the signing window has closed. It remains cancellable
|
|
590
|
+
until a signature has been accepted. After acceptance, `processing` disables
|
|
591
|
+
both actions. `cancelled`, `completed`, and `failed` are separate outcomes;
|
|
592
|
+
retain all three in history. These actions apply to payments; escrow
|
|
593
|
+
cancellation has its own authorization and settlement rules.
|
|
594
|
+
|
|
595
|
+
Availability can change between a read and a click. After a conflict or an
|
|
596
|
+
uncertain cancellation response, read recovery state again. Repeating an
|
|
597
|
+
already completed member cancellation returns the cancelled payment. Aborting
|
|
598
|
+
an HTTP request or cancelling an authorization ceremony does not cancel the
|
|
599
|
+
payment.
|
|
600
|
+
|
|
601
|
+
## Request cancellation and deadlines
|
|
375
602
|
|
|
376
603
|
Set `timeoutMs` on the client for a default request deadline. Mutation options and workflow polling also accept an `AbortSignal`:
|
|
377
604
|
|
|
@@ -386,6 +613,33 @@ await xkova.payments.cancel('pay_...', {
|
|
|
386
613
|
|
|
387
614
|
The SDK does not automatically retry writes. Use `withRetry` with a stable idempotency key when retry behavior is appropriate for your application.
|
|
388
615
|
|
|
616
|
+
## Product enrollment
|
|
617
|
+
|
|
618
|
+
After a member accepts your displayed terms, call
|
|
619
|
+
`resources.self.acceptProductEnrollment(product, { terms_version })` from the
|
|
620
|
+
BFF. Select the product and terms version on your server. Read the saved result
|
|
621
|
+
with `resources.self.productEnrollment(product)` when the member returns.
|
|
622
|
+
Acceptance does not require an `Idempotency-Key` header. Repeating the same
|
|
623
|
+
acceptance preserves its timestamp. Changed terms or credit parameters with the
|
|
624
|
+
same product are rejected.
|
|
625
|
+
|
|
626
|
+
Sandbox applications can include `sandbox_credit: { token_deployment_id,
|
|
627
|
+
amount }` to issue a test-token welcome credit. Use an active dUSDC deployment.
|
|
628
|
+
The credit is issued once per member, workspace, and product, across application
|
|
629
|
+
registrations. The daily workspace budget is 1000 dUSDC. Keep amounts and token
|
|
630
|
+
selection in the BFF, and give each product a stable identifier.
|
|
631
|
+
|
|
632
|
+
For Hosted Auth, set `require_passkey: true` to hold activation and the credit
|
|
633
|
+
until the member has an active passkey and has acknowledged recovery codes.
|
|
634
|
+
`setup_required` means terms are saved and security setup remains incomplete.
|
|
635
|
+
Open Account Center with the `security` intent, then read the enrollment again
|
|
636
|
+
on return. The setup requirement is fixed when the enrollment is accepted.
|
|
637
|
+
|
|
638
|
+
Poll the enrollment after acceptance. `opening` means delivery is pending;
|
|
639
|
+
`active` means the credit has a successful receipt and an indexed balance.
|
|
640
|
+
`requires_review` needs operator investigation. Do not create another product
|
|
641
|
+
identifier to retry an uncertain credit. Credits do not debit bank accounts.
|
|
642
|
+
|
|
389
643
|
## Errors
|
|
390
644
|
|
|
391
645
|
`XKOVAApiError.retryAfter` preserves the upstream `Retry-After` header when
|
|
@@ -405,6 +659,40 @@ try {
|
|
|
405
659
|
}
|
|
406
660
|
```
|
|
407
661
|
|
|
662
|
+
## Treasury vaults and transfer proposals
|
|
663
|
+
|
|
664
|
+
Use `client.treasury` from a trusted backend with the workspace's explicitly
|
|
665
|
+
granted treasury scopes and roles. Discover the chain and eligible assets before
|
|
666
|
+
creating a vault or proposal. An existing same-chain vault retains its real
|
|
667
|
+
owner set and threshold.
|
|
668
|
+
|
|
669
|
+
```ts
|
|
670
|
+
import { isHeldApproval } from '@xkova/sdk';
|
|
671
|
+
|
|
672
|
+
const vaults = await xkova.treasury.listWallets();
|
|
673
|
+
const proposal = await xkova.treasury.getTransfer('trf_...');
|
|
674
|
+
const counterparties = await xkova.treasury.listCounterparties({ limit: 20 });
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
Vault and counterparty setup can return a governance hold. Check `isHeldApproval`
|
|
678
|
+
before reading entity fields. Keep the original request and idempotency key;
|
|
679
|
+
resume through normal policy after independently eligible approvers complete the
|
|
680
|
+
required approval. The SDK does not approve, sign or retry a held operation.
|
|
681
|
+
|
|
682
|
+
`draftTransfer` creates a proposal. `getTransfer` reads its frozen signing context
|
|
683
|
+
and current quorum. Each eligible owner produces their own signature over that
|
|
684
|
+
exact Safe transaction. `submitTransferSignature` submits an existing signature;
|
|
685
|
+
it does not create a wallet or sign on anyone's behalf. `executeTransfer` retains
|
|
686
|
+
current role, signer, nonce, quorum and policy checks. A returned relay result is
|
|
687
|
+
not settlement; read the proposal until its actual confirmed or failed outcome.
|
|
688
|
+
After a timeout, reconcile the existing proposal before creating another one.
|
|
689
|
+
|
|
690
|
+
The API key's attributed staff ID is audit metadata, not a per-human session or
|
|
691
|
+
permission to bootstrap a staff wallet. This namespace does not expose Console
|
|
692
|
+
credentials, staff-wallet bootstrap credentials, or raw private-key material.
|
|
693
|
+
The supported workforce authentication and independent signer ceremonies remain
|
|
694
|
+
separate requirements for a complete customer treasury application.
|
|
695
|
+
|
|
408
696
|
## Webhooks and generated types
|
|
409
697
|
|
|
410
698
|
```ts
|
|
@@ -412,7 +700,19 @@ import { verifyWebhookSignature } from '@xkova/sdk/webhook';
|
|
|
412
700
|
import type { components, paths } from '@xkova/sdk/types';
|
|
413
701
|
```
|
|
414
702
|
|
|
415
|
-
Pass the raw request body to `verifyWebhookSignature`.
|
|
703
|
+
Pass the raw request body to `verifyWebhookSignature`. Import request and response types from `@xkova/sdk/types`.
|
|
704
|
+
|
|
705
|
+
Each `v1` signature must contain exactly 64 lowercase hexadecimal characters.
|
|
706
|
+
Malformed candidates are rejected without truncation; valid multiple-signature
|
|
707
|
+
rotation headers remain supported.
|
|
708
|
+
|
|
709
|
+
`tokenDeploy` submits once and observes the returned token until it is active.
|
|
710
|
+
Deployment operations cannot be read through the generic operation endpoint.
|
|
711
|
+
`tokenMint` waits for its exact mint operation to be confirmed before returning
|
|
712
|
+
the token. An already-active token does not establish mint success.
|
|
713
|
+
Cancellation, pending exhaustion, a failed operation, or an uncertain response
|
|
714
|
+
never causes these helpers to submit another mutation. Reconcile the retained
|
|
715
|
+
token or operation before deciding whether to retry explicitly.
|
|
416
716
|
|
|
417
717
|
The package also exposes `@xkova/sdk/rwa-verify` for offline RWA transparency proof verification and `@xkova/sdk/abi` for the documented customer contract ABIs.
|
|
418
718
|
|
|
@@ -432,14 +732,6 @@ idempotency, and settlement. It links the public customer OpenAPI and expanded
|
|
|
432
732
|
documentation. Installed declarations determine the methods available in your
|
|
433
733
|
version; live documentation may describe a newer release.
|
|
434
734
|
|
|
435
|
-
## Thirdweb and dependencies
|
|
436
|
-
|
|
437
|
-
The only direct runtime dependency is `viem`, used for offline RWA signature
|
|
438
|
-
verification. This SDK does not import Thirdweb. The optional `@xkova/browser`
|
|
439
|
-
browser companion has no runtime dependencies. XKOVA manages wallet signing,
|
|
440
|
-
and API provider metadata may name Thirdweb. You do not need to install its SDK
|
|
441
|
-
or obtain Thirdweb credentials.
|
|
442
|
-
|
|
443
735
|
## Contributing
|
|
444
736
|
|
|
445
737
|
Run `pnpm check` from the source repository root before committing. The
|
package/dist/abi.d.ts
CHANGED
|
@@ -336,6 +336,14 @@ export declare const erc20XGaslessAbi: readonly [{
|
|
|
336
336
|
readonly name: "";
|
|
337
337
|
readonly type: "string";
|
|
338
338
|
readonly internalType: "string";
|
|
339
|
+
}, {
|
|
340
|
+
readonly name: "";
|
|
341
|
+
readonly type: "uint8";
|
|
342
|
+
readonly internalType: "uint8";
|
|
343
|
+
}, {
|
|
344
|
+
readonly name: "";
|
|
345
|
+
readonly type: "address";
|
|
346
|
+
readonly internalType: "address";
|
|
339
347
|
}, {
|
|
340
348
|
readonly name: "";
|
|
341
349
|
readonly type: "address";
|
|
@@ -362,6 +370,10 @@ export declare const erc20XGaslessAbi: readonly [{
|
|
|
362
370
|
readonly name: "_symbol";
|
|
363
371
|
readonly type: "string";
|
|
364
372
|
readonly internalType: "string";
|
|
373
|
+
}, {
|
|
374
|
+
readonly name: "decimals_";
|
|
375
|
+
readonly type: "uint8";
|
|
376
|
+
readonly internalType: "uint8";
|
|
365
377
|
}, {
|
|
366
378
|
readonly name: "defaultAdmin";
|
|
367
379
|
readonly type: "address";
|
|
@@ -370,6 +382,10 @@ export declare const erc20XGaslessAbi: readonly [{
|
|
|
370
382
|
readonly name: "minter";
|
|
371
383
|
readonly type: "address";
|
|
372
384
|
readonly internalType: "address";
|
|
385
|
+
}, {
|
|
386
|
+
readonly name: "burner";
|
|
387
|
+
readonly type: "address";
|
|
388
|
+
readonly internalType: "address";
|
|
373
389
|
}, {
|
|
374
390
|
readonly name: "pauser";
|
|
375
391
|
readonly type: "address";
|
|
@@ -1062,6 +1078,10 @@ export declare const erc20XGaslessAbi: readonly [{
|
|
|
1062
1078
|
readonly type: "error";
|
|
1063
1079
|
readonly name: "InvalidAddress";
|
|
1064
1080
|
readonly inputs: readonly [];
|
|
1081
|
+
}, {
|
|
1082
|
+
readonly type: "error";
|
|
1083
|
+
readonly name: "InvalidDecimals";
|
|
1084
|
+
readonly inputs: readonly [];
|
|
1065
1085
|
}, {
|
|
1066
1086
|
readonly type: "error";
|
|
1067
1087
|
readonly name: "InvalidImplementation";
|
|
@@ -5482,6 +5502,14 @@ export declare const tokenizationAbis: {
|
|
|
5482
5502
|
readonly name: "";
|
|
5483
5503
|
readonly type: "string";
|
|
5484
5504
|
readonly internalType: "string";
|
|
5505
|
+
}, {
|
|
5506
|
+
readonly name: "";
|
|
5507
|
+
readonly type: "uint8";
|
|
5508
|
+
readonly internalType: "uint8";
|
|
5509
|
+
}, {
|
|
5510
|
+
readonly name: "";
|
|
5511
|
+
readonly type: "address";
|
|
5512
|
+
readonly internalType: "address";
|
|
5485
5513
|
}, {
|
|
5486
5514
|
readonly name: "";
|
|
5487
5515
|
readonly type: "address";
|
|
@@ -5508,6 +5536,10 @@ export declare const tokenizationAbis: {
|
|
|
5508
5536
|
readonly name: "_symbol";
|
|
5509
5537
|
readonly type: "string";
|
|
5510
5538
|
readonly internalType: "string";
|
|
5539
|
+
}, {
|
|
5540
|
+
readonly name: "decimals_";
|
|
5541
|
+
readonly type: "uint8";
|
|
5542
|
+
readonly internalType: "uint8";
|
|
5511
5543
|
}, {
|
|
5512
5544
|
readonly name: "defaultAdmin";
|
|
5513
5545
|
readonly type: "address";
|
|
@@ -5516,6 +5548,10 @@ export declare const tokenizationAbis: {
|
|
|
5516
5548
|
readonly name: "minter";
|
|
5517
5549
|
readonly type: "address";
|
|
5518
5550
|
readonly internalType: "address";
|
|
5551
|
+
}, {
|
|
5552
|
+
readonly name: "burner";
|
|
5553
|
+
readonly type: "address";
|
|
5554
|
+
readonly internalType: "address";
|
|
5519
5555
|
}, {
|
|
5520
5556
|
readonly name: "pauser";
|
|
5521
5557
|
readonly type: "address";
|
|
@@ -6208,6 +6244,10 @@ export declare const tokenizationAbis: {
|
|
|
6208
6244
|
readonly type: "error";
|
|
6209
6245
|
readonly name: "InvalidAddress";
|
|
6210
6246
|
readonly inputs: readonly [];
|
|
6247
|
+
}, {
|
|
6248
|
+
readonly type: "error";
|
|
6249
|
+
readonly name: "InvalidDecimals";
|
|
6250
|
+
readonly inputs: readonly [];
|
|
6211
6251
|
}, {
|
|
6212
6252
|
readonly type: "error";
|
|
6213
6253
|
readonly name: "InvalidImplementation";
|
package/dist/abi.js
CHANGED
|
@@ -443,6 +443,16 @@ export const erc20XGaslessAbi = [
|
|
|
443
443
|
"type": "string",
|
|
444
444
|
"internalType": "string"
|
|
445
445
|
},
|
|
446
|
+
{
|
|
447
|
+
"name": "",
|
|
448
|
+
"type": "uint8",
|
|
449
|
+
"internalType": "uint8"
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"name": "",
|
|
453
|
+
"type": "address",
|
|
454
|
+
"internalType": "address"
|
|
455
|
+
},
|
|
446
456
|
{
|
|
447
457
|
"name": "",
|
|
448
458
|
"type": "address",
|
|
@@ -476,6 +486,11 @@ export const erc20XGaslessAbi = [
|
|
|
476
486
|
"type": "string",
|
|
477
487
|
"internalType": "string"
|
|
478
488
|
},
|
|
489
|
+
{
|
|
490
|
+
"name": "decimals_",
|
|
491
|
+
"type": "uint8",
|
|
492
|
+
"internalType": "uint8"
|
|
493
|
+
},
|
|
479
494
|
{
|
|
480
495
|
"name": "defaultAdmin",
|
|
481
496
|
"type": "address",
|
|
@@ -486,6 +501,11 @@ export const erc20XGaslessAbi = [
|
|
|
486
501
|
"type": "address",
|
|
487
502
|
"internalType": "address"
|
|
488
503
|
},
|
|
504
|
+
{
|
|
505
|
+
"name": "burner",
|
|
506
|
+
"type": "address",
|
|
507
|
+
"internalType": "address"
|
|
508
|
+
},
|
|
489
509
|
{
|
|
490
510
|
"name": "pauser",
|
|
491
511
|
"type": "address",
|
|
@@ -1376,6 +1396,11 @@ export const erc20XGaslessAbi = [
|
|
|
1376
1396
|
"name": "InvalidAddress",
|
|
1377
1397
|
"inputs": []
|
|
1378
1398
|
},
|
|
1399
|
+
{
|
|
1400
|
+
"type": "error",
|
|
1401
|
+
"name": "InvalidDecimals",
|
|
1402
|
+
"inputs": []
|
|
1403
|
+
},
|
|
1379
1404
|
{
|
|
1380
1405
|
"type": "error",
|
|
1381
1406
|
"name": "InvalidImplementation",
|
package/dist/client.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { RampsResource } from './resources/ramps.js';
|
|
|
13
13
|
import { RwaResource } from './resources/rwa.js';
|
|
14
14
|
import { TenantResource } from './resources/tenant.js';
|
|
15
15
|
import { TokenizationResource } from './resources/tokenization.js';
|
|
16
|
+
import { TreasuryResource } from './resources/treasury.js';
|
|
16
17
|
import { TransactionsResource } from './resources/transactions.js';
|
|
17
18
|
import { WalletsResource } from './resources/wallets.js';
|
|
18
19
|
import { WebhooksResource } from './resources/webhooks.js';
|
|
@@ -47,6 +48,7 @@ export interface XKOVAMutationOptions extends XKOVARequestControl {
|
|
|
47
48
|
export declare class XKOVAClient {
|
|
48
49
|
private readonly config;
|
|
49
50
|
private readonly memberContext?;
|
|
51
|
+
private readonly workforceContext?;
|
|
50
52
|
private readonly apiBaseUrl;
|
|
51
53
|
private readonly fetchImpl;
|
|
52
54
|
private constructor();
|
|
@@ -65,6 +67,8 @@ export declare class XKOVAClient {
|
|
|
65
67
|
get rwa(): RwaResource;
|
|
66
68
|
get tenant(): TenantResource;
|
|
67
69
|
get tokenization(): TokenizationResource;
|
|
70
|
+
/** Tenant treasury operations retain server-side roles, governance and signer checks. */
|
|
71
|
+
get treasury(): TreasuryResource;
|
|
68
72
|
get transactions(): TransactionsResource;
|
|
69
73
|
get wallets(): WalletsResource;
|
|
70
74
|
get webhooks(): WebhooksResource;
|