-
Notifications
You must be signed in to change notification settings - Fork 203
/
kmd.ts
423 lines (397 loc) · 13.3 KB
/
kmd.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
import ServiceClient from './v2/serviceClient';
import * as txn from '../transaction';
import { CustomTokenHeader, KMDTokenHeader } from './urlTokenBaseHTTPClient';
export default class Kmd extends ServiceClient {
constructor(
token: string | KMDTokenHeader | CustomTokenHeader,
baseServer = 'http://127.0.0.1',
port: string | number = 7833,
headers = {}
) {
super('X-KMD-API-Token', token, baseServer, port, headers);
}
/**
* version returns a VersionResponse containing a list of kmd API versions supported by this running kmd instance.
*/
async versions() {
const res = await this.c.get('/versions');
return res.body;
}
/**
* listWallets returns a ListWalletsResponse containing the list of wallets known to kmd. Using a wallet ID
* returned from this endpoint, you can initialize a wallet handle with client.InitWalletHandle
*/
async listWallets() {
const res = await this.c.get('/v1/wallets');
return res.body;
}
/**
* createWallet creates a wallet with the specified name, password, driver,
* and master derivation key. If the master derivation key is blank, one is
* generated internally to kmd. CreateWallet returns a CreateWalletResponse
* containing information about the new wallet.
* @param walletName
* @param walletPassword
* @param walletDriverName
* @param walletMDK
*/
async createWallet(
walletName: string,
walletPassword: string,
walletMDK: Uint8Array = new Uint8Array(),
walletDriverName = 'sqlite'
) {
const req = {
wallet_name: walletName,
wallet_driver_name: walletDriverName,
wallet_password: walletPassword,
master_derivation_key: Buffer.from(walletMDK).toString('base64'),
};
const res = await this.c.post('/v1/wallet', req);
return res.body;
}
/**
* initWalletHandle accepts a wallet ID and a wallet password, and returns an
* initWalletHandleResponse containing a wallet handle token. This wallet
* handle token can be used for subsequent operations on this wallet, like key
* generation, transaction signing, etc.. WalletHandleTokens expire after a
* configurable number of seconds, and must be renewed periodically with
* RenewWalletHandle. It is good practice to call ReleaseWalletHandle when
* you're done interacting with this wallet.
* @param walletID
* @param walletPassword
*/
async initWalletHandle(walletID: string, walletPassword: string) {
const req = {
wallet_id: walletID,
wallet_password: walletPassword,
};
const res = await this.c.post('/v1/wallet/init', req);
return res.body;
}
/**
* releaseWalletHandle invalidates the passed wallet handle token, making
* it unusuable for subsequent wallet operations.
* @param walletHandle
*/
async releaseWalletHandle(walletHandle: string) {
const req = {
wallet_handle_token: walletHandle,
};
const res = await this.c.post('/v1/wallet/release', req);
return res.body;
}
/**
* renewWalletHandle accepts a wallet handle and attempts to renew it, moving
* the expiration time to some number of seconds in the future. It returns a
* RenewWalletHandleResponse containing the walletHandle and the number of
* seconds until expiration
* @param walletHandle
*/
async renewWalletHandle(walletHandle: string) {
const req = {
wallet_handle_token: walletHandle,
};
const res = await this.c.post('/v1/wallet/renew', req);
return res.body;
}
/**
* renameWallet accepts a wallet ID, wallet password, and a new wallet name,
* and renames the underlying wallet.
* @param walletID
* @param walletPassword
* @param newWalletName
*/
async renameWallet(
walletID: string,
walletPassword: string,
newWalletName: string
) {
const req = {
wallet_id: walletID,
wallet_password: walletPassword,
wallet_name: newWalletName,
};
const res = await this.c.post('/v1/wallet/rename', req);
return res.body;
}
/**
* getWallet accepts a wallet handle and returns high level information about
* this wallet in a GetWalletResponse.
* @param walletHandle
*/
async getWallet(walletHandle: string) {
const req = {
wallet_handle_token: walletHandle,
};
const res = await this.c.post('/v1/wallet/info', req);
return res.body;
}
/**
* exportMasterDerivationKey accepts a wallet handle and a wallet password, and
* returns an ExportMasterDerivationKeyResponse containing the master
* derivation key. This key can be used as an argument to CreateWallet in
* order to recover the keys generated by this wallet. The master derivation
* key can be encoded as a sequence of words using the mnemonic library, and
* @param walletHandle
* @param walletPassword
*/
async exportMasterDerivationKey(
walletHandle: string,
walletPassword: string
) {
const req = {
wallet_handle_token: walletHandle,
wallet_password: walletPassword,
};
const res = await this.c.post('/v1/master-key/export', req);
return {
master_derivation_key: Buffer.from(
res.body.master_derivation_key,
'base64'
),
};
}
/**
* importKey accepts a wallet handle and an ed25519 private key, and imports
* the key into the wallet. It returns an ImportKeyResponse containing the
* address corresponding to this private key.
* @param walletHandle
* @param secretKey
*/
async importKey(walletHandle: string, secretKey: Uint8Array) {
const req = {
wallet_handle_token: walletHandle,
private_key: Buffer.from(secretKey).toString('base64'),
};
const res = await this.c.post('/v1/key/import', req);
return res.body;
}
/**
* exportKey accepts a wallet handle, wallet password, and address, and returns
* an ExportKeyResponse containing the ed25519 private key corresponding to the
* address stored in the wallet.
* @param walletHandle
* @param walletPassword
* @param addr
*/
async exportKey(walletHandle: string, walletPassword: string, addr: string) {
const req = {
wallet_handle_token: walletHandle,
address: addr,
wallet_password: walletPassword,
};
const res = await this.c.post('/v1/key/export', req);
return { private_key: Buffer.from(res.body.private_key, 'base64') };
}
/**
* generateKey accepts a wallet handle, and then generates the next key in the
* wallet using its internal master derivation key. Two wallets with the same
* master derivation key will generate the same sequence of keys.
* @param walletHandle
*/
async generateKey(walletHandle: string) {
const req = {
wallet_handle_token: walletHandle,
display_mnemonic: false,
};
const res = await this.c.post('/v1/key', req);
return res.body;
}
/**
* deleteKey accepts a wallet handle, wallet password, and address, and deletes
* the information about this address from the wallet (including address and
* secret key). If DeleteKey is called on a key generated using GenerateKey,
* the same key will not be generated again. However, if a wallet is recovered
* using the master derivation key, a key generated in this way can be
* recovered.
* @param walletHandle
* @param walletPassword
* @param addr
*/
async deleteKey(walletHandle: string, walletPassword: string, addr: string) {
const req = {
wallet_handle_token: walletHandle,
address: addr,
wallet_password: walletPassword,
};
const res = await this.c.delete('/v1/key', req);
return res.body;
}
/**
* ListKeys accepts a wallet handle and returns a ListKeysResponse containing
* all of the addresses for which this wallet contains secret keys.
* @param walletHandle
*/
async listKeys(walletHandle: string) {
const req = {
wallet_handle_token: walletHandle,
};
const res = await this.c.post('/v1/key/list', req);
return res.body;
}
/**
* signTransaction accepts a wallet handle, wallet password, and a transaction,
* and returns and SignTransactionResponse containing an encoded, signed
* transaction. The transaction is signed using the key corresponding to the
* Sender field.
* @param walletHandle
* @param walletPassword
* @param transaction
*/
async signTransaction(
walletHandle: string,
walletPassword: string,
transaction: txn.TransactionLike
) {
const tx = txn.instantiateTxnIfNeeded(transaction);
const req = {
wallet_handle_token: walletHandle,
wallet_password: walletPassword,
transaction: Buffer.from(tx.toByte()).toString('base64'),
};
const res = await this.c.post('/v1/transaction/sign', req);
if (res.status === 200) {
return Buffer.from(res.body.signed_transaction, 'base64');
}
return res.body;
}
/**
* signTransactionWithSpecificPublicKey accepts a wallet handle, wallet password, a transaction, and a public key,
* and returns and SignTransactionResponse containing an encoded, signed
* transaction. The transaction is signed using the key corresponding to the
* publicKey arg.
* @param walletHandle
* @param walletPassword
* @param transaction
* @param publicKey - sign the txn with the key corresponding to publicKey (used for working with a rekeyed addr)
*/
async signTransactionWithSpecificPublicKey(
walletHandle: string,
walletPassword: string,
transaction: txn.TransactionLike,
publicKey: Uint8Array | string
) {
const tx = txn.instantiateTxnIfNeeded(transaction);
const req = {
wallet_handle_token: walletHandle,
wallet_password: walletPassword,
transaction: Buffer.from(tx.toByte()).toString('base64'),
public_key: Buffer.from(publicKey).toString('base64'),
};
const res = await this.c.post('/v1/transaction/sign', req);
if (res.status === 200) {
return Buffer.from(res.body.signed_transaction, 'base64');
}
return res.body;
}
/**
* listMultisig accepts a wallet handle and returns a ListMultisigResponse
* containing the multisig addresses whose preimages are stored in this wallet.
* A preimage is the information needed to reconstruct this multisig address,
* including multisig version information, threshold information, and a list
* of public keys.
* @param walletHandle
*/
async listMultisig(walletHandle: string) {
const req = {
wallet_handle_token: walletHandle,
};
const res = await this.c.post('/v1/multisig/list', req);
return res.body;
}
/**
* importMultisig accepts a wallet handle and the information required to
* generate a multisig address. It derives this address, and stores all of the
* information within the wallet. It returns a ImportMultisigResponse with the
* derived address.
* @param walletHandle
* @param version
* @param threshold
* @param pks
*/
async importMultisig(
walletHandle: string,
version: number,
threshold: number,
pks: string[]
) {
const req = {
wallet_handle_token: walletHandle,
multisig_version: version,
threshold,
pks,
};
const res = await this.c.post('/v1/multisig/import', req);
return res.body;
}
/**
* exportMultisig accepts a wallet handle, wallet password, and multisig
* address, and returns an ExportMultisigResponse containing the stored
* multisig preimage. The preimage contains all of the information necessary
* to derive the multisig address, including version, threshold, and a list of
* public keys.
* @param walletHandle
* @param walletPassword
* @param addr
*/
async exportMultisig(walletHandle: string, addr: string) {
const req = {
wallet_handle_token: walletHandle,
address: addr,
};
const res = await this.c.post('/v1/multisig/export', req);
return res.body;
}
/**
* signMultisigTransaction accepts a wallet handle, wallet password,
* transaction, public key (*not* an address), and an optional partial
* MultisigSig. It looks up the secret key corresponding to the public key, and
* returns a SignMultisigTransactionResponse containing a MultisigSig with a
* signature by the secret key included.
* @param walletHandle
* @param pw
* @param tx
* @param pk
* @param partial
*/
async signMultisigTransaction(
walletHandle: string,
pw: string,
transaction: txn.TransactionLike,
pk: Uint8Array | string,
partial: string
) {
const tx = txn.instantiateTxnIfNeeded(transaction);
const req = {
wallet_handle_token: walletHandle,
transaction: Buffer.from(tx.toByte()).toString('base64'),
public_key: Buffer.from(pk).toString('base64'),
partial_multisig: partial,
wallet_password: pw,
};
const res = await this.c.post('/v1/multisig/sign', req);
return res.body;
}
/**
* deleteMultisig accepts a wallet handle, wallet password, and multisig
* address, and deletes the information about this multisig address from the
* wallet (including address and secret key).
* @param walletHandle
* @param walletPassword
* @param addr
*/
async deleteMultisig(
walletHandle: string,
walletPassword: string,
addr: string
) {
const req = {
wallet_handle_token: walletHandle,
address: addr,
wallet_password: walletPassword,
};
const res = await this.c.delete('/v1/multisig', req);
return res.body;
}
}