@aztec/bot 0.0.1-commit.d6f2b3f94 → 0.0.1-commit.db765a8

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.
Files changed (46) hide show
  1. package/dest/amm_bot.d.ts +4 -4
  2. package/dest/amm_bot.d.ts.map +1 -1
  3. package/dest/amm_bot.js +23 -16
  4. package/dest/base_bot.d.ts +4 -4
  5. package/dest/base_bot.d.ts.map +1 -1
  6. package/dest/base_bot.js +9 -10
  7. package/dest/bot.d.ts +4 -4
  8. package/dest/bot.d.ts.map +1 -1
  9. package/dest/bot.js +4 -3
  10. package/dest/config.d.ts +30 -14
  11. package/dest/config.d.ts.map +1 -1
  12. package/dest/config.js +36 -8
  13. package/dest/cross_chain_bot.d.ts +54 -0
  14. package/dest/cross_chain_bot.d.ts.map +1 -0
  15. package/dest/cross_chain_bot.js +141 -0
  16. package/dest/factory.d.ts +20 -5
  17. package/dest/factory.d.ts.map +1 -1
  18. package/dest/factory.js +93 -24
  19. package/dest/index.d.ts +2 -1
  20. package/dest/index.d.ts.map +1 -1
  21. package/dest/index.js +1 -0
  22. package/dest/l1_to_l2_seeding.d.ts +8 -0
  23. package/dest/l1_to_l2_seeding.d.ts.map +1 -0
  24. package/dest/l1_to_l2_seeding.js +63 -0
  25. package/dest/runner.d.ts +3 -3
  26. package/dest/runner.d.ts.map +1 -1
  27. package/dest/runner.js +17 -1
  28. package/dest/store/bot_store.d.ts +30 -5
  29. package/dest/store/bot_store.d.ts.map +1 -1
  30. package/dest/store/bot_store.js +37 -6
  31. package/dest/store/index.d.ts +2 -2
  32. package/dest/store/index.d.ts.map +1 -1
  33. package/dest/utils.js +3 -3
  34. package/package.json +16 -13
  35. package/src/amm_bot.ts +23 -18
  36. package/src/base_bot.ts +8 -18
  37. package/src/bot.ts +7 -6
  38. package/src/config.ts +39 -10
  39. package/src/cross_chain_bot.ts +210 -0
  40. package/src/factory.ts +137 -30
  41. package/src/index.ts +1 -0
  42. package/src/l1_to_l2_seeding.ts +79 -0
  43. package/src/runner.ts +18 -5
  44. package/src/store/bot_store.ts +60 -5
  45. package/src/store/index.ts +1 -1
  46. package/src/utils.ts +3 -3
@@ -1,21 +1,40 @@
1
1
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
2
  import type { L2AmountClaim } from '@aztec/aztec.js/ethereum';
3
3
  import { type Logger } from '@aztec/foundation/log';
4
+ import { DateProvider } from '@aztec/foundation/timer';
4
5
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
5
6
  export interface BridgeClaimData {
6
7
  claim: L2AmountClaim;
7
8
  timestamp: number;
8
9
  recipient: string;
9
10
  }
11
+ export interface PendingL1ToL2Message {
12
+ /** Random content field sent in the message. */
13
+ content: string;
14
+ /** Secret for consuming the message. */
15
+ secret: string;
16
+ /** Hash of the secret. */
17
+ secretHash: string;
18
+ /** Hash of the L1→L2 message. */
19
+ msgHash: string;
20
+ /** L1 sender address (hex). */
21
+ sender: string;
22
+ /** Global leaf index in the L1→L2 message tree. */
23
+ globalLeafIndex: string;
24
+ /** Timestamp when the message was seeded. */
25
+ timestamp: number;
26
+ }
10
27
  /**
11
28
  * Simple data store for the bot to persist L1 bridge claims.
12
29
  */
13
30
  export declare class BotStore {
14
31
  private readonly store;
15
32
  private readonly log;
33
+ private readonly dateProvider;
16
34
  static readonly SCHEMA_VERSION = 1;
17
35
  private readonly bridgeClaims;
18
- constructor(store: AztecAsyncKVStore, log?: Logger);
36
+ private readonly pendingL1ToL2;
37
+ constructor(store: AztecAsyncKVStore, log?: Logger, dateProvider?: DateProvider);
19
38
  /**
20
39
  * Saves a bridge claim for a recipient.
21
40
  */
@@ -36,9 +55,15 @@ export declare class BotStore {
36
55
  * Cleans up old bridge claims (older than 24 hours).
37
56
  */
38
57
  cleanupOldClaims(maxAgeMs?: number): Promise<number>;
39
- /**
40
- * Closes the store.
41
- */
58
+ /** Saves a pending L1→L2 message keyed by msgHash. */
59
+ savePendingL1ToL2Message(msg: PendingL1ToL2Message): Promise<void>;
60
+ /** Returns all unconsumed pending L1→L2 messages. */
61
+ getUnconsumedL1ToL2Messages(): Promise<PendingL1ToL2Message[]>;
62
+ /** Deletes a consumed L1→L2 message from the store. */
63
+ deleteL1ToL2Message(msgHash: string): Promise<void>;
64
+ /** Cleans up pending L1→L2 messages older than maxAgeMs. */
65
+ cleanupOldPendingMessages(maxAgeMs?: number): Promise<number>;
66
+ /** Closes the store. */
42
67
  close(): Promise<void>;
43
68
  }
44
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm90X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmUvYm90X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUU5RCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQWlCLE1BQU0saUJBQWlCLENBQUM7QUFFeEUsTUFBTSxXQUFXLGVBQWU7SUFDOUIsS0FBSyxFQUFFLGFBQWEsQ0FBQztJQUNyQixTQUFTLEVBQUUsTUFBTSxDQUFDO0lBQ2xCLFNBQVMsRUFBRSxNQUFNLENBQUM7Q0FDbkI7QUFFRDs7R0FFRztBQUNILHFCQUFhLFFBQVE7SUFLakIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLO0lBQ3RCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRztJQUx0QixnQkFBdUIsY0FBYyxLQUFLO0lBQzFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFnQztJQUU3RCxZQUNtQixLQUFLLEVBQUUsaUJBQWlCLEVBQ3hCLEdBQUcsR0FBRSxNQUFrQyxFQUd6RDtJQUVEOztPQUVHO0lBQ1UsZUFBZSxDQUFDLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBa0J6RjtJQUVEOztPQUVHO0lBQ1UsY0FBYyxDQUFDLFNBQVMsRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUMsQ0FzQnpGO0lBRUQ7O09BRUc7SUFDVSxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHckU7SUFFRDs7T0FFRztJQUNVLGtCQUFrQixJQUFJLE9BQU8sQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQXdCNUQ7SUFFRDs7T0FFRztJQUNVLGdCQUFnQixDQUFDLFFBQVEsR0FBRSxNQUE0QixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FlckY7SUFFRDs7T0FFRztJQUNVLEtBQUssSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBR2xDO0NBQ0YifQ==
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm90X3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmUvYm90X3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUU5RCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBRXhFLE1BQU0sV0FBVyxlQUFlO0lBQzlCLEtBQUssRUFBRSxhQUFhLENBQUM7SUFDckIsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixTQUFTLEVBQUUsTUFBTSxDQUFDO0NBQ25CO0FBRUQsTUFBTSxXQUFXLG9CQUFvQjtJQUNuQyxnREFBZ0Q7SUFDaEQsT0FBTyxFQUFFLE1BQU0sQ0FBQztJQUNoQix3Q0FBd0M7SUFDeEMsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLDBCQUEwQjtJQUMxQixVQUFVLEVBQUUsTUFBTSxDQUFDO0lBQ25CLG1DQUFpQztJQUNqQyxPQUFPLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLCtCQUErQjtJQUMvQixNQUFNLEVBQUUsTUFBTSxDQUFDO0lBQ2YscURBQW1EO0lBQ25ELGVBQWUsRUFBRSxNQUFNLENBQUM7SUFDeEIsNkNBQTZDO0lBQzdDLFNBQVMsRUFBRSxNQUFNLENBQUM7Q0FDbkI7QUFFRDs7R0FFRztBQUNILHFCQUFhLFFBQVE7SUFNakIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLO0lBQ3RCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRztJQUNwQixPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVk7SUFQL0IsZ0JBQXVCLGNBQWMsS0FBSztJQUMxQyxPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBZ0M7SUFDN0QsT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQWdDO0lBRTlELFlBQ21CLEtBQUssRUFBRSxpQkFBaUIsRUFDeEIsR0FBRyxHQUFFLE1BQWtDLEVBQ3ZDLFlBQVksR0FBRSxZQUFpQyxFQUlqRTtJQUVEOztPQUVHO0lBQ1UsZUFBZSxDQUFDLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBa0J6RjtJQUVEOztPQUVHO0lBQ1UsY0FBYyxDQUFDLFNBQVMsRUFBRSxZQUFZLEdBQUcsT0FBTyxDQUFDLGVBQWUsR0FBRyxTQUFTLENBQUMsQ0FzQnpGO0lBRUQ7O09BRUc7SUFDVSxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsWUFBWSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHckU7SUFFRDs7T0FFRztJQUNVLGtCQUFrQixJQUFJLE9BQU8sQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQXdCNUQ7SUFFRDs7T0FFRztJQUNVLGdCQUFnQixDQUFDLFFBQVEsR0FBRSxNQUE0QixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FlckY7SUFFRCx3REFBc0Q7SUFDekMsd0JBQXdCLENBQUMsR0FBRyxFQUFFLG9CQUFvQixHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FHOUU7SUFFRCx1REFBcUQ7SUFDeEMsMkJBQTJCLElBQUksT0FBTyxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FNMUU7SUFFRCx5REFBdUQ7SUFDMUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBRy9EO0lBRUQsOERBQTREO0lBQy9DLHlCQUF5QixDQUFDLFFBQVEsR0FBRSxNQUE0QixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FZOUY7SUFFRCx3QkFBd0I7SUFDWCxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUdsQztDQUNGIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"bot_store.d.ts","sourceRoot":"","sources":["../../src/store/bot_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,QAAQ;IAKjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IALtB,gBAAuB,cAAc,KAAK;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgC;IAE7D,YACmB,KAAK,EAAE,iBAAiB,EACxB,GAAG,GAAE,MAAkC,EAGzD;IAED;;OAEG;IACU,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzF;IAED;;OAEG;IACU,cAAc,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAsBzF;IAED;;OAEG;IACU,iBAAiB,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;IAED;;OAEG;IACU,kBAAkB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAwB5D;IAED;;OAEG;IACU,gBAAgB,CAAC,QAAQ,GAAE,MAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,CAerF;IAED;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAGlC;CACF"}
1
+ {"version":3,"file":"bot_store.d.ts","sourceRoot":"","sources":["../../src/store/bot_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,qDAAmD;IACnD,eAAe,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,QAAQ;IAMjB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAP/B,gBAAuB,cAAc,KAAK;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgC;IAE9D,YACmB,KAAK,EAAE,iBAAiB,EACxB,GAAG,GAAE,MAAkC,EACvC,YAAY,GAAE,YAAiC,EAIjE;IAED;;OAEG;IACU,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzF;IAED;;OAEG;IACU,cAAc,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAsBzF;IAED;;OAEG;IACU,iBAAiB,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;IAED;;OAEG;IACU,kBAAkB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAwB5D;IAED;;OAEG;IACU,gBAAgB,CAAC,QAAQ,GAAE,MAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,CAerF;IAED,wDAAsD;IACzC,wBAAwB,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;IAED,uDAAqD;IACxC,2BAA2B,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAM1E;IAED,yDAAuD;IAC1C,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG/D;IAED,8DAA4D;IAC/C,yBAAyB,CAAC,QAAQ,GAAE,MAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,CAY9F;IAED,wBAAwB;IACX,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAGlC;CACF"}
@@ -1,16 +1,21 @@
1
1
  import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import { createLogger } from '@aztec/foundation/log';
3
+ import { DateProvider } from '@aztec/foundation/timer';
3
4
  /**
4
5
  * Simple data store for the bot to persist L1 bridge claims.
5
6
  */ export class BotStore {
6
7
  store;
7
8
  log;
9
+ dateProvider;
8
10
  static SCHEMA_VERSION = 1;
9
11
  bridgeClaims;
10
- constructor(store, log = createLogger('bot:store')){
12
+ pendingL1ToL2;
13
+ constructor(store, log = createLogger('bot:store'), dateProvider = new DateProvider()){
11
14
  this.store = store;
12
15
  this.log = log;
16
+ this.dateProvider = dateProvider;
13
17
  this.bridgeClaims = store.openMap('bridge_claims');
18
+ this.pendingL1ToL2 = store.openMap('pending_l1_to_l2');
14
19
  }
15
20
  /**
16
21
  * Saves a bridge claim for a recipient.
@@ -25,7 +30,7 @@ import { createLogger } from '@aztec/foundation/log';
25
30
  };
26
31
  const data = {
27
32
  claim: serializableClaim,
28
- timestamp: Date.now(),
33
+ timestamp: this.dateProvider.now(),
29
34
  recipient: recipient.toString()
30
35
  };
31
36
  await this.bridgeClaims.set(recipient.toString(), JSON.stringify(data));
@@ -85,7 +90,7 @@ import { createLogger } from '@aztec/foundation/log';
85
90
  /**
86
91
  * Cleans up old bridge claims (older than 24 hours).
87
92
  */ async cleanupOldClaims(maxAgeMs = 24 * 60 * 60 * 1000) {
88
- const now = Date.now();
93
+ const now = this.dateProvider.now();
89
94
  let cleanedCount = 0;
90
95
  const entries = this.bridgeClaims.entriesAsync();
91
96
  for await (const [key, data] of entries){
@@ -98,9 +103,35 @@ import { createLogger } from '@aztec/foundation/log';
98
103
  }
99
104
  return cleanedCount;
100
105
  }
101
- /**
102
- * Closes the store.
103
- */ async close() {
106
+ /** Saves a pending L1→L2 message keyed by msgHash. */ async savePendingL1ToL2Message(msg) {
107
+ await this.pendingL1ToL2.set(msg.msgHash, JSON.stringify(msg));
108
+ this.log.info(`Saved pending L1→L2 message ${msg.msgHash}`);
109
+ }
110
+ /** Returns all unconsumed pending L1→L2 messages. */ async getUnconsumedL1ToL2Messages() {
111
+ const messages = [];
112
+ for await (const [_, data] of this.pendingL1ToL2.entriesAsync()){
113
+ messages.push(JSON.parse(data));
114
+ }
115
+ return messages;
116
+ }
117
+ /** Deletes a consumed L1→L2 message from the store. */ async deleteL1ToL2Message(msgHash) {
118
+ await this.pendingL1ToL2.delete(msgHash);
119
+ this.log.info(`Deleted consumed L1→L2 message ${msgHash}`);
120
+ }
121
+ /** Cleans up pending L1→L2 messages older than maxAgeMs. */ async cleanupOldPendingMessages(maxAgeMs = 24 * 60 * 60 * 1000) {
122
+ const now = this.dateProvider.now();
123
+ let cleanedCount = 0;
124
+ for await (const [key, data] of this.pendingL1ToL2.entriesAsync()){
125
+ const parsed = JSON.parse(data);
126
+ if (now - parsed.timestamp > maxAgeMs) {
127
+ await this.pendingL1ToL2.delete(key);
128
+ cleanedCount++;
129
+ this.log.info(`Cleaned up old pending L1→L2 message ${key}`);
130
+ }
131
+ }
132
+ return cleanedCount;
133
+ }
134
+ /** Closes the store. */ async close() {
104
135
  await this.store.close();
105
136
  this.log.info('Closed bot data store');
106
137
  }
@@ -1,2 +1,2 @@
1
- export { BotStore, type BridgeClaimData } from './bot_store.js';
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUMifQ==
1
+ export { BotStore, type BridgeClaimData, type PendingL1ToL2Message } from './bot_store.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssZUFBZSxFQUFFLEtBQUssb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQyJ9
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
package/dest/utils.js CHANGED
@@ -4,10 +4,10 @@
4
4
  * @param who - Address to get the balance for.
5
5
  * @returns - Private and public token balances as bigints.
6
6
  */ export async function getBalances(token, who, from) {
7
- const privateBalance = await token.methods.balance_of_private(who).simulate({
7
+ const { result: privateBalance } = await token.methods.balance_of_private(who).simulate({
8
8
  from: from ?? who
9
9
  });
10
- const publicBalance = await token.methods.balance_of_public(who).simulate({
10
+ const { result: publicBalance } = await token.methods.balance_of_public(who).simulate({
11
11
  from: from ?? who
12
12
  });
13
13
  return {
@@ -16,7 +16,7 @@
16
16
  };
17
17
  }
18
18
  export async function getPrivateBalance(token, who, from) {
19
- const privateBalance = await token.methods.get_balance(who).simulate({
19
+ const { result: privateBalance } = await token.methods.get_balance(who).simulate({
20
20
  from: from ?? who
21
21
  });
22
22
  return privateBalance;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/bot",
3
- "version": "0.0.1-commit.d6f2b3f94",
3
+ "version": "0.0.1-commit.db765a8",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -54,20 +54,23 @@
54
54
  ]
55
55
  },
56
56
  "dependencies": {
57
- "@aztec/accounts": "0.0.1-commit.d6f2b3f94",
58
- "@aztec/aztec.js": "0.0.1-commit.d6f2b3f94",
59
- "@aztec/entrypoints": "0.0.1-commit.d6f2b3f94",
60
- "@aztec/ethereum": "0.0.1-commit.d6f2b3f94",
61
- "@aztec/foundation": "0.0.1-commit.d6f2b3f94",
62
- "@aztec/kv-store": "0.0.1-commit.d6f2b3f94",
63
- "@aztec/noir-contracts.js": "0.0.1-commit.d6f2b3f94",
64
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.d6f2b3f94",
65
- "@aztec/protocol-contracts": "0.0.1-commit.d6f2b3f94",
66
- "@aztec/stdlib": "0.0.1-commit.d6f2b3f94",
67
- "@aztec/telemetry-client": "0.0.1-commit.d6f2b3f94",
68
- "@aztec/test-wallet": "0.0.1-commit.d6f2b3f94",
57
+ "@aztec/accounts": "0.0.1-commit.db765a8",
58
+ "@aztec/aztec.js": "0.0.1-commit.db765a8",
59
+ "@aztec/entrypoints": "0.0.1-commit.db765a8",
60
+ "@aztec/ethereum": "0.0.1-commit.db765a8",
61
+ "@aztec/foundation": "0.0.1-commit.db765a8",
62
+ "@aztec/kv-store": "0.0.1-commit.db765a8",
63
+ "@aztec/l1-artifacts": "0.0.1-commit.db765a8",
64
+ "@aztec/noir-contracts.js": "0.0.1-commit.db765a8",
65
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.db765a8",
66
+ "@aztec/noir-test-contracts.js": "0.0.1-commit.db765a8",
67
+ "@aztec/protocol-contracts": "0.0.1-commit.db765a8",
68
+ "@aztec/stdlib": "0.0.1-commit.db765a8",
69
+ "@aztec/telemetry-client": "0.0.1-commit.db765a8",
70
+ "@aztec/wallets": "0.0.1-commit.db765a8",
69
71
  "source-map-support": "^0.5.21",
70
72
  "tslib": "^2.4.0",
73
+ "viem": "npm:@aztec/viem@2.38.2",
71
74
  "zod": "^3.23.8"
72
75
  },
73
76
  "devDependencies": {
package/src/amm_bot.ts CHANGED
@@ -6,7 +6,7 @@ import { jsonStringify } from '@aztec/foundation/json-rpc';
6
6
  import type { AMMContract } from '@aztec/noir-contracts.js/AMM';
7
7
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
8
8
  import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
9
- import type { TestWallet } from '@aztec/test-wallet/server';
9
+ import type { EmbeddedWallet } from '@aztec/wallets/embedded';
10
10
 
11
11
  import { BaseBot } from './base_bot.js';
12
12
  import type { BotConfig } from './config.js';
@@ -21,7 +21,7 @@ type Balances = { token0: bigint; token1: bigint };
21
21
  export class AmmBot extends BaseBot {
22
22
  protected constructor(
23
23
  node: AztecNode,
24
- wallet: TestWallet,
24
+ wallet: EmbeddedWallet,
25
25
  defaultAccountAddress: AztecAddress,
26
26
  public readonly amm: AMMContract,
27
27
  public readonly token0: TokenContract,
@@ -33,7 +33,7 @@ export class AmmBot extends BaseBot {
33
33
 
34
34
  static async create(
35
35
  config: BotConfig,
36
- wallet: TestWallet,
36
+ wallet: EmbeddedWallet,
37
37
  aztecNode: AztecNode,
38
38
  aztecNodeAdmin: AztecNodeAdmin | undefined,
39
39
  store: BotStore,
@@ -71,12 +71,14 @@ export class AmmBot extends BaseBot {
71
71
  .getFunctionCall(),
72
72
  });
73
73
 
74
- const amountOutMin = await amm.methods
75
- .get_amount_out_for_exact_in(
76
- await tokenIn.methods.balance_of_public(amm.address).simulate({ from: this.defaultAccountAddress }),
77
- await tokenOut.methods.balance_of_public(amm.address).simulate({ from: this.defaultAccountAddress }),
78
- amountIn,
79
- )
74
+ const { result: tokenInBalance } = await tokenIn.methods
75
+ .balance_of_public(amm.address)
76
+ .simulate({ from: this.defaultAccountAddress });
77
+ const { result: tokenOutBalance } = await tokenOut.methods
78
+ .balance_of_public(amm.address)
79
+ .simulate({ from: this.defaultAccountAddress });
80
+ const { result: amountOutMin } = await amm.methods
81
+ .get_amount_out_for_exact_in(tokenInBalance, tokenOutBalance, amountIn)
80
82
  .simulate({ from: this.defaultAccountAddress });
81
83
 
82
84
  const swapExactTokensInteraction = amm.methods
@@ -89,7 +91,8 @@ export class AmmBot extends BaseBot {
89
91
 
90
92
  this.log.verbose(`Sending transaction`, logCtx);
91
93
  this.log.info(`Tx. Balances: ${jsonStringify(balances)}`, { ...logCtx, balances });
92
- return swapExactTokensInteraction.send({ ...opts, wait: NO_WAIT });
94
+ const { txHash } = await swapExactTokensInteraction.send({ ...opts, wait: NO_WAIT });
95
+ return txHash;
93
96
  }
94
97
 
95
98
  protected override async onTxMined(receipt: TxReceipt, logCtx: object): Promise<void> {
@@ -110,15 +113,17 @@ export class AmmBot extends BaseBot {
110
113
  }
111
114
 
112
115
  private async getPublicBalanceFor(address: AztecAddress, from?: AztecAddress): Promise<Balances> {
113
- return {
114
- token0: await this.token0.methods.balance_of_public(address).simulate({ from: from ?? address }),
115
- token1: await this.token1.methods.balance_of_public(address).simulate({ from: from ?? address }),
116
- };
116
+ const { result: token0 } = await this.token0.methods.balance_of_public(address).simulate({ from: from ?? address });
117
+ const { result: token1 } = await this.token1.methods.balance_of_public(address).simulate({ from: from ?? address });
118
+ return { token0, token1 };
117
119
  }
118
120
  private async getPrivateBalanceFor(address: AztecAddress, from?: AztecAddress): Promise<Balances> {
119
- return {
120
- token0: await this.token0.methods.balance_of_private(address).simulate({ from: from ?? address }),
121
- token1: await this.token1.methods.balance_of_private(address).simulate({ from: from ?? address }),
122
- };
121
+ const { result: token0 } = await this.token0.methods
122
+ .balance_of_private(address)
123
+ .simulate({ from: from ?? address });
124
+ const { result: token1 } = await this.token1.methods
125
+ .balance_of_private(address)
126
+ .simulate({ from: from ?? address });
127
+ return { token0, token1 };
123
128
  }
124
129
  }
package/src/base_bot.ts CHANGED
@@ -1,16 +1,11 @@
1
1
  import { AztecAddress } from '@aztec/aztec.js/addresses';
2
- import {
3
- BatchCall,
4
- ContractFunctionInteraction,
5
- type SendInteractionOptions,
6
- waitForProven,
7
- } from '@aztec/aztec.js/contracts';
2
+ import { BatchCall, ContractFunctionInteraction, type SendInteractionOptions } from '@aztec/aztec.js/contracts';
8
3
  import { createLogger } from '@aztec/aztec.js/log';
9
4
  import { waitForTx } from '@aztec/aztec.js/node';
10
- import { TxHash, TxReceipt } from '@aztec/aztec.js/tx';
5
+ import { TxHash, TxReceipt, TxStatus } from '@aztec/aztec.js/tx';
11
6
  import { Gas } from '@aztec/stdlib/gas';
12
7
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
13
- import type { TestWallet } from '@aztec/test-wallet/server';
8
+ import type { EmbeddedWallet } from '@aztec/wallets/embedded';
14
9
 
15
10
  import type { BotConfig } from './config.js';
16
11
 
@@ -22,15 +17,15 @@ export abstract class BaseBot {
22
17
 
23
18
  protected constructor(
24
19
  public readonly node: AztecNode,
25
- public readonly wallet: TestWallet,
20
+ public readonly wallet: EmbeddedWallet,
26
21
  public readonly defaultAccountAddress: AztecAddress,
27
22
  public config: BotConfig,
28
23
  ) {}
29
24
 
30
25
  public async run(): Promise<TxReceipt | TxHash> {
31
26
  this.attempts++;
32
- const logCtx = { runId: Date.now() * 1000 + Math.floor(Math.random() * 1000) };
33
27
  const { followChain, txMinedWaitSeconds } = this.config;
28
+ const logCtx = { runId: Date.now() * 1000 + Math.floor(Math.random() * 1000), followChain, txMinedWaitSeconds };
34
29
 
35
30
  this.log.verbose(`Creating tx`, logCtx);
36
31
  const txHash = await this.createAndSendTx(logCtx);
@@ -40,14 +35,9 @@ export abstract class BaseBot {
40
35
  return txHash;
41
36
  }
42
37
 
43
- this.log.verbose(
44
- `Awaiting tx ${txHash.toString()} to be on the ${followChain} chain (timeout ${txMinedWaitSeconds}s)`,
45
- logCtx,
46
- );
47
- const receipt = await waitForTx(this.node, txHash, { timeout: txMinedWaitSeconds });
48
- if (followChain === 'PROVEN') {
49
- await waitForProven(this.node, receipt, { provenTimeout: txMinedWaitSeconds });
50
- }
38
+ const waitForStatus = TxStatus[followChain];
39
+ this.log.verbose(`Awaiting tx ${txHash.toString()} to be on the ${followChain} chain`, logCtx);
40
+ const receipt = await waitForTx(this.node, txHash, { timeout: txMinedWaitSeconds, waitForStatus });
51
41
  this.successes++;
52
42
  this.log.info(
53
43
  `Tx #${this.attempts} ${receipt.txHash} successfully mined in block ${receipt.blockNumber} (stats: ${this.successes}/${this.attempts} success)`,
package/src/bot.ts CHANGED
@@ -5,7 +5,7 @@ import { times } from '@aztec/foundation/collection';
5
5
  import type { PrivateTokenContract } from '@aztec/noir-contracts.js/PrivateToken';
6
6
  import type { TokenContract } from '@aztec/noir-contracts.js/Token';
7
7
  import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
8
- import type { TestWallet } from '@aztec/test-wallet/server';
8
+ import type { EmbeddedWallet } from '@aztec/wallets/embedded';
9
9
 
10
10
  import { BaseBot } from './base_bot.js';
11
11
  import type { BotConfig } from './config.js';
@@ -18,7 +18,7 @@ const TRANSFER_AMOUNT = 1;
18
18
  export class Bot extends BaseBot {
19
19
  protected constructor(
20
20
  node: AztecNode,
21
- wallet: TestWallet,
21
+ wallet: EmbeddedWallet,
22
22
  defaultAccountAddress: AztecAddress,
23
23
  public readonly token: TokenContract | PrivateTokenContract,
24
24
  public readonly recipient: AztecAddress,
@@ -29,7 +29,7 @@ export class Bot extends BaseBot {
29
29
 
30
30
  static async create(
31
31
  config: BotConfig,
32
- wallet: TestWallet,
32
+ wallet: EmbeddedWallet,
33
33
  aztecNode: AztecNode,
34
34
  aztecNodeAdmin: AztecNodeAdmin | undefined,
35
35
  store: BotStore,
@@ -76,14 +76,15 @@ export class Bot extends BaseBot {
76
76
  await batch.simulate({ from: this.defaultAccountAddress });
77
77
 
78
78
  this.log.verbose(`Sending transaction`, logCtx);
79
- return batch.send({ ...opts, wait: NO_WAIT });
79
+ const { txHash } = await batch.send({ ...opts, wait: NO_WAIT });
80
+ return txHash;
80
81
  }
81
82
 
82
83
  public async getBalances() {
83
84
  if (isStandardTokenContract(this.token)) {
84
85
  return {
85
86
  sender: await getBalances(this.token, this.defaultAccountAddress),
86
- recipient: await getBalances(this.token, this.recipient, this.defaultAccountAddress),
87
+ recipient: await getBalances(this.token, this.recipient),
87
88
  };
88
89
  } else {
89
90
  return {
@@ -92,7 +93,7 @@ export class Bot extends BaseBot {
92
93
  publicBalance: 0n,
93
94
  },
94
95
  recipient: {
95
- privateBalance: await getPrivateBalance(this.token, this.recipient, this.defaultAccountAddress),
96
+ privateBalance: await getPrivateBalance(this.token, this.recipient),
96
97
  publicBalance: 0n,
97
98
  },
98
99
  };
package/src/config.ts CHANGED
@@ -19,9 +19,12 @@ import type { ComponentsVersions } from '@aztec/stdlib/versioning';
19
19
 
20
20
  import { z } from 'zod';
21
21
 
22
- const BotFollowChain = ['NONE', 'PENDING', 'PROVEN'] as const;
22
+ const BotFollowChain = ['NONE', 'PROPOSED', 'CHECKPOINTED', 'PROVEN'] as const;
23
23
  type BotFollowChain = (typeof BotFollowChain)[number];
24
24
 
25
+ const BotMode = ['transfer', 'amm', 'crosschain'] as const;
26
+ type BotMode = (typeof BotMode)[number];
27
+
25
28
  export enum SupportedTokenContracts {
26
29
  TokenContract = 'TokenContract',
27
30
  PrivateTokenContract = 'PrivateTokenContract',
@@ -76,8 +79,12 @@ export type BotConfig = {
76
79
  maxConsecutiveErrors: number;
77
80
  /** Stops the bot if service becomes unhealthy */
78
81
  stopWhenUnhealthy: boolean;
79
- /** Deploy an AMM contract and do swaps instead of transfers */
80
- ammTxs: boolean;
82
+ /** Bot mode: transfer, amm, or crosschain. */
83
+ botMode: BotMode;
84
+ /** Number of L2→L1 messages per tx (crosschain mode). */
85
+ l2ToL1MessagesPerTx: number;
86
+ /** Max L1→L2 messages to keep in-flight (crosschain mode). */
87
+ l1ToL2SeedCount: number;
81
88
  } & Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKb'>;
82
89
 
83
90
  export const BotConfigSchema = zodFor<BotConfig>()(
@@ -107,7 +114,9 @@ export const BotConfigSchema = zodFor<BotConfig>()(
107
114
  contract: z.nativeEnum(SupportedTokenContracts),
108
115
  maxConsecutiveErrors: z.number().int().nonnegative(),
109
116
  stopWhenUnhealthy: z.boolean(),
110
- ammTxs: z.boolean().default(false),
117
+ botMode: z.enum(BotMode).default('transfer'),
118
+ l2ToL1MessagesPerTx: z.number().int().nonnegative().default(1),
119
+ l1ToL2SeedCount: z.number().int().nonnegative().default(1),
111
120
  dataDirectory: z.string().optional(),
112
121
  dataStoreMapSizeKb: z.number().optional(),
113
122
  })
@@ -213,10 +222,14 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
213
222
  description: 'Which chain the bot follows',
214
223
  defaultValue: 'NONE',
215
224
  parseEnv(val) {
216
- if (!(BotFollowChain as readonly string[]).includes(val.toUpperCase())) {
225
+ const upper = val.toUpperCase();
226
+ if (upper === 'PENDING') {
227
+ return 'CHECKPOINTED';
228
+ }
229
+ if (!(BotFollowChain as readonly string[]).includes(upper)) {
217
230
  throw new Error(`Invalid value for BOT_FOLLOW_CHAIN: ${val}`);
218
231
  }
219
- return val as BotFollowChain;
232
+ return upper as BotFollowChain;
220
233
  },
221
234
  },
222
235
  maxPendingTxs: {
@@ -264,10 +277,26 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
264
277
  description: 'Stops the bot if service becomes unhealthy',
265
278
  ...booleanConfigHelper(false),
266
279
  },
267
- ammTxs: {
268
- env: 'BOT_AMM_TXS',
269
- description: 'Deploy an AMM and send swaps to it',
270
- ...booleanConfigHelper(false),
280
+ botMode: {
281
+ env: 'BOT_MODE',
282
+ description: 'Bot mode: transfer, amm, or crosschain',
283
+ defaultValue: 'transfer' as BotMode,
284
+ parseEnv(val: string) {
285
+ if (!(BotMode as readonly string[]).includes(val)) {
286
+ throw new Error(`Invalid value for BOT_MODE: ${val}`);
287
+ }
288
+ return val as BotMode;
289
+ },
290
+ },
291
+ l2ToL1MessagesPerTx: {
292
+ env: 'BOT_L2_TO_L1_MESSAGES_PER_TX',
293
+ description: 'Number of L2→L1 messages per tx (crosschain mode)',
294
+ ...numberConfigHelper(1),
295
+ },
296
+ l1ToL2SeedCount: {
297
+ env: 'BOT_L1_TO_L2_SEED_COUNT',
298
+ description: 'Max L1→L2 messages to keep in-flight (crosschain mode)',
299
+ ...numberConfigHelper(1),
271
300
  },
272
301
  ...pickConfigMappings(dataConfigMappings, ['dataStoreMapSizeKb', 'dataDirectory']),
273
302
  };