This repository has been archived by the owner on Jul 21, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 24
/
message-feed.js
127 lines (115 loc) · 3.47 KB
/
message-feed.js
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
// @flow
import fs from 'mz/fs';
import path from 'path';
import {Account, BpfLoader, Connection, PublicKey} from '@solana/web3.js';
import {newSystemAccountWithAirdrop} from '../util/new-system-account-with-airdrop';
import * as Program from '../programs/message-feed';
export type MessageFeedMeta = {
programId: PublicKey,
firstMessageAccount: Account,
};
/**
* Manages the active instance of a Message Feed program
*/
export default class MessageFeedController {
meta: ?MessageFeedMeta;
loading: boolean;
connection: Connection;
constructor(connection: Connection) {
this.connection = connection;
}
async getMeta(): Promise<?MessageFeedMeta> {
if (this.loading) return;
if (this.meta) {
const {firstMessageAccount} = this.meta;
try {
await this.connection.getAccountInfo(firstMessageAccount.publicKey);
return this.meta;
} catch (err) {
console.error(
`getAccountInfo of ${firstMessageAccount.publicKey.toString()} failed: ${err}`,
);
this.meta = undefined;
}
}
this.reload();
}
async reload() {
this.loading = true;
try {
this.meta = await this.createMessageFeed();
this.loading = false;
} catch (err) {
console.error(`createMessageFeed failed: ${err}`);
} finally {
this.loading = false;
}
}
/**
* Creates a new Message Feed.
*/
async createMessageFeed(): Promise<MessageFeedMeta> {
const programId = await this.loadProgram();
console.log('Message feed program:', programId.toString());
console.log('Posting first message...');
const firstMessage = 'First post! 💫';
const {feeCalculator} = await this.connection.getRecentBlockhash();
const postMessageFee =
feeCalculator.lamportsPerSignature * 3; /* 1 payer + 2 signer keys */
const minAccountBalances =
(await this.connection.getMinimumBalanceForRentExemption(
Program.userAccountSize,
)) +
(await this.connection.getMinimumBalanceForRentExemption(
Program.messageAccountSize(firstMessage),
));
const payerAccount = await newSystemAccountWithAirdrop(
this.connection,
postMessageFee + minAccountBalances,
);
const firstMessageAccount = new Account();
await Program.postMessageWithProgramId(
this.connection,
programId,
payerAccount,
null,
firstMessageAccount,
firstMessage,
);
console.log(
'First message public key:',
firstMessageAccount.publicKey.toString(),
);
return {
programId,
firstMessageAccount,
};
}
/**
* Load a new instance of the Message Feed program
*/
async loadProgram(): Promise<PublicKey> {
const NUM_RETRIES = 100; /* allow some number of retries */
const elfFile = path.join(
__dirname,
'..',
'..',
'dist',
'programs',
'messagefeed.so',
);
console.log(`Reading ${elfFile}...`);
const elfData = await fs.readFile(elfFile);
console.log('Loading Message feed program...');
const {feeCalculator} = await this.connection.getRecentBlockhash();
const fees =
feeCalculator.lamportsPerSignature *
(BpfLoader.getMinNumSignatures(elfData.length) + NUM_RETRIES) +
(await this.connection.getMinimumBalanceForRentExemption(elfData.length));
const loaderAccount = await newSystemAccountWithAirdrop(
this.connection,
fees,
);
return BpfLoader.load(this.connection, loaderAccount, elfData);
}
}