-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
222 lines (194 loc) · 6.85 KB
/
index.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
import {PDFDocument, PDFFont, PDFPage, rgb} from 'pdf-lib';
import fontkit from '@pdf-lib/fontkit'
import {AccountQR, ContactQR, MnemonicQR, QRCode } from "symbol-qr-library";
import encodedFont from "./resources/encodedFont";
import encodedBasePdf from "./resources/encodedBasePdf";
import encodedBasePrivateKeyPdf from "./resources/encodedBasePrivateKeyPdf";
/**
* Default generation hash
*/
const DEFAULT_GENERATION_HASH_SEED = '57F7DA205008026C776CB6AED843393F04CD458E0AA2D9F1D5F31A402072B2D6';
/**
* Printing constants
*/
const MNEMONIC_POSITION = {
x: 244,
y: 46
};
const ADDRESS_POSITION = {
x: 244,
y: 115
};
const MNEMONIC_QR_POSITION = {
x: 344,
y: 205,
width: 150,
height: 150,
};
const ADDRESS_QR_POSITION = {
x: 550,
y: 205,
width: 150,
height: 150,
};
/**
* Abstraction for NetworkType sdk interface
*/
export type INetworkType = number;
/**
* HD Account info interface
*/
export type IHDAccountInfo = {
mnemonic: string,
rootAccountPublicKey: string,
rootAccountAddress: string
};
/**
* Account info interface
*/
export type IAccountInfo = {
name: string,
address: string,
publicKey: string,
privateKey: string
};
/**
* dHealth Paper wallet class
*/
class dHealthPaperWallet {
public hdAccount: IHDAccountInfo;
public accountInfos: IAccountInfo[];
public network: INetworkType;
public generationHashSeed: string;
constructor(hdAccountInfo: IHDAccountInfo, accountInfos: IAccountInfo[], network: INetworkType, generationHashSeed: string = DEFAULT_GENERATION_HASH_SEED) {
this.hdAccount = hdAccountInfo;
this.accountInfos = accountInfos;
this.network = network;
this.generationHashSeed = generationHashSeed
}
/**
* Exports as a PDF Uin8Array
*/
async toPdf(): Promise<Uint8Array> {
const plainPdfFile = new Buffer(encodedBasePdf, 'base64');
let pdfDoc = await PDFDocument.load(plainPdfFile);
const notoSansFontBytes = new Buffer(encodedFont, 'base64');
pdfDoc.registerFontkit(fontkit);
const notoSansFont = await pdfDoc.embedFont(notoSansFontBytes);
pdfDoc = await this.writeMnemonicPage(pdfDoc, notoSansFont);
for (let account of this.accountInfos) {
pdfDoc = await this.writeAccountPage(account, pdfDoc);
}
return pdfDoc.save();
}
/**
* Writes the mnemonic page into the given pdfDoc
* @param pdfDoc
* @param font
*/
private async writeMnemonicPage(pdfDoc: PDFDocument, font: PDFFont): Promise<PDFDocument> {
const pages = pdfDoc.getPages();
const page = pages[0];
await this.writeAddress(this.hdAccount.rootAccountAddress, page, font);
const mnemonicWords = this.hdAccount.mnemonic.split(' ');
const firstMnemonic = mnemonicWords.slice(0, Math.round(mnemonicWords.length / 2));
const secondMnemonic = mnemonicWords.slice(Math.round(mnemonicWords.length / 2), mnemonicWords.length);
await this.writePrivateInfo([firstMnemonic.join(' '), secondMnemonic.join(' ')], page, font);
const plainMnemonicQR = new MnemonicQR(this.hdAccount.mnemonic, this.network, this.generationHashSeed);
await this.writePrivateQR(plainMnemonicQR, pdfDoc, page);
const contactQR = new ContactQR('Root account', this.hdAccount.rootAccountPublicKey, this.network, this.generationHashSeed);
await this.writePublicQR(contactQR, pdfDoc, page);
return pdfDoc;
}
/**
* Writes the account page into the given pdfDoc
* @param account
* @param pdfDoc
*/
private async writeAccountPage(account: IAccountInfo, pdfDoc: PDFDocument): Promise<PDFDocument> {
const newPlainPdfFile = new Buffer(encodedBasePrivateKeyPdf, 'base64');
const newPdfDoc = await PDFDocument.load(newPlainPdfFile);
const notoSansFontBytes = new Buffer(encodedFont, 'base64');
newPdfDoc.registerFontkit(fontkit);
const font = await newPdfDoc.embedFont(notoSansFontBytes);
let accountPage = newPdfDoc.getPages()[0];
await this.writeAddress(account.address, accountPage, font);
await this.writePrivateInfo([account.privateKey], accountPage, font);
const accountQR = new AccountQR(account.privateKey, this.network, this.generationHashSeed);
await this.writePrivateQR(accountQR, newPdfDoc, accountPage);
const contactQR = new ContactQR(account.name, account.publicKey, this.network, this.generationHashSeed);
await this.writePublicQR(contactQR, newPdfDoc, accountPage);
[accountPage] = await pdfDoc.copyPages(newPdfDoc, [0]);
pdfDoc.addPage(accountPage);
return pdfDoc;
}
/**
* Writes address into the given pdfDoc
* @param address
* @param page
* @param font
*/
private async writeAddress(address: string, page: PDFPage, font: PDFFont): Promise<PDFPage> {
page.drawText(address, {
x: ADDRESS_POSITION.x,
y: ADDRESS_POSITION.y,
size: 12,
font: font,
color: rgb(82/256, 0, 198/256),
});
return page;
}
/**
* Writes private info into the pdfDoc
* @param privateLines
* @param page
* @param font
*/
private async writePrivateInfo(privateLines: string[], page: PDFPage, font: PDFFont): Promise<PDFPage> {
for (let i=0; i < privateLines.length; i++) {
page.drawText(privateLines[i], {
x: MNEMONIC_POSITION.x,
y: MNEMONIC_POSITION.y - (16 * i),
size: 9,
font: font,
color: rgb(82/256, 0, 198/256),
});
}
return page;
}
/**
* Writes the private QR (mnemonic or private key) into the given pdfDoc
* @param qr
* @param pdfDoc
* @param page
*/
private async writePrivateQR(qr: QRCode, pdfDoc: PDFDocument, page: PDFPage): Promise<PDFPage> {
const qrBase64 = await qr.toBase64().toPromise();
const png = await pdfDoc.embedPng(qrBase64);
page.drawImage(png, {
x: MNEMONIC_QR_POSITION.x,
y: MNEMONIC_QR_POSITION.y,
width: MNEMONIC_QR_POSITION.width,
height: MNEMONIC_QR_POSITION.height,
});
return page;
}
/**
* Writes the public QR into the given pdfDoc
* @param qr
* @param pdfDoc
* @param page
*/
private async writePublicQR(qr: QRCode, pdfDoc: PDFDocument, page: PDFPage): Promise<PDFPage> {
const qrBase64 = await qr.toBase64().toPromise();
const png = await pdfDoc.embedPng(qrBase64);
page.drawImage(png, {
x: ADDRESS_QR_POSITION.x,
y: ADDRESS_QR_POSITION.y,
width: ADDRESS_QR_POSITION.width,
height: ADDRESS_QR_POSITION.height,
});
return page;
}
}
export { dHealthPaperWallet };