@idos-network/kwil-infra 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.
Files changed (54) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +46 -1
  3. package/dist/actions/index.d.mts +2 -2
  4. package/dist/actions/index.mjs +1 -1370
  5. package/dist/actions/index.mjs.map +1 -1
  6. package/dist/facesign/index.d.mts +1 -1
  7. package/dist/facesign/index.mjs +1 -2
  8. package/dist/{facesign-signer-BC24j1eN.d.mts → facesign-signer-5I8juA7p.d.mts} +2 -1
  9. package/dist/facesign-signer-5I8juA7p.d.mts.map +1 -0
  10. package/dist/facesign-signer-z5T312uQ.mjs +2 -0
  11. package/dist/facesign-signer-z5T312uQ.mjs.map +1 -0
  12. package/dist/{index-iqkJfgWf.d.mts → index-Bqz6trCk.d.mts} +223 -136
  13. package/dist/index-Bqz6trCk.d.mts.map +1 -0
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +1 -429
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/signature-verification/index.d.mts +3 -4
  18. package/dist/signature-verification/index.d.mts.map +1 -1
  19. package/dist/signature-verification/index.mjs +1 -134
  20. package/dist/signature-verification/index.mjs.map +1 -1
  21. package/dist/xrp/utils.d.mts +130 -20
  22. package/dist/xrp/utils.d.mts.map +1 -1
  23. package/dist/xrp/utils.mjs +1 -104
  24. package/dist/xrp/utils.mjs.map +1 -1
  25. package/dist/xrpl-credentials/index.d.mts +6 -7
  26. package/dist/xrpl-credentials/index.d.mts.map +1 -1
  27. package/dist/xrpl-credentials/index.mjs +1 -223
  28. package/dist/xrpl-credentials/index.mjs.map +1 -1
  29. package/package.json +9 -8
  30. package/src/actions/actions.test.ts +189 -0
  31. package/src/actions/actions.ts +368 -467
  32. package/src/actions/index.ts +38 -0
  33. package/src/create-kgw-authenticated-fetch.test.ts +377 -0
  34. package/src/create-kgw-authenticated-fetch.ts +321 -0
  35. package/src/create-kwil-client.ts +33 -10
  36. package/src/create-kwil-signer.test.ts +80 -0
  37. package/src/create-kwil-signer.ts +31 -5
  38. package/src/facesign/facesign-signer.test.ts +77 -0
  39. package/src/facesign/facesign-signer.ts +50 -2
  40. package/src/index.ts +2 -0
  41. package/src/mm-token/create-mm-token-kwil-signer.test.ts +148 -0
  42. package/src/mm-token/create-mm-token-kwil-signer.ts +166 -0
  43. package/src/near/create-near-wallet-kwil-signer.ts +1 -1
  44. package/src/signature-verification/index.test.ts +18 -0
  45. package/src/signature-verification/index.ts +7 -1
  46. package/src/wait-for-kwil-tx.test.ts +92 -0
  47. package/src/wait-for-kwil-tx.ts +111 -0
  48. package/src/xrp/signer.ts +2 -1
  49. package/src/xrp/utils.ts +7 -25
  50. package/tsdown.config.ts +1 -0
  51. package/dist/facesign-signer-BC24j1eN.d.mts.map +0 -1
  52. package/dist/facesign-signer-qzCcwunk.mjs +0 -244
  53. package/dist/facesign-signer-qzCcwunk.mjs.map +0 -1
  54. package/dist/index-iqkJfgWf.d.mts.map +0 -1
@@ -1,224 +1,2 @@
1
- import { hexEncode, utf8Encode } from "@idos-network/utils/codecs";
2
- //#region src/xrpl-credentials/accept.ts
3
- /**
4
- * Creates a credential acceptance payload for XRPL transactions
5
- *
6
- * This function constructs a properly formatted payload for credential acceptance
7
- * transactions. The credential type is automatically encoded from UTF-8 to hex
8
- * format as required by XRPL specifications.
9
- *
10
- * @param issuerAddress - The XRPL address of the credential issuer
11
- * @param accountAddress - The XRPL address of the account accepting the credential
12
- * @param credentialType - The human-readable idOS credential type (e.g., "KYC")
13
- * @returns A properly formatted CredentialAcceptPayload object
14
- *
15
- * @example
16
- * ```typescript
17
- * const payload = OriginalCredentialAcceptPayload(
18
- * "rIssuerAddress123...",
19
- * "rAccountAddress456...",
20
- * "KYC"
21
- * );
22
- * // Result: {
23
- * // TransactionType: "CredentialAccept",
24
- * // Issuer: "rIssuerAddress123...",
25
- * // Account: "rAccountAddress456...",
26
- * // CredentialType: "4B5943" // Hex encoded "KYC"
27
- * // }
28
- * ```
29
- */
30
- function OriginalCredentialAcceptPayload(issuerAddress, accountAddress, credentialType) {
31
- return {
32
- TransactionType: "CredentialAccept",
33
- Issuer: issuerAddress,
34
- Account: accountAddress,
35
- CredentialType: hexEncode(utf8Encode(credentialType))
36
- };
37
- }
38
- /**
39
- * Creates a copy credential acceptance payload for XRPL transactions
40
- *
41
- * This function constructs a payload for accepting a copy of an existing credential
42
- * with additional metadata including the original issuer and a timelock period.
43
- * The CredentialType field is encoded as a composite string containing:
44
- * - "AG-" prefix (indicating copy credential)
45
- * - Original credential type
46
- * - Original issuer address
47
- * - Timelock period in years
48
- *
49
- * @param copyCredentialIssuerAddress - The XRPL address of the issuer created a XRPL Credential object related to idOS credential copy
50
- * @param accountAddress - The XRPL address of the account accepting the credential copy
51
- * @param originalCredentialIssuerAddress - The XRPL address of the issuer created a XRPL Credential object related to idOS original credential
52
- * @param credentialType - The human-readable idOScredential type (e.g., "KYC")
53
- * @param timelockYears - The number of years for the timelock period (must be non-negative integer)
54
- * @returns A properly formatted CredentialAcceptPayload object for copy credentials
55
- * @throws {Error} When timelockYears is not a non-negative integer
56
- *
57
- * @example
58
- * ```typescript
59
- * const payload = await CopyCredentialAcceptPayload(
60
- * "rCopyIssuerAddress123...",
61
- * "rAccountAddress456...",
62
- * "rOriginalIssuerAddress789...",
63
- * "KYC",
64
- * 2
65
- * );
66
- * // Result: {
67
- * // TransactionType: "CredentialAccept",
68
- * // Issuer: "rCopyIssuerAddress123...",
69
- * // Account: "rAccountAddress456...",
70
- * // CredentialType: "41472D4B59432D..." // Hex encoded "AG-KYC-{originalIssuer}-2Y"
71
- * // }
72
- * ```
73
- */
74
- async function CopyCredentialAcceptPayload(copyCredentialIssuerAddress, accountAddress, originalCredentialIssuerAddress, credentialType, timelockYears) {
75
- if (!Number.isInteger(timelockYears) || timelockYears < 0) throw new Error("timelockYears must be a non-negative integer");
76
- let decodeAccountID;
77
- try {
78
- ({decodeAccountID} = await import("xrpl"));
79
- } catch {
80
- throw new Error("Missing optional peer dependency \"xrpl\". Install it to use CopyCredentialAcceptPayload.");
81
- }
82
- return {
83
- TransactionType: "CredentialAccept",
84
- Issuer: copyCredentialIssuerAddress,
85
- Account: accountAddress,
86
- CredentialType: hexEncode(Buffer.concat([
87
- utf8Encode("AG"),
88
- utf8Encode("-"),
89
- utf8Encode(credentialType),
90
- utf8Encode("-"),
91
- decodeAccountID(originalCredentialIssuerAddress),
92
- utf8Encode("-"),
93
- utf8Encode(`${timelockYears}Y`)
94
- ]))
95
- };
96
- }
97
- //#endregion
98
- //#region src/xrpl-credentials/create.ts
99
- /**
100
- * Service class for creating credentials on the XRPL blockchain
101
- *
102
- * This service provides methods to create both original and copy credentials
103
- * on the XRPL. It handles connection management, transaction submission,
104
- * and proper encoding of credential data according to XRPL specifications.
105
- *
106
- * @example
107
- * ```typescript
108
- * const wallet = Wallet.fromSeed("s...");
109
- * const xrplService = await XrplCredentialsCreate.init("wss://s.devnet.rippletest.net:51233", wallet);
110
- *
111
- * // Create original credential
112
- * await xrplService.createCredentialForOriginal({
113
- * credId: "741a9caf-ec53-42c7-aed6-519950dcded5",
114
- * credType: "KYC",
115
- * userAddress: "rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe"
116
- * });
117
- * ```
118
- */
119
- var XrplCredentialsCreate = class XrplCredentialsCreate {
120
- #client;
121
- #wallet;
122
- #xrpl;
123
- constructor(nodeUrl, wallet, xrpl) {
124
- this.#xrpl = xrpl;
125
- this.#wallet = wallet;
126
- this.#client = new this.#xrpl.Client(nodeUrl);
127
- }
128
- /**
129
- * Creates a new XRPL credentials service instance.
130
- *
131
- * @param nodeUrl - The WebSocket URL of the XRPL node to connect to
132
- * @param wallet - The XRPL wallet to use for signing transactions
133
- */
134
- static async init(nodeUrl, wallet) {
135
- let xrpl;
136
- try {
137
- xrpl = await import("xrpl");
138
- } catch {
139
- throw new Error("Missing optional peer dependency 'xrpl'. Install it to use XrplCredentialsCreate.");
140
- }
141
- return new XrplCredentialsCreate(nodeUrl, wallet, xrpl);
142
- }
143
- /**
144
- * Creates a credential on the XRPL that reflects an idOS original credential.
145
- *
146
- * This method creates a new credential with the specified type and assigns it to the given user.
147
- * The credential type is encoded as a hex string, and the credential ID is encoded as a hex URI.
148
- *
149
- * @param params - Parameters for creating the original credential
150
- * @returns Promise resolving to the XRPL transaction result
151
- *
152
- * @example
153
- * ```typescript
154
- * await xrplService.createCredentialForOriginal({
155
- * credId: "741a9caf-ec53-42c7-aed6-519950dcded5",
156
- * credType: "KYC",
157
- * userAddress: "rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe"
158
- * });
159
- * ```
160
- */
161
- async createCredentialForOriginal(params) {
162
- const { credId, credType, userAddress } = params;
163
- await this.#client.connect();
164
- const res = await this.#client.submitAndWait({
165
- TransactionType: "CredentialCreate",
166
- Account: this.#wallet.address,
167
- Subject: userAddress,
168
- CredentialType: hexEncode(utf8Encode(credType)),
169
- URI: hexEncode(utf8Encode(credId))
170
- }, { wallet: this.#wallet });
171
- await this.#client.disconnect();
172
- return res;
173
- }
174
- /**
175
- * Creates a time-locked credential copy on the XRPL.
176
- *
177
- * This method creates a Credential object in XRPL that reflects an idOS credential copy.
178
- * The credential type includes metadata about the original issuer and time-lock duration.
179
- * The composite credential type follows the format: "AG-{type}-{originalIssuer}-{timelock}Y"
180
- *
181
- * @param params - Parameters for creating the time-locked credential copy
182
- * @returns Promise resolving to the XRPL transaction result
183
- *
184
- * @throws {Error} When timelockYears is not a non-negative integer
185
- *
186
- * @example
187
- * ```typescript
188
- * const result = await xrplService.createCredentialForCopy({
189
- * credId: "741a9caf-ec53-42c7-aed6-519950dcded5",
190
- * credType: "KYC",
191
- * userAddress: "rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe",
192
- * timelockYears: 5,
193
- * origCredIssuerAddress: "rU9C67bZ3ZvjXaJYwYqMqjMq1o4ZbwK3YN"
194
- * });
195
- * ```
196
- */
197
- async createCredentialForCopy(params) {
198
- const { credId, credType, userAddress, timelockYears, origCredIssuerAddress } = params;
199
- if (!Number.isInteger(timelockYears) || timelockYears < 0) throw new Error("timelockYears must be a non-negative integer");
200
- await this.#client.connect();
201
- const type = Buffer.concat([
202
- utf8Encode("AG"),
203
- utf8Encode("-"),
204
- utf8Encode(credType),
205
- utf8Encode("-"),
206
- this.#xrpl.decodeAccountID(origCredIssuerAddress),
207
- utf8Encode("-"),
208
- utf8Encode(`${timelockYears}Y`)
209
- ]);
210
- const res = await this.#client.submitAndWait({
211
- TransactionType: "CredentialCreate",
212
- Account: this.#wallet.address,
213
- Subject: userAddress,
214
- CredentialType: hexEncode(type),
215
- URI: hexEncode(utf8Encode(credId))
216
- }, { wallet: this.#wallet });
217
- await this.#client.disconnect();
218
- return res;
219
- }
220
- };
221
- //#endregion
222
- export { CopyCredentialAcceptPayload, OriginalCredentialAcceptPayload, XrplCredentialsCreate };
223
-
1
+ import{hexEncode as e,utf8Encode as t}from"@idos-network/utils/codecs";function n(n,r,i){return{TransactionType:`CredentialAccept`,Issuer:n,Account:r,CredentialType:e(t(i))}}async function r(n,r,i,a,o){if(!Number.isInteger(o)||o<0)throw Error(`timelockYears must be a non-negative integer`);let s;try{({decodeAccountID:s}=await import(`xrpl`))}catch{throw Error(`Missing optional peer dependency "xrpl". Install it to use CopyCredentialAcceptPayload.`)}let c=Buffer.concat([t(`AG`),t(`-`),t(a),t(`-`),s(i),t(`-`),t(`${o}Y`)]);return{TransactionType:`CredentialAccept`,Issuer:n,Account:r,CredentialType:e(c)}}var i=class n{#e;#t;#n;constructor(e,t,n){this.#n=n,this.#t=t,this.#e=new this.#n.Client(e)}static async init(e,t){let r;try{r=await import(`xrpl`)}catch{throw Error(`Missing optional peer dependency 'xrpl'. Install it to use XrplCredentialsCreate.`)}return new n(e,t,r)}async createCredentialForOriginal(n){let{credId:r,credType:i,userAddress:a}=n;await this.#e.connect();let o=await this.#e.submitAndWait({TransactionType:`CredentialCreate`,Account:this.#t.address,Subject:a,CredentialType:e(t(i)),URI:e(t(r))},{wallet:this.#t});return await this.#e.disconnect(),o}async createCredentialForCopy(n){let{credId:r,credType:i,userAddress:a,timelockYears:o,origCredIssuerAddress:s}=n;if(!Number.isInteger(o)||o<0)throw Error(`timelockYears must be a non-negative integer`);await this.#e.connect();let c=Buffer.concat([t(`AG`),t(`-`),t(i),t(`-`),this.#n.decodeAccountID(s),t(`-`),t(`${o}Y`)]),l=await this.#e.submitAndWait({TransactionType:`CredentialCreate`,Account:this.#t.address,Subject:a,CredentialType:e(c),URI:e(t(r))},{wallet:this.#t});return await this.#e.disconnect(),l}};export{r as CopyCredentialAcceptPayload,n as OriginalCredentialAcceptPayload,i as XrplCredentialsCreate};
224
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#client","#wallet","#xrpl"],"sources":["../../src/xrpl-credentials/accept.ts","../../src/xrpl-credentials/create.ts"],"sourcesContent":["import { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\n/**\n * Payload structure for XRPL CredentialAccept transaction\n *\n * This type defines the required fields for creating a credential acceptance\n * transaction on the XRP Ledger. The CredentialType field is automatically\n * encoded as a hex string from the UTF-8 representation of the credential type.\n */\nexport type CredentialAcceptPayload = {\n /** Transaction type identifier - must be \"CredentialAccept\" */\n TransactionType: \"CredentialAccept\";\n /** The issuer's XRPL address who created the Credential object */\n Issuer: string;\n /** The account's XRPL address who is receiving the credential */\n Account: string;\n /** The type of credential being accepted (encoded as hex string) */\n CredentialType: string;\n};\n\n/**\n * Creates a credential acceptance payload for XRPL transactions\n *\n * This function constructs a properly formatted payload for credential acceptance\n * transactions. The credential type is automatically encoded from UTF-8 to hex\n * format as required by XRPL specifications.\n *\n * @param issuerAddress - The XRPL address of the credential issuer\n * @param accountAddress - The XRPL address of the account accepting the credential\n * @param credentialType - The human-readable idOS credential type (e.g., \"KYC\")\n * @returns A properly formatted CredentialAcceptPayload object\n *\n * @example\n * ```typescript\n * const payload = OriginalCredentialAcceptPayload(\n * \"rIssuerAddress123...\",\n * \"rAccountAddress456...\",\n * \"KYC\"\n * );\n * // Result: {\n * // TransactionType: \"CredentialAccept\",\n * // Issuer: \"rIssuerAddress123...\",\n * // Account: \"rAccountAddress456...\",\n * // CredentialType: \"4B5943\" // Hex encoded \"KYC\"\n * // }\n * ```\n */\nexport function OriginalCredentialAcceptPayload(\n issuerAddress: string,\n accountAddress: string,\n credentialType: string,\n): CredentialAcceptPayload {\n // Encode the credential type from UTF-8 to hex format\n // This is required by XRPL for proper transaction processing\n const encodedCredentialType = hexEncode(utf8Encode(credentialType));\n\n return {\n TransactionType: \"CredentialAccept\",\n Issuer: issuerAddress,\n Account: accountAddress,\n CredentialType: encodedCredentialType,\n };\n}\n\n/**\n * Creates a copy credential acceptance payload for XRPL transactions\n *\n * This function constructs a payload for accepting a copy of an existing credential\n * with additional metadata including the original issuer and a timelock period.\n * The CredentialType field is encoded as a composite string containing:\n * - \"AG-\" prefix (indicating copy credential)\n * - Original credential type\n * - Original issuer address\n * - Timelock period in years\n *\n * @param copyCredentialIssuerAddress - The XRPL address of the issuer created a XRPL Credential object related to idOS credential copy\n * @param accountAddress - The XRPL address of the account accepting the credential copy\n * @param originalCredentialIssuerAddress - The XRPL address of the issuer created a XRPL Credential object related to idOS original credential\n * @param credentialType - The human-readable idOScredential type (e.g., \"KYC\")\n * @param timelockYears - The number of years for the timelock period (must be non-negative integer)\n * @returns A properly formatted CredentialAcceptPayload object for copy credentials\n * @throws {Error} When timelockYears is not a non-negative integer\n *\n * @example\n * ```typescript\n * const payload = await CopyCredentialAcceptPayload(\n * \"rCopyIssuerAddress123...\",\n * \"rAccountAddress456...\",\n * \"rOriginalIssuerAddress789...\",\n * \"KYC\",\n * 2\n * );\n * // Result: {\n * // TransactionType: \"CredentialAccept\",\n * // Issuer: \"rCopyIssuerAddress123...\",\n * // Account: \"rAccountAddress456...\",\n * // CredentialType: \"41472D4B59432D...\" // Hex encoded \"AG-KYC-{originalIssuer}-2Y\"\n * // }\n * ```\n */\nexport async function CopyCredentialAcceptPayload(\n copyCredentialIssuerAddress: string,\n accountAddress: string,\n originalCredentialIssuerAddress: string,\n credentialType: string,\n timelockYears: number,\n): Promise<CredentialAcceptPayload> {\n // Validate that timelockYears is a non-negative integer\n if (!Number.isInteger(timelockYears) || timelockYears < 0) {\n throw new Error(\"timelockYears must be a non-negative integer\");\n }\n\n let decodeAccountID: typeof import(\"xrpl\").decodeAccountID;\n try {\n ({ decodeAccountID } = await import(\"xrpl\"));\n } catch {\n throw new Error(\n 'Missing optional peer dependency \"xrpl\". Install it to use CopyCredentialAcceptPayload.',\n );\n }\n\n // Create a composite credential type string that includes:\n // - \"AG-\" prefix (indicating this is a copy credential)\n // - Original credential type\n // - Original issuer Account ID (decoded from XRPL address format)\n // - Timelock period in years\n const type = Buffer.concat([\n utf8Encode(\"AG\"),\n utf8Encode(\"-\"),\n utf8Encode(credentialType),\n utf8Encode(\"-\"),\n decodeAccountID(originalCredentialIssuerAddress),\n utf8Encode(\"-\"),\n utf8Encode(`${timelockYears}Y`),\n ]);\n\n return {\n TransactionType: \"CredentialAccept\",\n Issuer: copyCredentialIssuerAddress,\n Account: accountAddress,\n CredentialType: hexEncode(type),\n };\n}\n","import type { Client, TxResponse, Wallet } from \"xrpl\";\n\nimport { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\n/**\n * Parameters for creating an original credential on XRPL\n */\nexport type CreateCredentialForOriginalParams = {\n /** Unique identifier for the idOS credential, like `741a9caf-ec53-42c7-aed6-519950dcded5` */\n credId: string;\n /** Type/category of the credential, like `KYC` */\n credType: string;\n /** XRPL address of the user receiving the credential, like `rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe` */\n userAddress: string;\n};\n\n/**\n * Parameters for creating a time-locked copy credential on XRPL\n */\nexport type CreateCredentialForCopyParams = {\n /** Unique identifier for the idOS credential */\n credId: string;\n /** Type/category of the credential */\n credType: string;\n /** XRPL address of the user receiving the credential */\n userAddress: string;\n /** Number of years to lock the credential (must be non-negative integer) */\n timelockYears: number;\n /** XRPL address of the original credential issuer */\n origCredIssuerAddress: string;\n};\n\n/**\n * Service class for creating credentials on the XRPL blockchain\n *\n * This service provides methods to create both original and copy credentials\n * on the XRPL. It handles connection management, transaction submission,\n * and proper encoding of credential data according to XRPL specifications.\n *\n * @example\n * ```typescript\n * const wallet = Wallet.fromSeed(\"s...\");\n * const xrplService = await XrplCredentialsCreate.init(\"wss://s.devnet.rippletest.net:51233\", wallet);\n *\n * // Create original credential\n * await xrplService.createCredentialForOriginal({\n * credId: \"741a9caf-ec53-42c7-aed6-519950dcded5\",\n * credType: \"KYC\",\n * userAddress: \"rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe\"\n * });\n * ```\n */\nexport class XrplCredentialsCreate {\n readonly #client: Client;\n readonly #wallet: Wallet;\n readonly #xrpl: typeof import(\"xrpl\");\n\n constructor(nodeUrl: string, wallet: Wallet, xrpl: typeof import(\"xrpl\")) {\n this.#xrpl = xrpl;\n this.#wallet = wallet;\n this.#client = new this.#xrpl.Client(nodeUrl);\n }\n\n /**\n * Creates a new XRPL credentials service instance.\n *\n * @param nodeUrl - The WebSocket URL of the XRPL node to connect to\n * @param wallet - The XRPL wallet to use for signing transactions\n */\n static async init(nodeUrl: string, wallet: Wallet): Promise<XrplCredentialsCreate> {\n let xrpl: typeof import(\"xrpl\");\n\n try {\n xrpl = await import(\"xrpl\");\n } catch {\n throw new Error(\n \"Missing optional peer dependency 'xrpl'. Install it to use XrplCredentialsCreate.\",\n );\n }\n\n return new XrplCredentialsCreate(nodeUrl, wallet, xrpl);\n }\n\n /**\n * Creates a credential on the XRPL that reflects an idOS original credential.\n *\n * This method creates a new credential with the specified type and assigns it to the given user.\n * The credential type is encoded as a hex string, and the credential ID is encoded as a hex URI.\n *\n * @param params - Parameters for creating the original credential\n * @returns Promise resolving to the XRPL transaction result\n *\n * @example\n * ```typescript\n * await xrplService.createCredentialForOriginal({\n * credId: \"741a9caf-ec53-42c7-aed6-519950dcded5\",\n * credType: \"KYC\",\n * userAddress: \"rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe\"\n * });\n * ```\n */\n async createCredentialForOriginal(\n params: CreateCredentialForOriginalParams,\n ): Promise<TxResponse> {\n const { credId, credType, userAddress } = params;\n\n // Connect to the XRPL node\n await this.#client.connect();\n\n // Submit the credential creation transaction and wait for confirmation\n const res = await this.#client.submitAndWait(\n {\n TransactionType: \"CredentialCreate\",\n Account: this.#wallet.address,\n Subject: userAddress,\n // Encode credential type as hex string (required by XRPL)\n CredentialType: hexEncode(utf8Encode(credType)),\n // Encode credential ID as hex URI (required by XRPL)\n URI: hexEncode(utf8Encode(credId)),\n },\n {\n wallet: this.#wallet,\n },\n );\n\n // Disconnect from the XRPL node\n await this.#client.disconnect();\n\n return res;\n }\n\n /**\n * Creates a time-locked credential copy on the XRPL.\n *\n * This method creates a Credential object in XRPL that reflects an idOS credential copy.\n * The credential type includes metadata about the original issuer and time-lock duration.\n * The composite credential type follows the format: \"AG-{type}-{originalIssuer}-{timelock}Y\"\n *\n * @param params - Parameters for creating the time-locked credential copy\n * @returns Promise resolving to the XRPL transaction result\n *\n * @throws {Error} When timelockYears is not a non-negative integer\n *\n * @example\n * ```typescript\n * const result = await xrplService.createCredentialForCopy({\n * credId: \"741a9caf-ec53-42c7-aed6-519950dcded5\",\n * credType: \"KYC\",\n * userAddress: \"rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe\",\n * timelockYears: 5,\n * origCredIssuerAddress: \"rU9C67bZ3ZvjXaJYwYqMqjMq1o4ZbwK3YN\"\n * });\n * ```\n */\n async createCredentialForCopy(params: CreateCredentialForCopyParams): Promise<TxResponse> {\n const { credId, credType, userAddress, timelockYears, origCredIssuerAddress } = params;\n\n // Validate timelockYears is a non-negative integer\n if (!Number.isInteger(timelockYears) || timelockYears < 0) {\n throw new Error(\"timelockYears must be a non-negative integer\");\n }\n\n // Connect to the XRPL node\n await this.#client.connect();\n\n // Create composite credential type with metadata:\n // Format: \"AG-{credType}-{originalIssuer}-{timelock}Y\"\n const type = Buffer.concat([\n utf8Encode(\"AG\"), // \"AG\" prefix for copy credentials\n utf8Encode(\"-\"), // Separator\n utf8Encode(credType), // Original credential type\n utf8Encode(\"-\"), // Separator\n this.#xrpl.decodeAccountID(origCredIssuerAddress), // Original issuer address (decoded)\n utf8Encode(\"-\"), // Separator\n utf8Encode(`${timelockYears}Y`), // Timelock period in years\n ]);\n\n // Submit the credential copy creation transaction and wait for confirmation\n const res = await this.#client.submitAndWait(\n {\n TransactionType: \"CredentialCreate\",\n Account: this.#wallet.address,\n Subject: userAddress,\n // Use the composite credential type with metadata\n CredentialType: hexEncode(type),\n // Encode credential ID as hex URI (required by XRPL)\n URI: hexEncode(utf8Encode(credId)),\n },\n {\n wallet: this.#wallet,\n },\n );\n\n // Disconnect from the XRPL node\n await this.#client.disconnect();\n\n return res;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,SAAgB,gCACd,eACA,gBACA,gBACyB;CAKzB,OAAO;EACL,iBAAiB;EACjB,QAAQ;EACR,SAAS;EACT,gBAN4B,UAAU,WAAW,cAAc,CAM3B;CACtC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,eAAsB,4BACpB,6BACA,gBACA,iCACA,gBACA,eACkC;CAElC,IAAI,CAAC,OAAO,UAAU,aAAa,KAAK,gBAAgB,GACtD,MAAM,IAAI,MAAM,8CAA8C;CAGhE,IAAI;CACJ,IAAI;EACF,CAAC,CAAE,mBAAoB,MAAM,OAAO;CACtC,QAAQ;EACN,MAAM,IAAI,MACR,2FACF;CACF;CAiBA,OAAO;EACL,iBAAiB;EACjB,QAAQ;EACR,SAAS;EACT,gBAAgB,UAdL,OAAO,OAAO;GACzB,WAAW,IAAI;GACf,WAAW,GAAG;GACd,WAAW,cAAc;GACzB,WAAW,GAAG;GACd,gBAAgB,+BAA+B;GAC/C,WAAW,GAAG;GACd,WAAW,GAAG,cAAc,EAAE;EAChC,CAM+B,CAAC;CAChC;AACF;;;;;;;;;;;;;;;;;;;;;;;AC1FA,IAAa,wBAAb,MAAa,sBAAsB;CACjC;CACA;CACA;CAEA,YAAY,SAAiB,QAAgB,MAA6B;EACxE,KAAKE,QAAQ;EACb,KAAKD,UAAU;EACf,KAAKD,UAAU,IAAI,KAAKE,MAAM,OAAO,OAAO;CAC9C;;;;;;;CAQA,aAAa,KAAK,SAAiB,QAAgD;EACjF,IAAI;EAEJ,IAAI;GACF,OAAO,MAAM,OAAO;EACtB,QAAQ;GACN,MAAM,IAAI,MACR,mFACF;EACF;EAEA,OAAO,IAAI,sBAAsB,SAAS,QAAQ,IAAI;CACxD;;;;;;;;;;;;;;;;;;;CAoBA,MAAM,4BACJ,QACqB;EACrB,MAAM,EAAE,QAAQ,UAAU,gBAAgB;EAG1C,MAAM,KAAKF,QAAQ,QAAQ;EAG3B,MAAM,MAAM,MAAM,KAAKA,QAAQ,cAC7B;GACE,iBAAiB;GACjB,SAAS,KAAKC,QAAQ;GACtB,SAAS;GAET,gBAAgB,UAAU,WAAW,QAAQ,CAAC;GAE9C,KAAK,UAAU,WAAW,MAAM,CAAC;EACnC,GACA,EACE,QAAQ,KAAKA,QACf,CACF;EAGA,MAAM,KAAKD,QAAQ,WAAW;EAE9B,OAAO;CACT;;;;;;;;;;;;;;;;;;;;;;;;CAyBA,MAAM,wBAAwB,QAA4D;EACxF,MAAM,EAAE,QAAQ,UAAU,aAAa,eAAe,0BAA0B;EAGhF,IAAI,CAAC,OAAO,UAAU,aAAa,KAAK,gBAAgB,GACtD,MAAM,IAAI,MAAM,8CAA8C;EAIhE,MAAM,KAAKA,QAAQ,QAAQ;EAI3B,MAAM,OAAO,OAAO,OAAO;GACzB,WAAW,IAAI;GACf,WAAW,GAAG;GACd,WAAW,QAAQ;GACnB,WAAW,GAAG;GACd,KAAKE,MAAM,gBAAgB,qBAAqB;GAChD,WAAW,GAAG;GACd,WAAW,GAAG,cAAc,EAAE;EAChC,CAAC;EAGD,MAAM,MAAM,MAAM,KAAKF,QAAQ,cAC7B;GACE,iBAAiB;GACjB,SAAS,KAAKC,QAAQ;GACtB,SAAS;GAET,gBAAgB,UAAU,IAAI;GAE9B,KAAK,UAAU,WAAW,MAAM,CAAC;EACnC,GACA,EACE,QAAQ,KAAKA,QACf,CACF;EAGA,MAAM,KAAKD,QAAQ,WAAW;EAE9B,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/xrpl-credentials/accept.ts","../../src/xrpl-credentials/create.ts"],"sourcesContent":["import { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\n/**\n * Payload structure for XRPL CredentialAccept transaction\n *\n * This type defines the required fields for creating a credential acceptance\n * transaction on the XRP Ledger. The CredentialType field is automatically\n * encoded as a hex string from the UTF-8 representation of the credential type.\n */\nexport type CredentialAcceptPayload = {\n /** Transaction type identifier - must be \"CredentialAccept\" */\n TransactionType: \"CredentialAccept\";\n /** The issuer's XRPL address who created the Credential object */\n Issuer: string;\n /** The account's XRPL address who is receiving the credential */\n Account: string;\n /** The type of credential being accepted (encoded as hex string) */\n CredentialType: string;\n};\n\n/**\n * Creates a credential acceptance payload for XRPL transactions\n *\n * This function constructs a properly formatted payload for credential acceptance\n * transactions. The credential type is automatically encoded from UTF-8 to hex\n * format as required by XRPL specifications.\n *\n * @param issuerAddress - The XRPL address of the credential issuer\n * @param accountAddress - The XRPL address of the account accepting the credential\n * @param credentialType - The human-readable idOS credential type (e.g., \"KYC\")\n * @returns A properly formatted CredentialAcceptPayload object\n *\n * @example\n * ```typescript\n * const payload = OriginalCredentialAcceptPayload(\n * \"rIssuerAddress123...\",\n * \"rAccountAddress456...\",\n * \"KYC\"\n * );\n * // Result: {\n * // TransactionType: \"CredentialAccept\",\n * // Issuer: \"rIssuerAddress123...\",\n * // Account: \"rAccountAddress456...\",\n * // CredentialType: \"4B5943\" // Hex encoded \"KYC\"\n * // }\n * ```\n */\nexport function OriginalCredentialAcceptPayload(\n issuerAddress: string,\n accountAddress: string,\n credentialType: string,\n): CredentialAcceptPayload {\n // Encode the credential type from UTF-8 to hex format\n // This is required by XRPL for proper transaction processing\n const encodedCredentialType = hexEncode(utf8Encode(credentialType));\n\n return {\n TransactionType: \"CredentialAccept\",\n Issuer: issuerAddress,\n Account: accountAddress,\n CredentialType: encodedCredentialType,\n };\n}\n\n/**\n * Creates a copy credential acceptance payload for XRPL transactions\n *\n * This function constructs a payload for accepting a copy of an existing credential\n * with additional metadata including the original issuer and a timelock period.\n * The CredentialType field is encoded as a composite string containing:\n * - \"AG-\" prefix (indicating copy credential)\n * - Original credential type\n * - Original issuer address\n * - Timelock period in years\n *\n * @param copyCredentialIssuerAddress - The XRPL address of the issuer created a XRPL Credential object related to idOS credential copy\n * @param accountAddress - The XRPL address of the account accepting the credential copy\n * @param originalCredentialIssuerAddress - The XRPL address of the issuer created a XRPL Credential object related to idOS original credential\n * @param credentialType - The human-readable idOScredential type (e.g., \"KYC\")\n * @param timelockYears - The number of years for the timelock period (must be non-negative integer)\n * @returns A properly formatted CredentialAcceptPayload object for copy credentials\n * @throws {Error} When timelockYears is not a non-negative integer\n *\n * @example\n * ```typescript\n * const payload = await CopyCredentialAcceptPayload(\n * \"rCopyIssuerAddress123...\",\n * \"rAccountAddress456...\",\n * \"rOriginalIssuerAddress789...\",\n * \"KYC\",\n * 2\n * );\n * // Result: {\n * // TransactionType: \"CredentialAccept\",\n * // Issuer: \"rCopyIssuerAddress123...\",\n * // Account: \"rAccountAddress456...\",\n * // CredentialType: \"41472D4B59432D...\" // Hex encoded \"AG-KYC-{originalIssuer}-2Y\"\n * // }\n * ```\n */\nexport async function CopyCredentialAcceptPayload(\n copyCredentialIssuerAddress: string,\n accountAddress: string,\n originalCredentialIssuerAddress: string,\n credentialType: string,\n timelockYears: number,\n): Promise<CredentialAcceptPayload> {\n // Validate that timelockYears is a non-negative integer\n if (!Number.isInteger(timelockYears) || timelockYears < 0) {\n throw new Error(\"timelockYears must be a non-negative integer\");\n }\n\n let decodeAccountID: typeof import(\"xrpl\").decodeAccountID;\n try {\n ({ decodeAccountID } = await import(\"xrpl\"));\n } catch {\n throw new Error(\n 'Missing optional peer dependency \"xrpl\". Install it to use CopyCredentialAcceptPayload.',\n );\n }\n\n // Create a composite credential type string that includes:\n // - \"AG-\" prefix (indicating this is a copy credential)\n // - Original credential type\n // - Original issuer Account ID (decoded from XRPL address format)\n // - Timelock period in years\n const type = Buffer.concat([\n utf8Encode(\"AG\"),\n utf8Encode(\"-\"),\n utf8Encode(credentialType),\n utf8Encode(\"-\"),\n decodeAccountID(originalCredentialIssuerAddress),\n utf8Encode(\"-\"),\n utf8Encode(`${timelockYears}Y`),\n ]);\n\n return {\n TransactionType: \"CredentialAccept\",\n Issuer: copyCredentialIssuerAddress,\n Account: accountAddress,\n CredentialType: hexEncode(type),\n };\n}\n","import type { Client, TxResponse, Wallet } from \"xrpl\";\n\nimport { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\n/**\n * Parameters for creating an original credential on XRPL\n */\nexport type CreateCredentialForOriginalParams = {\n /** Unique identifier for the idOS credential, like `741a9caf-ec53-42c7-aed6-519950dcded5` */\n credId: string;\n /** Type/category of the credential, like `KYC` */\n credType: string;\n /** XRPL address of the user receiving the credential, like `rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe` */\n userAddress: string;\n};\n\n/**\n * Parameters for creating a time-locked copy credential on XRPL\n */\nexport type CreateCredentialForCopyParams = {\n /** Unique identifier for the idOS credential */\n credId: string;\n /** Type/category of the credential */\n credType: string;\n /** XRPL address of the user receiving the credential */\n userAddress: string;\n /** Number of years to lock the credential (must be non-negative integer) */\n timelockYears: number;\n /** XRPL address of the original credential issuer */\n origCredIssuerAddress: string;\n};\n\n/**\n * Service class for creating credentials on the XRPL blockchain\n *\n * This service provides methods to create both original and copy credentials\n * on the XRPL. It handles connection management, transaction submission,\n * and proper encoding of credential data according to XRPL specifications.\n *\n * @example\n * ```typescript\n * const wallet = Wallet.fromSeed(\"s...\");\n * const xrplService = await XrplCredentialsCreate.init(\"wss://s.devnet.rippletest.net:51233\", wallet);\n *\n * // Create original credential\n * await xrplService.createCredentialForOriginal({\n * credId: \"741a9caf-ec53-42c7-aed6-519950dcded5\",\n * credType: \"KYC\",\n * userAddress: \"rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe\"\n * });\n * ```\n */\nexport class XrplCredentialsCreate {\n readonly #client: Client;\n readonly #wallet: Wallet;\n readonly #xrpl: typeof import(\"xrpl\");\n\n constructor(nodeUrl: string, wallet: Wallet, xrpl: typeof import(\"xrpl\")) {\n this.#xrpl = xrpl;\n this.#wallet = wallet;\n this.#client = new this.#xrpl.Client(nodeUrl);\n }\n\n /**\n * Creates a new XRPL credentials service instance.\n *\n * @param nodeUrl - The WebSocket URL of the XRPL node to connect to\n * @param wallet - The XRPL wallet to use for signing transactions\n */\n static async init(nodeUrl: string, wallet: Wallet): Promise<XrplCredentialsCreate> {\n let xrpl: typeof import(\"xrpl\");\n\n try {\n xrpl = await import(\"xrpl\");\n } catch {\n throw new Error(\n \"Missing optional peer dependency 'xrpl'. Install it to use XrplCredentialsCreate.\",\n );\n }\n\n return new XrplCredentialsCreate(nodeUrl, wallet, xrpl);\n }\n\n /**\n * Creates a credential on the XRPL that reflects an idOS original credential.\n *\n * This method creates a new credential with the specified type and assigns it to the given user.\n * The credential type is encoded as a hex string, and the credential ID is encoded as a hex URI.\n *\n * @param params - Parameters for creating the original credential\n * @returns Promise resolving to the XRPL transaction result\n *\n * @example\n * ```typescript\n * await xrplService.createCredentialForOriginal({\n * credId: \"741a9caf-ec53-42c7-aed6-519950dcded5\",\n * credType: \"KYC\",\n * userAddress: \"rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe\"\n * });\n * ```\n */\n async createCredentialForOriginal(\n params: CreateCredentialForOriginalParams,\n ): Promise<TxResponse> {\n const { credId, credType, userAddress } = params;\n\n // Connect to the XRPL node\n await this.#client.connect();\n\n // Submit the credential creation transaction and wait for confirmation\n const res = await this.#client.submitAndWait(\n {\n TransactionType: \"CredentialCreate\",\n Account: this.#wallet.address,\n Subject: userAddress,\n // Encode credential type as hex string (required by XRPL)\n CredentialType: hexEncode(utf8Encode(credType)),\n // Encode credential ID as hex URI (required by XRPL)\n URI: hexEncode(utf8Encode(credId)),\n },\n {\n wallet: this.#wallet,\n },\n );\n\n // Disconnect from the XRPL node\n await this.#client.disconnect();\n\n return res;\n }\n\n /**\n * Creates a time-locked credential copy on the XRPL.\n *\n * This method creates a Credential object in XRPL that reflects an idOS credential copy.\n * The credential type includes metadata about the original issuer and time-lock duration.\n * The composite credential type follows the format: \"AG-{type}-{originalIssuer}-{timelock}Y\"\n *\n * @param params - Parameters for creating the time-locked credential copy\n * @returns Promise resolving to the XRPL transaction result\n *\n * @throws {Error} When timelockYears is not a non-negative integer\n *\n * @example\n * ```typescript\n * const result = await xrplService.createCredentialForCopy({\n * credId: \"741a9caf-ec53-42c7-aed6-519950dcded5\",\n * credType: \"KYC\",\n * userAddress: \"rPT1Sjq2YGrBMTttX4GZHjKu9dyf6bpAYe\",\n * timelockYears: 5,\n * origCredIssuerAddress: \"rU9C67bZ3ZvjXaJYwYqMqjMq1o4ZbwK3YN\"\n * });\n * ```\n */\n async createCredentialForCopy(params: CreateCredentialForCopyParams): Promise<TxResponse> {\n const { credId, credType, userAddress, timelockYears, origCredIssuerAddress } = params;\n\n // Validate timelockYears is a non-negative integer\n if (!Number.isInteger(timelockYears) || timelockYears < 0) {\n throw new Error(\"timelockYears must be a non-negative integer\");\n }\n\n // Connect to the XRPL node\n await this.#client.connect();\n\n // Create composite credential type with metadata:\n // Format: \"AG-{credType}-{originalIssuer}-{timelock}Y\"\n const type = Buffer.concat([\n utf8Encode(\"AG\"), // \"AG\" prefix for copy credentials\n utf8Encode(\"-\"), // Separator\n utf8Encode(credType), // Original credential type\n utf8Encode(\"-\"), // Separator\n this.#xrpl.decodeAccountID(origCredIssuerAddress), // Original issuer address (decoded)\n utf8Encode(\"-\"), // Separator\n utf8Encode(`${timelockYears}Y`), // Timelock period in years\n ]);\n\n // Submit the credential copy creation transaction and wait for confirmation\n const res = await this.#client.submitAndWait(\n {\n TransactionType: \"CredentialCreate\",\n Account: this.#wallet.address,\n Subject: userAddress,\n // Use the composite credential type with metadata\n CredentialType: hexEncode(type),\n // Encode credential ID as hex URI (required by XRPL)\n URI: hexEncode(utf8Encode(credId)),\n },\n {\n wallet: this.#wallet,\n },\n );\n\n // Disconnect from the XRPL node\n await this.#client.disconnect();\n\n return res;\n }\n}\n"],"mappings":"uEA+CA,SAAgB,EACd,EACA,EACA,EACyB,CAKzB,MAAO,CACL,gBAAiB,mBACjB,OAAQ,EACR,QAAS,EACT,eAN4B,EAAU,EAAW,CAAc,CAM3B,CACtC,CACF,CAsCA,eAAsB,EACpB,EACA,EACA,EACA,EACA,EACkC,CAElC,GAAI,CAAC,OAAO,UAAU,CAAa,GAAK,EAAgB,EACtD,MAAU,MAAM,8CAA8C,EAGhE,IAAI,EACJ,GAAI,EACD,oBAAsB,MAAM,OAAO,QACtC,MAAQ,CACN,MAAU,MACR,yFACF,CACF,CAOA,IAAM,EAAO,OAAO,OAAO,CACzB,EAAW,IAAI,EACf,EAAW,GAAG,EACd,EAAW,CAAc,EACzB,EAAW,GAAG,EACd,EAAgB,CAA+B,EAC/C,EAAW,GAAG,EACd,EAAW,GAAG,EAAc,EAAE,CAChC,CAAC,EAED,MAAO,CACL,gBAAiB,mBACjB,OAAQ,EACR,QAAS,EACT,eAAgB,EAAU,CAAI,CAChC,CACF,CC1FA,IAAa,EAAb,MAAa,CAAsB,CACjC,GACA,GACA,GAEA,YAAY,EAAiB,EAAgB,EAA6B,CACxE,KAAK,GAAQ,EACb,KAAK,GAAU,EACf,KAAK,GAAU,IAAI,KAAK,GAAM,OAAO,CAAO,CAC9C,CAQA,aAAa,KAAK,EAAiB,EAAgD,CACjF,IAAI,EAEJ,GAAI,CACF,EAAO,MAAM,OAAO,OACtB,MAAQ,CACN,MAAU,MACR,mFACF,CACF,CAEA,OAAO,IAAI,EAAsB,EAAS,EAAQ,CAAI,CACxD,CAoBA,MAAM,4BACJ,EACqB,CACrB,GAAM,CAAE,SAAQ,WAAU,eAAgB,EAG1C,MAAM,KAAK,GAAQ,QAAQ,EAG3B,IAAM,EAAM,MAAM,KAAK,GAAQ,cAC7B,CACE,gBAAiB,mBACjB,QAAS,KAAK,GAAQ,QACtB,QAAS,EAET,eAAgB,EAAU,EAAW,CAAQ,CAAC,EAE9C,IAAK,EAAU,EAAW,CAAM,CAAC,CACnC,EACA,CACE,OAAQ,KAAK,EACf,CACF,EAKA,OAFA,MAAM,KAAK,GAAQ,WAAW,EAEvB,CACT,CAyBA,MAAM,wBAAwB,EAA4D,CACxF,GAAM,CAAE,SAAQ,WAAU,cAAa,gBAAe,yBAA0B,EAGhF,GAAI,CAAC,OAAO,UAAU,CAAa,GAAK,EAAgB,EACtD,MAAU,MAAM,8CAA8C,EAIhE,MAAM,KAAK,GAAQ,QAAQ,EAI3B,IAAM,EAAO,OAAO,OAAO,CACzB,EAAW,IAAI,EACf,EAAW,GAAG,EACd,EAAW,CAAQ,EACnB,EAAW,GAAG,EACd,KAAK,GAAM,gBAAgB,CAAqB,EAChD,EAAW,GAAG,EACd,EAAW,GAAG,EAAc,EAAE,CAChC,CAAC,EAGK,EAAM,MAAM,KAAK,GAAQ,cAC7B,CACE,gBAAiB,mBACjB,QAAS,KAAK,GAAQ,QACtB,QAAS,EAET,eAAgB,EAAU,CAAI,EAE9B,IAAK,EAAU,EAAW,CAAM,CAAC,CACnC,EACA,CACE,OAAQ,KAAK,EACf,CACF,EAKA,OAFA,MAAM,KAAK,GAAQ,WAAW,EAEvB,CACT,CACF"}
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@idos-network/kwil-infra",
3
- "version": "1.5.0",
3
+ "version": "2.2.2",
4
4
  "description": "Infrastructure and wallets for idOS",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "github:idos-network/idos-sdk-js"
8
+ "url": "git+https://github.com/idos-network/idos-sdk-js.git",
9
+ "directory": "packages/kwil-infra"
9
10
  },
10
11
  "type": "module",
11
12
  "sideEffects": false,
@@ -42,20 +43,20 @@
42
43
  "access": "public"
43
44
  },
44
45
  "dependencies": {
45
- "@idos-network/kwil-js": "0.1.5",
46
+ "@idos-network/kwil-js": "0.2.1",
47
+ "@idos-network/utils": "2.2.2",
46
48
  "tiny-invariant": "^1.3.3",
47
49
  "tweetnacl": "^1.0.3",
48
- "zod": "4.4.3",
49
- "@idos-network/utils": "1.5.0"
50
+ "zod": "4.5.4"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@gemwallet/api": "^3.8.0",
53
54
  "@types/node": "25.9.5",
54
- "@vitest/coverage-v8": "4.1.10",
55
+ "@vitest/coverage-v8": "4.1.11",
55
56
  "jsdom": "^22.1.0",
56
- "tsdown": "^0.22.14",
57
+ "tsdown": "^0.23.0",
57
58
  "typescript": "^5.9.3",
58
- "vitest": "4.1.10",
59
+ "vitest": "4.1.11",
59
60
  "xumm": "^1.8.0"
60
61
  },
61
62
  "peerDependencies": {
@@ -0,0 +1,189 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import {
4
+ addWalletMessage,
5
+ CreatePreliminaryCredentialsByDwgInputSchema,
6
+ getUser,
7
+ SharePreliminaryCredentialInputSchema,
8
+ UpsertWalletAsInserterInputSchema,
9
+ walletTypeSchema,
10
+ } from "./actions";
11
+
12
+ const validPreliminaryCredentialsByDwgInput = {
13
+ request_id: "00000000-0000-4000-8000-000000000001",
14
+ issuer_auth_public_key: "issuer-auth-public-key",
15
+ original_encryptor_public_key: "original-encryptor-public-key",
16
+ original_id: "00000000-0000-4000-8000-000000000002",
17
+ original_content_uri: "ipfs://bafkreiepinbumzepnoln7co5vea4kf3lcctnqolb3u6bvsellgznymt2uq",
18
+ original_content_size: 123,
19
+ original_public_notes: "{}",
20
+ original_public_notes_signature: "original-public-notes-signature",
21
+ original_broader_signature: "original-broader-signature",
22
+ copy_encryptor_public_key: "copy-encryptor-public-key",
23
+ copy_id: "00000000-0000-4000-8000-000000000003",
24
+ copy_content_uri: "ipfs://bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku",
25
+ copy_content_size: 456,
26
+ copy_public_notes_signature: "copy-public-notes-signature",
27
+ copy_broader_signature: "copy-broader-signature",
28
+ content_hash: "content-hash",
29
+ dwg_owner: "dwg-owner",
30
+ dwg_grantee: "dwg-grantee",
31
+ dwg_issuer_public_key: "dwg-issuer-public-key",
32
+ dwg_id: "00000000-0000-4000-8000-000000000004",
33
+ dwg_access_grant_timelock: "2026-01-01T00:00:00Z",
34
+ dwg_not_before: "2026-01-01T00:00:00Z",
35
+ dwg_not_after: "2026-12-31T23:59:59Z",
36
+ dwg_signature: "dwg-signature",
37
+ };
38
+
39
+ const validShareCredentialInput = {
40
+ request_id: "00000000-0000-4000-8000-000000000005",
41
+ copy_id: "00000000-0000-4000-8000-000000000006",
42
+ original_id: "00000000-0000-4000-8000-000000000007",
43
+ public_notes: "",
44
+ public_notes_signature: "public-notes-signature",
45
+ broader_signature: "broader-signature",
46
+ content_uri: "ipfs://bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku",
47
+ content_size: 456,
48
+ content_hash: "content-hash",
49
+ encryptor_public_key: "encryptor-public-key",
50
+ issuer_auth_public_key: "issuer-auth-public-key",
51
+ grantee_wallet_identifier: "grantee-wallet-identifier",
52
+ locked_until: 0,
53
+ };
54
+
55
+ describe("CreatePreliminaryCredentialsByDwgInputSchema", () => {
56
+ it("accepts IPFS and UKYC content URIs and positive integer sizes", () => {
57
+ expect(() =>
58
+ CreatePreliminaryCredentialsByDwgInputSchema.parse(validPreliminaryCredentialsByDwgInput),
59
+ ).not.toThrow();
60
+ expect(() =>
61
+ CreatePreliminaryCredentialsByDwgInputSchema.parse({
62
+ ...validPreliminaryCredentialsByDwgInput,
63
+ original_content_uri: "ukyc://original",
64
+ copy_content_uri: "ukyc://copy",
65
+ }),
66
+ ).not.toThrow();
67
+ });
68
+
69
+ it.each([
70
+ ["https URI", { original_content_uri: "https://example.com/blob" }],
71
+ [
72
+ "bare CID",
73
+ { copy_content_uri: "bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku" },
74
+ ],
75
+ ])("rejects non-blob content URI (%s)", (_label, override) => {
76
+ expect(() =>
77
+ CreatePreliminaryCredentialsByDwgInputSchema.parse({
78
+ ...validPreliminaryCredentialsByDwgInput,
79
+ ...override,
80
+ }),
81
+ ).toThrow();
82
+ });
83
+
84
+ it.each([
85
+ ["zero", { original_content_size: 0 }],
86
+ ["negative", { original_content_size: -1 }],
87
+ ["non-integer", { copy_content_size: 1.5 }],
88
+ ])("rejects %s content size", (_label, override) => {
89
+ expect(() =>
90
+ CreatePreliminaryCredentialsByDwgInputSchema.parse({
91
+ ...validPreliminaryCredentialsByDwgInput,
92
+ ...override,
93
+ }),
94
+ ).toThrow();
95
+ });
96
+ });
97
+
98
+ describe("SharePreliminaryCredentialInputSchema", () => {
99
+ it("accepts IPFS and UKYC content URIs and positive integer sizes", () => {
100
+ expect(() =>
101
+ SharePreliminaryCredentialInputSchema.parse(validShareCredentialInput),
102
+ ).not.toThrow();
103
+ expect(() =>
104
+ SharePreliminaryCredentialInputSchema.parse({
105
+ ...validShareCredentialInput,
106
+ content_uri: "ukyc://copy",
107
+ }),
108
+ ).not.toThrow();
109
+ });
110
+
111
+ it("rejects non-blob content URIs", () => {
112
+ expect(() =>
113
+ SharePreliminaryCredentialInputSchema.parse({
114
+ ...validShareCredentialInput,
115
+ content_uri: "https://example.com/blob",
116
+ }),
117
+ ).toThrow();
118
+ });
119
+
120
+ it.each([
121
+ ["zero", 0],
122
+ ["negative", -1],
123
+ ["non-integer", 1.5],
124
+ ])("rejects %s content size", (_label, content_size) => {
125
+ expect(() =>
126
+ SharePreliminaryCredentialInputSchema.parse({
127
+ ...validShareCredentialInput,
128
+ content_size,
129
+ }),
130
+ ).toThrow();
131
+ });
132
+ });
133
+
134
+ describe("MM wallet type schemas", () => {
135
+ it("accepts MM as a wallet type", () => {
136
+ expect(walletTypeSchema.parse("MM")).toBe("MM");
137
+ });
138
+
139
+ it("accepts MM wallets created by trusted inserters", () => {
140
+ expect(() =>
141
+ UpsertWalletAsInserterInputSchema.parse({
142
+ id: "00000000-0000-4000-8000-000000000008",
143
+ user_id: "00000000-0000-4000-8000-000000000009",
144
+ address: "mm-signing-public-key",
145
+ public_key: "mm-signing-public-key",
146
+ wallet_type: "MM",
147
+ signature: "",
148
+ }),
149
+ ).not.toThrow();
150
+ });
151
+ });
152
+
153
+ const addWalletMessageInput = {
154
+ address: "mm-signing-public-key",
155
+ wallet_type: "MM" as const,
156
+ user_id: "00000000-0000-4000-8000-000000000001",
157
+ not_before: "2025-02-13T11:22:06Z",
158
+ not_after: "2025-02-13T11:37:06Z",
159
+ };
160
+
161
+ describe("addWalletMessage", () => {
162
+ it("returns the validated first row", async () => {
163
+ await expect(
164
+ addWalletMessage(
165
+ { call: async () => [{ message: "sign this" }] } as never,
166
+ addWalletMessageInput,
167
+ ),
168
+ ).resolves.toEqual({ message: "sign this" });
169
+ });
170
+
171
+ it("rejects an empty or missing result", async () => {
172
+ await expect(
173
+ addWalletMessage({ call: async () => [] } as never, addWalletMessageInput),
174
+ ).rejects.toThrow();
175
+ await expect(
176
+ addWalletMessage({ call: async () => undefined } as never, addWalletMessageInput),
177
+ ).rejects.toThrow();
178
+ });
179
+ });
180
+
181
+ describe("getUser", () => {
182
+ it("throws an explicit not-found error when the view is empty", async () => {
183
+ await expect(
184
+ getUser({
185
+ call: async () => [],
186
+ } as never),
187
+ ).rejects.toThrow("get_user returned no rows");
188
+ });
189
+ });