@xkova/sdk 0.1.0-alpha.2 → 0.1.0-alpha.4
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 +114 -27
- package/dist/client.js +3 -2
- package/dist/generated/types.d.ts +526 -327
- package/dist/member-action-intents.js +2 -2
- package/dist/member-bff.d.ts +0 -16
- package/dist/member-bff.js +10 -70
- package/dist/member-resources.d.ts +50 -0
- package/dist/member-resources.js +3 -0
- package/dist/resources/account-holders.d.ts +24 -0
- package/dist/resources/account-holders.js +8 -2
- package/dist/resources/payments.d.ts +13 -0
- package/dist/resources/payments.js +7 -0
- package/dist/resources/ramps.d.ts +72 -63
- package/dist/resources/rwa.d.ts +9 -9
- package/dist/url.d.ts +1 -0
- package/dist/url.js +4 -0
- package/llms.txt +20 -0
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { isAllowedProtocol } from './url.js';
|
|
2
3
|
export class XKOVAMemberIntentError extends Error {
|
|
3
4
|
code;
|
|
4
5
|
status;
|
|
@@ -33,8 +34,7 @@ export class XKOVAMemberActionIntents {
|
|
|
33
34
|
location.username ||
|
|
34
35
|
location.password ||
|
|
35
36
|
location.hash ||
|
|
36
|
-
(location
|
|
37
|
-
!(location.protocol === 'http:' && location.hostname === 'localhost')))
|
|
37
|
+
!isAllowedProtocol(location))
|
|
38
38
|
throw new TypeError('Action review requires the exact application origin');
|
|
39
39
|
const snapshot = JSON.parse(canonicalJson({
|
|
40
40
|
request: input.request,
|
package/dist/member-bff.d.ts
CHANGED
|
@@ -350,20 +350,6 @@ export declare class XKOVAMemberBffClient {
|
|
|
350
350
|
readonly redirectUri: string;
|
|
351
351
|
readonly transactionStore: XKOVAMemberAuthorizationTransactionStore<TApplicationData>;
|
|
352
352
|
}): Promise<XKOVAHostedMemberAuthorizationStart>;
|
|
353
|
-
/**
|
|
354
|
-
* Available only to sandbox applications enabled for demo sign-in. The stored
|
|
355
|
-
* Hosted transaction determines the demo account and callback. An uncertain
|
|
356
|
-
* response preserves the key so a retry recovers the same reservation.
|
|
357
|
-
* Complete the returned callback using
|
|
358
|
-
* completeHostedAuthorization and the original browser flow cookie.
|
|
359
|
-
*/
|
|
360
|
-
completeSandboxDemoAuthorization<TApplicationData>(input: {
|
|
361
|
-
readonly state: string;
|
|
362
|
-
readonly transactionStore: XKOVAMemberAuthorizationTransactionStore<TApplicationData>;
|
|
363
|
-
}): Promise<{
|
|
364
|
-
readonly callbackUrl: string;
|
|
365
|
-
readonly expiresAt: string;
|
|
366
|
-
}>;
|
|
367
353
|
/**
|
|
368
354
|
* Completes the one-time Hosted Auth result-code exchange and persists the
|
|
369
355
|
* provider-neutral XKOVA member session. The returned projection is safe for
|
|
@@ -492,8 +478,6 @@ export declare class XKOVAMemberBffClient {
|
|
|
492
478
|
private readSessionMaterial;
|
|
493
479
|
private requestSignal;
|
|
494
480
|
}
|
|
495
|
-
/** Only confirmed admission rejections may release a customer's pending demo reservation. */
|
|
496
|
-
export declare function isDefinitiveXKOVASandboxDemoAdmissionFailure(error: unknown): boolean;
|
|
497
481
|
export declare function projectXKOVAMemberSession(session: XKOVAMemberContext): XKOVABrowserMemberProjection;
|
|
498
482
|
export declare function serializeXKOVAMemberSessionCookie(input: {
|
|
499
483
|
readonly cookieName: string;
|
package/dist/member-bff.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
|
|
2
2
|
import { XKOVAApiError } from './errors.js';
|
|
3
|
+
import { isAllowedProtocol } from './url.js';
|
|
3
4
|
import { XKOVAClient } from './client.js';
|
|
4
5
|
import { XKOVAMemberResources } from './member-resources.js';
|
|
5
6
|
import { XKOVAMemberActionIntents, } from './member-action-intents.js';
|
|
@@ -195,54 +196,6 @@ export class XKOVAMemberBffClient {
|
|
|
195
196
|
throw error;
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
|
-
/**
|
|
199
|
-
* Available only to sandbox applications enabled for demo sign-in. The stored
|
|
200
|
-
* Hosted transaction determines the demo account and callback. An uncertain
|
|
201
|
-
* response preserves the key so a retry recovers the same reservation.
|
|
202
|
-
* Complete the returned callback using
|
|
203
|
-
* completeHostedAuthorization and the original browser flow cookie.
|
|
204
|
-
*/
|
|
205
|
-
async completeSandboxDemoAuthorization(input) {
|
|
206
|
-
if (!this.options.apiKey.startsWith('xkv_test_') ||
|
|
207
|
-
!this.options.publishableKey.startsWith('xkova_pk_sandbox_')) {
|
|
208
|
-
throw new XKOVAMemberAuthorizationTerminalError('provider_rejected', 'Demo admission requires a sandbox application');
|
|
209
|
-
}
|
|
210
|
-
const stateHash = hashOpaque(input.state);
|
|
211
|
-
return input.transactionStore.runExclusive(stateHash, async () => {
|
|
212
|
-
const transaction = await input.transactionStore.get(stateHash);
|
|
213
|
-
if (!transaction || transaction.expiresAt <= Date.now()) {
|
|
214
|
-
throw new XKOVAMemberAuthorizationTerminalError('transaction_unavailable', 'Demo admission requires an active Hosted transaction');
|
|
215
|
-
}
|
|
216
|
-
assertMemberBffClientFingerprint(transaction.clientFingerprint, this.clientFingerprint);
|
|
217
|
-
if (transaction.status !== 'pending' ||
|
|
218
|
-
transaction.completionMode !== 'hosted_result_code' ||
|
|
219
|
-
!transaction.authorizationUrl) {
|
|
220
|
-
throw new XKOVAMemberAuthorizationTerminalError('transaction_unavailable', 'Demo admission requires a completed Hosted start');
|
|
221
|
-
}
|
|
222
|
-
const authorization = new URL(normalizeHostedAuthorizationUrl(transaction.authorizationUrl));
|
|
223
|
-
const capability = authorization.searchParams.get('transaction');
|
|
224
|
-
if (!/^\/authorize\/?$/.test(authorization.pathname) ||
|
|
225
|
-
!capability ||
|
|
226
|
-
!/^[A-Za-z0-9_-]{43}$/.test(capability)) {
|
|
227
|
-
throw new XKOVAMemberAuthorizationTerminalError('transaction_unavailable', 'Demo admission capability is invalid');
|
|
228
|
-
}
|
|
229
|
-
const value = await this.postJson('/member-auth/hosted/authorizations/sandbox-demo', { transaction: capability }, undefined, `sandbox-demo-${stateHash}`);
|
|
230
|
-
const body = requireObject(value, 'Sandbox demo admission');
|
|
231
|
-
const { expiresAt } = boundedAuthorizationExpiry(body, transaction.expiresAt, 'Sandbox demo admission');
|
|
232
|
-
const callback = new URL(requireString(body, 'redirect_url', 'Sandbox demo admission'));
|
|
233
|
-
const code = callback.searchParams.get('code');
|
|
234
|
-
if (!sameCallback(callback, new URL(transaction.redirectUri)) ||
|
|
235
|
-
callback.searchParams.getAll('state').length !== 1 ||
|
|
236
|
-
callback.searchParams.get('state') !== input.state ||
|
|
237
|
-
callback.searchParams.getAll('code').length !== 1 ||
|
|
238
|
-
!code ||
|
|
239
|
-
callback.searchParams.has('error')) {
|
|
240
|
-
throw new Error('Sandbox demo admission returned the wrong callback binding');
|
|
241
|
-
}
|
|
242
|
-
assertHostedAuthorizationResultCode(code);
|
|
243
|
-
return { callbackUrl: callback.toString(), expiresAt };
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
199
|
/**
|
|
247
200
|
* Completes the one-time Hosted Auth result-code exchange and persists the
|
|
248
201
|
* provider-neutral XKOVA member session. The returned projection is safe for
|
|
@@ -560,7 +513,7 @@ export class XKOVAMemberBffClient {
|
|
|
560
513
|
clientFingerprint: this.clientFingerprint,
|
|
561
514
|
codeVerifier,
|
|
562
515
|
redirectUri: returnUri,
|
|
563
|
-
exchangeAttemptId:
|
|
516
|
+
exchangeAttemptId: randomUUID(),
|
|
564
517
|
sessionReference: input.sessionReference,
|
|
565
518
|
intent: 'action',
|
|
566
519
|
...(applicationReturnUri !== undefined && { applicationReturnUri }),
|
|
@@ -1210,14 +1163,6 @@ export class XKOVAMemberBffClient {
|
|
|
1210
1163
|
: AbortSignal.timeout(this.options.timeoutMs);
|
|
1211
1164
|
}
|
|
1212
1165
|
}
|
|
1213
|
-
/** Only confirmed admission rejections may release a customer's pending demo reservation. */
|
|
1214
|
-
export function isDefinitiveXKOVASandboxDemoAdmissionFailure(error) {
|
|
1215
|
-
return (error instanceof XKOVAMemberAuthorizationTerminalError ||
|
|
1216
|
-
(error instanceof XKOVAApiError &&
|
|
1217
|
-
(error.status < 500 ||
|
|
1218
|
-
error.code === 'demo_persona_unavailable' ||
|
|
1219
|
-
error.code === 'demo_login_disabled')));
|
|
1220
|
-
}
|
|
1221
1166
|
export function projectXKOVAMemberSession(session) {
|
|
1222
1167
|
return {
|
|
1223
1168
|
signedIn: true,
|
|
@@ -1339,8 +1284,8 @@ function normalizeApiBaseUrl(baseUrl) {
|
|
|
1339
1284
|
if (url.username || url.password || url.search || url.hash) {
|
|
1340
1285
|
throw new TypeError('XKOVA member BFF baseUrl must be an API origin or /v1 base URL');
|
|
1341
1286
|
}
|
|
1342
|
-
if (
|
|
1343
|
-
throw new TypeError('XKOVA member BFF baseUrl must use HTTPS or
|
|
1287
|
+
if (!isAllowedProtocol(url)) {
|
|
1288
|
+
throw new TypeError('XKOVA member BFF baseUrl must use HTTPS or loopback HTTP');
|
|
1344
1289
|
}
|
|
1345
1290
|
const pathname = url.pathname.replace(/\/+$/, '');
|
|
1346
1291
|
if (pathname !== '' && pathname !== '/v1') {
|
|
@@ -1353,16 +1298,15 @@ function normalizeCallbackUri(value) {
|
|
|
1353
1298
|
if (url.username || url.password || url.search || url.hash) {
|
|
1354
1299
|
throw new TypeError('member authorization redirectUri must not contain credentials, query, or fragment');
|
|
1355
1300
|
}
|
|
1356
|
-
if (
|
|
1357
|
-
throw new TypeError('member authorization redirectUri must use HTTPS or
|
|
1301
|
+
if (!isAllowedProtocol(url)) {
|
|
1302
|
+
throw new TypeError('member authorization redirectUri must use HTTPS or loopback HTTP');
|
|
1358
1303
|
}
|
|
1359
1304
|
return url.toString();
|
|
1360
1305
|
}
|
|
1361
1306
|
function normalizeBrowserOrigin(value) {
|
|
1362
1307
|
const url = new URL(value);
|
|
1363
|
-
if (url.origin !== value ||
|
|
1364
|
-
|
|
1365
|
-
throw new TypeError('member authorization browserOrigin must be an exact HTTPS or localhost origin');
|
|
1308
|
+
if (url.origin !== value || !isAllowedProtocol(url)) {
|
|
1309
|
+
throw new TypeError('member authorization browserOrigin must be an exact HTTPS or loopback origin');
|
|
1366
1310
|
}
|
|
1367
1311
|
return value;
|
|
1368
1312
|
}
|
|
@@ -1372,18 +1316,14 @@ function normalizeApplicationReturnUri(value, browserOrigin) {
|
|
|
1372
1316
|
url.username ||
|
|
1373
1317
|
url.password ||
|
|
1374
1318
|
url.hash ||
|
|
1375
|
-
|
|
1319
|
+
!isAllowedProtocol(url)) {
|
|
1376
1320
|
throw new TypeError('member action applicationReturnUri must use the exact browser origin');
|
|
1377
1321
|
}
|
|
1378
1322
|
return url.toString();
|
|
1379
1323
|
}
|
|
1380
1324
|
function normalizeHostedAuthorizationUrl(value) {
|
|
1381
1325
|
const url = new URL(value);
|
|
1382
|
-
if (url.username ||
|
|
1383
|
-
url.password ||
|
|
1384
|
-
url.hash ||
|
|
1385
|
-
(url.protocol !== 'https:' &&
|
|
1386
|
-
!(url.protocol === 'http:' && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')))) {
|
|
1326
|
+
if (url.username || url.password || url.hash || !isAllowedProtocol(url)) {
|
|
1387
1327
|
throw new Error('XKOVA member Hosted authorization URL must use HTTPS or loopback HTTP without credentials or a fragment');
|
|
1388
1328
|
}
|
|
1389
1329
|
return url.toString();
|
|
@@ -18,6 +18,56 @@ export declare class XKOVAMemberResources {
|
|
|
18
18
|
get paymentRequests(): import("./resources/index.js").PaymentRequestsResource;
|
|
19
19
|
get wallets(): import("./resources/index.js").WalletsResource;
|
|
20
20
|
readonly self: {
|
|
21
|
+
profile: () => Promise<{
|
|
22
|
+
id: import("./generated/types.js").components["schemas"]["AccountHolderId"];
|
|
23
|
+
tenant_id?: string;
|
|
24
|
+
state: "active" | "held" | "closed" | "closed_uncooperative" | "provisioning_failed";
|
|
25
|
+
state_reason?: string | null;
|
|
26
|
+
state_changed_at?: import("./generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
27
|
+
tier: "tier_1" | "tier_2";
|
|
28
|
+
tier_2_uplift_status?: "not_requested" | "pending" | "passed" | "failed";
|
|
29
|
+
first_use_completed: boolean;
|
|
30
|
+
cip_payload?: {
|
|
31
|
+
name_hash?: string;
|
|
32
|
+
dob_hash?: string;
|
|
33
|
+
id_hash?: string;
|
|
34
|
+
address_hash?: string;
|
|
35
|
+
} | null;
|
|
36
|
+
cip_accepted_at?: import("./generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
37
|
+
merchant_role_state?: "none" | "pending_review" | "approved" | "rejected" | "revoked";
|
|
38
|
+
auto_save_contacts?: boolean;
|
|
39
|
+
created_at: import("./generated/types.js").components["schemas"]["TimestampUtc"];
|
|
40
|
+
updated_at?: import("./generated/types.js").components["schemas"]["TimestampUtc"];
|
|
41
|
+
email?: string | null;
|
|
42
|
+
first_name?: string | null;
|
|
43
|
+
last_name?: string | null;
|
|
44
|
+
phone?: string | null;
|
|
45
|
+
avatar_url?: string | null;
|
|
46
|
+
}>;
|
|
47
|
+
productEnrollment: (product: string, control?: XKOVARequestControl) => Promise<{
|
|
48
|
+
product: string;
|
|
49
|
+
status: "not_opened" | "setup_required" | "opening" | "active" | "requires_review";
|
|
50
|
+
terms_version: string | null;
|
|
51
|
+
accepted_at: string | null;
|
|
52
|
+
credit: {
|
|
53
|
+
amount: string;
|
|
54
|
+
token_deployment_id: string;
|
|
55
|
+
status: "pending" | "submitted" | "settled" | "requires_review";
|
|
56
|
+
transaction_hash: string | null;
|
|
57
|
+
} | null;
|
|
58
|
+
}>;
|
|
59
|
+
acceptProductEnrollment: (product: string, body: ReqBody<"acceptAccountHolderSelfProductEnrollment">, opts?: XKOVAMutationOptions) => Promise<{
|
|
60
|
+
product: string;
|
|
61
|
+
status: "not_opened" | "setup_required" | "opening" | "active" | "requires_review";
|
|
62
|
+
terms_version: string | null;
|
|
63
|
+
accepted_at: string | null;
|
|
64
|
+
credit: {
|
|
65
|
+
amount: string;
|
|
66
|
+
token_deployment_id: string;
|
|
67
|
+
status: "pending" | "submitted" | "settled" | "requires_review";
|
|
68
|
+
transaction_hash: string | null;
|
|
69
|
+
} | null;
|
|
70
|
+
}>;
|
|
21
71
|
actionReadiness: (control?: XKOVARequestControl) => Promise<{
|
|
22
72
|
authorization_method: "hosted_passkey" | "external_oidc";
|
|
23
73
|
setup_status: "passkey_required" | "recovery_acknowledgement_required" | "recovery_required" | "ready" | "externally_managed";
|
package/dist/member-resources.js
CHANGED
|
@@ -31,6 +31,9 @@ export class XKOVAMemberResources {
|
|
|
31
31
|
return this.client.wallets;
|
|
32
32
|
}
|
|
33
33
|
self = {
|
|
34
|
+
profile: () => this.client.accountHolders.retrieve(this.accountHolderId),
|
|
35
|
+
productEnrollment: (product, control) => this.client.accountHolders.selfProductEnrollment(this.context, product, control),
|
|
36
|
+
acceptProductEnrollment: (product, body, opts) => this.client.accountHolders.acceptSelfProductEnrollment(this.context, product, body, opts),
|
|
34
37
|
actionReadiness: (control) => this.client.accountHolders.selfActionReadiness({ ...this.context, accountHolderId: this.accountHolderId }, control),
|
|
35
38
|
sandboxBankingContext: (control) => this.client.accountHolders.selfSandboxBankingContext(this.context, control),
|
|
36
39
|
verification: (control) => this.client.accountHolders.selfVerification(this.context, control),
|
|
@@ -118,6 +118,30 @@ export declare class AccountHoldersResource extends Resource {
|
|
|
118
118
|
}[];
|
|
119
119
|
verification_url: string | null;
|
|
120
120
|
}>;
|
|
121
|
+
selfProductEnrollment(context: XKOVAMemberSessionContext, product: string, control?: XKOVARequestControl): Promise<{
|
|
122
|
+
product: string;
|
|
123
|
+
status: "not_opened" | "setup_required" | "opening" | "active" | "requires_review";
|
|
124
|
+
terms_version: string | null;
|
|
125
|
+
accepted_at: string | null;
|
|
126
|
+
credit: {
|
|
127
|
+
amount: string;
|
|
128
|
+
token_deployment_id: string;
|
|
129
|
+
status: "pending" | "submitted" | "settled" | "requires_review";
|
|
130
|
+
transaction_hash: string | null;
|
|
131
|
+
} | null;
|
|
132
|
+
}>;
|
|
133
|
+
acceptSelfProductEnrollment(context: XKOVAMemberSessionContext, product: string, body: ReqBody<'acceptAccountHolderSelfProductEnrollment'>, opts?: XKOVAMutationOptions): Promise<{
|
|
134
|
+
product: string;
|
|
135
|
+
status: "not_opened" | "setup_required" | "opening" | "active" | "requires_review";
|
|
136
|
+
terms_version: string | null;
|
|
137
|
+
accepted_at: string | null;
|
|
138
|
+
credit: {
|
|
139
|
+
amount: string;
|
|
140
|
+
token_deployment_id: string;
|
|
141
|
+
status: "pending" | "submitted" | "settled" | "requires_review";
|
|
142
|
+
transaction_hash: string | null;
|
|
143
|
+
} | null;
|
|
144
|
+
}>;
|
|
121
145
|
selfBalance(context: XKOVAMemberSessionContext, control?: XKOVARequestControl): Promise<{
|
|
122
146
|
balances: import("../generated/types.js").components["schemas"]["AccountHolderSelfBalanceEntry"][];
|
|
123
147
|
}>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Resource } from './base.js';
|
|
2
2
|
import { XKOVAUploadError } from '../errors.js';
|
|
3
|
+
import { isAllowedProtocol } from '../url.js';
|
|
3
4
|
function memberSessionHeaders(context) {
|
|
4
5
|
return {
|
|
5
6
|
'X-Member-Session-Id': context.memberSessionId,
|
|
@@ -30,6 +31,12 @@ export class AccountHoldersResource extends Resource {
|
|
|
30
31
|
selfVerification(context, control) {
|
|
31
32
|
return this.getJson('/account-holders/self/verification', undefined, control, memberSessionHeaders(context));
|
|
32
33
|
}
|
|
34
|
+
selfProductEnrollment(context, product, control) {
|
|
35
|
+
return this.getJson(`/account-holders/self/product-enrollments/${this.enc(product)}`, undefined, control, memberSessionHeaders(context));
|
|
36
|
+
}
|
|
37
|
+
acceptSelfProductEnrollment(context, product, body, opts) {
|
|
38
|
+
return this.postJson(`/account-holders/self/product-enrollments/${this.enc(product)}`, body, opts, undefined, memberSessionHeaders(context));
|
|
39
|
+
}
|
|
33
40
|
selfBalance(context, control) {
|
|
34
41
|
return this.getJson('/account-holders/self/balance', undefined, control, memberSessionHeaders(context));
|
|
35
42
|
}
|
|
@@ -115,8 +122,7 @@ export class AccountHoldersResource extends Resource {
|
|
|
115
122
|
if (target.username ||
|
|
116
123
|
target.password ||
|
|
117
124
|
target.hash ||
|
|
118
|
-
(target
|
|
119
|
-
!(target.protocol === 'http:' && target.hostname === 'localhost')) ||
|
|
125
|
+
!isAllowedProtocol(target) ||
|
|
120
126
|
!Number.isFinite(Date.parse(upload.expires_at)) ||
|
|
121
127
|
Date.parse(upload.expires_at) <= Date.now()) {
|
|
122
128
|
throw new XKOVAUploadError('The avatar upload capability is invalid or expired');
|
|
@@ -178,5 +178,18 @@ export declare class PaymentsResource extends Resource {
|
|
|
178
178
|
created_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
179
179
|
finalized_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
180
180
|
}>;
|
|
181
|
+
/** Requires a resolved member session. Only the sender can continue or cancel. */
|
|
182
|
+
recovery(id: string): Promise<{
|
|
183
|
+
payment: import("../generated/types.js").components["schemas"]["Payment"];
|
|
184
|
+
state: "awaiting_approval" | "approval_expired" | "on_hold" | "processing" | "completed" | "cancelled" | "failed";
|
|
185
|
+
can_continue: boolean;
|
|
186
|
+
can_cancel: boolean;
|
|
187
|
+
}>;
|
|
188
|
+
cancelForMember(id: string, opts?: XKOVAMutationOptions): Promise<{
|
|
189
|
+
payment: import("../generated/types.js").components["schemas"]["Payment"];
|
|
190
|
+
state: "awaiting_approval" | "approval_expired" | "on_hold" | "processing" | "completed" | "cancelled" | "failed";
|
|
191
|
+
can_continue: boolean;
|
|
192
|
+
can_cancel: boolean;
|
|
193
|
+
}>;
|
|
181
194
|
}
|
|
182
195
|
export {};
|
|
@@ -30,4 +30,11 @@ export class PaymentsResource extends Resource {
|
|
|
30
30
|
cancel(id, opts) {
|
|
31
31
|
return this.postJson(`/payments/${this.enc(id)}/cancel`, undefined, opts);
|
|
32
32
|
}
|
|
33
|
+
/** Requires a resolved member session. Only the sender can continue or cancel. */
|
|
34
|
+
recovery(id) {
|
|
35
|
+
return this.getJson(`/account-holders/self/payments/${this.enc(id)}/recovery`);
|
|
36
|
+
}
|
|
37
|
+
cancelForMember(id, opts) {
|
|
38
|
+
return this.postJson(`/account-holders/self/payments/${this.enc(id)}/cancel`, undefined, opts);
|
|
39
|
+
}
|
|
33
40
|
}
|
|
@@ -11,31 +11,34 @@ export declare class RampsResource extends Resource {
|
|
|
11
11
|
has_more: boolean;
|
|
12
12
|
}>;
|
|
13
13
|
createFunding(body: ReqBody<'createFundingRequest'>, opts?: RampRequestOptions): Promise<{
|
|
14
|
-
id
|
|
15
|
-
tenant_id
|
|
16
|
-
workspace_id
|
|
14
|
+
id: import("../generated/types.js").components["schemas"]["FundingRequestId"];
|
|
15
|
+
tenant_id: string;
|
|
16
|
+
workspace_id: string;
|
|
17
17
|
chain: import("../generated/types.js").components["schemas"]["ChainDescriptor"];
|
|
18
|
-
account_holder_id
|
|
19
|
-
amount
|
|
20
|
-
currency
|
|
21
|
-
state
|
|
22
|
-
failure_reason_code
|
|
23
|
-
x_partner_reference
|
|
24
|
-
quote_id
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
account_holder_id: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
19
|
+
amount: import("../generated/types.js").components["schemas"]["Money"];
|
|
20
|
+
currency: string;
|
|
21
|
+
state: "pending_compliance" | "pending_issuance" | "settled" | "failed";
|
|
22
|
+
failure_reason_code: string | null;
|
|
23
|
+
x_partner_reference: string | null;
|
|
24
|
+
quote_id: string | null;
|
|
25
|
+
quote_rate: string | null;
|
|
26
|
+
quote_stablecoin_amount: import("../generated/types.js").components["schemas"]["Money"] | null;
|
|
27
|
+
quote_partner_fee_fiat: import("../generated/types.js").components["schemas"]["Money"] | null;
|
|
28
|
+
bank_debit_transfer_id: string | null;
|
|
29
|
+
partner_status: string | null;
|
|
30
|
+
last_event_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
31
|
+
metadata: {
|
|
29
32
|
[key: string]: unknown;
|
|
30
33
|
} | null;
|
|
31
34
|
settlement_order: "hold_first" | "debit_first" | null;
|
|
32
|
-
idempotency_key
|
|
33
|
-
correlation_id
|
|
34
|
-
ramp_profile
|
|
35
|
-
hosted_redirect_url
|
|
36
|
-
created_at
|
|
37
|
-
updated_at
|
|
38
|
-
settled_at
|
|
35
|
+
idempotency_key: string;
|
|
36
|
+
correlation_id: string;
|
|
37
|
+
ramp_profile: "mock" | "sandbox" | "coinbase";
|
|
38
|
+
hosted_redirect_url: string | null;
|
|
39
|
+
created_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
40
|
+
updated_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
41
|
+
settled_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
39
42
|
}>;
|
|
40
43
|
/**
|
|
41
44
|
* One-call sandbox funding convenience. This invokes the normal funding
|
|
@@ -43,58 +46,64 @@ export declare class RampsResource extends Resource {
|
|
|
43
46
|
* resource, state transitions, webhooks, and idempotency behavior.
|
|
44
47
|
*/
|
|
45
48
|
fundSandboxWallet(body: SandboxFundingBody, opts?: RampRequestOptions): Promise<{
|
|
46
|
-
id
|
|
47
|
-
tenant_id
|
|
48
|
-
workspace_id
|
|
49
|
+
id: import("../generated/types.js").components["schemas"]["FundingRequestId"];
|
|
50
|
+
tenant_id: string;
|
|
51
|
+
workspace_id: string;
|
|
49
52
|
chain: import("../generated/types.js").components["schemas"]["ChainDescriptor"];
|
|
50
|
-
account_holder_id
|
|
51
|
-
amount
|
|
52
|
-
currency
|
|
53
|
-
state
|
|
54
|
-
failure_reason_code
|
|
55
|
-
x_partner_reference
|
|
56
|
-
quote_id
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
account_holder_id: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
54
|
+
amount: import("../generated/types.js").components["schemas"]["Money"];
|
|
55
|
+
currency: string;
|
|
56
|
+
state: "pending_compliance" | "pending_issuance" | "settled" | "failed";
|
|
57
|
+
failure_reason_code: string | null;
|
|
58
|
+
x_partner_reference: string | null;
|
|
59
|
+
quote_id: string | null;
|
|
60
|
+
quote_rate: string | null;
|
|
61
|
+
quote_stablecoin_amount: import("../generated/types.js").components["schemas"]["Money"] | null;
|
|
62
|
+
quote_partner_fee_fiat: import("../generated/types.js").components["schemas"]["Money"] | null;
|
|
63
|
+
bank_debit_transfer_id: string | null;
|
|
64
|
+
partner_status: string | null;
|
|
65
|
+
last_event_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
66
|
+
metadata: {
|
|
61
67
|
[key: string]: unknown;
|
|
62
68
|
} | null;
|
|
63
69
|
settlement_order: "hold_first" | "debit_first" | null;
|
|
64
|
-
idempotency_key
|
|
65
|
-
correlation_id
|
|
66
|
-
ramp_profile
|
|
67
|
-
hosted_redirect_url
|
|
68
|
-
created_at
|
|
69
|
-
updated_at
|
|
70
|
-
settled_at
|
|
70
|
+
idempotency_key: string;
|
|
71
|
+
correlation_id: string;
|
|
72
|
+
ramp_profile: "mock" | "sandbox" | "coinbase";
|
|
73
|
+
hosted_redirect_url: string | null;
|
|
74
|
+
created_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
75
|
+
updated_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
76
|
+
settled_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
71
77
|
}>;
|
|
72
78
|
getFunding(id: string): Promise<{
|
|
73
|
-
id
|
|
74
|
-
tenant_id
|
|
75
|
-
workspace_id
|
|
79
|
+
id: import("../generated/types.js").components["schemas"]["FundingRequestId"];
|
|
80
|
+
tenant_id: string;
|
|
81
|
+
workspace_id: string;
|
|
76
82
|
chain: import("../generated/types.js").components["schemas"]["ChainDescriptor"];
|
|
77
|
-
account_holder_id
|
|
78
|
-
amount
|
|
79
|
-
currency
|
|
80
|
-
state
|
|
81
|
-
failure_reason_code
|
|
82
|
-
x_partner_reference
|
|
83
|
-
quote_id
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
account_holder_id: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
84
|
+
amount: import("../generated/types.js").components["schemas"]["Money"];
|
|
85
|
+
currency: string;
|
|
86
|
+
state: "pending_compliance" | "pending_issuance" | "settled" | "failed";
|
|
87
|
+
failure_reason_code: string | null;
|
|
88
|
+
x_partner_reference: string | null;
|
|
89
|
+
quote_id: string | null;
|
|
90
|
+
quote_rate: string | null;
|
|
91
|
+
quote_stablecoin_amount: import("../generated/types.js").components["schemas"]["Money"] | null;
|
|
92
|
+
quote_partner_fee_fiat: import("../generated/types.js").components["schemas"]["Money"] | null;
|
|
93
|
+
bank_debit_transfer_id: string | null;
|
|
94
|
+
partner_status: string | null;
|
|
95
|
+
last_event_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
96
|
+
metadata: {
|
|
88
97
|
[key: string]: unknown;
|
|
89
98
|
} | null;
|
|
90
99
|
settlement_order: "hold_first" | "debit_first" | null;
|
|
91
|
-
idempotency_key
|
|
92
|
-
correlation_id
|
|
93
|
-
ramp_profile
|
|
94
|
-
hosted_redirect_url
|
|
95
|
-
created_at
|
|
96
|
-
updated_at
|
|
97
|
-
settled_at
|
|
100
|
+
idempotency_key: string;
|
|
101
|
+
correlation_id: string;
|
|
102
|
+
ramp_profile: "mock" | "sandbox" | "coinbase";
|
|
103
|
+
hosted_redirect_url: string | null;
|
|
104
|
+
created_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
105
|
+
updated_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
106
|
+
settled_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
98
107
|
}>;
|
|
99
108
|
listOffRamp(query?: Query<'listOffRampRequests'>): Promise<{
|
|
100
109
|
data: import("../generated/types.js").components["schemas"]["OffRampRequest"][];
|
package/dist/resources/rwa.d.ts
CHANGED
|
@@ -75,10 +75,10 @@ export declare class RwaResource extends Resource {
|
|
|
75
75
|
bound_at: string;
|
|
76
76
|
}>;
|
|
77
77
|
proposeSchemaRebind(body: ReqBody<'proposeRwaSchemaRebind'>, opts?: XKOVAMutationOptions): Promise<{
|
|
78
|
-
ceremony_id:
|
|
78
|
+
ceremony_id: import("../generated/types.js").components["schemas"]["SchemaRebindId"];
|
|
79
79
|
}>;
|
|
80
80
|
getSchemaRebind(id: string): Promise<{
|
|
81
|
-
id:
|
|
81
|
+
id: import("../generated/types.js").components["schemas"]["SchemaRebindId"];
|
|
82
82
|
status: "proposed" | "dry_run_passed" | "dry_run_failed" | "attested" | "committed" | "failed";
|
|
83
83
|
asset_schema_id: string;
|
|
84
84
|
from_version: number;
|
|
@@ -119,7 +119,7 @@ export declare class RwaResource extends Resource {
|
|
|
119
119
|
submitAttestedEntry(tokenId: string, fieldPath: string, body: ReqBody<'submitRwaAttestedEntry'>, opts?: XKOVAMutationOptions): Promise<{
|
|
120
120
|
committed: boolean;
|
|
121
121
|
deduped: boolean;
|
|
122
|
-
attester_id:
|
|
122
|
+
attester_id: import("../generated/types.js").components["schemas"]["RwaAttesterId"];
|
|
123
123
|
attester_address: string;
|
|
124
124
|
attested_digest: string;
|
|
125
125
|
}>;
|
|
@@ -183,7 +183,7 @@ export declare class RwaResource extends Resource {
|
|
|
183
183
|
created_at: string;
|
|
184
184
|
}>;
|
|
185
185
|
createCorporateAction(tokenId: string, body: ReqBody<'createRwaCorporateAction'>, opts?: XKOVAMutationOptions): Promise<{
|
|
186
|
-
id:
|
|
186
|
+
id: import("../generated/types.js").components["schemas"]["CorporateActionId"];
|
|
187
187
|
customer_token_id: string;
|
|
188
188
|
kind: "redemption" | "split" | "consolidation" | "additional_issuance" | "capital_call" | "mandatory_conversion";
|
|
189
189
|
state: string;
|
|
@@ -201,7 +201,7 @@ export declare class RwaResource extends Resource {
|
|
|
201
201
|
created_at: string;
|
|
202
202
|
}>;
|
|
203
203
|
getCorporateAction(tokenId: string, caId: string): Promise<{
|
|
204
|
-
id:
|
|
204
|
+
id: import("../generated/types.js").components["schemas"]["CorporateActionId"];
|
|
205
205
|
customer_token_id: string;
|
|
206
206
|
kind: "redemption" | "split" | "consolidation" | "additional_issuance" | "capital_call" | "mandatory_conversion";
|
|
207
207
|
state: string;
|
|
@@ -219,7 +219,7 @@ export declare class RwaResource extends Resource {
|
|
|
219
219
|
created_at: string;
|
|
220
220
|
}>;
|
|
221
221
|
advanceCorporateAction(tokenId: string, caId: string, opts?: XKOVAMutationOptions): Promise<{
|
|
222
|
-
id:
|
|
222
|
+
id: import("../generated/types.js").components["schemas"]["CorporateActionId"];
|
|
223
223
|
customer_token_id: string;
|
|
224
224
|
kind: "redemption" | "split" | "consolidation" | "additional_issuance" | "capital_call" | "mandatory_conversion";
|
|
225
225
|
state: string;
|
|
@@ -285,7 +285,7 @@ export declare class RwaResource extends Resource {
|
|
|
285
285
|
reason: string;
|
|
286
286
|
}>;
|
|
287
287
|
listAttesters(tokenId: string): Promise<{
|
|
288
|
-
id:
|
|
288
|
+
id: import("../generated/types.js").components["schemas"]["RwaAttesterId"];
|
|
289
289
|
customer_token_id: string | null;
|
|
290
290
|
display_name: string;
|
|
291
291
|
attester_address: string;
|
|
@@ -294,7 +294,7 @@ export declare class RwaResource extends Resource {
|
|
|
294
294
|
created_at: string;
|
|
295
295
|
}[]>;
|
|
296
296
|
registerAttester(tokenId: string, body: ReqBody<'registerRwaAttester'>, opts?: XKOVAMutationOptions): Promise<{
|
|
297
|
-
id:
|
|
297
|
+
id: import("../generated/types.js").components["schemas"]["RwaAttesterId"];
|
|
298
298
|
customer_token_id: string | null;
|
|
299
299
|
display_name: string;
|
|
300
300
|
attester_address: string;
|
|
@@ -303,7 +303,7 @@ export declare class RwaResource extends Resource {
|
|
|
303
303
|
created_at: string;
|
|
304
304
|
}>;
|
|
305
305
|
revokeAttester(tokenId: string, attesterId: string, opts?: XKOVAMutationOptions): Promise<{
|
|
306
|
-
id:
|
|
306
|
+
id: import("../generated/types.js").components["schemas"]["RwaAttesterId"];
|
|
307
307
|
customer_token_id: string | null;
|
|
308
308
|
display_name: string;
|
|
309
309
|
attester_address: string;
|
package/dist/url.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isAllowedProtocol(url: URL): boolean;
|
package/dist/url.js
ADDED
package/llms.txt
CHANGED
|
@@ -74,6 +74,26 @@ API availability does not grant permission. Product entitlement, selected API-ke
|
|
|
74
74
|
- Reuse one createMemberActionReference() from @xkova/browser for a durable review. Save the draft before setup detours. Expired or missing reviews require checking activity and an explicit new review.
|
|
75
75
|
- Setup readiness is advisory. beginMemberAction() and completeMemberAction() obtain fresh approval for the exact resource. Browser code must not receive provider wallet credentials or internal signing capabilities. Completion of authorization is distinct from execution and settlement.
|
|
76
76
|
|
|
77
|
+
## Payment recovery
|
|
78
|
+
|
|
79
|
+
Use resolved.resources.payments.recovery(paymentId) to read the current
|
|
80
|
+
member's payment and available actions. Only the sender can continue or cancel.
|
|
81
|
+
On explicit cancellation, call cancelForMember(paymentId) after BFF session,
|
|
82
|
+
Origin and CSRF checks. The principal needs payment.read and payment.cancel.
|
|
83
|
+
Cancellation sends no value and does not require a passkey.
|
|
84
|
+
|
|
85
|
+
Continue only when can_continue is true. Begin a fresh member action for the
|
|
86
|
+
same payment resourceId with action sign, then complete the registered proof
|
|
87
|
+
ceremony. Never create another payment, change its fees or deadline, or reuse
|
|
88
|
+
an expired signing credential. A new session for the same member can recover
|
|
89
|
+
the payment without its original draft. Expired approvals remain cancellable;
|
|
90
|
+
accepted signatures close cancellation. Keep cancelled payments in history.
|
|
91
|
+
After a conflict or uncertain cancellation, re-read state before another action.
|
|
92
|
+
|
|
77
93
|
## Before handing off code
|
|
78
94
|
|
|
79
95
|
List the Console setup and stores the application needs. Test denied access, uncertain writes, pagination, cancellation, and terminal outcomes. Report a missing method or setup requirement explicitly. Do not invent methods, suppress type errors, or bypass authorization to make an example run.
|
|
96
|
+
|
|
97
|
+
## Product opt-in
|
|
98
|
+
|
|
99
|
+
Use resolveResources().self.productEnrollment(product) to read acceptance and credit status. After explicit consent, call self.acceptProductEnrollment(product, { terms_version, sandbox_credit? }). The BFF chooses the product, terms, amount, and token. Reads do not enroll members. Acceptance needs no Idempotency-Key header; reuse the same product and parameters when retrying. Sandbox credits are dUSDC only and issued once per workspace/member/product; the workspace daily budget is 1000 dUSDC. Poll opening until active. Treat requires_review as unresolved delivery, never as permission to request a second product credit.
|