@idos-network/client 1.2.0 → 2.2.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/README.md +15 -9
- package/dist/index.d.ts +48 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -464
- package/dist/index.js.map +1 -1
- package/package.json +15 -9
- package/src/enclave/helpers.ts +10 -6
- package/src/enclave/iframe-enclave.test.ts +26 -0
- package/src/enclave/iframe-enclave.ts +6 -3
- package/src/index.test.ts +338 -0
- package/src/index.ts +277 -58
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
|
|
29
29
|
const idOSClientWithoutSigner = await createIDOSClient({
|
|
30
30
|
nodeUrl: "https://nodes.idos.network",
|
|
31
|
+
// Must share KGW's session-cookie Domain (typically same host as nodeUrl).
|
|
32
|
+
blobGatewayUrl: "https://blob-gateway.idos.network",
|
|
31
33
|
enclaveOptions: {
|
|
32
34
|
container: "#idosContainer",
|
|
33
35
|
},
|
|
@@ -53,14 +55,6 @@ const credentials = await loggedInClient.filterCredentials({
|
|
|
53
55
|
},
|
|
54
56
|
});
|
|
55
57
|
|
|
56
|
-
// If we found a credentials which we can use, we will ask user for AccessGrant
|
|
57
|
-
// which we later can use in our consumer to get the users data
|
|
58
|
-
const ag = await loggedInClient.requestAccessGrant(credentials[0].id, {
|
|
59
|
-
consumerAuthPublicKey: "CONSUMER_PUBLIC_KEY",
|
|
60
|
-
consumerEncryptionPublicKey: "CONSUMER_ENC_PUBLIC_KEY",
|
|
61
|
-
lockedUntil: lockedUntil: Math.floor(Date.now() / 1000) + 90 * 24 * 60 * 60, // 3 months from now
|
|
62
|
-
});
|
|
63
|
-
|
|
64
58
|
// Also when the user is logged in, we can ask him to add another wallet
|
|
65
59
|
// wallet type is required.
|
|
66
60
|
await loggedInClient.addWallet({
|
|
@@ -73,6 +67,18 @@ await loggedInClient.addWallet({
|
|
|
73
67
|
});
|
|
74
68
|
```
|
|
75
69
|
|
|
70
|
+
### Request an access grant
|
|
71
|
+
|
|
72
|
+
The logged-in user issues the shared copy (ephemeral user-side signing key). No original-issuer secret is required.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const ag = await loggedInClient.requestAccessGrant(credentials[0].id, {
|
|
76
|
+
consumerAuthPublicKey: "CONSUMER_PUBLIC_KEY",
|
|
77
|
+
consumerEncryptionPublicKey: "CONSUMER_ENC_PUBLIC_KEY",
|
|
78
|
+
lockedUntil: Math.floor(Date.now() / 1000) + 90 * 24 * 60 * 60, // 3 months from now
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
76
82
|
### Supported Wallet Types
|
|
77
83
|
|
|
78
84
|
- `"evm"` - Ethereum Virtual Machine compatible wallets (Ethereum, Polygon, etc.)
|
|
@@ -94,7 +100,7 @@ For complete documentation, examples, and implementation guides:
|
|
|
94
100
|
- **Profile & Session Lifecycle** - Check profile existence, attach a wallet signer, and log users in/out
|
|
95
101
|
- **Enclave-Backed Encryption** - Generate user encryption profiles and decrypt credential content safely via the enclave
|
|
96
102
|
- **Credential Access & Filtering** - Fetch credentials, read decrypted content, and filter by issuer, level, and field rules
|
|
97
|
-
- **Credential Sharing Flows** - Request
|
|
103
|
+
- **Credential Sharing Flows** - Request DWG messages, create access grants, and share credentials with controlled lock times
|
|
98
104
|
- **Wallet Management** - Add, list, and remove wallets (single or batch), including MPC-aware wallet synchronization
|
|
99
105
|
- **Multi-Chain Wallet Support** - Works with EVM, NEAR, XRPL, and Stellar wallet types
|
|
100
106
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { recordFilter } from "@idos-network/credentials/utils";
|
|
1
|
+
import { Addon, BaseLevel, recordFilter } from "@idos-network/credentials/utils";
|
|
2
2
|
import { KwilActionClient, Wallet, signNearMessage } from "@idos-network/kwil-infra";
|
|
3
|
-
import { AddAttributeInput, AddWalletInput,
|
|
3
|
+
import { AddAttributeInput, AddWalletInput, AddWalletMessageInput, DelegatedWriteGrantBaseParams, GetAccessGrantsGrantedInput, GetWalletsOutput, SharePreliminaryCredentialInput, WalletType, idOSCredential, idOSCredentialListItem, idOSDelegatedWriteGrant, idOSGrant, idOSUser, idOSUserAttribute, idOSWallet, toDelegatedWriteGrantBaseParams } from "@idos-network/kwil-infra/actions";
|
|
4
|
+
import { KwilSigner } from "@idos-network/kwil-js";
|
|
5
|
+
import { BlobGateway } from "@idos-network/utils/blob-gateway";
|
|
4
6
|
import { Store } from "@idos-network/utils/store";
|
|
5
7
|
import { BaseProvider, EnclaveOptions, EncryptionPasswordStore, PublicEncryptionProfile } from "@idos-network/enclave";
|
|
6
|
-
import {
|
|
7
|
-
import { idOSCredential as idOSCredential$1 } from "@idos-network/credentials/types";
|
|
8
|
+
import { idOSCredentialRecord } from "@idos-network/credentials/types";
|
|
8
9
|
import { AddAddressMessageToSign, AddAddressSignatureMessage, RemoveAddressMessageToSign, RemoveAddressSignatureMessage } from "@idos-network/enclave/mpc";
|
|
9
|
-
|
|
10
10
|
//#region src/enclave/iframe-enclave.d.ts
|
|
11
11
|
interface IframeEnclaveOptions extends EnclaveOptions {
|
|
12
12
|
container: string;
|
|
13
13
|
url?: string;
|
|
14
14
|
throwOnUserCancelUnlock?: boolean;
|
|
15
15
|
}
|
|
16
|
-
declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
16
|
+
export declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
17
17
|
private container;
|
|
18
18
|
private iframe;
|
|
19
19
|
private hostUrl;
|
|
@@ -21,17 +21,20 @@ declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
|
21
21
|
constructor(options: IframeEnclaveOptions);
|
|
22
22
|
/** @see parent method */
|
|
23
23
|
load(): Promise<void>;
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Embedding pages cannot reset enclave storage. The iframe rejects `reset`
|
|
26
|
+
* because it deletes every idOS-* key with no origin check.
|
|
27
|
+
*/
|
|
25
28
|
reset(): Promise<void>;
|
|
26
29
|
/** @override parent method to call iframe */
|
|
27
30
|
reconfigure(options?: Omit<IframeEnclaveOptions, "container" | "url">): Promise<void>;
|
|
28
31
|
/** @override parent method to call iframe */
|
|
29
32
|
confirm(message: string): Promise<boolean>;
|
|
30
33
|
/** @override parent method to call iframe */
|
|
31
|
-
filterCredentials(credentials:
|
|
34
|
+
filterCredentials(credentials: idOSCredentialRecord[], privateFieldFilters: {
|
|
32
35
|
pick: Record<string, unknown[]>;
|
|
33
36
|
omit: Record<string, unknown[]>;
|
|
34
|
-
}): Promise<
|
|
37
|
+
}): Promise<idOSCredentialRecord[]>;
|
|
35
38
|
/** @override parent method to call iframe */
|
|
36
39
|
encrypt(message: Uint8Array, receiverPublicKey: Uint8Array): Promise<{
|
|
37
40
|
content: Uint8Array;
|
|
@@ -56,36 +59,44 @@ declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
|
56
59
|
}
|
|
57
60
|
//#endregion
|
|
58
61
|
//#region src/index.d.ts
|
|
59
|
-
type Properties<T> = { [K in keyof T as Exclude<T[K], Function> extends never ? never : K]: T[K] };
|
|
60
|
-
type idOSClient = idOSClientConfiguration | idOSClientIdle | idOSClientWithUserSigner | idOSClientLoggedIn;
|
|
61
|
-
declare class idOSClientConfiguration<Provider extends BaseProvider = IframeEnclave> {
|
|
62
|
+
type Properties<T> = { [K in keyof T as Exclude<T[K], Function> extends never ? never : K]: T[K]; };
|
|
63
|
+
export type idOSClient = idOSClientConfiguration | idOSClientIdle | idOSClientWithUserSigner | idOSClientLoggedIn;
|
|
64
|
+
export declare class idOSClientConfiguration<Provider extends BaseProvider = IframeEnclave> {
|
|
62
65
|
readonly state: "configuration";
|
|
63
66
|
readonly chainId?: string;
|
|
64
67
|
readonly nodeUrl: string;
|
|
68
|
+
readonly blobGatewayUrl?: string;
|
|
65
69
|
readonly enclaveOptions: Omit<Provider["options"], "mode">;
|
|
66
70
|
readonly store: Store;
|
|
67
71
|
readonly enclaveProvider: BaseProvider;
|
|
68
72
|
constructor(params: {
|
|
69
73
|
chainId?: string;
|
|
70
74
|
nodeUrl: string;
|
|
75
|
+
/**
|
|
76
|
+
* Optional blob gateway base URL. Defaults to `nodeUrl`.
|
|
77
|
+
* In the browser this must share KGW's session-cookie Domain
|
|
78
|
+
* (typically the same host), because reads use `credentials: "include"`.
|
|
79
|
+
*/
|
|
80
|
+
blobGatewayUrl?: string;
|
|
71
81
|
enclaveOptions: Omit<Provider["options"], "mode">;
|
|
72
82
|
enclaveProvider?: new (options: Omit<Provider["options"], "mode">) => Provider;
|
|
73
83
|
store?: Store;
|
|
74
84
|
});
|
|
75
85
|
createClient(): Promise<idOSClientIdle>;
|
|
76
86
|
}
|
|
77
|
-
declare class idOSClientIdle {
|
|
87
|
+
export declare class idOSClientIdle {
|
|
78
88
|
readonly state: "idle";
|
|
79
89
|
readonly store: Store;
|
|
80
90
|
readonly kwilClient: KwilActionClient;
|
|
81
91
|
readonly enclaveProvider: BaseProvider;
|
|
82
|
-
|
|
92
|
+
readonly blobGateway: BlobGateway;
|
|
93
|
+
constructor(store: Store, kwilClient: KwilActionClient, enclaveProvider: BaseProvider, blobGateway: BlobGateway);
|
|
83
94
|
static fromConfig(params: idOSClientConfiguration<BaseProvider>): Promise<idOSClientIdle>;
|
|
84
95
|
addressHasProfile(address: string): Promise<boolean>;
|
|
85
96
|
withUserSigner(_signer: Wallet): Promise<idOSClientWithUserSigner>;
|
|
86
97
|
logOut(): Promise<idOSClientIdle>;
|
|
87
98
|
}
|
|
88
|
-
declare class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>, "state"> {
|
|
99
|
+
export declare class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>, "state"> {
|
|
89
100
|
readonly state: "with-user-signer";
|
|
90
101
|
readonly store: Store;
|
|
91
102
|
readonly kwilClient: KwilActionClient;
|
|
@@ -95,13 +106,15 @@ declare class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle
|
|
|
95
106
|
readonly walletIdentifier: string;
|
|
96
107
|
readonly walletPublicKey: string | undefined;
|
|
97
108
|
readonly walletType: WalletType;
|
|
98
|
-
|
|
109
|
+
readonly blobGateway: BlobGateway;
|
|
110
|
+
constructor(idOSClientIdle: idOSClientIdle, signer: Wallet, kwilSigner: KwilSigner, walletIdentifier: string, walletPublicKey: string | undefined, walletType: WalletType, blobGateway: BlobGateway);
|
|
99
111
|
logOut(): Promise<idOSClientIdle>;
|
|
100
112
|
hasProfile(): Promise<boolean>;
|
|
101
113
|
createUserEncryptionProfile(userId: string, forceEncryptionPasswordStore?: EncryptionPasswordStore): Promise<PublicEncryptionProfile>;
|
|
102
114
|
logIn(): Promise<idOSClientLoggedIn>;
|
|
103
115
|
}
|
|
104
|
-
declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, "state"> {
|
|
116
|
+
export declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, "state"> {
|
|
117
|
+
#private;
|
|
105
118
|
readonly state: "logged-in";
|
|
106
119
|
readonly store: Store;
|
|
107
120
|
readonly kwilClient: KwilActionClient;
|
|
@@ -112,21 +125,24 @@ declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSi
|
|
|
112
125
|
readonly walletPublicKey: string | undefined;
|
|
113
126
|
readonly walletType: WalletType;
|
|
114
127
|
readonly user: idOSUser;
|
|
128
|
+
readonly blobGateway: BlobGateway;
|
|
115
129
|
constructor(idOSClientWithUserSigner: idOSClientWithUserSigner, user: idOSUser);
|
|
116
130
|
logOut(): Promise<idOSClientIdle>;
|
|
117
131
|
requestDWGMessage(params: idOSDelegatedWriteGrant): Promise<string>;
|
|
132
|
+
createCredential(publicNotes: string, plaintextContent: Uint8Array<ArrayBufferLike>, issuerSigningSecretKey?: Uint8Array): Promise<Omit<idOSCredential, "user_id" | "content" | "inserter_type" | "inserter_id">>;
|
|
118
133
|
removeCredential(id: string): Promise<{
|
|
119
134
|
id: string;
|
|
120
135
|
}>;
|
|
121
136
|
getCredentialById(id: string): Promise<idOSCredential | undefined>;
|
|
122
|
-
shareCredential(credential:
|
|
137
|
+
shareCredential(credential: SharePreliminaryCredentialInput): Promise<SharePreliminaryCredentialInput>;
|
|
123
138
|
getAllCredentials(): Promise<idOSCredentialListItem[]>;
|
|
124
139
|
getAccessGrantsOwned(): Promise<idOSGrant[]>;
|
|
125
140
|
getAttributes(): Promise<idOSUserAttribute[]>;
|
|
126
141
|
createAttribute(attribute: AddAttributeInput): Promise<AddAttributeInput>;
|
|
127
142
|
getCredentialContentSha256Hash(id: string): Promise<string>;
|
|
128
143
|
getCredentialContent(id: string): Promise<string>;
|
|
129
|
-
|
|
144
|
+
getCredentialWithEncryptedContent(id: string): Promise<idOSCredential>;
|
|
145
|
+
getCredentialSharedContent(id: string): Promise<string>;
|
|
130
146
|
getGrants(params: Partial<GetAccessGrantsGrantedInput>): Promise<{
|
|
131
147
|
grants: idOSGrant[];
|
|
132
148
|
totalCount: number;
|
|
@@ -137,6 +153,7 @@ declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSi
|
|
|
137
153
|
revokeAccessGrant(id: string): Promise<{
|
|
138
154
|
id: string;
|
|
139
155
|
}>;
|
|
156
|
+
addWalletMessage(params: AddWalletMessageInput): Promise<string>;
|
|
140
157
|
addWallet(params: AddWalletInput): Promise<AddWalletInput>;
|
|
141
158
|
getWallets(): Promise<GetWalletsOutput[]>;
|
|
142
159
|
removeWallet(id: string): Promise<{
|
|
@@ -156,24 +173,26 @@ declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSi
|
|
|
156
173
|
omit: Parameters<typeof recordFilter>[2];
|
|
157
174
|
};
|
|
158
175
|
credentialLevelOrHigherFilter?: {
|
|
159
|
-
userLevel:
|
|
160
|
-
requiredAddons:
|
|
176
|
+
userLevel: BaseLevel;
|
|
177
|
+
requiredAddons: Addon[];
|
|
161
178
|
};
|
|
162
179
|
}): Promise<idOSCredentialListItem[]>;
|
|
163
|
-
requestAccessGrant(credentialId: string, {
|
|
164
|
-
consumerEncryptionPublicKey,
|
|
165
|
-
consumerAuthPublicKey,
|
|
166
|
-
lockedUntil
|
|
167
|
-
}: {
|
|
180
|
+
requestAccessGrant(credentialId: string, { consumerEncryptionPublicKey, consumerAuthPublicKey, lockedUntil }: {
|
|
168
181
|
consumerEncryptionPublicKey: string;
|
|
169
182
|
consumerAuthPublicKey: string;
|
|
170
183
|
lockedUntil?: number;
|
|
171
|
-
}): Promise<
|
|
184
|
+
}): Promise<SharePreliminaryCredentialInput>;
|
|
172
185
|
}
|
|
173
|
-
declare function createIDOSClient(params: {
|
|
186
|
+
export declare function createIDOSClient(params: {
|
|
174
187
|
nodeUrl: string;
|
|
188
|
+
/**
|
|
189
|
+
* Optional blob gateway base URL. Defaults to `nodeUrl`.
|
|
190
|
+
* In the browser this must share KGW's session-cookie Domain
|
|
191
|
+
* (typically the same host), because reads use `credentials: "include"`.
|
|
192
|
+
*/
|
|
193
|
+
blobGatewayUrl?: string;
|
|
175
194
|
enclaveOptions: Omit<IframeEnclave["options"], "mode">;
|
|
176
195
|
}): idOSClientConfiguration<IframeEnclave>;
|
|
177
196
|
//#endregion
|
|
178
|
-
export {
|
|
197
|
+
export { type DelegatedWriteGrantBaseParams, type idOSCredential, type idOSCredentialListItem, type idOSDelegatedWriteGrant, type idOSGrant, type idOSUser, type idOSUserAttribute, type idOSWallet, signNearMessage, toDelegatedWriteGrantBaseParams };
|
|
179
198
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"mappings":";;;;;;;;;;UAgBiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"mappings":"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"}
|