ethsub
Version:
A bridge between ethereum and substrate
135 lines (134 loc) • 4.46 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.init = exports.Service = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const level_1 = __importDefault(require("level"));
const use_services_1 = require("use-services");
const types_1 = require("./types");
const services_1 = require("./services");
const ETH_BN_KEY = "bn:eth";
const SUB_BN_KEY = "bn:sub";
class Service {
constructor(option) {
this.args = option.args;
}
async [use_services_1.INIT_KEY]() {
await fs_1.default.promises.mkdir(this.args.dataDir, { recursive: true });
this.db = (0, level_1.default)(path_1.default.resolve(this.args.dataDir, "db"), {
valueEncoding: "json",
});
}
async storeEthBlockNum(blockNum) {
await this.db.put(ETH_BN_KEY, blockNum);
}
async loadEthBlockNum() {
const value = await this.safeGet(ETH_BN_KEY);
return value || 0;
}
async storeSubBlockNum(blockNum) {
await this.db.put(SUB_BN_KEY, blockNum);
}
async loadSubBlockNum() {
const value = await this.safeGet(SUB_BN_KEY);
return value || 0;
}
async storeMsg(msg) {
const key = this.stringifyMsgKey(msg);
await this.db
.batch()
.put(key, {
payload: msg.payload,
name: msg.resource.name,
})
.put(`${key}:${types_1.BridgeMsgStatus.Pending}`, Date.now())
.write();
}
async loadMsg(key) {
const value = await this.safeGet(key);
if (!value)
return;
const { source, destination, nonce } = this.parseMsgKey(key);
const { name, payload } = value;
const resource = services_1.srvs.settings.resources.find((v) => v.name === name);
return {
source,
destination,
nonce,
resource,
type: resource.type,
payload,
};
}
async storeMsgStatus(msg, status) {
const key = this.stringifyMsgKey(msg);
const batch = this.db.batch();
for (const statusValue in types_1.BridgeMsgStatus) {
if (/^\d+$/.test(statusValue)) {
if (statusValue === status.toString()) {
batch.put(`${key}:${statusValue}`, Date.now());
}
else {
batch.del(`${key}:${statusValue}`);
}
}
}
await batch.write();
}
async loadMsgStatus(msg) {
const key = this.stringifyMsgKey(msg);
const keys = [];
for (const statusValue in types_1.BridgeMsgStatus) {
if (/^\d+$/.test(statusValue)) {
keys.push(`${key}:${statusValue}`);
}
}
const values = await this.db.getMany(keys);
for (let i = 0; i < values.length; i++) {
return i;
}
return types_1.BridgeMsgStatus.Pending;
}
async nextMsg(source, destination) {
const re = new RegExp(`^msg:${source}:${destination}:\\d+:${types_1.BridgeMsgStatus.Pending}$`);
const key = await this.firstKey((key) => re.test(key));
if (!key)
return;
const { nonce } = this.parseMsgKey(key);
return this.loadMsg(this.stringifyMsgKey({ source, destination, nonce }));
}
async safeGet(key) {
try {
const value = await this.db.get(key);
return value;
}
catch (_a) {
return null;
}
}
async firstKey(pred = (_) => true) {
for await (const [key] of this.db.iterator({ values: false })) {
if (pred(key))
return key;
}
}
parseMsgKey(key) {
const [source, destination, nonce, status] = key
.slice(4)
.split(":")
.map((v) => parseInt(v));
return { source, destination, nonce, status };
}
stringifyMsgKey(msg, status) {
let key = `msg:${msg.source}:${msg.destination}:${msg.nonce}`;
if (typeof status !== "undefined") {
key += ":" + status;
}
return key;
}
}
exports.Service = Service;
exports.init = (0, use_services_1.createInitFn)(Service);