-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.ts
More file actions
108 lines (97 loc) · 3.53 KB
/
handler.ts
File metadata and controls
108 lines (97 loc) · 3.53 KB
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
import { D1Storage } from "./storage";
import {
type MintEventRaw,
type ProposeUtxoEventRaw,
type RedeemRequestEventRaw,
type SolvedEventRaw,
type SignatureRecordedEventRaw,
type SuiEventNode,
UtxoStatus,
} from "./models";
import { logger } from "@gonative-cc/lib/logger";
import { fromBase64 } from "@mysten/sui/utils";
export class SuiEventHandler {
private storage: D1Storage;
private setupId: number;
constructor(storage: D1Storage, setupId: number) {
this.storage = storage;
this.setupId = setupId;
}
public async handleEvents(events: SuiEventNode[]) {
for (const e of events) {
const json = e.json;
if (e.type.includes("::nbtc::MintEvent")) {
await this.handleMint(e.txDigest, json as MintEventRaw);
} else if (e.type.includes("::nbtc::RedeemRequestEvent")) {
await this.handleRedeemRequest(e.txDigest, json as RedeemRequestEventRaw);
} else if (e.type.includes("::nbtc::ProposeUtxoEvent")) {
await this.handleProposeUtxo(json as ProposeUtxoEventRaw);
} else if (e.type.includes("::nbtc::redeem_request::SolvedEvent")) {
await this.handleSolvedRedeem(json as SolvedEventRaw);
} else if (e.type.includes("::nbtc::redeem_request::SignatureRecordedEvent")) {
await this.handleIkaSignatureRecorded(json as SignatureRecordedEventRaw);
}
}
}
private async handleMint(txDigest: string, e: MintEventRaw) {
// NOTE: Sui contract gives us the txid in big-endian, but bitcoinjs-lib's tx.getId()
// returns it in little-endian (see https://github.com/bitcoinjs/bitcoinjs-lib/blob/dc8d9e26f2b9c7380aec7877155bde97594a9ade/ts_src/transaction.ts#L617)
// so we reverse here to match what the btcindexer uses
const txId = fromBase64(e.btc_tx_id).reverse().toHex();
await this.storage.insertUtxo({
nbtc_utxo_id: Number(e.utxo_id),
dwallet_id: e.dwallet_id,
txid: txId,
vout: e.btc_vout,
amount: Number(e.btc_amount),
script_pubkey: fromBase64(e.btc_script_publickey),
setup_id: this.setupId,
status: UtxoStatus.Available,
locked_until: null,
});
logger.info({ msg: "Indexed Mint", utxo: e.utxo_id });
}
private async handleRedeemRequest(txDigest: string, e: RedeemRequestEventRaw) {
await this.storage.insertRedeemRequest({
redeem_id: Number(e.redeem_id),
redeemer: e.redeemer,
recipient_script: fromBase64(e.recipient_script),
amount: Number(e.amount),
created_at: Number(e.created_at),
setup_id: this.setupId,
sui_tx: txDigest,
});
logger.info({ msg: "Indexed Redeem Request", id: e.redeem_id });
}
private async handleProposeUtxo(e: ProposeUtxoEventRaw) {
// NOTE: the event is only emmited if the proposal is the best, thats why we are locking them here,
// we should lock them when we are proposing already, and here we should just attempt to lock else ignore
await this.storage.lockUtxos(e.utxo_ids.map(Number));
logger.info({
msg: "Locked UTXOs for Proposal",
redeemId: e.redeem_id,
count: e.utxo_ids.length,
});
}
private async handleSolvedRedeem(e: SolvedEventRaw) {
await this.storage.upsertRedeemInputs(
Number(e.redeem_id),
e.utxo_ids.map(Number),
e.dwallet_ids,
);
await this.storage.markRedeemSigning(Number(e.redeem_id));
logger.info({
msg: "Marked redeem as solved and added inputs",
redeemId: e.redeem_id,
utxos: e.utxo_ids.length,
});
}
private async handleIkaSignatureRecorded(e: SignatureRecordedEventRaw) {
await this.storage.markRedeemInputVerified(Number(e.redeem_id), Number(e.utxo_id));
logger.info({
msg: "Marked redeem input as verified",
redeemId: e.redeem_id,
utxoId: e.utxo_id,
});
}
}