@invonetwork/web-sdk 0.2.1 → 0.4.0
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/CHANGELOG.md +48 -1
- package/LICENSE +18 -17
- package/README.md +495 -393
- package/dist/chunk-EEWOAUXO.js +249 -0
- package/dist/index.cjs +188 -63
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.js +54 -31
- package/dist/server.cjs +474 -59
- package/dist/server.d.cts +177 -13
- package/dist/server.d.ts +177 -13
- package/dist/server.js +339 -29
- package/dist/{errors-DV5QsftP.d.cts → types-CBMLNwbe.d.cts} +152 -42
- package/dist/{errors-DV5QsftP.d.ts → types-CBMLNwbe.d.ts} +152 -42
- package/package.json +10 -2
- package/dist/chunk-A44O4KC3.js +0 -147
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ClientConfig, A as ApproveResult,
|
|
2
|
-
export { I as InvoError, R as Rail, V as VerificationMethod } from './
|
|
1
|
+
import { C as ClientConfig, a as CallOptions, A as ApproveResult, b as ConfirmReceiptResult, L as LinkDeviceResult } from './types-CBMLNwbe.js';
|
|
2
|
+
export { I as InvoError, c as InvoErrorInfo, d as InvoHooks, e as InvoRequestInfo, f as InvoResponseInfo, R as Rail, V as VerificationMethod } from './types-CBMLNwbe.js';
|
|
3
3
|
|
|
4
4
|
declare class InvoClient {
|
|
5
5
|
private readonly http;
|
|
@@ -10,19 +10,19 @@ declare class InvoClient {
|
|
|
10
10
|
constructor(config: ClientConfig);
|
|
11
11
|
private assertWebAuthn;
|
|
12
12
|
/** Enroll a passkey for the token's identity (register/begin -> create() -> register/complete). */
|
|
13
|
-
enrollPasskey(): Promise<{
|
|
13
|
+
enrollPasskey(opts?: CallOptions): Promise<{
|
|
14
14
|
status: string;
|
|
15
15
|
device: unknown;
|
|
16
16
|
raw: Record<string, unknown>;
|
|
17
17
|
}>;
|
|
18
18
|
/** Approve a SEND with the player's passkey. */
|
|
19
|
-
approveSend(transactionId: string): Promise<ApproveResult>;
|
|
19
|
+
approveSend(transactionId: string, opts?: CallOptions): Promise<ApproveResult>;
|
|
20
20
|
/** Approve a TRANSFER with the player's passkey (returns the sender's claim code). */
|
|
21
|
-
approveTransfer(transactionId: string): Promise<ApproveResult>;
|
|
21
|
+
approveTransfer(transactionId: string, opts?: CallOptions): Promise<ApproveResult>;
|
|
22
22
|
/** Recipient self-claims a SEND with their passkey. */
|
|
23
|
-
confirmReceiptSend(transactionId: string): Promise<ConfirmReceiptResult>;
|
|
23
|
+
confirmReceiptSend(transactionId: string, opts?: CallOptions): Promise<ConfirmReceiptResult>;
|
|
24
24
|
/** Recipient self-claims a TRANSFER with their passkey. */
|
|
25
|
-
confirmReceiptTransfer(transactionId: string): Promise<ConfirmReceiptResult>;
|
|
25
|
+
confirmReceiptTransfer(transactionId: string, opts?: CallOptions): Promise<ConfirmReceiptResult>;
|
|
26
26
|
/**
|
|
27
27
|
* Interchangeable methods (§4.6): prove an *already-enrolled* method (e.g. the
|
|
28
28
|
* INVO app device key) to authorize adding a new partner passkey. The returned
|
|
@@ -31,7 +31,7 @@ declare class InvoClient {
|
|
|
31
31
|
*
|
|
32
32
|
* begin -> navigator.credentials.get() -> complete with { link_id, webauthn_assertion }.
|
|
33
33
|
*/
|
|
34
|
-
linkDevice(linkId: string): Promise<LinkDeviceResult>;
|
|
34
|
+
linkDevice(linkId: string, opts?: CallOptions): Promise<LinkDeviceResult>;
|
|
35
35
|
/** POST with the current player token. Token-expiry retry is handled one level
|
|
36
36
|
* up by withTokenRetry (which re-runs the whole ceremony, not a single call). */
|
|
37
37
|
private post;
|
|
@@ -49,4 +49,4 @@ declare class InvoClient {
|
|
|
49
49
|
private confirmReceipt;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export { ApproveResult, ClientConfig, ConfirmReceiptResult, InvoClient, LinkDeviceResult };
|
|
52
|
+
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, InvoClient, LinkDeviceResult };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { assertSecureBaseUrl, Http, InvoError } from './chunk-
|
|
2
|
-
export { InvoError } from './chunk-
|
|
1
|
+
import { assertSecureBaseUrl, Http, InvoError } from './chunk-EEWOAUXO.js';
|
|
2
|
+
export { InvoError } from './chunk-EEWOAUXO.js';
|
|
3
3
|
|
|
4
4
|
// src/shared/webauthn.ts
|
|
5
5
|
function b64urlToBuffer(value) {
|
|
@@ -91,7 +91,10 @@ var InvoClient = class {
|
|
|
91
91
|
this.http = new Http({
|
|
92
92
|
baseUrl: config.baseUrl,
|
|
93
93
|
timeoutMs: config.timeoutMs,
|
|
94
|
-
fetchImpl: config.fetch
|
|
94
|
+
fetchImpl: config.fetch,
|
|
95
|
+
maxRetries: config.maxRetries,
|
|
96
|
+
retryBaseDelayMs: config.retryBaseDelayMs,
|
|
97
|
+
hooks: config.hooks
|
|
95
98
|
// Browser: do NOT set User-Agent (forbidden header); the browser's own UA is fine.
|
|
96
99
|
});
|
|
97
100
|
this.auth = { kind: "bearer", token: config.token };
|
|
@@ -103,38 +106,43 @@ var InvoClient = class {
|
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
108
|
/** Enroll a passkey for the token's identity (register/begin -> create() -> register/complete). */
|
|
106
|
-
async enrollPasskey() {
|
|
109
|
+
async enrollPasskey(opts) {
|
|
107
110
|
this.assertWebAuthn();
|
|
111
|
+
const signal = opts?.signal;
|
|
108
112
|
return this.withTokenRetry(async () => {
|
|
109
113
|
const options = await this.post(
|
|
110
|
-
"/api/sdk/webauthn/register/begin"
|
|
114
|
+
"/api/sdk/webauthn/register/begin",
|
|
115
|
+
void 0,
|
|
116
|
+
signal
|
|
111
117
|
);
|
|
112
118
|
const cred = await navigator.credentials.create({
|
|
113
|
-
publicKey: toCreationOptions(options)
|
|
119
|
+
publicKey: toCreationOptions(options),
|
|
120
|
+
signal
|
|
114
121
|
});
|
|
115
122
|
if (!cred) throw new Error("Passkey creation was cancelled or returned no credential.");
|
|
116
123
|
const raw = await this.post(
|
|
117
124
|
"/api/sdk/webauthn/register/complete",
|
|
118
|
-
{ credential: registrationToJSON(cred) }
|
|
125
|
+
{ credential: registrationToJSON(cred) },
|
|
126
|
+
signal
|
|
119
127
|
);
|
|
120
128
|
return { status: String(raw["status"] ?? ""), device: raw["device"] ?? null, raw };
|
|
121
129
|
});
|
|
122
130
|
}
|
|
123
131
|
/** Approve a SEND with the player's passkey. */
|
|
124
|
-
async approveSend(transactionId) {
|
|
125
|
-
return this.approve("send", transactionId);
|
|
132
|
+
async approveSend(transactionId, opts) {
|
|
133
|
+
return this.approve("send", transactionId, opts);
|
|
126
134
|
}
|
|
127
135
|
/** Approve a TRANSFER with the player's passkey (returns the sender's claim code). */
|
|
128
|
-
async approveTransfer(transactionId) {
|
|
129
|
-
return this.approve("transfers", transactionId);
|
|
136
|
+
async approveTransfer(transactionId, opts) {
|
|
137
|
+
return this.approve("transfers", transactionId, opts);
|
|
130
138
|
}
|
|
131
139
|
/** Recipient self-claims a SEND with their passkey. */
|
|
132
|
-
async confirmReceiptSend(transactionId) {
|
|
133
|
-
return this.confirmReceipt("send", transactionId);
|
|
140
|
+
async confirmReceiptSend(transactionId, opts) {
|
|
141
|
+
return this.confirmReceipt("send", transactionId, opts);
|
|
134
142
|
}
|
|
135
143
|
/** Recipient self-claims a TRANSFER with their passkey. */
|
|
136
|
-
async confirmReceiptTransfer(transactionId) {
|
|
137
|
-
return this.confirmReceipt("transfers", transactionId);
|
|
144
|
+
async confirmReceiptTransfer(transactionId, opts) {
|
|
145
|
+
return this.confirmReceipt("transfers", transactionId, opts);
|
|
138
146
|
}
|
|
139
147
|
/**
|
|
140
148
|
* Interchangeable methods (§4.6): prove an *already-enrolled* method (e.g. the
|
|
@@ -144,15 +152,19 @@ var InvoClient = class {
|
|
|
144
152
|
*
|
|
145
153
|
* begin -> navigator.credentials.get() -> complete with { link_id, webauthn_assertion }.
|
|
146
154
|
*/
|
|
147
|
-
async linkDevice(linkId) {
|
|
155
|
+
async linkDevice(linkId, opts) {
|
|
148
156
|
if (!linkId) throw new Error("linkDevice requires a `linkId`.");
|
|
157
|
+
const signal = opts?.signal;
|
|
149
158
|
return this.withTokenRetry(async () => {
|
|
150
|
-
const assertion = await this.runAssertion(
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
const assertion = await this.runAssertion(
|
|
160
|
+
"/api/sdk/device/link/webauthn/begin",
|
|
161
|
+
{ link_id: linkId },
|
|
162
|
+
signal
|
|
163
|
+
);
|
|
153
164
|
const raw = await this.post(
|
|
154
165
|
"/api/sdk/device/link/webauthn/complete",
|
|
155
|
-
{ link_id: linkId, webauthn_assertion: assertion }
|
|
166
|
+
{ link_id: linkId, webauthn_assertion: assertion },
|
|
167
|
+
signal
|
|
156
168
|
);
|
|
157
169
|
return { status: String(raw["status"] ?? ""), raw };
|
|
158
170
|
});
|
|
@@ -160,8 +172,8 @@ var InvoClient = class {
|
|
|
160
172
|
// --- internals ---
|
|
161
173
|
/** POST with the current player token. Token-expiry retry is handled one level
|
|
162
174
|
* up by withTokenRetry (which re-runs the whole ceremony, not a single call). */
|
|
163
|
-
async post(path, body) {
|
|
164
|
-
return this.http.post(path, body, this.auth);
|
|
175
|
+
async post(path, body, signal) {
|
|
176
|
+
return this.http.post(path, body, this.auth, { signal });
|
|
165
177
|
}
|
|
166
178
|
/**
|
|
167
179
|
* Run a whole flow, retrying it ONCE if any call fails with SDK_TOKEN_EXPIRED
|
|
@@ -192,22 +204,29 @@ var InvoClient = class {
|
|
|
192
204
|
this.auth = { kind: "bearer", token: fresh };
|
|
193
205
|
return true;
|
|
194
206
|
}
|
|
195
|
-
async runAssertion(beginPath, beginBody) {
|
|
207
|
+
async runAssertion(beginPath, beginBody, signal) {
|
|
196
208
|
this.assertWebAuthn();
|
|
197
|
-
const options = await this.post(beginPath, beginBody);
|
|
209
|
+
const options = await this.post(beginPath, beginBody, signal);
|
|
198
210
|
const cred = await navigator.credentials.get({
|
|
199
|
-
publicKey: toRequestOptions(options)
|
|
211
|
+
publicKey: toRequestOptions(options),
|
|
212
|
+
signal
|
|
200
213
|
});
|
|
201
214
|
if (!cred) throw new Error("Passkey assertion was cancelled or returned no credential.");
|
|
202
215
|
return assertionToJSON(cred);
|
|
203
216
|
}
|
|
204
|
-
async approve(flow, transactionId) {
|
|
217
|
+
async approve(flow, transactionId, opts) {
|
|
205
218
|
const id = encodeURIComponent(transactionId);
|
|
219
|
+
const signal = opts?.signal;
|
|
206
220
|
return this.withTokenRetry(async () => {
|
|
207
|
-
const assertion = await this.runAssertion(
|
|
221
|
+
const assertion = await this.runAssertion(
|
|
222
|
+
`/api/sdk/${flow}/${id}/approve/webauthn/begin`,
|
|
223
|
+
void 0,
|
|
224
|
+
signal
|
|
225
|
+
);
|
|
208
226
|
const raw = await this.post(
|
|
209
227
|
`/api/sdk/${flow}/${id}/approve`,
|
|
210
|
-
{ webauthn_assertion: assertion }
|
|
228
|
+
{ webauthn_assertion: assertion },
|
|
229
|
+
signal
|
|
211
230
|
);
|
|
212
231
|
return {
|
|
213
232
|
status: String(raw["status"] ?? ""),
|
|
@@ -219,15 +238,19 @@ var InvoClient = class {
|
|
|
219
238
|
};
|
|
220
239
|
});
|
|
221
240
|
}
|
|
222
|
-
async confirmReceipt(flow, transactionId) {
|
|
241
|
+
async confirmReceipt(flow, transactionId, opts) {
|
|
223
242
|
const id = encodeURIComponent(transactionId);
|
|
243
|
+
const signal = opts?.signal;
|
|
224
244
|
return this.withTokenRetry(async () => {
|
|
225
245
|
const assertion = await this.runAssertion(
|
|
226
|
-
`/api/sdk/${flow}/${id}/confirm-receipt/webauthn/begin
|
|
246
|
+
`/api/sdk/${flow}/${id}/confirm-receipt/webauthn/begin`,
|
|
247
|
+
void 0,
|
|
248
|
+
signal
|
|
227
249
|
);
|
|
228
250
|
const raw = await this.post(
|
|
229
251
|
`/api/sdk/${flow}/${id}/confirm-receipt`,
|
|
230
|
-
{ webauthn_assertion: assertion }
|
|
252
|
+
{ webauthn_assertion: assertion },
|
|
253
|
+
signal
|
|
231
254
|
);
|
|
232
255
|
return { status: String(raw["status"] ?? ""), raw };
|
|
233
256
|
});
|