@mainnet-cash/postgresql-storage 2.1.0-alpha.5
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/README.md +3 -0
- package/dist/module/SqlProvider.d.ts +30 -0
- package/dist/module/SqlProvider.js +159 -0
- package/dist/module/SqlProvider.js.map +1 -0
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.js +3 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/util.d.ts +7 -0
- package/dist/module/util.js +24 -0
- package/dist/module/util.js.map +1 -0
- package/dist/module/webhook/Webhook.d.ts +35 -0
- package/dist/module/webhook/Webhook.js +77 -0
- package/dist/module/webhook/Webhook.js.map +1 -0
- package/dist/module/webhook/WebhookBch.d.ts +13 -0
- package/dist/module/webhook/WebhookBch.js +141 -0
- package/dist/module/webhook/WebhookBch.js.map +1 -0
- package/dist/module/webhook/WebhookWorker.d.ts +22 -0
- package/dist/module/webhook/WebhookWorker.js +94 -0
- package/dist/module/webhook/WebhookWorker.js.map +1 -0
- package/dist/module/webhook/index.d.ts +4 -0
- package/dist/module/webhook/index.js +5 -0
- package/dist/module/webhook/index.js.map +1 -0
- package/dist/module/webhook/interface.d.ts +7 -0
- package/dist/module/webhook/interface.js +2 -0
- package/dist/module/webhook/interface.js.map +1 -0
- package/dist/tsconfig.browser.tsbuildinfo +1 -0
- package/package.json +34 -0
- package/src/SqlProvider.test.ts +264 -0
- package/src/SqlProvider.ts +233 -0
- package/src/Wallet.test.ts +571 -0
- package/src/createWallet.test.ts +158 -0
- package/src/index.test.ts +67 -0
- package/src/index.ts +2 -0
- package/src/util.ts +30 -0
- package/src/webhook/Webhook.test.ts +9 -0
- package/src/webhook/Webhook.ts +99 -0
- package/src/webhook/WebhookBch.test.ts +323 -0
- package/src/webhook/WebhookBch.ts +198 -0
- package/src/webhook/WebhookWorker.test.ts +94 -0
- package/src/webhook/WebhookWorker.ts +119 -0
- package/src/webhook/index.ts +4 -0
- package/src/webhook/interface.ts +7 -0
- package/tsconfig.browser.json +6 -0
- package/tsconfig.json +28 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { StorageProvider, WalletI, TxI } from "mainnet-js";
|
|
2
|
+
import { RegisterWebhookParams } from "./webhook/interface.js";
|
|
3
|
+
import { getSslConfig } from "./util.js";
|
|
4
|
+
import parseDbUrl from "parse-database-url";
|
|
5
|
+
import pg from "pg";
|
|
6
|
+
import format from "pg-format";
|
|
7
|
+
import { Webhook, WebhookRecurrence, WebhookType } from "./webhook/index.js";
|
|
8
|
+
|
|
9
|
+
export default class SqlProvider implements StorageProvider {
|
|
10
|
+
private db;
|
|
11
|
+
private config;
|
|
12
|
+
private info;
|
|
13
|
+
private formatter;
|
|
14
|
+
private walletTable: string;
|
|
15
|
+
private webhookTable: string = "webhook";
|
|
16
|
+
private isInit = false;
|
|
17
|
+
|
|
18
|
+
public constructor(walletTable?: string) {
|
|
19
|
+
this.walletTable = walletTable ? walletTable : "wallet";
|
|
20
|
+
if (!process.env.DATABASE_URL) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
"Named wallets and webhooks require a postgres DATABASE_URL environment variable to be set"
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
let dbConfig = parseDbUrl(process.env.DATABASE_URL);
|
|
26
|
+
let ssl = getSslConfig();
|
|
27
|
+
if (ssl) {
|
|
28
|
+
dbConfig.ssl = ssl;
|
|
29
|
+
}
|
|
30
|
+
this.config = dbConfig;
|
|
31
|
+
|
|
32
|
+
const Pool = pg.Pool;
|
|
33
|
+
this.db = new Pool(dbConfig);
|
|
34
|
+
this.formatter = format;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public getConfig() {
|
|
38
|
+
return this.config;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public async init(): Promise<StorageProvider> {
|
|
42
|
+
if (!this.isInit) {
|
|
43
|
+
this.isInit = true;
|
|
44
|
+
await this.db;
|
|
45
|
+
await this.formatter;
|
|
46
|
+
|
|
47
|
+
let createWalletTable = this.formatter(
|
|
48
|
+
"CREATE TABLE IF NOT EXISTS %I (id SERIAL, name TEXT PRIMARY KEY, wallet TEXT );",
|
|
49
|
+
this.walletTable
|
|
50
|
+
);
|
|
51
|
+
const resWallet = await this.db.query(createWalletTable);
|
|
52
|
+
|
|
53
|
+
let createWebhookTable = this.formatter(
|
|
54
|
+
"CREATE TABLE IF NOT EXISTS %I (" +
|
|
55
|
+
"id SERIAL PRIMARY KEY," +
|
|
56
|
+
"cashaddr TEXT," +
|
|
57
|
+
"type TEXT," +
|
|
58
|
+
"recurrence TEXT," +
|
|
59
|
+
"url TEXT," +
|
|
60
|
+
"status TEXT," +
|
|
61
|
+
"tx_seen JSON," +
|
|
62
|
+
"last_height INTEGER," +
|
|
63
|
+
"expires_at TIMESTAMPTZ" +
|
|
64
|
+
");",
|
|
65
|
+
this.webhookTable
|
|
66
|
+
);
|
|
67
|
+
const resWebhook = await this.db.query(createWebhookTable);
|
|
68
|
+
|
|
69
|
+
if (!resWallet || !resWebhook)
|
|
70
|
+
throw new Error("Failed to init SqlProvider");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public async close(): Promise<StorageProvider> {
|
|
77
|
+
await this.db.end();
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public getInfo(): string {
|
|
82
|
+
return this.info;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public async addWallet(name: string, walletId: string): Promise<boolean> {
|
|
86
|
+
let text = this.formatter(
|
|
87
|
+
"INSERT into %I (name,wallet) VALUES ($1, $2);",
|
|
88
|
+
this.walletTable
|
|
89
|
+
);
|
|
90
|
+
return await this.db.query(text, [name, walletId]);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public async getWallets(): Promise<Array<WalletI>> {
|
|
94
|
+
let text = this.formatter("SELECT * FROM %I;", this.walletTable);
|
|
95
|
+
let result = await this.db.query(text);
|
|
96
|
+
if (result) {
|
|
97
|
+
const WalletArray: WalletI[] = await Promise.all(
|
|
98
|
+
result.rows.map(async (obj: WalletI) => {
|
|
99
|
+
return obj;
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
return WalletArray;
|
|
103
|
+
} else {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public async getWallet(name: string): Promise<WalletI | undefined> {
|
|
109
|
+
let text = this.formatter(
|
|
110
|
+
"SELECT * FROM %I WHERE name = $1;",
|
|
111
|
+
this.walletTable
|
|
112
|
+
);
|
|
113
|
+
let result = await this.db.query(text, [name]);
|
|
114
|
+
let w = result.rows[0];
|
|
115
|
+
return w;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public async updateWallet(name: string, walletId: string): Promise<void> {
|
|
119
|
+
let text = this.formatter(
|
|
120
|
+
"UPDATE %I SET wallet = $1 WHERE name = $2;",
|
|
121
|
+
this.walletTable
|
|
122
|
+
);
|
|
123
|
+
await this.db.query(text, [walletId, name]);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public async walletExists(name: string): Promise<boolean> {
|
|
127
|
+
return (await this.getWallet(name)) !== undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public async webhookFromDb(hook: Webhook) {
|
|
131
|
+
const { WebhookBch } = await import("./webhook/WebhookBch.js");
|
|
132
|
+
return new WebhookBch(hook);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public async addWebhook(params: RegisterWebhookParams): Promise<Webhook> {
|
|
136
|
+
// init db if it was not, useful for external api calls
|
|
137
|
+
await this.init();
|
|
138
|
+
|
|
139
|
+
params.type = params.type || WebhookType.transactionInOut;
|
|
140
|
+
params.recurrence = params.recurrence || WebhookRecurrence.once;
|
|
141
|
+
const expireTimeout =
|
|
142
|
+
Number(process.env.WEBHOOK_EXPIRE_TIMEOUT_SECONDS) || 86400;
|
|
143
|
+
params.duration_sec = params.duration_sec || expireTimeout;
|
|
144
|
+
params.duration_sec =
|
|
145
|
+
params.duration_sec > expireTimeout ? expireTimeout : params.duration_sec;
|
|
146
|
+
|
|
147
|
+
const expires_at = new Date(
|
|
148
|
+
new Date().getTime() + params.duration_sec * 1000
|
|
149
|
+
);
|
|
150
|
+
let text = this.formatter(
|
|
151
|
+
"INSERT into %I (cashaddr,type,recurrence,url,status,tx_seen,last_height,expires_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;",
|
|
152
|
+
this.webhookTable
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const result = await this.db.query(text, [
|
|
156
|
+
params.cashaddr,
|
|
157
|
+
params.type,
|
|
158
|
+
params.recurrence,
|
|
159
|
+
params.url,
|
|
160
|
+
"",
|
|
161
|
+
"[]",
|
|
162
|
+
0,
|
|
163
|
+
expires_at.toISOString(),
|
|
164
|
+
]);
|
|
165
|
+
const hook = await this.webhookFromDb(result.rows[0]);
|
|
166
|
+
hook.db = this;
|
|
167
|
+
return hook;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public async getWebhooks(): Promise<Array<Webhook>> {
|
|
171
|
+
let text = this.formatter("SELECT * FROM %I;", this.webhookTable);
|
|
172
|
+
let result = await this.db.query(text);
|
|
173
|
+
if (result) {
|
|
174
|
+
const WebhookArray: Webhook[] = await Promise.all(
|
|
175
|
+
result.rows.map(async (obj: any) => {
|
|
176
|
+
obj = await this.webhookFromDb(obj);
|
|
177
|
+
obj.db = this;
|
|
178
|
+
return obj;
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
return WebhookArray;
|
|
182
|
+
} else {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public async getWebhook(id: number): Promise<Webhook | undefined> {
|
|
188
|
+
const text = this.formatter(
|
|
189
|
+
"SELECT * FROM %I WHERE id = $1;",
|
|
190
|
+
this.webhookTable
|
|
191
|
+
);
|
|
192
|
+
const result = await this.db.query(text, [id]);
|
|
193
|
+
let hook = result.rows[0];
|
|
194
|
+
if (hook) {
|
|
195
|
+
hook = this.webhookFromDb(hook);
|
|
196
|
+
hook.db = this;
|
|
197
|
+
}
|
|
198
|
+
return hook;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
public async setWebhookStatus(id: number, status: string): Promise<void> {
|
|
202
|
+
let text = this.formatter(
|
|
203
|
+
"UPDATE %I SET status = $1 WHERE id = $2;",
|
|
204
|
+
this.webhookTable
|
|
205
|
+
);
|
|
206
|
+
await this.db.query(text, [status, id]);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public async setWebhookSeenTxLastHeight(
|
|
210
|
+
id: number,
|
|
211
|
+
tx_seen: Array<TxI>,
|
|
212
|
+
last_height: number
|
|
213
|
+
): Promise<void> {
|
|
214
|
+
let text = this.formatter(
|
|
215
|
+
"UPDATE %I SET tx_seen = $1, last_height = $2 WHERE id = $3;",
|
|
216
|
+
this.webhookTable
|
|
217
|
+
);
|
|
218
|
+
await this.db.query(text, [JSON.stringify(tx_seen), last_height, id]);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public async deleteWebhook(id: number): Promise<void> {
|
|
222
|
+
let text = this.formatter(
|
|
223
|
+
"DELETE FROM %I WHERE id = $1;",
|
|
224
|
+
this.webhookTable
|
|
225
|
+
);
|
|
226
|
+
await this.db.query(text, [id]);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public async clearWebhooks(): Promise<void> {
|
|
230
|
+
let text = this.formatter("DELETE FROM %I;", this.webhookTable);
|
|
231
|
+
await this.db.query(text);
|
|
232
|
+
}
|
|
233
|
+
}
|