@idos-network/client 1.5.0 → 2.2.2
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 +51 -26
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -464
- package/dist/index.js.map +1 -1
- package/package.json +13 -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 +521 -0
- package/src/index.ts +513 -98
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,10 +1,11 @@
|
|
|
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
|
//#region src/enclave/iframe-enclave.d.ts
|
|
10
11
|
interface IframeEnclaveOptions extends EnclaveOptions {
|
|
@@ -12,7 +13,7 @@ interface IframeEnclaveOptions extends EnclaveOptions {
|
|
|
12
13
|
url?: string;
|
|
13
14
|
throwOnUserCancelUnlock?: boolean;
|
|
14
15
|
}
|
|
15
|
-
declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
16
|
+
export declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
16
17
|
private container;
|
|
17
18
|
private iframe;
|
|
18
19
|
private hostUrl;
|
|
@@ -20,17 +21,20 @@ declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
|
20
21
|
constructor(options: IframeEnclaveOptions);
|
|
21
22
|
/** @see parent method */
|
|
22
23
|
load(): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Embedding pages cannot reset enclave storage. The iframe rejects `reset`
|
|
26
|
+
* because it deletes every idOS-* key with no origin check.
|
|
27
|
+
*/
|
|
24
28
|
reset(): Promise<void>;
|
|
25
29
|
/** @override parent method to call iframe */
|
|
26
30
|
reconfigure(options?: Omit<IframeEnclaveOptions, "container" | "url">): Promise<void>;
|
|
27
31
|
/** @override parent method to call iframe */
|
|
28
32
|
confirm(message: string): Promise<boolean>;
|
|
29
33
|
/** @override parent method to call iframe */
|
|
30
|
-
filterCredentials(credentials:
|
|
34
|
+
filterCredentials(credentials: idOSCredentialRecord[], privateFieldFilters: {
|
|
31
35
|
pick: Record<string, unknown[]>;
|
|
32
36
|
omit: Record<string, unknown[]>;
|
|
33
|
-
}): Promise<
|
|
37
|
+
}): Promise<idOSCredentialRecord[]>;
|
|
34
38
|
/** @override parent method to call iframe */
|
|
35
39
|
encrypt(message: Uint8Array, receiverPublicKey: Uint8Array): Promise<{
|
|
36
40
|
content: Uint8Array;
|
|
@@ -56,76 +60,90 @@ declare class IframeEnclave extends BaseProvider<IframeEnclaveOptions> {
|
|
|
56
60
|
//#endregion
|
|
57
61
|
//#region src/index.d.ts
|
|
58
62
|
type Properties<T> = { [K in keyof T as Exclude<T[K], Function> extends never ? never : K]: T[K]; };
|
|
59
|
-
type idOSClient = idOSClientConfiguration | idOSClientIdle | idOSClientWithUserSigner | idOSClientLoggedIn;
|
|
60
|
-
declare class idOSClientConfiguration<Provider extends BaseProvider = IframeEnclave> {
|
|
63
|
+
export type idOSClient = idOSClientConfiguration | idOSClientIdle | idOSClientWithUserSigner | idOSClientLoggedIn;
|
|
64
|
+
export declare class idOSClientConfiguration<Provider extends BaseProvider = IframeEnclave> {
|
|
61
65
|
readonly state: "configuration";
|
|
62
66
|
readonly chainId?: string;
|
|
63
67
|
readonly nodeUrl: string;
|
|
68
|
+
readonly blobGatewayUrl?: string;
|
|
64
69
|
readonly enclaveOptions: Omit<Provider["options"], "mode">;
|
|
65
70
|
readonly store: Store;
|
|
66
71
|
readonly enclaveProvider: BaseProvider;
|
|
67
72
|
constructor(params: {
|
|
68
73
|
chainId?: string;
|
|
69
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;
|
|
70
81
|
enclaveOptions: Omit<Provider["options"], "mode">;
|
|
71
82
|
enclaveProvider?: new (options: Omit<Provider["options"], "mode">) => Provider;
|
|
72
83
|
store?: Store;
|
|
73
84
|
});
|
|
74
85
|
createClient(): Promise<idOSClientIdle>;
|
|
75
86
|
}
|
|
76
|
-
declare class idOSClientIdle {
|
|
87
|
+
export declare class idOSClientIdle {
|
|
77
88
|
readonly state: "idle";
|
|
78
89
|
readonly store: Store;
|
|
79
90
|
readonly kwilClient: KwilActionClient;
|
|
80
91
|
readonly enclaveProvider: BaseProvider;
|
|
81
|
-
|
|
92
|
+
readonly blobGateway: BlobGateway;
|
|
93
|
+
constructor(store: Store, kwilClient: KwilActionClient, enclaveProvider: BaseProvider, blobGateway: BlobGateway);
|
|
82
94
|
static fromConfig(params: idOSClientConfiguration<BaseProvider>): Promise<idOSClientIdle>;
|
|
83
95
|
addressHasProfile(address: string): Promise<boolean>;
|
|
84
96
|
withUserSigner(_signer: Wallet): Promise<idOSClientWithUserSigner>;
|
|
85
97
|
logOut(): Promise<idOSClientIdle>;
|
|
86
98
|
}
|
|
87
|
-
declare class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>, "state"> {
|
|
99
|
+
export declare class idOSClientWithUserSigner implements Omit<Properties<idOSClientIdle>, "state"> {
|
|
100
|
+
#private;
|
|
88
101
|
readonly state: "with-user-signer";
|
|
89
102
|
readonly store: Store;
|
|
90
|
-
readonly kwilClient: KwilActionClient;
|
|
91
|
-
readonly enclaveProvider: BaseProvider;
|
|
92
103
|
readonly signer: Wallet;
|
|
93
104
|
readonly kwilSigner: KwilSigner;
|
|
94
105
|
readonly walletIdentifier: string;
|
|
95
106
|
readonly walletPublicKey: string | undefined;
|
|
96
107
|
readonly walletType: WalletType;
|
|
97
|
-
|
|
108
|
+
readonly blobGateway: BlobGateway;
|
|
109
|
+
constructor(idOSClientIdle: idOSClientIdle, signer: Wallet, kwilSigner: KwilSigner, walletIdentifier: string, walletPublicKey: string | undefined, walletType: WalletType, blobGateway: BlobGateway);
|
|
110
|
+
get kwilClient(): KwilActionClient;
|
|
111
|
+
get enclaveProvider(): BaseProvider;
|
|
98
112
|
logOut(): Promise<idOSClientIdle>;
|
|
99
113
|
hasProfile(): Promise<boolean>;
|
|
100
114
|
createUserEncryptionProfile(userId: string, forceEncryptionPasswordStore?: EncryptionPasswordStore): Promise<PublicEncryptionProfile>;
|
|
101
115
|
logIn(): Promise<idOSClientLoggedIn>;
|
|
102
116
|
}
|
|
103
|
-
declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, "state"> {
|
|
117
|
+
export declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSigner>, "state"> {
|
|
118
|
+
#private;
|
|
104
119
|
readonly state: "logged-in";
|
|
105
120
|
readonly store: Store;
|
|
106
|
-
readonly kwilClient: KwilActionClient;
|
|
107
|
-
readonly enclaveProvider: BaseProvider;
|
|
108
121
|
readonly signer: Wallet;
|
|
109
122
|
readonly kwilSigner: KwilSigner;
|
|
110
123
|
readonly walletIdentifier: string;
|
|
111
124
|
readonly walletPublicKey: string | undefined;
|
|
112
125
|
readonly walletType: WalletType;
|
|
113
126
|
readonly user: idOSUser;
|
|
127
|
+
readonly blobGateway: BlobGateway;
|
|
114
128
|
constructor(idOSClientWithUserSigner: idOSClientWithUserSigner, user: idOSUser);
|
|
129
|
+
get kwilClient(): KwilActionClient;
|
|
130
|
+
get enclaveProvider(): BaseProvider;
|
|
115
131
|
logOut(): Promise<idOSClientIdle>;
|
|
116
132
|
requestDWGMessage(params: idOSDelegatedWriteGrant): Promise<string>;
|
|
133
|
+
createCredential(publicNotes: string, plaintextContent: Uint8Array<ArrayBufferLike>, issuerSigningSecretKey?: Uint8Array): Promise<Omit<idOSCredential, "user_id" | "content" | "inserter_type" | "inserter_id">>;
|
|
117
134
|
removeCredential(id: string): Promise<{
|
|
118
135
|
id: string;
|
|
119
136
|
}>;
|
|
120
137
|
getCredentialById(id: string): Promise<idOSCredential | undefined>;
|
|
121
|
-
shareCredential(credential:
|
|
138
|
+
shareCredential(credential: SharePreliminaryCredentialInput): Promise<SharePreliminaryCredentialInput>;
|
|
122
139
|
getAllCredentials(): Promise<idOSCredentialListItem[]>;
|
|
123
140
|
getAccessGrantsOwned(): Promise<idOSGrant[]>;
|
|
124
141
|
getAttributes(): Promise<idOSUserAttribute[]>;
|
|
125
142
|
createAttribute(attribute: AddAttributeInput): Promise<AddAttributeInput>;
|
|
126
143
|
getCredentialContentSha256Hash(id: string): Promise<string>;
|
|
127
144
|
getCredentialContent(id: string): Promise<string>;
|
|
128
|
-
|
|
145
|
+
getCredentialWithEncryptedContent(id: string): Promise<idOSCredential>;
|
|
146
|
+
getCredentialSharedContent(id: string): Promise<string>;
|
|
129
147
|
getGrants(params: Partial<GetAccessGrantsGrantedInput>): Promise<{
|
|
130
148
|
grants: idOSGrant[];
|
|
131
149
|
totalCount: number;
|
|
@@ -136,6 +154,7 @@ declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSi
|
|
|
136
154
|
revokeAccessGrant(id: string): Promise<{
|
|
137
155
|
id: string;
|
|
138
156
|
}>;
|
|
157
|
+
addWalletMessage(params: AddWalletMessageInput): Promise<string>;
|
|
139
158
|
addWallet(params: AddWalletInput): Promise<AddWalletInput>;
|
|
140
159
|
getWallets(): Promise<GetWalletsOutput[]>;
|
|
141
160
|
removeWallet(id: string): Promise<{
|
|
@@ -155,20 +174,26 @@ declare class idOSClientLoggedIn implements Omit<Properties<idOSClientWithUserSi
|
|
|
155
174
|
omit: Parameters<typeof recordFilter>[2];
|
|
156
175
|
};
|
|
157
176
|
credentialLevelOrHigherFilter?: {
|
|
158
|
-
userLevel:
|
|
159
|
-
requiredAddons:
|
|
177
|
+
userLevel: BaseLevel;
|
|
178
|
+
requiredAddons: Addon[];
|
|
160
179
|
};
|
|
161
180
|
}): Promise<idOSCredentialListItem[]>;
|
|
162
181
|
requestAccessGrant(credentialId: string, { consumerEncryptionPublicKey, consumerAuthPublicKey, lockedUntil }: {
|
|
163
182
|
consumerEncryptionPublicKey: string;
|
|
164
183
|
consumerAuthPublicKey: string;
|
|
165
184
|
lockedUntil?: number;
|
|
166
|
-
}): Promise<
|
|
185
|
+
}): Promise<SharePreliminaryCredentialInput>;
|
|
167
186
|
}
|
|
168
|
-
declare function createIDOSClient(params: {
|
|
187
|
+
export declare function createIDOSClient(params: {
|
|
169
188
|
nodeUrl: string;
|
|
189
|
+
/**
|
|
190
|
+
* Optional blob gateway base URL. Defaults to `nodeUrl`.
|
|
191
|
+
* In the browser this must share KGW's session-cookie Domain
|
|
192
|
+
* (typically the same host), because reads use `credentials: "include"`.
|
|
193
|
+
*/
|
|
194
|
+
blobGatewayUrl?: string;
|
|
170
195
|
enclaveOptions: Omit<IframeEnclave["options"], "mode">;
|
|
171
196
|
}): idOSClientConfiguration<IframeEnclave>;
|
|
172
197
|
//#endregion
|
|
173
|
-
export {
|
|
198
|
+
export { type DelegatedWriteGrantBaseParams, type idOSCredential, type idOSCredentialListItem, type idOSDelegatedWriteGrant, type idOSGrant, type idOSUser, type idOSUserAttribute, type idOSWallet, signNearMessage, toDelegatedWriteGrantBaseParams };
|
|
174
199
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/enclave/iframe-enclave.ts","../src/index.ts"],"mappings":"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"}
|