-
Notifications
You must be signed in to change notification settings - Fork 150
/
CLIKey.ts
125 lines (112 loc) · 3.21 KB
/
CLIKey.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
import { Key } from './Key';
import {
StdSignMsg,
StdSignature,
AccPubKey,
AccAddress,
ValAddress,
ValPubKey,
} from '../core';
import { execSync } from 'child_process';
import { fileSync } from 'tmp';
import { writeFileSync } from 'fs';
interface CLIKeyParams {
keyName: string;
multisig?: string;
cliPath?: string;
home?: string;
}
/**
* Key implementation that uses `terracli` to sign transactions. Keys should be registered
* in `terracli`'s OS keyring.
*
* NOTE: This Key implementation overrides `createSignature()` and only provide a shim
* for `sign()`.
*/
export class CLIKey extends Key {
private _accAddress?: AccAddress;
private _accPubKey?: AccPubKey;
/**
*
* @param keyName name of the key for terracli
* @param multisig (optional) address of multisig account on behalf of which transaction shall be signed
* @param cliPath (optional) path of terracli
* @param home (optional) home option for terracli
*/
constructor(private params: CLIKeyParams) {
super();
params.cliPath = params.cliPath || 'terracli';
}
private generateCommand(args: string) {
return `${this.params.cliPath} ${args} -o json ${
this.params.home ? `--home ${this.params.home}` : ''
}`;
}
private loadAccountDetails() {
const details = JSON.parse(
execSync(
this.generateCommand(`keys show ${this.params.keyName}`)
).toString()
);
this._accAddress = details.address;
this._accPubKey = details.pubkey;
}
/**
* Terra account address. `terra-` prefixed.
*/
public get accAddress(): AccAddress {
if (!this._accAddress) {
this.loadAccountDetails();
return this.accAddress;
}
return this._accAddress;
}
/**
* Terra validator address. `terravaloper-` prefixed.
*/
public get valAddress(): ValAddress {
if (!this._accAddress) {
this.loadAccountDetails();
return this.valAddress;
}
return ValAddress.fromAccAddress(this._accAddress);
}
/**
* Terra account public key. `terrapub-` prefixed.
*/
public get accPubKey(): AccPubKey {
if (!this._accPubKey) {
this.loadAccountDetails();
return this.accPubKey;
}
return this._accPubKey;
}
/**
* Terra validator public key. `terravaloperpub-` prefixed.
*/
public get valPubKey(): ValPubKey {
if (!this._accPubKey) {
this.loadAccountDetails();
return this.valPubKey;
}
return ValPubKey.fromAccPubKey(this._accPubKey);
}
public async sign(): Promise<Buffer> {
throw new Error(
'CLIKey does not use sign() -- use createSignature() directly.'
);
}
public async createSignature(tx: StdSignMsg): Promise<StdSignature> {
const tmpobj = fileSync({ postfix: '.json' });
writeFileSync(tmpobj.fd, tx.toStdTx().toJSON());
const result = execSync(
this.generateCommand(
`tx sign ${tmpobj.name} --yes --signature-only --from ${this.params.keyName} --offline ` +
`--chain-id ${tx.chain_id} --account-number ${tx.account_number} --sequence ${tx.sequence} ` +
`${this.params.multisig ? `--multisig ${this.params.multisig}` : ''}`
)
).toString();
tmpobj.removeCallback();
return StdSignature.fromData(JSON.parse(result));
}
}