@didcid/keymaster 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/keymaster-client.cjs +271 -122
- package/dist/cjs/keymaster.cjs +302 -15
- package/dist/cjs/node.cjs +1 -0
- package/dist/esm/cli.js +160 -2
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/keymaster-client.js +271 -122
- package/dist/esm/keymaster-client.js.map +1 -1
- package/dist/esm/keymaster.js +291 -16
- package/dist/esm/keymaster.js.map +1 -1
- package/dist/types/keymaster-client.d.ts +20 -1
- package/dist/types/keymaster.d.ts +19 -2
- package/dist/types/types.d.ts +33 -2
- package/package.json +6 -5
package/dist/cjs/keymaster.cjs
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var imageSize = require('image-size');
|
|
6
6
|
var fileType = require('file-type');
|
|
7
|
+
var lightBolt11Decoder = require('light-bolt11-decoder');
|
|
7
8
|
var db_typeGuards = require('./db/typeGuards.cjs');
|
|
8
9
|
require('crypto');
|
|
9
10
|
|
|
@@ -466,6 +467,18 @@ class UnknownIDError extends ArchonError {
|
|
|
466
467
|
super(UnknownIDError.type, detail);
|
|
467
468
|
}
|
|
468
469
|
}
|
|
470
|
+
class LightningNotConfiguredError extends ArchonError {
|
|
471
|
+
static type = 'Lightning not configured';
|
|
472
|
+
constructor(detail) {
|
|
473
|
+
super(LightningNotConfiguredError.type, detail);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
class LightningUnavailableError extends ArchonError {
|
|
477
|
+
static type = 'Lightning service unavailable';
|
|
478
|
+
constructor(detail) {
|
|
479
|
+
super(LightningUnavailableError.type, detail);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
469
482
|
|
|
470
483
|
const base32 = rfc4648({
|
|
471
484
|
prefix: 'b',
|
|
@@ -2806,6 +2819,23 @@ class Keymaster {
|
|
|
2806
2819
|
async getMnemonicForDerivation(wallet) {
|
|
2807
2820
|
return decryptWithPassphrase(wallet.seed.mnemonicEnc, this.passphrase);
|
|
2808
2821
|
}
|
|
2822
|
+
async changePassphrase(newPassphrase) {
|
|
2823
|
+
if (!newPassphrase) {
|
|
2824
|
+
throw new InvalidParameterError('newPassphrase');
|
|
2825
|
+
}
|
|
2826
|
+
const wallet = await this.loadWallet();
|
|
2827
|
+
const mnemonic = await decryptWithPassphrase(wallet.seed.mnemonicEnc, this.passphrase);
|
|
2828
|
+
const mnemonicEnc = await encryptWithPassphrase(mnemonic, newPassphrase);
|
|
2829
|
+
wallet.seed.mnemonicEnc = mnemonicEnc;
|
|
2830
|
+
this.passphrase = newPassphrase;
|
|
2831
|
+
this._walletCache = wallet;
|
|
2832
|
+
const encrypted = await this.encryptWalletForStorage(wallet);
|
|
2833
|
+
const ok = await this.db.saveWallet(encrypted, true);
|
|
2834
|
+
if (!ok) {
|
|
2835
|
+
throw new KeymasterError('Failed to save wallet with new passphrase');
|
|
2836
|
+
}
|
|
2837
|
+
return true;
|
|
2838
|
+
}
|
|
2809
2839
|
async checkWallet() {
|
|
2810
2840
|
const wallet = await this.loadWallet();
|
|
2811
2841
|
let checked = 0;
|
|
@@ -3907,6 +3937,262 @@ class Keymaster {
|
|
|
3907
3937
|
});
|
|
3908
3938
|
return true;
|
|
3909
3939
|
}
|
|
3940
|
+
async addNostr(name) {
|
|
3941
|
+
const keypair = await this.fetchKeyPair(name);
|
|
3942
|
+
if (!keypair) {
|
|
3943
|
+
throw new InvalidParameterError('id');
|
|
3944
|
+
}
|
|
3945
|
+
const nostr = this.cipher.jwkToNostr(keypair.publicJwk);
|
|
3946
|
+
const id = await this.fetchIdInfo(name);
|
|
3947
|
+
await this.mergeData(id.did, { nostr });
|
|
3948
|
+
return nostr;
|
|
3949
|
+
}
|
|
3950
|
+
async removeNostr(name) {
|
|
3951
|
+
const id = await this.fetchIdInfo(name);
|
|
3952
|
+
return this.mergeData(id.did, { nostr: null });
|
|
3953
|
+
}
|
|
3954
|
+
async exportNsec(name) {
|
|
3955
|
+
const keypair = await this.fetchKeyPair(name);
|
|
3956
|
+
if (!keypair) {
|
|
3957
|
+
throw new InvalidParameterError('id');
|
|
3958
|
+
}
|
|
3959
|
+
return this.cipher.jwkToNsec(keypair.privateJwk);
|
|
3960
|
+
}
|
|
3961
|
+
async signNostrEvent(event) {
|
|
3962
|
+
const keypair = await this.fetchKeyPair();
|
|
3963
|
+
if (!keypair) {
|
|
3964
|
+
throw new InvalidParameterError('id');
|
|
3965
|
+
}
|
|
3966
|
+
const nostr = this.cipher.jwkToNostr(keypair.publicJwk);
|
|
3967
|
+
const serialized = JSON.stringify([
|
|
3968
|
+
0,
|
|
3969
|
+
nostr.pubkey,
|
|
3970
|
+
event.created_at,
|
|
3971
|
+
event.kind,
|
|
3972
|
+
event.tags,
|
|
3973
|
+
event.content,
|
|
3974
|
+
]);
|
|
3975
|
+
const id = this.cipher.hashMessage(serialized);
|
|
3976
|
+
const sig = this.cipher.signSchnorr(id, keypair.privateJwk);
|
|
3977
|
+
return {
|
|
3978
|
+
...event,
|
|
3979
|
+
id,
|
|
3980
|
+
pubkey: nostr.pubkey,
|
|
3981
|
+
sig,
|
|
3982
|
+
};
|
|
3983
|
+
}
|
|
3984
|
+
// Lightning helpers
|
|
3985
|
+
requireDrawbridge() {
|
|
3986
|
+
const drawbridge = this.gatekeeper;
|
|
3987
|
+
if (typeof drawbridge.createLightningWallet !== 'function') {
|
|
3988
|
+
throw new LightningUnavailableError('Gateway does not support Lightning');
|
|
3989
|
+
}
|
|
3990
|
+
return drawbridge;
|
|
3991
|
+
}
|
|
3992
|
+
async getLightningConfig(name) {
|
|
3993
|
+
const drawbridge = this.requireDrawbridge();
|
|
3994
|
+
const url = drawbridge.url;
|
|
3995
|
+
let wallet = await this.loadWallet();
|
|
3996
|
+
let idInfo = await this.fetchIdInfo(name, wallet);
|
|
3997
|
+
if (!idInfo.lightning) {
|
|
3998
|
+
throw new LightningNotConfiguredError(`No Lightning wallet configured for ${idInfo.did}`);
|
|
3999
|
+
}
|
|
4000
|
+
// Migrate old flat format to per-URL dictionary
|
|
4001
|
+
if ('walletId' in idInfo.lightning) {
|
|
4002
|
+
await this.mutateWallet(async (wallet) => {
|
|
4003
|
+
const idInfo = await this.fetchIdInfo(name, wallet);
|
|
4004
|
+
if (idInfo.lightning && 'walletId' in idInfo.lightning) {
|
|
4005
|
+
idInfo.lightning = { [url]: idInfo.lightning };
|
|
4006
|
+
}
|
|
4007
|
+
});
|
|
4008
|
+
wallet = await this.loadWallet();
|
|
4009
|
+
idInfo = await this.fetchIdInfo(name, wallet);
|
|
4010
|
+
}
|
|
4011
|
+
const config = idInfo.lightning[url];
|
|
4012
|
+
if (!config) {
|
|
4013
|
+
throw new LightningNotConfiguredError(`No Lightning wallet configured for ${idInfo.did} on ${url}`);
|
|
4014
|
+
}
|
|
4015
|
+
return config;
|
|
4016
|
+
}
|
|
4017
|
+
// Lightning methods
|
|
4018
|
+
async addLightning(name) {
|
|
4019
|
+
try {
|
|
4020
|
+
return await this.getLightningConfig(name);
|
|
4021
|
+
}
|
|
4022
|
+
catch (e) {
|
|
4023
|
+
if (e.type !== LightningNotConfiguredError.type)
|
|
4024
|
+
throw e;
|
|
4025
|
+
}
|
|
4026
|
+
const drawbridge = this.requireDrawbridge();
|
|
4027
|
+
const url = drawbridge.url;
|
|
4028
|
+
let result;
|
|
4029
|
+
await this.mutateWallet(async (wallet) => {
|
|
4030
|
+
const idInfo = await this.fetchIdInfo(name, wallet);
|
|
4031
|
+
const store = (idInfo.lightning || {});
|
|
4032
|
+
const walletName = `archon-${idInfo.did.split(':').pop()?.substring(0, 12)}`;
|
|
4033
|
+
const created = await drawbridge.createLightningWallet(walletName);
|
|
4034
|
+
store[url] = {
|
|
4035
|
+
walletId: created.walletId,
|
|
4036
|
+
adminKey: created.adminKey,
|
|
4037
|
+
invoiceKey: created.invoiceKey,
|
|
4038
|
+
};
|
|
4039
|
+
idInfo.lightning = store;
|
|
4040
|
+
result = store[url];
|
|
4041
|
+
});
|
|
4042
|
+
return result;
|
|
4043
|
+
}
|
|
4044
|
+
async removeLightning(name) {
|
|
4045
|
+
// Migrate old format if possible (ignore errors)
|
|
4046
|
+
try {
|
|
4047
|
+
await this.getLightningConfig(name);
|
|
4048
|
+
}
|
|
4049
|
+
catch { /* ok */ }
|
|
4050
|
+
// Try to get URL for targeted removal; fall back to removing all
|
|
4051
|
+
const gk = this.gatekeeper;
|
|
4052
|
+
const url = gk.url ? new URL(gk.url).origin : null;
|
|
4053
|
+
await this.mutateWallet(async (wallet) => {
|
|
4054
|
+
const idInfo = await this.fetchIdInfo(name, wallet);
|
|
4055
|
+
if (!idInfo.lightning)
|
|
4056
|
+
return;
|
|
4057
|
+
if (url) {
|
|
4058
|
+
const store = idInfo.lightning;
|
|
4059
|
+
delete store[url];
|
|
4060
|
+
if (Object.keys(store).length === 0) {
|
|
4061
|
+
delete idInfo.lightning;
|
|
4062
|
+
}
|
|
4063
|
+
}
|
|
4064
|
+
else {
|
|
4065
|
+
delete idInfo.lightning;
|
|
4066
|
+
}
|
|
4067
|
+
});
|
|
4068
|
+
return true;
|
|
4069
|
+
}
|
|
4070
|
+
async getLightningBalance(name) {
|
|
4071
|
+
const drawbridge = this.requireDrawbridge();
|
|
4072
|
+
const config = await this.getLightningConfig(name);
|
|
4073
|
+
return drawbridge.getLightningBalance(config.invoiceKey);
|
|
4074
|
+
}
|
|
4075
|
+
async createLightningInvoice(amount, memo = '', name) {
|
|
4076
|
+
if (!amount || amount <= 0) {
|
|
4077
|
+
throw new InvalidParameterError('amount');
|
|
4078
|
+
}
|
|
4079
|
+
const drawbridge = this.requireDrawbridge();
|
|
4080
|
+
const config = await this.getLightningConfig(name);
|
|
4081
|
+
return drawbridge.createLightningInvoice(config.invoiceKey, amount, memo);
|
|
4082
|
+
}
|
|
4083
|
+
async payLightningInvoice(bolt11, name) {
|
|
4084
|
+
if (!bolt11) {
|
|
4085
|
+
throw new InvalidParameterError('bolt11');
|
|
4086
|
+
}
|
|
4087
|
+
const drawbridge = this.requireDrawbridge();
|
|
4088
|
+
const config = await this.getLightningConfig(name);
|
|
4089
|
+
return drawbridge.payLightningInvoice(config.adminKey, bolt11);
|
|
4090
|
+
}
|
|
4091
|
+
async checkLightningPayment(paymentHash, name) {
|
|
4092
|
+
if (!paymentHash) {
|
|
4093
|
+
throw new InvalidParameterError('paymentHash');
|
|
4094
|
+
}
|
|
4095
|
+
const drawbridge = this.requireDrawbridge();
|
|
4096
|
+
const config = await this.getLightningConfig(name);
|
|
4097
|
+
const data = await drawbridge.checkLightningPayment(config.invoiceKey, paymentHash);
|
|
4098
|
+
return {
|
|
4099
|
+
paid: data.paid,
|
|
4100
|
+
preimage: data.preimage,
|
|
4101
|
+
paymentHash,
|
|
4102
|
+
};
|
|
4103
|
+
}
|
|
4104
|
+
async decodeLightningInvoice(bolt11) {
|
|
4105
|
+
if (!bolt11) {
|
|
4106
|
+
throw new InvalidParameterError('bolt11');
|
|
4107
|
+
}
|
|
4108
|
+
const decoded = lightBolt11Decoder.decode(bolt11);
|
|
4109
|
+
const info = {};
|
|
4110
|
+
let timestamp;
|
|
4111
|
+
for (const section of decoded.sections) {
|
|
4112
|
+
switch (section.name) {
|
|
4113
|
+
case 'amount':
|
|
4114
|
+
info.amount = `${parseInt(section.value) / 1000} sats`;
|
|
4115
|
+
break;
|
|
4116
|
+
case 'description':
|
|
4117
|
+
info.description = section.value;
|
|
4118
|
+
break;
|
|
4119
|
+
case 'timestamp':
|
|
4120
|
+
timestamp = section.value;
|
|
4121
|
+
info.created = new Date(section.value * 1000).toISOString();
|
|
4122
|
+
break;
|
|
4123
|
+
case 'expiry':
|
|
4124
|
+
info.expiry = `${section.value} seconds`;
|
|
4125
|
+
break;
|
|
4126
|
+
case 'payment_hash':
|
|
4127
|
+
info.payment_hash = section.value;
|
|
4128
|
+
break;
|
|
4129
|
+
case 'coin_network':
|
|
4130
|
+
info.network = section.value?.bech32;
|
|
4131
|
+
break;
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
if (timestamp !== undefined && decoded.expiry !== undefined) {
|
|
4135
|
+
info.expires = new Date((timestamp + decoded.expiry) * 1000).toISOString();
|
|
4136
|
+
}
|
|
4137
|
+
return info;
|
|
4138
|
+
}
|
|
4139
|
+
async publishLightning(name) {
|
|
4140
|
+
const drawbridge = this.requireDrawbridge();
|
|
4141
|
+
const config = await this.getLightningConfig(name);
|
|
4142
|
+
const id = await this.fetchIdInfo(name);
|
|
4143
|
+
const did = id.did;
|
|
4144
|
+
// Register invoiceKey on Drawbridge using DID suffix as key
|
|
4145
|
+
const didSuffix = did.split(':').pop();
|
|
4146
|
+
const result = await drawbridge.publishLightning(didSuffix, config.invoiceKey);
|
|
4147
|
+
// Add service endpoint to DID document
|
|
4148
|
+
const doc = await this.resolveDID(did);
|
|
4149
|
+
const services = doc.didDocument?.service || [];
|
|
4150
|
+
const serviceId = `${did}#lightning`;
|
|
4151
|
+
// Remove existing lightning service if present
|
|
4152
|
+
const filtered = services.filter(s => s.id !== serviceId);
|
|
4153
|
+
const publicHost = result.publicHost || drawbridge.url;
|
|
4154
|
+
filtered.push({
|
|
4155
|
+
id: serviceId,
|
|
4156
|
+
type: 'Lightning',
|
|
4157
|
+
serviceEndpoint: `${publicHost}/invoice/${didSuffix}`,
|
|
4158
|
+
});
|
|
4159
|
+
doc.didDocument.service = filtered;
|
|
4160
|
+
await this.updateDID(did, doc);
|
|
4161
|
+
return true;
|
|
4162
|
+
}
|
|
4163
|
+
async unpublishLightning(name) {
|
|
4164
|
+
const drawbridge = this.requireDrawbridge();
|
|
4165
|
+
const id = await this.fetchIdInfo(name);
|
|
4166
|
+
const did = id.did;
|
|
4167
|
+
// Unregister from Drawbridge using DID suffix as key
|
|
4168
|
+
const didSuffix = did.split(':').pop();
|
|
4169
|
+
await drawbridge.unpublishLightning(didSuffix);
|
|
4170
|
+
// Remove service endpoint from DID document
|
|
4171
|
+
const doc = await this.resolveDID(did);
|
|
4172
|
+
const services = doc.didDocument?.service || [];
|
|
4173
|
+
const serviceId = `${did}#lightning`;
|
|
4174
|
+
const filtered = services.filter(s => s.id !== serviceId);
|
|
4175
|
+
if (filtered.length > 0) {
|
|
4176
|
+
doc.didDocument.service = filtered;
|
|
4177
|
+
}
|
|
4178
|
+
else {
|
|
4179
|
+
delete doc.didDocument.service;
|
|
4180
|
+
}
|
|
4181
|
+
await this.updateDID(did, doc);
|
|
4182
|
+
return true;
|
|
4183
|
+
}
|
|
4184
|
+
async zapLightning(id, amount, memo, name) {
|
|
4185
|
+
const did = await this.lookupDID(id);
|
|
4186
|
+
if (!did) {
|
|
4187
|
+
throw new InvalidParameterError('did');
|
|
4188
|
+
}
|
|
4189
|
+
if (!amount || amount <= 0) {
|
|
4190
|
+
throw new InvalidParameterError('amount');
|
|
4191
|
+
}
|
|
4192
|
+
const drawbridge = this.requireDrawbridge();
|
|
4193
|
+
const config = await this.getLightningConfig(name);
|
|
4194
|
+
return drawbridge.zapLightning(config.adminKey, did, amount, memo);
|
|
4195
|
+
}
|
|
3910
4196
|
async testAgent(id) {
|
|
3911
4197
|
const doc = await this.resolveDID(id);
|
|
3912
4198
|
return doc.didDocumentRegistration?.type === 'agent';
|
|
@@ -4331,26 +4617,27 @@ class Keymaster {
|
|
|
4331
4617
|
}
|
|
4332
4618
|
async createGroup(name, options = {}) {
|
|
4333
4619
|
const group = {
|
|
4334
|
-
|
|
4335
|
-
members: []
|
|
4620
|
+
version: 2,
|
|
4621
|
+
members: [],
|
|
4336
4622
|
};
|
|
4337
|
-
return this.createAsset({ group }, options);
|
|
4623
|
+
return this.createAsset({ name, group }, options);
|
|
4338
4624
|
}
|
|
4339
4625
|
async getGroup(id) {
|
|
4340
4626
|
const asset = await this.resolveAsset(id);
|
|
4341
4627
|
if (!asset) {
|
|
4342
4628
|
return null;
|
|
4343
4629
|
}
|
|
4344
|
-
//
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
return castOldAsset;
|
|
4630
|
+
// V2: { name, group: { version: 2, members } }
|
|
4631
|
+
if (asset.group?.version === 2) {
|
|
4632
|
+
return { name: asset.name, members: asset.group.members };
|
|
4348
4633
|
}
|
|
4349
|
-
|
|
4350
|
-
if (
|
|
4351
|
-
|
|
4634
|
+
// V1: { group: { name, members } }
|
|
4635
|
+
if (asset.group?.name && Array.isArray(asset.group?.members)) {
|
|
4636
|
+
const group = asset.group;
|
|
4637
|
+
await this.mergeData(id, { name: group.name, group: { version: 2, members: group.members } });
|
|
4638
|
+
return group;
|
|
4352
4639
|
}
|
|
4353
|
-
return
|
|
4640
|
+
return null;
|
|
4354
4641
|
}
|
|
4355
4642
|
async addGroupMember(groupId, memberId) {
|
|
4356
4643
|
const groupDID = await this.lookupDID(groupId);
|
|
@@ -4381,8 +4668,8 @@ class Keymaster {
|
|
|
4381
4668
|
}
|
|
4382
4669
|
const members = new Set(group.members);
|
|
4383
4670
|
members.add(memberDID);
|
|
4384
|
-
|
|
4385
|
-
return this.mergeData(groupDID, { group });
|
|
4671
|
+
const updatedMembers = Array.from(members);
|
|
4672
|
+
return this.mergeData(groupDID, { group: { version: 2, members: updatedMembers } });
|
|
4386
4673
|
}
|
|
4387
4674
|
async removeGroupMember(groupId, memberId) {
|
|
4388
4675
|
const groupDID = await this.lookupDID(groupId);
|
|
@@ -4404,8 +4691,8 @@ class Keymaster {
|
|
|
4404
4691
|
}
|
|
4405
4692
|
const members = new Set(group.members);
|
|
4406
4693
|
members.delete(memberDID);
|
|
4407
|
-
|
|
4408
|
-
return this.mergeData(groupDID, { group });
|
|
4694
|
+
const updatedMembers = Array.from(members);
|
|
4695
|
+
return this.mergeData(groupDID, { group: { version: 2, members: updatedMembers } });
|
|
4409
4696
|
}
|
|
4410
4697
|
async testGroup(groupId, memberId) {
|
|
4411
4698
|
try {
|
package/dist/cjs/node.cjs
CHANGED
package/dist/esm/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from 'path';
|
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import dotenv from 'dotenv';
|
|
7
7
|
import Keymaster from './keymaster.js';
|
|
8
|
-
import
|
|
8
|
+
import DrawbridgeClient from '@didcid/gatekeeper/drawbridge';
|
|
9
9
|
import CipherNode from '@didcid/cipher/node';
|
|
10
10
|
import WalletJson from './db/json.js';
|
|
11
11
|
import WalletSQLite from './db/sqlite.js';
|
|
@@ -46,6 +46,18 @@ program
|
|
|
46
46
|
console.error(error.error || error.message || error);
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
|
+
program
|
|
50
|
+
.command('change-passphrase <new-passphrase>')
|
|
51
|
+
.description('Re-encrypt wallet with a new passphrase')
|
|
52
|
+
.action(async (newPassphrase) => {
|
|
53
|
+
try {
|
|
54
|
+
const ok = await keymaster.changePassphrase(newPassphrase);
|
|
55
|
+
console.log(ok ? 'OK' : 'Failed');
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error(error.error || error.message || error);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
49
61
|
program
|
|
50
62
|
.command('check-wallet')
|
|
51
63
|
.description('Validate DIDs in wallet')
|
|
@@ -689,6 +701,152 @@ program
|
|
|
689
701
|
console.error(error.error || error.message || error);
|
|
690
702
|
}
|
|
691
703
|
});
|
|
704
|
+
// Nostr commands
|
|
705
|
+
program
|
|
706
|
+
.command('add-nostr [id]')
|
|
707
|
+
.description('Derive and add nostr keys to an agent DID')
|
|
708
|
+
.action(async (id) => {
|
|
709
|
+
try {
|
|
710
|
+
const nostr = await keymaster.addNostr(id);
|
|
711
|
+
console.log(JSON.stringify(nostr, null, 4));
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
console.error(error.error || error.message || error);
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
program
|
|
718
|
+
.command('remove-nostr [id]')
|
|
719
|
+
.description('Remove nostr keys from an agent DID')
|
|
720
|
+
.action(async (id) => {
|
|
721
|
+
try {
|
|
722
|
+
await keymaster.removeNostr(id);
|
|
723
|
+
console.log(UPDATE_OK);
|
|
724
|
+
}
|
|
725
|
+
catch (error) {
|
|
726
|
+
console.error(error.error || error.message || error);
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
// Lightning commands
|
|
730
|
+
program
|
|
731
|
+
.command('add-lightning [id]')
|
|
732
|
+
.description('Create a Lightning wallet for a DID')
|
|
733
|
+
.action(async (id) => {
|
|
734
|
+
try {
|
|
735
|
+
const config = await keymaster.addLightning(id);
|
|
736
|
+
console.log(JSON.stringify(config, null, 4));
|
|
737
|
+
}
|
|
738
|
+
catch (error) {
|
|
739
|
+
console.error(error.error || error.message || error);
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
program
|
|
743
|
+
.command('remove-lightning [id]')
|
|
744
|
+
.description('Remove Lightning wallet from a DID')
|
|
745
|
+
.action(async (id) => {
|
|
746
|
+
try {
|
|
747
|
+
await keymaster.removeLightning(id);
|
|
748
|
+
console.log(UPDATE_OK);
|
|
749
|
+
}
|
|
750
|
+
catch (error) {
|
|
751
|
+
console.error(error.error || error.message || error);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
program
|
|
755
|
+
.command('lightning-balance [id]')
|
|
756
|
+
.description('Check Lightning wallet balance')
|
|
757
|
+
.action(async (id) => {
|
|
758
|
+
try {
|
|
759
|
+
const balance = await keymaster.getLightningBalance(id);
|
|
760
|
+
console.log(`${balance.balance} sats`);
|
|
761
|
+
}
|
|
762
|
+
catch (error) {
|
|
763
|
+
console.error(error.error || error.message || error);
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
program
|
|
767
|
+
.command('lightning-decode <bolt11>')
|
|
768
|
+
.description('Decode a Lightning BOLT11 invoice')
|
|
769
|
+
.action(async (bolt11) => {
|
|
770
|
+
try {
|
|
771
|
+
const info = await keymaster.decodeLightningInvoice(bolt11);
|
|
772
|
+
console.log(JSON.stringify(info, null, 4));
|
|
773
|
+
}
|
|
774
|
+
catch (error) {
|
|
775
|
+
console.error(error.error || error.message || error);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
program
|
|
779
|
+
.command('lightning-invoice <amount> <memo> [id]')
|
|
780
|
+
.description('Create a Lightning invoice to receive sats')
|
|
781
|
+
.action(async (amount, memo, id) => {
|
|
782
|
+
try {
|
|
783
|
+
const invoice = await keymaster.createLightningInvoice(parseInt(amount), memo, id);
|
|
784
|
+
console.log(JSON.stringify(invoice, null, 4));
|
|
785
|
+
}
|
|
786
|
+
catch (error) {
|
|
787
|
+
console.error(error.error || error.message || error);
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
program
|
|
791
|
+
.command('lightning-pay <bolt11> [id]')
|
|
792
|
+
.description('Pay a Lightning invoice')
|
|
793
|
+
.action(async (bolt11, id) => {
|
|
794
|
+
try {
|
|
795
|
+
const payment = await keymaster.payLightningInvoice(bolt11, id);
|
|
796
|
+
console.log(JSON.stringify(payment, null, 4));
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
console.error(error.error || error.message || error);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
program
|
|
803
|
+
.command('lightning-check <paymentHash> [id]')
|
|
804
|
+
.description('Check status of a Lightning payment')
|
|
805
|
+
.action(async (paymentHash, id) => {
|
|
806
|
+
try {
|
|
807
|
+
const status = await keymaster.checkLightningPayment(paymentHash, id);
|
|
808
|
+
console.log(JSON.stringify(status, null, 4));
|
|
809
|
+
}
|
|
810
|
+
catch (error) {
|
|
811
|
+
console.error(error.error || error.message || error);
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
program
|
|
815
|
+
.command('publish-lightning [id]')
|
|
816
|
+
.description('Publish Lightning service endpoint for a DID')
|
|
817
|
+
.action(async (id) => {
|
|
818
|
+
try {
|
|
819
|
+
await keymaster.publishLightning(id);
|
|
820
|
+
console.log(UPDATE_OK);
|
|
821
|
+
}
|
|
822
|
+
catch (error) {
|
|
823
|
+
console.error(error.error || error.message || error);
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
program
|
|
827
|
+
.command('unpublish-lightning [id]')
|
|
828
|
+
.description('Remove Lightning service endpoint from a DID')
|
|
829
|
+
.action(async (id) => {
|
|
830
|
+
try {
|
|
831
|
+
await keymaster.unpublishLightning(id);
|
|
832
|
+
console.log(UPDATE_OK);
|
|
833
|
+
}
|
|
834
|
+
catch (error) {
|
|
835
|
+
console.error(error.error || error.message || error);
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
program
|
|
839
|
+
.command('lightning-zap <did> <amount> [memo]')
|
|
840
|
+
.description('Send sats to a DID via Lightning')
|
|
841
|
+
.action(async (did, amount, memo) => {
|
|
842
|
+
try {
|
|
843
|
+
const result = await keymaster.zapLightning(did, parseInt(amount), memo);
|
|
844
|
+
console.log(JSON.stringify(result, null, 4));
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
console.error(error.error || error.message || error);
|
|
848
|
+
}
|
|
849
|
+
});
|
|
692
850
|
// Group commands
|
|
693
851
|
program
|
|
694
852
|
.command('create-group <groupName>')
|
|
@@ -1545,7 +1703,7 @@ async function run() {
|
|
|
1545
1703
|
}
|
|
1546
1704
|
try {
|
|
1547
1705
|
// Initialize gatekeeper client
|
|
1548
|
-
const gatekeeper = new
|
|
1706
|
+
const gatekeeper = new DrawbridgeClient();
|
|
1549
1707
|
await gatekeeper.connect({
|
|
1550
1708
|
url: gatekeeperURL,
|
|
1551
1709
|
waitUntilReady: true,
|