@aztec/bot 0.0.1-fake-ceab37513c → 0.0.6-commit.a2d1860fe9
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/dest/amm_bot.d.ts +9 -10
- package/dest/amm_bot.d.ts.map +1 -1
- package/dest/amm_bot.js +27 -20
- package/dest/base_bot.d.ts +12 -9
- package/dest/base_bot.d.ts.map +1 -1
- package/dest/base_bot.js +28 -29
- package/dest/bot.d.ts +9 -10
- package/dest/bot.d.ts.map +1 -1
- package/dest/bot.js +12 -10
- package/dest/config.d.ts +82 -63
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +61 -31
- package/dest/cross_chain_bot.d.ts +54 -0
- package/dest/cross_chain_bot.d.ts.map +1 -0
- package/dest/cross_chain_bot.js +140 -0
- package/dest/factory.d.ts +27 -34
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +271 -151
- package/dest/index.d.ts +3 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -0
- package/dest/interface.d.ts +2 -2
- package/dest/interface.d.ts.map +1 -1
- package/dest/interface.js +1 -1
- package/dest/l1_to_l2_seeding.d.ts +8 -0
- package/dest/l1_to_l2_seeding.d.ts.map +1 -0
- package/dest/l1_to_l2_seeding.js +63 -0
- package/dest/rpc.d.ts +1 -1
- package/dest/runner.d.ts +12 -13
- package/dest/runner.d.ts.map +1 -1
- package/dest/runner.js +445 -61
- package/dest/store/bot_store.d.ts +69 -0
- package/dest/store/bot_store.d.ts.map +1 -0
- package/dest/store/bot_store.js +138 -0
- package/dest/store/index.d.ts +2 -0
- package/dest/store/index.d.ts.map +1 -0
- package/dest/store/index.js +1 -0
- package/dest/utils.d.ts +4 -4
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +5 -5
- package/package.json +19 -13
- package/src/amm_bot.ts +40 -32
- package/src/base_bot.ts +27 -39
- package/src/bot.ts +25 -13
- package/src/config.ts +101 -72
- package/src/cross_chain_bot.ts +209 -0
- package/src/factory.ts +313 -177
- package/src/index.ts +2 -0
- package/src/interface.ts +1 -1
- package/src/l1_to_l2_seeding.ts +79 -0
- package/src/runner.ts +33 -24
- package/src/store/bot_store.ts +196 -0
- package/src/store/index.ts +1 -0
- package/src/utils.ts +10 -5
package/src/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { Bot } from './bot.js';
|
|
2
2
|
export { AmmBot } from './amm_bot.js';
|
|
3
|
+
export { CrossChainBot } from './cross_chain_bot.js';
|
|
3
4
|
export { BotRunner } from './runner.js';
|
|
5
|
+
export { BotStore } from './store/bot_store.js';
|
|
4
6
|
export {
|
|
5
7
|
type BotConfig,
|
|
6
8
|
getBotConfigFromEnv,
|
package/src/interface.ts
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { generateClaimSecret } from '@aztec/aztec.js/ethereum';
|
|
2
|
+
import type { ExtendedViemWalletClient } from '@aztec/ethereum/types';
|
|
3
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
4
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
7
|
+
import { InboxAbi } from '@aztec/l1-artifacts';
|
|
8
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
9
|
+
|
|
10
|
+
import { decodeEventLog, getContract } from 'viem';
|
|
11
|
+
|
|
12
|
+
import type { BotStore, PendingL1ToL2Message } from './store/index.js';
|
|
13
|
+
|
|
14
|
+
/** Sends an L1→L2 message via the Inbox contract and stores it. */
|
|
15
|
+
export async function seedL1ToL2Message(
|
|
16
|
+
l1Client: ExtendedViemWalletClient,
|
|
17
|
+
inboxAddress: EthAddress,
|
|
18
|
+
l2Recipient: AztecAddress,
|
|
19
|
+
rollupVersion: bigint,
|
|
20
|
+
store: BotStore,
|
|
21
|
+
log: Logger,
|
|
22
|
+
): Promise<PendingL1ToL2Message> {
|
|
23
|
+
log.info('Seeding L1→L2 message');
|
|
24
|
+
const [secret, secretHash] = await generateClaimSecret(log);
|
|
25
|
+
const content = Fr.random();
|
|
26
|
+
|
|
27
|
+
const inbox = getContract({
|
|
28
|
+
address: inboxAddress.toString(),
|
|
29
|
+
abi: InboxAbi,
|
|
30
|
+
client: l1Client,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const txHash = await inbox.write.sendL2Message(
|
|
34
|
+
[{ actor: l2Recipient.toString(), version: rollupVersion }, content.toString(), secretHash.toString()],
|
|
35
|
+
{ gas: 1_000_000n },
|
|
36
|
+
);
|
|
37
|
+
log.info(`L1→L2 message sent in tx ${txHash}`);
|
|
38
|
+
|
|
39
|
+
const txReceipt = await l1Client.waitForTransactionReceipt({ hash: txHash });
|
|
40
|
+
if (txReceipt.status !== 'success') {
|
|
41
|
+
throw new Error(`L1→L2 message tx failed: ${txHash}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Extract MessageSent event
|
|
45
|
+
const messageSentLogs = compactArray(
|
|
46
|
+
txReceipt.logs
|
|
47
|
+
.filter(l => l.address.toLowerCase() === inboxAddress.toString().toLowerCase())
|
|
48
|
+
.map(l => {
|
|
49
|
+
try {
|
|
50
|
+
return decodeEventLog({ abi: InboxAbi, eventName: 'MessageSent', data: l.data, topics: l.topics });
|
|
51
|
+
} catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (messageSentLogs.length !== 1) {
|
|
58
|
+
throw new Error(`Expected 1 MessageSent event, got ${messageSentLogs.length}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const event = messageSentLogs[0];
|
|
62
|
+
|
|
63
|
+
const msgHash = event.args.hash;
|
|
64
|
+
const globalLeafIndex = event.args.index;
|
|
65
|
+
|
|
66
|
+
const msg: PendingL1ToL2Message = {
|
|
67
|
+
content: content.toString(),
|
|
68
|
+
secret: secret.toString(),
|
|
69
|
+
secretHash: secretHash.toString(),
|
|
70
|
+
msgHash,
|
|
71
|
+
sender: l1Client.account!.address,
|
|
72
|
+
globalLeafIndex: globalLeafIndex.toString(),
|
|
73
|
+
timestamp: Date.now(),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
await store.savePendingL1ToL2Message(msg);
|
|
77
|
+
log.info(`Seeded L1→L2 message msgHash=${msg.msgHash}`);
|
|
78
|
+
return msg;
|
|
79
|
+
}
|
package/src/runner.ts
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createLogger } from '@aztec/aztec.js/log';
|
|
2
|
+
import type { AztecNode } from '@aztec/aztec.js/node';
|
|
2
3
|
import { omit } from '@aztec/foundation/collection';
|
|
3
4
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
4
|
-
import {
|
|
5
|
-
import { type TelemetryClient, type Traceable, type Tracer,
|
|
5
|
+
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
6
|
+
import { type TelemetryClient, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
|
|
7
|
+
import type { EmbeddedWallet } from '@aztec/wallets/embedded';
|
|
6
8
|
|
|
7
9
|
import { AmmBot } from './amm_bot.js';
|
|
8
10
|
import type { BaseBot } from './base_bot.js';
|
|
9
11
|
import { Bot } from './bot.js';
|
|
10
|
-
import {
|
|
12
|
+
import type { BotConfig } from './config.js';
|
|
13
|
+
import { CrossChainBot } from './cross_chain_bot.js';
|
|
11
14
|
import type { BotInfo, BotRunnerApi } from './interface.js';
|
|
15
|
+
import { BotStore } from './store/index.js';
|
|
12
16
|
|
|
13
17
|
export class BotRunner implements BotRunnerApi, Traceable {
|
|
14
18
|
private log = createLogger('bot');
|
|
15
19
|
private bot?: Promise<BaseBot>;
|
|
16
|
-
private pxe?: PXE;
|
|
17
|
-
private node: AztecNode;
|
|
18
|
-
private nodeAdmin?: AztecNodeAdmin;
|
|
19
20
|
private runningPromise: RunningPromise;
|
|
20
21
|
private consecutiveErrors = 0;
|
|
21
22
|
private healthy = true;
|
|
@@ -24,19 +25,14 @@ export class BotRunner implements BotRunnerApi, Traceable {
|
|
|
24
25
|
|
|
25
26
|
public constructor(
|
|
26
27
|
private config: BotConfig,
|
|
27
|
-
|
|
28
|
+
private readonly wallet: EmbeddedWallet,
|
|
29
|
+
private readonly aztecNode: AztecNode,
|
|
30
|
+
private readonly telemetry: TelemetryClient,
|
|
31
|
+
private readonly aztecNodeAdmin: AztecNodeAdmin | undefined,
|
|
32
|
+
private readonly store: BotStore,
|
|
28
33
|
) {
|
|
29
|
-
this.tracer =
|
|
30
|
-
|
|
31
|
-
if (!dependencies.node && !config.nodeUrl) {
|
|
32
|
-
throw new Error(`Missing node URL in config or dependencies`);
|
|
33
|
-
}
|
|
34
|
-
const versions = getVersions();
|
|
35
|
-
const fetch = makeTracedFetch([1, 2, 3], true);
|
|
36
|
-
this.node = dependencies.node ?? createAztecNodeClient(config.nodeUrl!, versions, fetch);
|
|
37
|
-
this.nodeAdmin =
|
|
38
|
-
dependencies.nodeAdmin ??
|
|
39
|
-
(config.nodeAdminUrl ? createAztecNodeAdminClient(config.nodeAdminUrl, versions, fetch) : undefined);
|
|
34
|
+
this.tracer = telemetry.getTracer('Bot');
|
|
35
|
+
|
|
40
36
|
this.runningPromise = new RunningPromise(() => this.#work(), this.log, config.txIntervalSeconds * 1000);
|
|
41
37
|
}
|
|
42
38
|
|
|
@@ -74,6 +70,7 @@ export class BotRunner implements BotRunnerApi, Traceable {
|
|
|
74
70
|
this.log.verbose(`Stopping bot`);
|
|
75
71
|
await this.runningPromise.stop();
|
|
76
72
|
}
|
|
73
|
+
await this.store.close();
|
|
77
74
|
this.log.info(`Stopped bot`);
|
|
78
75
|
}
|
|
79
76
|
|
|
@@ -144,15 +141,27 @@ export class BotRunner implements BotRunnerApi, Traceable {
|
|
|
144
141
|
if (!this.bot) {
|
|
145
142
|
throw new Error(`Bot is not initialized`);
|
|
146
143
|
}
|
|
147
|
-
const botAddress = await this.bot.then(b => b.
|
|
144
|
+
const botAddress = await this.bot.then(b => b.defaultAccountAddress);
|
|
148
145
|
return { botAddress };
|
|
149
146
|
}
|
|
150
147
|
|
|
151
148
|
async #createBot() {
|
|
152
149
|
try {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
switch (this.config.botMode) {
|
|
151
|
+
case 'crosschain':
|
|
152
|
+
this.bot = CrossChainBot.create(this.config, this.wallet, this.aztecNode, this.aztecNodeAdmin, this.store);
|
|
153
|
+
break;
|
|
154
|
+
case 'amm':
|
|
155
|
+
this.bot = AmmBot.create(this.config, this.wallet, this.aztecNode, this.aztecNodeAdmin, this.store);
|
|
156
|
+
break;
|
|
157
|
+
case 'transfer':
|
|
158
|
+
this.bot = Bot.create(this.config, this.wallet, this.aztecNode, this.aztecNodeAdmin, this.store);
|
|
159
|
+
break;
|
|
160
|
+
default: {
|
|
161
|
+
const _exhaustive: never = this.config.botMode;
|
|
162
|
+
throw new Error(`Unsupported bot mode: [${_exhaustive}]`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
156
165
|
await this.bot;
|
|
157
166
|
} catch (err) {
|
|
158
167
|
this.log.error(`Error setting up bot: ${err}`);
|
|
@@ -163,7 +172,7 @@ export class BotRunner implements BotRunnerApi, Traceable {
|
|
|
163
172
|
@trackSpan('Bot.work')
|
|
164
173
|
async #work() {
|
|
165
174
|
if (this.config.maxPendingTxs > 0) {
|
|
166
|
-
const pendingTxCount = await this.
|
|
175
|
+
const pendingTxCount = await this.aztecNode.getPendingTxCount();
|
|
167
176
|
if (pendingTxCount >= this.config.maxPendingTxs) {
|
|
168
177
|
this.log.verbose(`Not sending bot tx since node has ${pendingTxCount} pending txs`);
|
|
169
178
|
return;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { AztecAddress } from '@aztec/aztec.js/addresses';
|
|
2
|
+
import type { L2AmountClaim } from '@aztec/aztec.js/ethereum';
|
|
3
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
|
+
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
7
|
+
|
|
8
|
+
export interface BridgeClaimData {
|
|
9
|
+
claim: L2AmountClaim;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
recipient: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PendingL1ToL2Message {
|
|
15
|
+
/** Random content field sent in the message. */
|
|
16
|
+
content: string;
|
|
17
|
+
/** Secret for consuming the message. */
|
|
18
|
+
secret: string;
|
|
19
|
+
/** Hash of the secret. */
|
|
20
|
+
secretHash: string;
|
|
21
|
+
/** Hash of the L1→L2 message. */
|
|
22
|
+
msgHash: string;
|
|
23
|
+
/** L1 sender address (hex). */
|
|
24
|
+
sender: string;
|
|
25
|
+
/** Global leaf index in the L1→L2 message tree. */
|
|
26
|
+
globalLeafIndex: string;
|
|
27
|
+
/** Timestamp when the message was seeded. */
|
|
28
|
+
timestamp: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Simple data store for the bot to persist L1 bridge claims.
|
|
33
|
+
*/
|
|
34
|
+
export class BotStore {
|
|
35
|
+
public static readonly SCHEMA_VERSION = 1;
|
|
36
|
+
private readonly bridgeClaims: AztecAsyncMap<string, string>;
|
|
37
|
+
private readonly pendingL1ToL2: AztecAsyncMap<string, string>;
|
|
38
|
+
|
|
39
|
+
constructor(
|
|
40
|
+
private readonly store: AztecAsyncKVStore,
|
|
41
|
+
private readonly log: Logger = createLogger('bot:store'),
|
|
42
|
+
private readonly dateProvider: DateProvider = new DateProvider(),
|
|
43
|
+
) {
|
|
44
|
+
this.bridgeClaims = store.openMap<string, string>('bridge_claims');
|
|
45
|
+
this.pendingL1ToL2 = store.openMap<string, string>('pending_l1_to_l2');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Saves a bridge claim for a recipient.
|
|
50
|
+
*/
|
|
51
|
+
public async saveBridgeClaim(recipient: AztecAddress, claim: L2AmountClaim): Promise<void> {
|
|
52
|
+
// Convert Fr fields and BigInts to strings for JSON serialization
|
|
53
|
+
const serializableClaim = {
|
|
54
|
+
claimAmount: claim.claimAmount.toString(),
|
|
55
|
+
claimSecret: claim.claimSecret.toString(),
|
|
56
|
+
claimSecretHash: claim.claimSecretHash.toString(),
|
|
57
|
+
messageHash: claim.messageHash,
|
|
58
|
+
messageLeafIndex: claim.messageLeafIndex.toString(),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const data = {
|
|
62
|
+
claim: serializableClaim,
|
|
63
|
+
timestamp: this.dateProvider.now(),
|
|
64
|
+
recipient: recipient.toString(),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
await this.bridgeClaims.set(recipient.toString(), JSON.stringify(data));
|
|
68
|
+
this.log.info(`Saved bridge claim for ${recipient.toString()}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Gets a bridge claim for a recipient if it exists.
|
|
73
|
+
*/
|
|
74
|
+
public async getBridgeClaim(recipient: AztecAddress): Promise<BridgeClaimData | undefined> {
|
|
75
|
+
const data = await this.bridgeClaims.getAsync(recipient.toString());
|
|
76
|
+
if (!data) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const parsed = JSON.parse(data);
|
|
81
|
+
|
|
82
|
+
// Reconstruct L2AmountClaim from serialized data
|
|
83
|
+
const claim: L2AmountClaim = {
|
|
84
|
+
claimAmount: BigInt(parsed.claim.claimAmount),
|
|
85
|
+
claimSecret: Fr.fromString(parsed.claim.claimSecret),
|
|
86
|
+
claimSecretHash: Fr.fromString(parsed.claim.claimSecretHash),
|
|
87
|
+
messageHash: parsed.claim.messageHash,
|
|
88
|
+
messageLeafIndex: BigInt(parsed.claim.messageLeafIndex),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
claim,
|
|
93
|
+
timestamp: parsed.timestamp,
|
|
94
|
+
recipient: parsed.recipient,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Deletes a bridge claim for a recipient.
|
|
100
|
+
*/
|
|
101
|
+
public async deleteBridgeClaim(recipient: AztecAddress): Promise<void> {
|
|
102
|
+
await this.bridgeClaims.delete(recipient.toString());
|
|
103
|
+
this.log.info(`Deleted bridge claim for ${recipient.toString()}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets all stored bridge claims.
|
|
108
|
+
*/
|
|
109
|
+
public async getAllBridgeClaims(): Promise<BridgeClaimData[]> {
|
|
110
|
+
const claims: BridgeClaimData[] = [];
|
|
111
|
+
const entries = this.bridgeClaims.entriesAsync();
|
|
112
|
+
|
|
113
|
+
for await (const [_, data] of entries) {
|
|
114
|
+
const parsed = JSON.parse(data);
|
|
115
|
+
|
|
116
|
+
// Reconstruct L2AmountClaim from serialized data
|
|
117
|
+
const claim: L2AmountClaim = {
|
|
118
|
+
claimAmount: BigInt(parsed.claim.claimAmount),
|
|
119
|
+
claimSecret: Fr.fromString(parsed.claim.claimSecret),
|
|
120
|
+
claimSecretHash: Fr.fromString(parsed.claim.claimSecretHash),
|
|
121
|
+
messageHash: parsed.claim.messageHash,
|
|
122
|
+
messageLeafIndex: BigInt(parsed.claim.messageLeafIndex),
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
claims.push({
|
|
126
|
+
claim,
|
|
127
|
+
timestamp: parsed.timestamp,
|
|
128
|
+
recipient: parsed.recipient,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return claims;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Cleans up old bridge claims (older than 24 hours).
|
|
137
|
+
*/
|
|
138
|
+
public async cleanupOldClaims(maxAgeMs: number = 24 * 60 * 60 * 1000): Promise<number> {
|
|
139
|
+
const now = this.dateProvider.now();
|
|
140
|
+
let cleanedCount = 0;
|
|
141
|
+
const entries = this.bridgeClaims.entriesAsync();
|
|
142
|
+
|
|
143
|
+
for await (const [key, data] of entries) {
|
|
144
|
+
const parsed = JSON.parse(data);
|
|
145
|
+
if (now - parsed.timestamp > maxAgeMs) {
|
|
146
|
+
await this.bridgeClaims.delete(key);
|
|
147
|
+
cleanedCount++;
|
|
148
|
+
this.log.info(`Cleaned up old bridge claim for ${parsed.recipient}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return cleanedCount;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Saves a pending L1→L2 message keyed by msgHash. */
|
|
156
|
+
public async savePendingL1ToL2Message(msg: PendingL1ToL2Message): Promise<void> {
|
|
157
|
+
await this.pendingL1ToL2.set(msg.msgHash, JSON.stringify(msg));
|
|
158
|
+
this.log.info(`Saved pending L1→L2 message ${msg.msgHash}`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Returns all unconsumed pending L1→L2 messages. */
|
|
162
|
+
public async getUnconsumedL1ToL2Messages(): Promise<PendingL1ToL2Message[]> {
|
|
163
|
+
const messages: PendingL1ToL2Message[] = [];
|
|
164
|
+
for await (const [_, data] of this.pendingL1ToL2.entriesAsync()) {
|
|
165
|
+
messages.push(JSON.parse(data));
|
|
166
|
+
}
|
|
167
|
+
return messages;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Deletes a consumed L1→L2 message from the store. */
|
|
171
|
+
public async deleteL1ToL2Message(msgHash: string): Promise<void> {
|
|
172
|
+
await this.pendingL1ToL2.delete(msgHash);
|
|
173
|
+
this.log.info(`Deleted consumed L1→L2 message ${msgHash}`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Cleans up pending L1→L2 messages older than maxAgeMs. */
|
|
177
|
+
public async cleanupOldPendingMessages(maxAgeMs: number = 24 * 60 * 60 * 1000): Promise<number> {
|
|
178
|
+
const now = this.dateProvider.now();
|
|
179
|
+
let cleanedCount = 0;
|
|
180
|
+
for await (const [key, data] of this.pendingL1ToL2.entriesAsync()) {
|
|
181
|
+
const parsed = JSON.parse(data);
|
|
182
|
+
if (now - parsed.timestamp > maxAgeMs) {
|
|
183
|
+
await this.pendingL1ToL2.delete(key);
|
|
184
|
+
cleanedCount++;
|
|
185
|
+
this.log.info(`Cleaned up old pending L1→L2 message ${key}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return cleanedCount;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Closes the store. */
|
|
192
|
+
public async close(): Promise<void> {
|
|
193
|
+
await this.store.close();
|
|
194
|
+
this.log.info('Closed bot data store');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BotStore, type BridgeClaimData, type PendingL1ToL2Message } from './bot_store.js';
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ContractBase } from '@aztec/aztec.js/contracts';
|
|
2
2
|
import type { AMMContract } from '@aztec/noir-contracts.js/AMM';
|
|
3
3
|
import type { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
|
|
4
4
|
import type { TokenContract } from '@aztec/noir-contracts.js/Token';
|
|
@@ -13,14 +13,19 @@ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
13
13
|
export async function getBalances(
|
|
14
14
|
token: TokenContract,
|
|
15
15
|
who: AztecAddress,
|
|
16
|
+
from?: AztecAddress,
|
|
16
17
|
): Promise<{ privateBalance: bigint; publicBalance: bigint }> {
|
|
17
|
-
const privateBalance = await token.methods.balance_of_private(who).simulate({ from: who });
|
|
18
|
-
const publicBalance = await token.methods.balance_of_public(who).simulate({ from: who });
|
|
18
|
+
const privateBalance = await token.methods.balance_of_private(who).simulate({ from: from ?? who });
|
|
19
|
+
const publicBalance = await token.methods.balance_of_public(who).simulate({ from: from ?? who });
|
|
19
20
|
return { privateBalance, publicBalance };
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export async function getPrivateBalance(
|
|
23
|
-
|
|
23
|
+
export async function getPrivateBalance(
|
|
24
|
+
token: PrivateTokenContract,
|
|
25
|
+
who: AztecAddress,
|
|
26
|
+
from?: AztecAddress,
|
|
27
|
+
): Promise<bigint> {
|
|
28
|
+
const privateBalance = await token.methods.get_balance(who).simulate({ from: from ?? who });
|
|
24
29
|
return privateBalance;
|
|
25
30
|
}
|
|
26
31
|
|