@didcid/keymaster 0.4.2 → 0.4.4

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 CHANGED
@@ -125,150 +125,105 @@ keymaster list-ids
125
125
 
126
126
  #### Commands
127
127
 
128
- ##### Wallet Management
129
-
130
- | Command | Description |
131
- |---------|-------------|
132
- | `create-wallet` | Create a new wallet (or show existing) |
133
- | `new-wallet` | Create a new wallet |
134
- | `show-wallet` | Display wallet contents |
135
- | `check-wallet` | Validate DIDs in wallet |
136
- | `fix-wallet` | Remove invalid DIDs from wallet |
137
- | `import-wallet <phrase>` | Create wallet from recovery phrase |
138
- | `show-mnemonic` | Show recovery phrase |
139
- | `backup-wallet-file <file>` | Backup wallet to file |
140
- | `restore-wallet-file <file>` | Restore wallet from file |
141
- | `backup-wallet-did` | Backup wallet to encrypted DID |
142
- | `recover-wallet-did [did]` | Recover wallet from DID |
143
-
144
- ##### Identity Management
145
-
146
- | Command | Description |
147
- |---------|-------------|
148
- | `create-id <name>` | Create a new identity |
149
- | `list-ids` | List all identities |
150
- | `use-id <name>` | Set current identity |
151
- | `remove-id <name>` | Delete an identity |
152
- | `rename-id <old> <new>` | Rename an identity |
153
- | `resolve-id` | Resolve current identity |
154
- | `rotate-keys` | Generate new keys for current ID |
155
- | `backup-id` | Backup current ID to registry |
156
- | `recover-id <did>` | Recover ID from DID |
157
-
158
- ##### DID Operations
159
-
160
- | Command | Description |
161
- |---------|-------------|
162
- | `resolve-did <did>` | Resolve a DID document |
163
- | `resolve-did-version <did> <ver>` | Resolve specific version |
164
- | `revoke-did <did>` | Permanently revoke a DID |
165
-
166
- ##### Encryption & Signing
167
-
168
- | Command | Description |
169
- |---------|-------------|
170
- | `encrypt-message <msg> <did>` | Encrypt message for recipient |
171
- | `encrypt-file <file> <did>` | Encrypt file for recipient |
172
- | `decrypt-did <did>` | Decrypt an encrypted message |
173
- | `decrypt-json <did>` | Decrypt encrypted JSON |
174
- | `sign-file <file>` | Sign a JSON file |
175
- | `verify-file <file>` | Verify signature in file |
176
-
177
- ##### Credentials
178
-
179
- | Command | Description |
180
- |---------|-------------|
181
- | `bind-credential <schema> <subject>` | Create bound credential |
182
- | `issue-credential <file>` | Issue a credential |
183
- | `list-issued` | List issued credentials |
184
- | `revoke-credential <did>` | Revoke a credential |
185
- | `accept-credential <did>` | Accept a credential |
186
- | `list-credentials` | List held credentials |
187
- | `get-credential <did>` | Get credential by DID |
188
- | `publish-credential <did>` | Publish credential existence |
189
- | `reveal-credential <did>` | Reveal credential publicly |
190
- | `unpublish-credential <did>` | Remove from manifest |
191
-
192
- ##### Challenges & Responses
193
-
194
- | Command | Description |
195
- |---------|-------------|
196
- | `create-challenge [file]` | Create a challenge |
197
- | `create-challenge-cc <did>` | Create challenge from credential |
198
- | `create-response <challenge>` | Respond to a challenge |
199
- | `verify-response <response>` | Verify a response |
200
-
201
- ##### Aliases
202
-
203
- | Command | Description |
204
- |---------|-------------|
205
- | `add-alias <alias> <did>` | Add alias for DID |
206
- | `get-alias <alias>` | Get DID by alias |
207
- | `remove-alias <alias>` | Remove alias |
208
- | `list-aliases` | List all aliases |
209
-
210
- ##### Groups
211
-
212
- | Command | Description |
213
- |---------|-------------|
214
- | `create-group <name>` | Create a group |
215
- | `list-groups` | List owned groups |
216
- | `get-group <did>` | Get group details |
217
- | `add-group-member <group> <member>` | Add member to group |
218
- | `remove-group-member <group> <member>` | Remove member |
219
- | `test-group <group> [member]` | Test group membership |
220
-
221
- ##### Schemas
222
-
223
- | Command | Description |
224
- |---------|-------------|
225
- | `create-schema <file>` | Create schema from file |
226
- | `list-schemas` | List owned schemas |
227
- | `get-schema <did>` | Get schema by DID |
228
- | `create-schema-template <schema>` | Generate template |
229
-
230
- ##### Assets
231
-
232
- | Command | Description |
233
- |---------|-------------|
234
- | `create-asset` | Create empty asset |
235
- | `create-asset-json <file>` | Create from JSON file |
236
- | `create-asset-image <file>` | Create from image |
237
- | `create-asset-file <file>` | Create from file |
238
- | `get-asset <id>` | Get asset by ID |
239
- | `update-asset-json <id> <file>` | Update with JSON |
240
- | `update-asset-image <id> <file>` | Update with image |
241
- | `update-asset-file <id> <file>` | Update with file |
242
- | `transfer-asset <id> <controller>` | Transfer ownership |
243
- | `clone-asset <id>` | Clone an asset |
244
- | `set-property <id> <key> [value]` | Set asset property |
245
- | `list-assets` | List owned assets |
246
-
247
- ##### Polls
248
-
249
- | Command | Description |
250
- |---------|-------------|
251
- | `create-poll-template` | Create poll template |
252
- | `create-poll <file>` | Create poll from file |
253
- | `view-poll <poll>` | View poll details |
254
- | `vote-poll <poll> <vote>` | Vote in poll |
255
- | `update-poll <ballot>` | Add ballot to poll |
256
- | `publish-poll <poll>` | Publish results (hidden) |
257
- | `reveal-poll <poll>` | Publish results (revealed) |
258
- | `unpublish-poll <poll>` | Remove results |
259
-
260
- ##### Vaults
261
-
262
- | Command | Description |
263
- |---------|-------------|
264
- | `create-vault` | Create a vault |
265
- | `list-vault-items <id>` | List vault items |
266
- | `add-vault-member <id> <member>` | Add vault member |
267
- | `remove-vault-member <id> <member>` | Remove member |
268
- | `list-vault-members <id>` | List members |
269
- | `add-vault-item <id> <file>` | Add file to vault |
270
- | `remove-vault-item <id> <item>` | Remove item |
271
- | `get-vault-item <id> <item> <file>` | Download item |
128
+ | Category | Command | Description |
129
+ |----------|---------|-------------|
130
+ | Wallet | `create-wallet` | Create a new wallet (or show existing) |
131
+ | Wallet | `new-wallet` | Create a new wallet |
132
+ | Wallet | `show-wallet` | Display wallet contents |
133
+ | Wallet | `check-wallet` | Validate DIDs in wallet |
134
+ | Wallet | `fix-wallet` | Remove invalid DIDs from wallet |
135
+ | Wallet | `import-wallet <phrase>` | Create wallet from recovery phrase |
136
+ | Wallet | `show-mnemonic` | Show recovery phrase |
137
+ | Wallet | `backup-wallet-file <file>` | Backup wallet to file |
138
+ | Wallet | `restore-wallet-file <file>` | Restore wallet from file |
139
+ | Wallet | `backup-wallet-did` | Backup wallet to encrypted DID |
140
+ | Wallet | `recover-wallet-did [did]` | Recover wallet from DID |
141
+ | Wallet | `change-passphrase <new>` | Re-encrypt wallet with a new passphrase |
142
+ | Identity | `create-id <name>` | Create a new identity |
143
+ | Identity | `list-ids` | List all identities |
144
+ | Identity | `use-id <name>` | Set current identity |
145
+ | Identity | `remove-id <name>` | Delete an identity |
146
+ | Identity | `rename-id <old> <new>` | Rename an identity |
147
+ | Identity | `resolve-id` | Resolve current identity |
148
+ | Identity | `rotate-keys` | Generate new keys for current ID |
149
+ | Identity | `backup-id` | Backup current ID to registry |
150
+ | Identity | `recover-id <did>` | Recover ID from DID |
151
+ | DID | `resolve-did <did>` | Resolve a DID document |
152
+ | DID | `resolve-did-version <did> <ver>` | Resolve specific version |
153
+ | DID | `revoke-did <did>` | Permanently revoke a DID |
154
+ | Encryption | `encrypt-message <msg> <did>` | Encrypt message for recipient |
155
+ | Encryption | `encrypt-file <file> <did>` | Encrypt file for recipient |
156
+ | Encryption | `decrypt-did <did>` | Decrypt an encrypted message |
157
+ | Encryption | `decrypt-json <did>` | Decrypt encrypted JSON |
158
+ | Encryption | `sign-file <file>` | Sign a JSON file |
159
+ | Encryption | `verify-file <file>` | Verify signature in file |
160
+ | Credentials | `bind-credential <schema> <subject>` | Create bound credential |
161
+ | Credentials | `issue-credential <file>` | Issue a credential |
162
+ | Credentials | `list-issued` | List issued credentials |
163
+ | Credentials | `revoke-credential <did>` | Revoke a credential |
164
+ | Credentials | `accept-credential <did>` | Accept a credential |
165
+ | Credentials | `list-credentials` | List held credentials |
166
+ | Credentials | `get-credential <did>` | Get credential by DID |
167
+ | Credentials | `publish-credential <did>` | Publish credential existence |
168
+ | Credentials | `reveal-credential <did>` | Reveal credential publicly |
169
+ | Credentials | `unpublish-credential <did>` | Remove from manifest |
170
+ | Challenges | `create-challenge [file]` | Create a challenge |
171
+ | Challenges | `create-challenge-cc <did>` | Create challenge from credential |
172
+ | Challenges | `create-response <challenge>` | Respond to a challenge |
173
+ | Challenges | `verify-response <response>` | Verify a response |
174
+ | Aliases | `add-alias <alias> <did>` | Add alias for DID |
175
+ | Aliases | `get-alias <alias>` | Get DID by alias |
176
+ | Aliases | `remove-alias <alias>` | Remove alias |
177
+ | Aliases | `list-aliases` | List all aliases |
178
+ | Groups | `create-group <name>` | Create a group |
179
+ | Groups | `list-groups` | List owned groups |
180
+ | Groups | `get-group <did>` | Get group details |
181
+ | Groups | `add-group-member <group> <member>` | Add member to group |
182
+ | Groups | `remove-group-member <group> <member>` | Remove member |
183
+ | Groups | `test-group <group> [member]` | Test group membership |
184
+ | Schemas | `create-schema <file>` | Create schema from file |
185
+ | Schemas | `list-schemas` | List owned schemas |
186
+ | Schemas | `get-schema <did>` | Get schema by DID |
187
+ | Schemas | `create-schema-template <schema>` | Generate template |
188
+ | Assets | `create-asset` | Create empty asset |
189
+ | Assets | `create-asset-json <file>` | Create from JSON file |
190
+ | Assets | `create-asset-image <file>` | Create from image |
191
+ | Assets | `create-asset-file <file>` | Create from file |
192
+ | Assets | `get-asset <id>` | Get asset by ID |
193
+ | Assets | `update-asset-json <id> <file>` | Update with JSON |
194
+ | Assets | `update-asset-image <id> <file>` | Update with image |
195
+ | Assets | `update-asset-file <id> <file>` | Update with file |
196
+ | Assets | `transfer-asset <id> <controller>` | Transfer ownership |
197
+ | Assets | `clone-asset <id>` | Clone an asset |
198
+ | Assets | `set-property <id> <key> [value]` | Set asset property |
199
+ | Assets | `list-assets` | List owned assets |
200
+ | Polls | `create-poll-template` | Create poll template |
201
+ | Polls | `create-poll <file>` | Create poll from file |
202
+ | Polls | `view-poll <poll>` | View poll details |
203
+ | Polls | `vote-poll <poll> <vote>` | Vote in poll |
204
+ | Polls | `update-poll <ballot>` | Add ballot to poll |
205
+ | Polls | `publish-poll <poll>` | Publish results (hidden) |
206
+ | Polls | `reveal-poll <poll>` | Publish results (revealed) |
207
+ | Polls | `unpublish-poll <poll>` | Remove results |
208
+ | Vaults | `create-vault` | Create a vault |
209
+ | Vaults | `list-vault-items <id>` | List vault items |
210
+ | Vaults | `add-vault-member <id> <member>` | Add vault member |
211
+ | Vaults | `remove-vault-member <id> <member>` | Remove member |
212
+ | Vaults | `list-vault-members <id>` | List members |
213
+ | Vaults | `add-vault-item <id> <file>` | Add file to vault |
214
+ | Vaults | `remove-vault-item <id> <item>` | Remove item |
215
+ | Vaults | `get-vault-item <id> <item> <file>` | Download item |
216
+ | Lightning | `add-lightning [id]` | Create a Lightning wallet for a DID |
217
+ | Lightning | `remove-lightning [id]` | Remove Lightning wallet from a DID |
218
+ | Lightning | `lightning-balance [id]` | Check Lightning wallet balance |
219
+ | Lightning | `lightning-invoice <amount> <memo> [id]` | Create invoice to receive sats |
220
+ | Lightning | `lightning-pay <bolt11> [id]` | Pay a Lightning invoice |
221
+ | Lightning | `lightning-check <hash> [id]` | Check status of a payment |
222
+ | Lightning | `lightning-decode <bolt11>` | Decode a BOLT11 invoice |
223
+ | Lightning | `lightning-zap <recipient> <amount> [memo]` | Send sats to a DID, alias, or Lightning Address |
224
+ | Lightning | `lightning-payments [id]` | Show payment history |
225
+ | Lightning | `publish-lightning [id]` | Publish Lightning service endpoint for a DID |
226
+ | Lightning | `unpublish-lightning [id]` | Remove Lightning service endpoint from a DID |
272
227
 
273
228
  #### Command Options
274
229
 
@@ -78,6 +78,15 @@ class KeymasterClient {
78
78
  console.log('Keymaster service is ready!');
79
79
  }
80
80
  }
81
+ async getVersion() {
82
+ try {
83
+ const response = await this.axios.get(`${this.API}/version`);
84
+ return response.data;
85
+ }
86
+ catch (error) {
87
+ throwError(error);
88
+ }
89
+ }
81
90
  async isReady() {
82
91
  try {
83
92
  const response = await this.axios.get(`${this.API}/ready`);
@@ -276,6 +285,15 @@ class KeymasterClient {
276
285
  throwError(error);
277
286
  }
278
287
  }
288
+ async changeRegistry(id, registry) {
289
+ try {
290
+ const response = await this.axios.post(`${this.API}/ids/${id}/change-registry`, { registry });
291
+ return response.data.ok;
292
+ }
293
+ catch (error) {
294
+ throwError(error);
295
+ }
296
+ }
279
297
  async backupId(id) {
280
298
  try {
281
299
  if (!id) {
@@ -460,6 +478,15 @@ class KeymasterClient {
460
478
  throwError(error);
461
479
  }
462
480
  }
481
+ async getLightningPayments(name) {
482
+ try {
483
+ const response = await this.axios.post(`${this.API}/lightning/payments`, { id: name });
484
+ return response.data.payments;
485
+ }
486
+ catch (error) {
487
+ throwError(error);
488
+ }
489
+ }
463
490
  async resolveDID(id, options) {
464
491
  try {
465
492
  if (options) {
@@ -1015,7 +1042,7 @@ class KeymasterClient {
1015
1042
  const response = await this.axios.post(`${this.API}/files`, data, {
1016
1043
  headers: {
1017
1044
  'Content-Type': 'application/octet-stream',
1018
- 'X-Options': JSON.stringify(options), // Pass options as a custom header
1045
+ 'X-Options': JSON.stringify(options),
1019
1046
  }
1020
1047
  });
1021
1048
  return response.data.did;
@@ -1024,12 +1051,28 @@ class KeymasterClient {
1024
1051
  throwError(error);
1025
1052
  }
1026
1053
  }
1054
+ async createFileStream(stream, options = {}) {
1055
+ try {
1056
+ const response = await this.axios.post(`${this.API}/files`, stream, {
1057
+ headers: {
1058
+ 'Content-Type': 'application/octet-stream',
1059
+ 'X-Options': JSON.stringify(options),
1060
+ },
1061
+ maxBodyLength: Infinity,
1062
+ maxContentLength: Infinity,
1063
+ });
1064
+ return response.data.did;
1065
+ }
1066
+ catch (error) {
1067
+ throwError(error);
1068
+ }
1069
+ }
1027
1070
  async updateFile(id, data, options = {}) {
1028
1071
  try {
1029
1072
  const response = await this.axios.put(`${this.API}/files/${id}`, data, {
1030
1073
  headers: {
1031
1074
  'Content-Type': 'application/octet-stream',
1032
- 'X-Options': JSON.stringify(options), // Pass options as a custom header
1075
+ 'X-Options': JSON.stringify(options),
1033
1076
  }
1034
1077
  });
1035
1078
  return response.data.ok;
@@ -1038,6 +1081,22 @@ class KeymasterClient {
1038
1081
  throwError(error);
1039
1082
  }
1040
1083
  }
1084
+ async updateFileStream(id, stream, options = {}) {
1085
+ try {
1086
+ const response = await this.axios.put(`${this.API}/files/${id}`, stream, {
1087
+ headers: {
1088
+ 'Content-Type': 'application/octet-stream',
1089
+ 'X-Options': JSON.stringify(options),
1090
+ },
1091
+ maxBodyLength: Infinity,
1092
+ maxContentLength: Infinity,
1093
+ });
1094
+ return response.data.ok;
1095
+ }
1096
+ catch (error) {
1097
+ throwError(error);
1098
+ }
1099
+ }
1041
1100
  async getFile(id) {
1042
1101
  try {
1043
1102
  const response = await this.axios.get(`${this.API}/files/${id}`);
@@ -3361,6 +3361,24 @@ class Keymaster {
3361
3361
  const file = await this.generateFileAsset(filename, buffer);
3362
3362
  return this.mergeData(id, { file });
3363
3363
  }
3364
+ async generateFileAssetFromStream(filename, stream, contentType, bytes) {
3365
+ const cid = await this.gatekeeper.addDataStream(stream);
3366
+ return { cid, filename, type: contentType, bytes };
3367
+ }
3368
+ async createFileStream(stream, options = {}) {
3369
+ const filename = options.filename || 'file';
3370
+ const contentType = options.contentType || 'application/octet-stream';
3371
+ const bytes = options.bytes || 0;
3372
+ const file = await this.generateFileAssetFromStream(filename, stream, contentType, bytes);
3373
+ return this.createAsset({ file }, options);
3374
+ }
3375
+ async updateFileStream(id, stream, options = {}) {
3376
+ const filename = options.filename || 'file';
3377
+ const contentType = options.contentType || 'application/octet-stream';
3378
+ const bytes = options.bytes || 0;
3379
+ const file = await this.generateFileAssetFromStream(filename, stream, contentType, bytes);
3380
+ return this.mergeData(id, { file });
3381
+ }
3364
3382
  async getFile(id) {
3365
3383
  const asset = await this.resolveAsset(id);
3366
3384
  const file = asset.file;
@@ -3565,6 +3583,23 @@ class Keymaster {
3565
3583
  }
3566
3584
  return ok;
3567
3585
  }
3586
+ async changeRegistry(id, registry) {
3587
+ if (!registry) {
3588
+ throw new InvalidParameterError('registry');
3589
+ }
3590
+ const did = await this.lookupDID(id);
3591
+ const current = await this.resolveDID(did);
3592
+ const currentRegistry = current.didDocumentRegistration?.registry;
3593
+ if (registry === currentRegistry) {
3594
+ return true;
3595
+ }
3596
+ return this.updateDID(did, {
3597
+ didDocumentRegistration: {
3598
+ ...current.didDocumentRegistration,
3599
+ registry,
3600
+ },
3601
+ });
3602
+ }
3568
3603
  async addToOwned(did, owner) {
3569
3604
  await this.mutateWallet(async (wallet) => {
3570
3605
  const id = await this.fetchIdInfo(owner, wallet);
@@ -4182,16 +4217,29 @@ class Keymaster {
4182
4217
  return true;
4183
4218
  }
4184
4219
  async zapLightning(id, amount, memo, name) {
4185
- const did = await this.lookupDID(id);
4186
- if (!did) {
4187
- throw new InvalidParameterError('did');
4220
+ const isLud16 = id.includes('@') && !id.startsWith('did:');
4221
+ let recipient;
4222
+ if (isLud16) {
4223
+ recipient = id;
4224
+ }
4225
+ else {
4226
+ const did = await this.lookupDID(id);
4227
+ if (!did) {
4228
+ throw new InvalidParameterError('did');
4229
+ }
4230
+ recipient = did;
4188
4231
  }
4189
4232
  if (!amount || amount <= 0) {
4190
4233
  throw new InvalidParameterError('amount');
4191
4234
  }
4192
4235
  const drawbridge = this.requireDrawbridge();
4193
4236
  const config = await this.getLightningConfig(name);
4194
- return drawbridge.zapLightning(config.adminKey, did, amount, memo);
4237
+ return drawbridge.zapLightning(config.adminKey, recipient, amount, memo);
4238
+ }
4239
+ async getLightningPayments(name) {
4240
+ const drawbridge = this.requireDrawbridge();
4241
+ const config = await this.getLightningConfig(name);
4242
+ return drawbridge.getLightningPayments(config.adminKey);
4195
4243
  }
4196
4244
  async testAgent(id) {
4197
4245
  const doc = await this.resolveDID(id);
package/dist/esm/cli.js CHANGED
@@ -335,6 +335,18 @@ program
335
335
  console.error(`cannot revoke ${did}`);
336
336
  }
337
337
  });
338
+ program
339
+ .command('change-registry <id> <registry>')
340
+ .description('Changes the registry for an existing DID')
341
+ .action(async (id, registry) => {
342
+ try {
343
+ const ok = await keymaster.changeRegistry(id, registry);
344
+ console.log(ok ? UPDATE_OK : UPDATE_FAILED);
345
+ }
346
+ catch (error) {
347
+ console.error(error.error || error.message || error);
348
+ }
349
+ });
338
350
  // Encryption commands
339
351
  program
340
352
  .command('encrypt-message <message> <did>')
@@ -836,17 +848,40 @@ program
836
848
  }
837
849
  });
838
850
  program
839
- .command('lightning-zap <did> <amount> [memo]')
840
- .description('Send sats to a DID via Lightning')
841
- .action(async (did, amount, memo) => {
851
+ .command('lightning-zap <recipient> <amount> [memo]')
852
+ .description('Send sats via Lightning (DID, alias, or Lightning Address)')
853
+ .action(async (recipient, amount, memo) => {
842
854
  try {
843
- const result = await keymaster.zapLightning(did, parseInt(amount), memo);
855
+ const result = await keymaster.zapLightning(recipient, parseInt(amount), memo);
844
856
  console.log(JSON.stringify(result, null, 4));
845
857
  }
846
858
  catch (error) {
847
859
  console.error(error.error || error.message || error);
848
860
  }
849
861
  });
862
+ program
863
+ .command('lightning-payments [id]')
864
+ .description('Show Lightning payment history')
865
+ .action(async (id) => {
866
+ try {
867
+ const payments = await keymaster.getLightningPayments(id);
868
+ if (payments.length === 0) {
869
+ console.log('No payments found.');
870
+ return;
871
+ }
872
+ for (const p of payments) {
873
+ const d = p.time ? new Date(p.time) : null;
874
+ const date = d ? `${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}` : '—';
875
+ const fee = p.fee > 0 ? ` (fee: ${p.fee})` : '';
876
+ const memo = p.memo ? ` "${p.memo}"` : '';
877
+ const status = p.pending ? ' [pending]' : '';
878
+ console.log(`${date} ${p.amount} sats${fee}${memo}${status}`);
879
+ }
880
+ }
881
+ catch (error) {
882
+ console.error(error.error || error.message || error);
883
+ }
884
+ });
850
885
  // Group commands
851
886
  program
852
887
  .command('create-group <groupName>')
@@ -1033,9 +1068,10 @@ program
1033
1068
  .action(async (file, options) => {
1034
1069
  try {
1035
1070
  const { alias, registry } = options;
1036
- const data = fs.readFileSync(file);
1037
1071
  const filename = path.basename(file);
1038
- const did = await keymaster.createFile(data, { filename, alias, registry });
1072
+ const bytes = fs.statSync(file).size;
1073
+ const stream = fs.createReadStream(file);
1074
+ const did = await keymaster.createFileStream(stream, { filename, alias, registry, bytes });
1039
1075
  console.log(did);
1040
1076
  }
1041
1077
  catch (error) {
@@ -1135,9 +1171,10 @@ program
1135
1171
  .description('Update an asset from a file')
1136
1172
  .action(async (id, file) => {
1137
1173
  try {
1138
- const data = fs.readFileSync(file);
1139
1174
  const filename = path.basename(file);
1140
- const ok = await keymaster.updateFile(id, data, { filename });
1175
+ const bytes = fs.statSync(file).size;
1176
+ const stream = fs.createReadStream(file);
1177
+ const ok = await keymaster.updateFileStream(id, stream, { filename, bytes });
1141
1178
  console.log(ok ? UPDATE_OK : UPDATE_FAILED);
1142
1179
  }
1143
1180
  catch (error) {