@idos-network/issuer 1.0.0-rc.1.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/LICENSE +21 -0
- package/README.md +19 -0
- package/dist/index.d.ts +205 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21274 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
- package/src/assets/add-user.drawio.svg +558 -0
- package/src/assets/country-codes.xml +271 -0
- package/src/assets/ed25519-signature-2020-v1.json +93 -0
- package/src/assets/idos-credential-subject-v1.json +32 -0
- package/src/assets/idos-credentials-v1.json +9 -0
- package/src/assets/v1.json +273 -0
- package/src/index.ts +155 -0
- package/src/services/credential.service.ts +207 -0
- package/src/services/credentials-builder.service.ts +203 -0
- package/src/services/credentials-builder.test.ts +100 -0
- package/src/services/grant.service.ts +59 -0
- package/src/services/user.service.ts +75 -0
- package/src/types.d.ts +4 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { Ed25519Signature2020 } from "@digitalbazaar/ed25519-signature-2020";
|
|
2
|
+
import { Ed25519VerificationKey2020 } from "@digitalbazaar/ed25519-verification-key-2020";
|
|
3
|
+
import * as vc from "@digitalbazaar/vc";
|
|
4
|
+
import * as base85 from "base85";
|
|
5
|
+
import { JsonLdDocumentLoader } from "jsonld-document-loader";
|
|
6
|
+
import ed25519Signature2020V1 from "../assets/ed25519-signature-2020-v1.json";
|
|
7
|
+
import idosCredentialSubjectV1 from "../assets/idos-credential-subject-v1.json";
|
|
8
|
+
import idosCredentialsV1 from "../assets/idos-credentials-v1.json";
|
|
9
|
+
import v1 from "../assets/v1.json";
|
|
10
|
+
|
|
11
|
+
export interface CredentialFields {
|
|
12
|
+
id: string;
|
|
13
|
+
|
|
14
|
+
/* Level of KYC verification performed (e.g., basic, intermediate, advanced). */
|
|
15
|
+
level: string;
|
|
16
|
+
|
|
17
|
+
/* @default Date.now() */
|
|
18
|
+
issued?: Date;
|
|
19
|
+
|
|
20
|
+
/* Date the credential was approved. */
|
|
21
|
+
approvedAt?: Date;
|
|
22
|
+
|
|
23
|
+
/* Date the credential was revoked. */
|
|
24
|
+
expirationDate?: Date;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CredentialResidentialAddress {
|
|
28
|
+
/* Street address. */
|
|
29
|
+
street: string;
|
|
30
|
+
|
|
31
|
+
/* House number. */
|
|
32
|
+
houseNumber?: string;
|
|
33
|
+
|
|
34
|
+
/* Additional address information (e.g., apartment number). */
|
|
35
|
+
additionalAddressInfo?: string;
|
|
36
|
+
|
|
37
|
+
/* Locality (e.g., city, town). */
|
|
38
|
+
city: string;
|
|
39
|
+
|
|
40
|
+
/* Postal code. */
|
|
41
|
+
postalCode: string;
|
|
42
|
+
|
|
43
|
+
/* Country. */
|
|
44
|
+
country: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface CredentialSubject {
|
|
48
|
+
/* ID(unique credential) Unique identifier for the credential itself. */
|
|
49
|
+
id: string;
|
|
50
|
+
|
|
51
|
+
/* Given name of the individual. */
|
|
52
|
+
firstName: string;
|
|
53
|
+
|
|
54
|
+
/* Surname of the individual. */
|
|
55
|
+
familyName: string;
|
|
56
|
+
|
|
57
|
+
/* Family name at birth (e.g., maiden name). */
|
|
58
|
+
maidenName?: string;
|
|
59
|
+
|
|
60
|
+
/* Unique identifier issued by a government authority (e.g., SSN, Tax ID). */
|
|
61
|
+
governmentId?: string;
|
|
62
|
+
|
|
63
|
+
/* Type of government identifier (e.g., Social Security Number, Tax ID, etc.). */
|
|
64
|
+
governmentIdType?: string;
|
|
65
|
+
|
|
66
|
+
/* Date of birth of the individual. */
|
|
67
|
+
dateOfBirth: Date;
|
|
68
|
+
|
|
69
|
+
/* City and state/province of birth. */
|
|
70
|
+
placeOfBirth: string;
|
|
71
|
+
|
|
72
|
+
/* Country that issued the identity document. */
|
|
73
|
+
idDocumentCountry: string;
|
|
74
|
+
|
|
75
|
+
/* ID Document Number Unique number on the identity document. */
|
|
76
|
+
idDocumentNumber: string;
|
|
77
|
+
|
|
78
|
+
/* ID Document Type Type of identity document(e.g., Passport, Driver's License, National ID). */
|
|
79
|
+
idDocumentType: string;
|
|
80
|
+
|
|
81
|
+
/* ID Document Date of Issue Date the identity document was issued. */
|
|
82
|
+
idDocumentDateOfIssue: Date;
|
|
83
|
+
|
|
84
|
+
/* ID Document Date of Expiry Expiration date of the identity document - if applicable. */
|
|
85
|
+
idDocumentDateOfExpiry?: Date;
|
|
86
|
+
|
|
87
|
+
/* ID Document Front File File or URL representing the front of the identity document. */
|
|
88
|
+
idDocumentFrontFile: Buffer;
|
|
89
|
+
|
|
90
|
+
/* ID Document Back File File or URL representing the back of the identity document - if applicable. */
|
|
91
|
+
idDocumentBackFile?: Buffer;
|
|
92
|
+
|
|
93
|
+
/* (ID Document) Selfie File File or URL of a selfie with the identity document for verification purposes. */
|
|
94
|
+
selfieFile: Buffer;
|
|
95
|
+
|
|
96
|
+
/* Residential Address Full residential address of the individual - if applicable. */
|
|
97
|
+
residentialAddress?: CredentialResidentialAddress;
|
|
98
|
+
|
|
99
|
+
/* Residential Address Proof Category Type of document provided to verify the address(e.g., utility bill, bank statement). */
|
|
100
|
+
residentialAddressProofCategory?: string;
|
|
101
|
+
|
|
102
|
+
/* Residential Address Proof Date Of Issue Date the address proof document was issued. */
|
|
103
|
+
residentialAddressProofDateOfIssue?: Date;
|
|
104
|
+
|
|
105
|
+
/* Residential Address Proof File File or URL of the document provided as address proof. */
|
|
106
|
+
residentialAddressProofFile?: Buffer;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface CredentialsIssuerConfig {
|
|
110
|
+
/* Issuers id */
|
|
111
|
+
id: string;
|
|
112
|
+
|
|
113
|
+
/* Issuer of the credential (URL). */
|
|
114
|
+
controller: string;
|
|
115
|
+
|
|
116
|
+
/* Issuer's private key in multibase format. */
|
|
117
|
+
privateKeyMultibase: string;
|
|
118
|
+
|
|
119
|
+
/* Issuer's public key in multibase format. */
|
|
120
|
+
publicKeyMultibase: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const CONTEXT_V1 = "https://www.w3.org/2018/credentials/v1";
|
|
124
|
+
const CONTEXT_IDOS_CREDENTIALS_V1 =
|
|
125
|
+
"https://raw.githubusercontent.com/idos-network/idos-sdk-js/1bc3503f5302a7e42777076445d5b05fec8db429/packages/issuer-sdk-js/assets/idos-credentials-v1.json";
|
|
126
|
+
const CONTEXT_IDOS_CREDENTIALS_V1_SUBJECT =
|
|
127
|
+
"https://raw.githubusercontent.com/idos-network/idos-sdk-js/1bc3503f5302a7e42777076445d5b05fec8db429/packages/issuer-sdk-js/assets/idos-credential-subject-v1.json";
|
|
128
|
+
const CONTEXT_ED25519_SIGNATURE_2020_V1 = "https://w3id.org/security/suites/ed25519-2020/v1";
|
|
129
|
+
|
|
130
|
+
export class CredentialsBuilderService {
|
|
131
|
+
private fileToBase85(file: Buffer) {
|
|
132
|
+
return base85.encode(file, "ascii85");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private capitalizeFirstLetter(str: string) {
|
|
136
|
+
return str[0].toUpperCase() + str.slice(1);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private convertValues<
|
|
140
|
+
K extends CredentialFields | CredentialSubject | CredentialResidentialAddress,
|
|
141
|
+
>(fields: K, prefix?: string): Record<string, unknown> {
|
|
142
|
+
const acc: Record<string, unknown> = {};
|
|
143
|
+
|
|
144
|
+
for (const key in fields) {
|
|
145
|
+
if (Object.hasOwn(fields, key)) {
|
|
146
|
+
const value = fields[key];
|
|
147
|
+
const name = prefix ? `${prefix}${this.capitalizeFirstLetter(key)}` : key;
|
|
148
|
+
if (value instanceof Date) {
|
|
149
|
+
acc[name] = value.toISOString();
|
|
150
|
+
} else if (value instanceof Buffer) {
|
|
151
|
+
// Convert file to base85
|
|
152
|
+
acc[name] = this.fileToBase85(value);
|
|
153
|
+
} else {
|
|
154
|
+
acc[name] = value;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return acc;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// biome-ignore lint/suspicious/noExplicitAny: Using `any` to avoid type errors.
|
|
163
|
+
buildDocumentLoader(): any {
|
|
164
|
+
const loader = new JsonLdDocumentLoader();
|
|
165
|
+
loader.addStatic(CONTEXT_V1, v1);
|
|
166
|
+
loader.addStatic(CONTEXT_IDOS_CREDENTIALS_V1, idosCredentialsV1);
|
|
167
|
+
loader.addStatic(CONTEXT_IDOS_CREDENTIALS_V1_SUBJECT, idosCredentialSubjectV1);
|
|
168
|
+
loader.addStatic(CONTEXT_ED25519_SIGNATURE_2020_V1, ed25519Signature2020V1);
|
|
169
|
+
|
|
170
|
+
return loader.build();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async buildCredentials(
|
|
174
|
+
fields: CredentialFields,
|
|
175
|
+
subject: CredentialSubject,
|
|
176
|
+
issuer: CredentialsIssuerConfig,
|
|
177
|
+
// biome-ignore lint/suspicious/noExplicitAny: Using `any` to avoid type errors.
|
|
178
|
+
): Promise<any> {
|
|
179
|
+
const { residentialAddress, ...subjectData } = subject;
|
|
180
|
+
|
|
181
|
+
// Create credentials container
|
|
182
|
+
const credential = {
|
|
183
|
+
"@context": [CONTEXT_V1, CONTEXT_IDOS_CREDENTIALS_V1, CONTEXT_ED25519_SIGNATURE_2020_V1],
|
|
184
|
+
type: ["VerifiableCredential"],
|
|
185
|
+
issuer: issuer.controller,
|
|
186
|
+
...this.convertValues(fields),
|
|
187
|
+
credentialSubject: {
|
|
188
|
+
"@context": CONTEXT_IDOS_CREDENTIALS_V1_SUBJECT,
|
|
189
|
+
...this.convertValues(subjectData),
|
|
190
|
+
...(residentialAddress ? this.convertValues(residentialAddress, "residentialAddress") : {}),
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const key = await Ed25519VerificationKey2020.from({
|
|
195
|
+
...issuer,
|
|
196
|
+
type: "Ed25519VerificationKey2020",
|
|
197
|
+
});
|
|
198
|
+
const suite = new Ed25519Signature2020({ key });
|
|
199
|
+
const documentLoader = this.buildDocumentLoader();
|
|
200
|
+
|
|
201
|
+
return vc.issue({ credential, suite, documentLoader });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Ed25519Signature2020 } from "@digitalbazaar/ed25519-signature-2020";
|
|
2
|
+
import { Ed25519VerificationKey2020 } from "@digitalbazaar/ed25519-verification-key-2020";
|
|
3
|
+
import * as vc from "@digitalbazaar/vc";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { CredentialsBuilderService } from "./credentials-builder.service";
|
|
6
|
+
|
|
7
|
+
describe("buildVerifiableCredentials", () => {
|
|
8
|
+
it("should create a verifiable vc", async () => {
|
|
9
|
+
const id = "z6MkszZtxCmA2Ce4vUV132PCuLQmwnaDD5mw2L23fGNnsiX3";
|
|
10
|
+
const issuer = "https://vc-issuers.cool.id/idos";
|
|
11
|
+
|
|
12
|
+
const builder = new CredentialsBuilderService();
|
|
13
|
+
|
|
14
|
+
const data = await builder.buildCredentials(
|
|
15
|
+
{
|
|
16
|
+
id: `${issuer}/credentials/${id}`,
|
|
17
|
+
level: "human",
|
|
18
|
+
issued: new Date("2022-01-01"),
|
|
19
|
+
approvedAt: new Date("2022-01-01"),
|
|
20
|
+
expirationDate: new Date("2030-01-01"),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: `uuid:${id}`,
|
|
24
|
+
firstName: "John",
|
|
25
|
+
familyName: "Lennon",
|
|
26
|
+
governmentIdType: "SSN",
|
|
27
|
+
governmentId: "123-45-6789",
|
|
28
|
+
dateOfBirth: new Date("1980-01-01"),
|
|
29
|
+
placeOfBirth: "New York, NY",
|
|
30
|
+
idDocumentCountry: "US",
|
|
31
|
+
idDocumentNumber: "123456789",
|
|
32
|
+
idDocumentType: "Passport",
|
|
33
|
+
idDocumentDateOfIssue: new Date("2022-01-01"),
|
|
34
|
+
idDocumentDateOfExpiry: new Date("2025-01-01"),
|
|
35
|
+
idDocumentFrontFile: Buffer.from("Front of ID document"),
|
|
36
|
+
idDocumentBackFile: Buffer.from("Back of ID document"),
|
|
37
|
+
selfieFile: Buffer.from("Selfie"),
|
|
38
|
+
residentialAddress: {
|
|
39
|
+
street: "Main St",
|
|
40
|
+
houseNumber: "123",
|
|
41
|
+
additionalAddressInfo: "Apt 1",
|
|
42
|
+
city: "New York",
|
|
43
|
+
postalCode: "10001",
|
|
44
|
+
country: "US",
|
|
45
|
+
},
|
|
46
|
+
residentialAddressProofCategory: "Utility Bill",
|
|
47
|
+
residentialAddressProofDateOfIssue: new Date("2022-01-01"),
|
|
48
|
+
residentialAddressProofFile: Buffer.from("Proof of address"),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: `${issuer}/keys/1`,
|
|
52
|
+
controller: `${issuer}/issuer/1`,
|
|
53
|
+
publicKeyMultibase: "z6MkrQDe6W8yspNAZyVXw9Rt9s8FuP61y9XRnRhA2kbQ1Jyj",
|
|
54
|
+
privateKeyMultibase:
|
|
55
|
+
"zrv4XwF1S61SJuUjQpaAPCoM7QJiw8J3EDFPQ4AGN5D3r3iaR8mcSeJZoYjSWe6PqgSfwtC3KPvAvHQ7QxGeNp9rZ2m",
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// Check if residential address is properly prefixed
|
|
60
|
+
expect(data.credentialSubject.residentialAddressStreet).toBe("Main St");
|
|
61
|
+
expect(data.credentialSubject.residentialAddressHouseNumber).toBe("123");
|
|
62
|
+
expect(data.credentialSubject.residentialAddressAdditionalAddressInfo).toBe("Apt 1");
|
|
63
|
+
expect(data.credentialSubject.residentialAddressCity).toBe("New York");
|
|
64
|
+
expect(data.credentialSubject.residentialAddressPostalCode).toBe("10001");
|
|
65
|
+
expect(data.credentialSubject.residentialAddressCountry).toBe("US");
|
|
66
|
+
|
|
67
|
+
// Check if proof is properly constructed
|
|
68
|
+
expect(data.proof.proofPurpose).toBe("assertionMethod");
|
|
69
|
+
expect(data.proof.type).toBe("Ed25519Signature2020");
|
|
70
|
+
expect(data.proof.verificationMethod).toBe("https://vc-issuers.cool.id/idos/keys/1");
|
|
71
|
+
|
|
72
|
+
const publicKey = await Ed25519VerificationKey2020.from({
|
|
73
|
+
id: `${issuer}/keys/1`,
|
|
74
|
+
controller: `${issuer}/issuer/1`,
|
|
75
|
+
publicKeyMultibase: "z6MkrQDe6W8yspNAZyVXw9Rt9s8FuP61y9XRnRhA2kbQ1Jyj",
|
|
76
|
+
type: "Ed25519VerificationKey2020",
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const vcVerifyingSuite = new Ed25519Signature2020({
|
|
80
|
+
key: publicKey,
|
|
81
|
+
verificationMethod: publicKey.id,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const controller = {
|
|
85
|
+
"@context": "https://w3id.org/security/v2",
|
|
86
|
+
id: publicKey.controller,
|
|
87
|
+
assertionMethod: [publicKey.id],
|
|
88
|
+
authentication: [publicKey.id],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Verify the signature
|
|
92
|
+
const verifyCredentialResult = await vc.verifyCredential({
|
|
93
|
+
credential: data,
|
|
94
|
+
suite: vcVerifyingSuite,
|
|
95
|
+
controller,
|
|
96
|
+
documentLoader: builder.buildDocumentLoader(),
|
|
97
|
+
});
|
|
98
|
+
expect(verifyCredentialResult.verified).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type KwilActionClient,
|
|
3
|
+
NoncedBox,
|
|
4
|
+
base64Encode,
|
|
5
|
+
hexEncodeSha256Hash,
|
|
6
|
+
type idOSCredential,
|
|
7
|
+
utf8Encode,
|
|
8
|
+
} from "@idos-network/core";
|
|
9
|
+
import { createAccessGrantByDag as _createAccessGrantByDag } from "@idos-network/core/kwil-actions";
|
|
10
|
+
import invariant from "tiny-invariant";
|
|
11
|
+
|
|
12
|
+
export type CreateAccessGrantFromDAGParams = {
|
|
13
|
+
dag_data_id: string;
|
|
14
|
+
dag_owner_wallet_identifier: string;
|
|
15
|
+
dag_grantee_wallet_identifier: string;
|
|
16
|
+
dag_signature: string;
|
|
17
|
+
dag_locked_until: number;
|
|
18
|
+
dag_content_hash: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export class GrantService {
|
|
22
|
+
readonly #kwilClient: KwilActionClient;
|
|
23
|
+
readonly #encryptionSecretKey: Uint8Array;
|
|
24
|
+
|
|
25
|
+
constructor(kwilClient: KwilActionClient, encryptionSecretKey: Uint8Array) {
|
|
26
|
+
this.#kwilClient = kwilClient;
|
|
27
|
+
this.#encryptionSecretKey = encryptionSecretKey;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async createAccessGrantFromDAG(
|
|
31
|
+
params: CreateAccessGrantFromDAGParams,
|
|
32
|
+
getCredentialIdByContentHash: (contentHash: string) => Promise<string | null>,
|
|
33
|
+
getSharedCredential: (id: string) => Promise<idOSCredential | null>,
|
|
34
|
+
): Promise<CreateAccessGrantFromDAGParams | null> {
|
|
35
|
+
const credentialId = await getCredentialIdByContentHash(params.dag_content_hash);
|
|
36
|
+
|
|
37
|
+
invariant(credentialId, "Missing `idOSCredential` id");
|
|
38
|
+
|
|
39
|
+
const credential = await getSharedCredential(credentialId);
|
|
40
|
+
|
|
41
|
+
invariant(credential, "`idOSCredential` with id `{credentialId}` not found");
|
|
42
|
+
|
|
43
|
+
const plaintextContent = await NoncedBox.nonceFromBase64SecretKey(
|
|
44
|
+
base64Encode(this.#encryptionSecretKey),
|
|
45
|
+
).decrypt(credential.content, credential.encryptor_public_key);
|
|
46
|
+
|
|
47
|
+
// Get the content hash from the plaintext content
|
|
48
|
+
const contentHash = hexEncodeSha256Hash(utf8Encode(plaintextContent));
|
|
49
|
+
|
|
50
|
+
// Check if the content hash matches the content hash in the credential
|
|
51
|
+
if (contentHash !== params.dag_content_hash) {
|
|
52
|
+
throw new Error("Hash mismatch between `DAG` and `idOSCredential` content");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const result = await _createAccessGrantByDag(this.#kwilClient, params);
|
|
56
|
+
|
|
57
|
+
return result ?? null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { KwilActionClient } from "@idos-network/core";
|
|
2
|
+
import {
|
|
3
|
+
createUser as _createUser,
|
|
4
|
+
hasProfile as _hasProfile,
|
|
5
|
+
upsertWalletAsInserter as _upsertWalletAsInserter,
|
|
6
|
+
} from "@idos-network/core/kwil-actions";
|
|
7
|
+
import type { idOSUser, idOSWallet } from "@idos-network/core/types";
|
|
8
|
+
|
|
9
|
+
export type CreateProfileReqParams = Omit<idOSUser, "id"> & {
|
|
10
|
+
id?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type UpsertWalletReqParams = Omit<idOSWallet, "id"> & {
|
|
14
|
+
id?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type CreateWalletReqParams = Omit<UpsertWalletReqParams, "user_id"> & {
|
|
18
|
+
id?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export class UserService {
|
|
22
|
+
readonly #kwilClient: KwilActionClient;
|
|
23
|
+
|
|
24
|
+
constructor(kwilClient: KwilActionClient) {
|
|
25
|
+
this.#kwilClient = kwilClient;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#ensureEntityId<T extends { id?: string }>(entity: T): T & { id: string } {
|
|
29
|
+
if (!entity.id) {
|
|
30
|
+
(entity as T & { id: string }).id = crypto.randomUUID();
|
|
31
|
+
}
|
|
32
|
+
return entity as T & { id: string };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async hasProfile(userAddress: string): Promise<boolean> {
|
|
36
|
+
return _hasProfile(this.#kwilClient, userAddress);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async createUserProfile(params: CreateProfileReqParams): Promise<idOSUser> {
|
|
40
|
+
const payload = this.#ensureEntityId(params);
|
|
41
|
+
await _createUser(this.#kwilClient, payload);
|
|
42
|
+
return payload;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async upsertWalletAsInserter(params: UpsertWalletReqParams): Promise<idOSWallet> {
|
|
46
|
+
const payload = this.#ensureEntityId(params);
|
|
47
|
+
await _upsertWalletAsInserter(this.#kwilClient, payload);
|
|
48
|
+
return payload;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async createUser(
|
|
52
|
+
user: CreateProfileReqParams,
|
|
53
|
+
wallet: CreateWalletReqParams,
|
|
54
|
+
): Promise<[idOSUser, idOSWallet]> {
|
|
55
|
+
const user_id = user.id ?? crypto.randomUUID();
|
|
56
|
+
const wallet_id = wallet.id ?? crypto.randomUUID();
|
|
57
|
+
|
|
58
|
+
const userReqParams = {
|
|
59
|
+
...user,
|
|
60
|
+
id: user_id,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const userResponse = await this.createUserProfile(userReqParams);
|
|
64
|
+
|
|
65
|
+
const walletReqParams = {
|
|
66
|
+
...wallet,
|
|
67
|
+
user_id,
|
|
68
|
+
id: wallet_id,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const walletResponse = await this.upsertWalletAsInserter(walletReqParams);
|
|
72
|
+
|
|
73
|
+
return [userResponse, walletResponse];
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/types.d.ts
ADDED