@wopr-network/platform-core 1.67.0 → 1.68.0

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 (140) hide show
  1. package/dist/auth/better-auth.js +7 -0
  2. package/dist/billing/crypto/btc/checkout.d.ts +4 -0
  3. package/dist/billing/crypto/btc/checkout.js +1 -2
  4. package/dist/billing/crypto/btc/index.d.ts +0 -4
  5. package/dist/billing/crypto/btc/index.js +0 -2
  6. package/dist/billing/crypto/evm/__tests__/checkout.test.js +8 -11
  7. package/dist/billing/crypto/evm/__tests__/eth-checkout.test.js +15 -1
  8. package/dist/billing/crypto/evm/checkout.d.ts +2 -0
  9. package/dist/billing/crypto/evm/checkout.js +1 -2
  10. package/dist/billing/crypto/evm/eth-checkout.d.ts +13 -2
  11. package/dist/billing/crypto/evm/eth-checkout.js +2 -4
  12. package/dist/billing/crypto/evm/eth-settler.d.ts +1 -1
  13. package/dist/billing/crypto/evm/index.d.ts +2 -8
  14. package/dist/billing/crypto/evm/index.js +0 -3
  15. package/dist/billing/crypto/evm/types.d.ts +16 -0
  16. package/dist/billing/crypto/index.d.ts +1 -6
  17. package/dist/billing/crypto/index.js +2 -3
  18. package/dist/billing/crypto/types.d.ts +0 -43
  19. package/dist/billing/crypto/types.js +1 -24
  20. package/dist/email/client.js +16 -0
  21. package/package.json +4 -7
  22. package/src/auth/better-auth.ts +8 -0
  23. package/src/billing/crypto/btc/checkout.ts +3 -2
  24. package/src/billing/crypto/btc/index.ts +0 -4
  25. package/src/billing/crypto/evm/__tests__/checkout.test.ts +10 -12
  26. package/src/billing/crypto/evm/__tests__/eth-checkout.test.ts +17 -1
  27. package/src/billing/crypto/evm/__tests__/eth-settler.test.ts +1 -1
  28. package/src/billing/crypto/evm/checkout.ts +3 -2
  29. package/src/billing/crypto/evm/eth-checkout.ts +15 -6
  30. package/src/billing/crypto/evm/eth-settler.ts +1 -1
  31. package/src/billing/crypto/evm/index.ts +8 -7
  32. package/src/billing/crypto/evm/types.ts +17 -0
  33. package/src/billing/crypto/index.ts +14 -12
  34. package/src/billing/crypto/types.ts +0 -63
  35. package/src/email/client.ts +18 -0
  36. package/dist/billing/crypto/__tests__/address-gen.test.d.ts +0 -1
  37. package/dist/billing/crypto/__tests__/address-gen.test.js +0 -219
  38. package/dist/billing/crypto/__tests__/key-server.test.d.ts +0 -1
  39. package/dist/billing/crypto/__tests__/key-server.test.js +0 -742
  40. package/dist/billing/crypto/__tests__/watcher-service.test.d.ts +0 -1
  41. package/dist/billing/crypto/__tests__/watcher-service.test.js +0 -174
  42. package/dist/billing/crypto/address-gen.d.ts +0 -24
  43. package/dist/billing/crypto/address-gen.js +0 -176
  44. package/dist/billing/crypto/btc/__tests__/watcher.test.d.ts +0 -1
  45. package/dist/billing/crypto/btc/__tests__/watcher.test.js +0 -170
  46. package/dist/billing/crypto/btc/watcher.d.ts +0 -44
  47. package/dist/billing/crypto/btc/watcher.js +0 -118
  48. package/dist/billing/crypto/evm/__tests__/eth-watcher.test.d.ts +0 -1
  49. package/dist/billing/crypto/evm/__tests__/eth-watcher.test.js +0 -167
  50. package/dist/billing/crypto/evm/__tests__/watcher-confirmations.test.d.ts +0 -1
  51. package/dist/billing/crypto/evm/__tests__/watcher-confirmations.test.js +0 -159
  52. package/dist/billing/crypto/evm/__tests__/watcher.test.d.ts +0 -1
  53. package/dist/billing/crypto/evm/__tests__/watcher.test.js +0 -145
  54. package/dist/billing/crypto/evm/eth-watcher.d.ts +0 -66
  55. package/dist/billing/crypto/evm/eth-watcher.js +0 -121
  56. package/dist/billing/crypto/evm/watcher.d.ts +0 -51
  57. package/dist/billing/crypto/evm/watcher.js +0 -156
  58. package/dist/billing/crypto/key-server-entry.d.ts +0 -1
  59. package/dist/billing/crypto/key-server-entry.js +0 -122
  60. package/dist/billing/crypto/key-server.d.ts +0 -32
  61. package/dist/billing/crypto/key-server.js +0 -472
  62. package/dist/billing/crypto/oracle/__tests__/chainlink.test.d.ts +0 -1
  63. package/dist/billing/crypto/oracle/__tests__/chainlink.test.js +0 -83
  64. package/dist/billing/crypto/oracle/__tests__/coingecko.test.d.ts +0 -1
  65. package/dist/billing/crypto/oracle/__tests__/coingecko.test.js +0 -65
  66. package/dist/billing/crypto/oracle/__tests__/composite.test.d.ts +0 -1
  67. package/dist/billing/crypto/oracle/__tests__/composite.test.js +0 -48
  68. package/dist/billing/crypto/oracle/__tests__/convert.test.d.ts +0 -1
  69. package/dist/billing/crypto/oracle/__tests__/convert.test.js +0 -61
  70. package/dist/billing/crypto/oracle/__tests__/fixed.test.d.ts +0 -1
  71. package/dist/billing/crypto/oracle/__tests__/fixed.test.js +0 -20
  72. package/dist/billing/crypto/oracle/chainlink.d.ts +0 -26
  73. package/dist/billing/crypto/oracle/chainlink.js +0 -62
  74. package/dist/billing/crypto/oracle/coingecko.d.ts +0 -22
  75. package/dist/billing/crypto/oracle/coingecko.js +0 -71
  76. package/dist/billing/crypto/oracle/composite.d.ts +0 -14
  77. package/dist/billing/crypto/oracle/composite.js +0 -34
  78. package/dist/billing/crypto/oracle/convert.d.ts +0 -30
  79. package/dist/billing/crypto/oracle/convert.js +0 -51
  80. package/dist/billing/crypto/oracle/fixed.d.ts +0 -10
  81. package/dist/billing/crypto/oracle/fixed.js +0 -22
  82. package/dist/billing/crypto/oracle/index.d.ts +0 -9
  83. package/dist/billing/crypto/oracle/index.js +0 -6
  84. package/dist/billing/crypto/oracle/types.d.ts +0 -22
  85. package/dist/billing/crypto/oracle/types.js +0 -7
  86. package/dist/billing/crypto/plugin/__tests__/integration.test.d.ts +0 -1
  87. package/dist/billing/crypto/plugin/__tests__/integration.test.js +0 -58
  88. package/dist/billing/crypto/plugin/__tests__/interfaces.test.d.ts +0 -1
  89. package/dist/billing/crypto/plugin/__tests__/interfaces.test.js +0 -46
  90. package/dist/billing/crypto/plugin/__tests__/registry.test.d.ts +0 -1
  91. package/dist/billing/crypto/plugin/__tests__/registry.test.js +0 -49
  92. package/dist/billing/crypto/plugin/index.d.ts +0 -2
  93. package/dist/billing/crypto/plugin/index.js +0 -1
  94. package/dist/billing/crypto/plugin/interfaces.d.ts +0 -97
  95. package/dist/billing/crypto/plugin/interfaces.js +0 -2
  96. package/dist/billing/crypto/plugin/registry.d.ts +0 -8
  97. package/dist/billing/crypto/plugin/registry.js +0 -21
  98. package/dist/billing/crypto/plugin-watcher-service.d.ts +0 -32
  99. package/dist/billing/crypto/plugin-watcher-service.js +0 -113
  100. package/dist/billing/crypto/tron/__tests__/address-convert.test.d.ts +0 -1
  101. package/dist/billing/crypto/tron/__tests__/address-convert.test.js +0 -55
  102. package/dist/billing/crypto/tron/address-convert.d.ts +0 -14
  103. package/dist/billing/crypto/tron/address-convert.js +0 -93
  104. package/dist/billing/crypto/watcher-service.d.ts +0 -55
  105. package/dist/billing/crypto/watcher-service.js +0 -438
  106. package/src/billing/crypto/__tests__/address-gen.test.ts +0 -264
  107. package/src/billing/crypto/__tests__/key-server.test.ts +0 -823
  108. package/src/billing/crypto/__tests__/watcher-service.test.ts +0 -242
  109. package/src/billing/crypto/address-gen.ts +0 -185
  110. package/src/billing/crypto/btc/__tests__/watcher.test.ts +0 -201
  111. package/src/billing/crypto/btc/watcher.ts +0 -161
  112. package/src/billing/crypto/evm/__tests__/eth-watcher.test.ts +0 -190
  113. package/src/billing/crypto/evm/__tests__/watcher-confirmations.test.ts +0 -191
  114. package/src/billing/crypto/evm/__tests__/watcher.test.ts +0 -167
  115. package/src/billing/crypto/evm/eth-watcher.ts +0 -182
  116. package/src/billing/crypto/evm/watcher.ts +0 -204
  117. package/src/billing/crypto/key-server-entry.ts +0 -144
  118. package/src/billing/crypto/key-server.ts +0 -617
  119. package/src/billing/crypto/oracle/__tests__/chainlink.test.ts +0 -107
  120. package/src/billing/crypto/oracle/__tests__/coingecko.test.ts +0 -75
  121. package/src/billing/crypto/oracle/__tests__/composite.test.ts +0 -61
  122. package/src/billing/crypto/oracle/__tests__/convert.test.ts +0 -74
  123. package/src/billing/crypto/oracle/__tests__/fixed.test.ts +0 -23
  124. package/src/billing/crypto/oracle/chainlink.ts +0 -86
  125. package/src/billing/crypto/oracle/coingecko.ts +0 -96
  126. package/src/billing/crypto/oracle/composite.ts +0 -35
  127. package/src/billing/crypto/oracle/convert.ts +0 -53
  128. package/src/billing/crypto/oracle/fixed.ts +0 -25
  129. package/src/billing/crypto/oracle/index.ts +0 -9
  130. package/src/billing/crypto/oracle/types.ts +0 -28
  131. package/src/billing/crypto/plugin/__tests__/integration.test.ts +0 -64
  132. package/src/billing/crypto/plugin/__tests__/interfaces.test.ts +0 -51
  133. package/src/billing/crypto/plugin/__tests__/registry.test.ts +0 -58
  134. package/src/billing/crypto/plugin/index.ts +0 -17
  135. package/src/billing/crypto/plugin/interfaces.ts +0 -106
  136. package/src/billing/crypto/plugin/registry.ts +0 -26
  137. package/src/billing/crypto/plugin-watcher-service.ts +0 -148
  138. package/src/billing/crypto/tron/__tests__/address-convert.test.ts +0 -67
  139. package/src/billing/crypto/tron/address-convert.ts +0 -89
  140. package/src/billing/crypto/watcher-service.ts +0 -549
@@ -194,6 +194,13 @@ function authOptions(cfg) {
194
194
  }
195
195
  if (user.emailVerified)
196
196
  return;
197
+ if (process.env.SKIP_EMAIL_VERIFICATION === "true") {
198
+ // raw SQL: better-auth manages the "user" table schema; Drizzle schema is not available in this auth hook context
199
+ await pool.query('UPDATE "user" SET "emailVerified" = true WHERE id = $1', [user.id]);
200
+ user.emailVerified = true;
201
+ logger.info("Email verification skipped (SKIP_EMAIL_VERIFICATION=true)", { userId: user.id });
202
+ return;
203
+ }
197
204
  try {
198
205
  await initVerificationSchema(pool);
199
206
  const { token } = await generateVerificationToken(pool, user.id);
@@ -3,6 +3,10 @@ import type { BtcCheckoutOpts } from "./types.js";
3
3
  export declare const MIN_BTC_USD = 10;
4
4
  export interface BtcCheckoutDeps {
5
5
  chargeStore: Pick<ICryptoChargeRepository, "getNextDerivationIndex" | "createStablecoinCharge">;
6
+ /** HD key derivation function — injected from @wopr-network/platform-crypto-server. */
7
+ deriveAddress: (xpub: string, index: number, encoding: string, params?: {
8
+ hrp?: string;
9
+ }) => string;
6
10
  xpub: string;
7
11
  network?: "mainnet" | "testnet" | "regtest";
8
12
  }
@@ -1,5 +1,4 @@
1
1
  import { Credit } from "../../../credits/credit.js";
2
- import { deriveAddress } from "../address-gen.js";
3
2
  export const MIN_BTC_USD = 10;
4
3
  /**
5
4
  * Create a BTC checkout — derive a unique deposit address, store the charge.
@@ -18,7 +17,7 @@ export async function createBtcCheckout(deps, opts) {
18
17
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
19
18
  const derivationIndex = await deps.chargeStore.getNextDerivationIndex();
20
19
  const hrpMap = { mainnet: "bc", testnet: "tb", regtest: "bcrt" };
21
- const depositAddress = deriveAddress(deps.xpub, derivationIndex, "bech32", {
20
+ const depositAddress = deps.deriveAddress(deps.xpub, derivationIndex, "bech32", {
22
21
  hrp: hrpMap[network],
23
22
  });
24
23
  const referenceId = `btc:${depositAddress}`;
@@ -1,10 +1,6 @@
1
- export type { EncodingParams } from "../address-gen.js";
2
- export { deriveAddress, deriveTreasury, isValidXpub } from "../address-gen.js";
3
1
  export type { BtcCheckoutDeps, BtcCheckoutResult } from "./checkout.js";
4
2
  export { createBtcCheckout, MIN_BTC_USD } from "./checkout.js";
5
3
  export { centsToSats, loadBitcoindConfig, satsToCents } from "./config.js";
6
4
  export type { BtcSettlerDeps } from "./settler.js";
7
5
  export { settleBtcPayment } from "./settler.js";
8
6
  export type { BitcoindConfig, BtcCheckoutOpts, BtcPaymentEvent } from "./types.js";
9
- export type { BtcWatcherOpts } from "./watcher.js";
10
- export { BtcWatcher, createBitcoindRpc } from "./watcher.js";
@@ -1,5 +1,3 @@
1
- export { deriveAddress, deriveTreasury, isValidXpub } from "../address-gen.js";
2
1
  export { createBtcCheckout, MIN_BTC_USD } from "./checkout.js";
3
2
  export { centsToSats, loadBitcoindConfig, satsToCents } from "./config.js";
4
3
  export { settleBtcPayment } from "./settler.js";
5
- export { BtcWatcher, createBitcoindRpc } from "./watcher.js";
@@ -1,20 +1,17 @@
1
- import { HDKey } from "@scure/bip32";
2
1
  import { describe, expect, it, vi } from "vitest";
3
2
  import { createStablecoinCheckout } from "../checkout.js";
4
- function makeTestXpub() {
5
- const seed = new Uint8Array(32);
6
- seed[0] = 1;
7
- const master = HDKey.fromMasterSeed(seed);
8
- return master.derive("m/44'/60'/0'").publicExtendedKey;
3
+ const TEST_XPUB = "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8";
4
+ /** Deterministic mock returns a valid-looking EVM address for any index. */
5
+ function mockDeriveAddress(_xpub, index, _encoding) {
6
+ return `0x${index.toString(16).padStart(40, "0")}`;
9
7
  }
10
- const TEST_XPUB = makeTestXpub();
11
8
  describe("createStablecoinCheckout", () => {
12
9
  it("derives address and creates charge", async () => {
13
10
  const mockChargeStore = {
14
11
  getNextDerivationIndex: vi.fn().mockResolvedValue(42),
15
12
  createStablecoinCharge: vi.fn().mockResolvedValue(undefined),
16
13
  };
17
- const result = await createStablecoinCheckout({ chargeStore: mockChargeStore, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 10, chain: "base", token: "USDC" });
14
+ const result = await createStablecoinCheckout({ chargeStore: mockChargeStore, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 10, chain: "base", token: "USDC" });
18
15
  expect(result.depositAddress).toMatch(/^0x[0-9a-fA-F]{40}$/);
19
16
  expect(result.amountRaw).toBe("10000000"); // 10 USDC = 10 * 10^6
20
17
  expect(result.chain).toBe("base");
@@ -30,14 +27,14 @@ describe("createStablecoinCheckout", () => {
30
27
  getNextDerivationIndex: vi.fn().mockResolvedValue(0),
31
28
  createStablecoinCharge: vi.fn().mockResolvedValue(undefined),
32
29
  };
33
- await expect(createStablecoinCheckout({ chargeStore: mockChargeStore, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 5, chain: "base", token: "USDC" })).rejects.toThrow("Minimum");
30
+ await expect(createStablecoinCheckout({ chargeStore: mockChargeStore, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 5, chain: "base", token: "USDC" })).rejects.toThrow("Minimum");
34
31
  });
35
32
  it("stores deposit address in lowercase", async () => {
36
33
  const mockChargeStore = {
37
34
  getNextDerivationIndex: vi.fn().mockResolvedValue(0),
38
35
  createStablecoinCharge: vi.fn().mockResolvedValue(undefined),
39
36
  };
40
- await createStablecoinCheckout({ chargeStore: mockChargeStore, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 10, chain: "base", token: "USDC" });
37
+ await createStablecoinCheckout({ chargeStore: mockChargeStore, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 10, chain: "base", token: "USDC" });
41
38
  const chargeInput = mockChargeStore.createStablecoinCharge.mock.calls[0][0];
42
39
  expect(chargeInput.depositAddress).toBe(chargeInput.depositAddress.toLowerCase());
43
40
  });
@@ -46,7 +43,7 @@ describe("createStablecoinCheckout", () => {
46
43
  getNextDerivationIndex: vi.fn().mockResolvedValue(0),
47
44
  createStablecoinCharge: vi.fn().mockResolvedValue(undefined),
48
45
  };
49
- const result = await createStablecoinCheckout({ chargeStore: mockChargeStore, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 25, chain: "base", token: "USDC" });
46
+ const result = await createStablecoinCheckout({ chargeStore: mockChargeStore, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB }, { tenant: "t1", amountUsd: 25, chain: "base", token: "USDC" });
50
47
  expect(result.amountRaw).toBe("25000000"); // 25 * 10^6
51
48
  const chargeInput = mockChargeStore.createStablecoinCharge.mock.calls[0][0];
52
49
  expect(chargeInput.amountUsdCents).toBe(2500);
@@ -1,6 +1,18 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
2
  import { createEthCheckout, MIN_ETH_USD } from "../eth-checkout.js";
3
3
  const mockOracle = { getPrice: vi.fn().mockResolvedValue({ priceMicros: 3_500_000_000, updatedAt: new Date() }) };
4
+ /** Deterministic mock — returns a valid-looking EVM address for any index. */
5
+ function mockDeriveAddress(_xpub, index, _encoding) {
6
+ return `0x${index.toString(16).padStart(40, "0")}`;
7
+ }
8
+ /**
9
+ * centsToNative: Convert USD cents to native token base units.
10
+ * Formula: (cents * 10_000 * 10^decimals) / priceMicros
11
+ * This mirrors the real oracle/convert.ts logic.
12
+ */
13
+ function mockCentsToNative(cents, priceMicros, decimals) {
14
+ return (BigInt(cents) * 10000n * 10n ** BigInt(decimals)) / BigInt(priceMicros);
15
+ }
4
16
  function makeDeps(derivationIndex = 0) {
5
17
  return {
6
18
  chargeStore: {
@@ -8,6 +20,8 @@ function makeDeps(derivationIndex = 0) {
8
20
  createStablecoinCharge: vi.fn().mockResolvedValue(undefined),
9
21
  },
10
22
  oracle: mockOracle,
23
+ deriveAddress: mockDeriveAddress,
24
+ centsToNative: mockCentsToNative,
11
25
  xpub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
12
26
  };
13
27
  }
@@ -18,7 +32,7 @@ describe("createEthCheckout", () => {
18
32
  expect(result.amountUsd).toBe(50);
19
33
  expect(result.priceMicros).toBe(3_500_000_000);
20
34
  expect(result.chain).toBe("base");
21
- // $50 = 5000 cents × 10000 micros/cent × 10^18 / 3_500_000_000 micros = 14285714285714285n
35
+ // $50 = 5000 cents * 10000 micros/cent * 10^18 / 3_500_000_000 micros = 14285714285714285n
22
36
  expect(result.expectedWei).toBe("14285714285714285");
23
37
  expect(result.depositAddress).toMatch(/^0x/);
24
38
  expect(result.referenceId).toMatch(/^eth:base:0x/);
@@ -3,6 +3,8 @@ import type { StablecoinCheckoutOpts } from "./types.js";
3
3
  export declare const MIN_STABLECOIN_USD = 10;
4
4
  export interface StablecoinCheckoutDeps {
5
5
  chargeStore: Pick<ICryptoChargeRepository, "getNextDerivationIndex" | "createStablecoinCharge">;
6
+ /** HD key derivation function — injected from @wopr-network/platform-crypto-server. */
7
+ deriveAddress: (xpub: string, index: number, encoding: string) => string;
6
8
  xpub: string;
7
9
  }
8
10
  export interface StablecoinCheckoutResult {
@@ -1,5 +1,4 @@
1
1
  import { Credit } from "../../../credits/credit.js";
2
- import { deriveAddress } from "../address-gen.js";
3
2
  import { getTokenConfig, tokenAmountFromCents } from "./config.js";
4
3
  export const MIN_STABLECOIN_USD = 10;
5
4
  /**
@@ -23,7 +22,7 @@ export async function createStablecoinCheckout(deps, opts) {
23
22
  const maxRetries = 3;
24
23
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
25
24
  const derivationIndex = await deps.chargeStore.getNextDerivationIndex();
26
- const depositAddress = deriveAddress(deps.xpub, derivationIndex, "evm");
25
+ const depositAddress = deps.deriveAddress(deps.xpub, derivationIndex, "evm");
27
26
  const referenceId = `sc:${opts.chain}:${opts.token.toLowerCase()}:${depositAddress.toLowerCase()}`;
28
27
  try {
29
28
  await deps.chargeStore.createStablecoinCharge({
@@ -1,10 +1,21 @@
1
1
  import type { ICryptoChargeRepository } from "../charge-store.js";
2
- import type { IPriceOracle } from "../oracle/types.js";
3
2
  import type { EvmChain } from "./types.js";
4
3
  export declare const MIN_ETH_USD = 10;
4
+ /** Price oracle interface — injected from @wopr-network/platform-crypto-server. */
5
+ export interface EthPriceOracle {
6
+ getPrice(asset: string): Promise<{
7
+ priceMicros: number;
8
+ }>;
9
+ }
10
+ /** Convert USD cents to native token base units (e.g. wei for ETH). */
11
+ export type CentsToNativeFn = (cents: number, priceMicros: number, decimals: number) => bigint;
5
12
  export interface EthCheckoutDeps {
6
13
  chargeStore: Pick<ICryptoChargeRepository, "getNextDerivationIndex" | "createStablecoinCharge">;
7
- oracle: IPriceOracle;
14
+ oracle: EthPriceOracle;
15
+ /** HD key derivation function — injected from @wopr-network/platform-crypto-server. */
16
+ deriveAddress: (xpub: string, index: number, encoding: string) => string;
17
+ /** Convert cents to native base units — injected from @wopr-network/platform-crypto-server. */
18
+ centsToNative: CentsToNativeFn;
8
19
  xpub: string;
9
20
  }
10
21
  export interface EthCheckoutOpts {
@@ -1,6 +1,4 @@
1
1
  import { Credit } from "../../../credits/credit.js";
2
- import { deriveAddress } from "../address-gen.js";
3
- import { centsToNative } from "../oracle/convert.js";
4
2
  export const MIN_ETH_USD = 10;
5
3
  /**
6
4
  * Create an ETH checkout — derive deposit address, lock price, store charge.
@@ -17,11 +15,11 @@ export async function createEthCheckout(deps, opts) {
17
15
  }
18
16
  const amountUsdCents = Credit.fromDollars(opts.amountUsd).toCentsRounded();
19
17
  const { priceMicros } = await deps.oracle.getPrice("ETH");
20
- const expectedWei = centsToNative(amountUsdCents, priceMicros, 18);
18
+ const expectedWei = deps.centsToNative(amountUsdCents, priceMicros, 18);
21
19
  const maxRetries = 3;
22
20
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
23
21
  const derivationIndex = await deps.chargeStore.getNextDerivationIndex();
24
- const depositAddress = deriveAddress(deps.xpub, derivationIndex, "evm");
22
+ const depositAddress = deps.deriveAddress(deps.xpub, derivationIndex, "evm");
25
23
  const referenceId = `eth:${opts.chain}:${depositAddress}`;
26
24
  try {
27
25
  await deps.chargeStore.createStablecoinCharge({
@@ -1,7 +1,7 @@
1
1
  import type { ILedger } from "../../../credits/ledger.js";
2
2
  import type { ICryptoChargeRepository } from "../charge-store.js";
3
3
  import type { CryptoWebhookResult } from "../types.js";
4
- import type { EthPaymentEvent } from "./eth-watcher.js";
4
+ import type { EthPaymentEvent } from "./types.js";
5
5
  export interface EthSettlerDeps {
6
6
  chargeStore: Pick<ICryptoChargeRepository, "getByDepositAddress" | "updateStatus" | "markCredited">;
7
7
  creditLedger: Pick<ILedger, "credit" | "hasReferenceId">;
@@ -1,16 +1,10 @@
1
- export type { EncodingParams } from "../address-gen.js";
2
- export { deriveAddress, isValidXpub } from "../address-gen.js";
3
1
  export type { StablecoinCheckoutDeps, StablecoinCheckoutResult } from "./checkout.js";
4
2
  export { createStablecoinCheckout, MIN_STABLECOIN_USD } from "./checkout.js";
5
3
  export { centsFromTokenAmount, getChainConfig, getTokenConfig, tokenAmountFromCents } from "./config.js";
6
- export type { EthCheckoutDeps, EthCheckoutOpts, EthCheckoutResult } from "./eth-checkout.js";
4
+ export type { CentsToNativeFn, EthCheckoutDeps, EthCheckoutOpts, EthCheckoutResult, EthPriceOracle, } from "./eth-checkout.js";
7
5
  export { createEthCheckout, MIN_ETH_USD } from "./eth-checkout.js";
8
6
  export type { EthSettlerDeps } from "./eth-settler.js";
9
7
  export { settleEthPayment } from "./eth-settler.js";
10
- export type { EthPaymentEvent, EthWatcherOpts } from "./eth-watcher.js";
11
- export { EthWatcher } from "./eth-watcher.js";
12
8
  export type { EvmSettlerDeps } from "./settler.js";
13
9
  export { settleEvmPayment } from "./settler.js";
14
- export type { ChainConfig, EvmChain, EvmPaymentEvent, StablecoinCheckoutOpts, StablecoinToken, TokenConfig, } from "./types.js";
15
- export type { EvmWatcherOpts } from "./watcher.js";
16
- export { createRpcCaller, EvmWatcher } from "./watcher.js";
10
+ export type { ChainConfig, EthPaymentEvent, EvmChain, EvmPaymentEvent, StablecoinCheckoutOpts, StablecoinToken, TokenConfig, } from "./types.js";
@@ -1,8 +1,5 @@
1
- export { deriveAddress, isValidXpub } from "../address-gen.js";
2
1
  export { createStablecoinCheckout, MIN_STABLECOIN_USD } from "./checkout.js";
3
2
  export { centsFromTokenAmount, getChainConfig, getTokenConfig, tokenAmountFromCents } from "./config.js";
4
3
  export { createEthCheckout, MIN_ETH_USD } from "./eth-checkout.js";
5
4
  export { settleEthPayment } from "./eth-settler.js";
6
- export { EthWatcher } from "./eth-watcher.js";
7
5
  export { settleEvmPayment } from "./settler.js";
8
- export { createRpcCaller, EvmWatcher } from "./watcher.js";
@@ -35,6 +35,22 @@ export interface EvmPaymentEvent {
35
35
  /** Required confirmations for this chain. */
36
36
  readonly confirmationsRequired: number;
37
37
  }
38
+ /** Event emitted on each confirmation increment for a native ETH deposit. */
39
+ export interface EthPaymentEvent {
40
+ readonly chain: EvmChain;
41
+ readonly from: string;
42
+ readonly to: string;
43
+ /** Raw value in wei (BigInt as string for serialization). */
44
+ readonly valueWei: string;
45
+ /** USD cents equivalent at detection time (integer). */
46
+ readonly amountUsdCents: number;
47
+ readonly txHash: string;
48
+ readonly blockNumber: number;
49
+ /** Current confirmation count (latest block - tx block). */
50
+ readonly confirmations: number;
51
+ /** Required confirmations for this chain. */
52
+ readonly confirmationsRequired: number;
53
+ }
38
54
  /** Options for creating a stablecoin checkout. */
39
55
  export interface StablecoinCheckoutOpts {
40
56
  tenant: string;
@@ -6,15 +6,10 @@ export { CryptoServiceClient, loadCryptoConfig } from "./client.js";
6
6
  export type { IWatcherCursorStore } from "./cursor-store.js";
7
7
  export { DrizzleWatcherCursorStore } from "./cursor-store.js";
8
8
  export * from "./evm/index.js";
9
- export type { KeyServerDeps } from "./key-server.js";
10
- export { createKeyServerApp } from "./key-server.js";
11
9
  export type { KeyServerWebhookDeps as CryptoWebhookDeps, KeyServerWebhookPayload as CryptoWebhookPayload, KeyServerWebhookResult as CryptoWebhookResult, } from "./key-server-webhook.js";
12
10
  export { handleKeyServerWebhook, handleKeyServerWebhook as handleCryptoWebhook, normalizeStatus, } from "./key-server-webhook.js";
13
- export * from "./oracle/index.js";
14
11
  export type { IPaymentMethodStore, PaymentMethodRecord } from "./payment-method-store.js";
15
12
  export { DrizzlePaymentMethodStore } from "./payment-method-store.js";
16
- export type { IAddressEncoder, IChainPlugin, IChainWatcher, ICurveDeriver, ISweepStrategy, PaymentEvent, } from "./plugin/index.js";
17
- export { PluginRegistry } from "./plugin/index.js";
18
- export type { CryptoCharge, CryptoChargeStatus, CryptoPaymentState } from "./types.js";
13
+ export type { CryptoCharge, CryptoChargeStatus, CryptoPaymentState, CryptoWebhookResult as SettlerWebhookResult, } from "./types.js";
19
14
  export type { UnifiedCheckoutDeps, UnifiedCheckoutResult } from "./unified-checkout.js";
20
15
  export { createUnifiedCheckout, MIN_CHECKOUT_USD as MIN_PAYMENT_USD, MIN_CHECKOUT_USD } from "./unified-checkout.js";
@@ -1,11 +1,10 @@
1
+ // Client
2
+ // Chain-specific settlers + checkouts
1
3
  export * from "./btc/index.js";
2
4
  export { CryptoChargeRepository, DrizzleCryptoChargeRepository } from "./charge-store.js";
3
5
  export { CryptoServiceClient, loadCryptoConfig } from "./client.js";
4
6
  export { DrizzleWatcherCursorStore } from "./cursor-store.js";
5
7
  export * from "./evm/index.js";
6
- export { createKeyServerApp } from "./key-server.js";
7
8
  export { handleKeyServerWebhook, handleKeyServerWebhook as handleCryptoWebhook, normalizeStatus, } from "./key-server-webhook.js";
8
- export * from "./oracle/index.js";
9
9
  export { DrizzlePaymentMethodStore } from "./payment-method-store.js";
10
- export { PluginRegistry } from "./plugin/index.js";
11
10
  export { createUnifiedCheckout, MIN_CHECKOUT_USD as MIN_PAYMENT_USD, MIN_CHECKOUT_USD } from "./unified-checkout.js";
@@ -23,42 +23,6 @@ export interface CryptoCheckoutOpts {
23
23
  /** Amount in USD (minimum $10). */
24
24
  amountUsd: number;
25
25
  }
26
- /** Webhook payload received from BTCPay Server (InvoiceSettled event). */
27
- export interface CryptoWebhookPayload {
28
- /** BTCPay delivery ID (for deduplication). */
29
- deliveryId: string;
30
- /** Webhook ID. */
31
- webhookId: string;
32
- /** Original delivery ID (same as deliveryId on first delivery). */
33
- originalDeliveryId: string;
34
- /** Whether this is a redelivery. */
35
- isRedelivery: boolean;
36
- /** Event type (e.g. "InvoiceSettled", "InvoiceProcessing", "InvoiceExpired"). */
37
- type: string;
38
- /** Unix timestamp. */
39
- timestamp: number;
40
- /** BTCPay store ID. */
41
- storeId: string;
42
- /** BTCPay invoice ID. */
43
- invoiceId: string;
44
- /** Invoice metadata (echoed from creation). */
45
- metadata: Record<string, unknown>;
46
- /** Whether admin manually marked as settled (InvoiceSettled only). */
47
- manuallyMarked?: boolean;
48
- /** Whether customer overpaid (InvoiceSettled only). */
49
- overPaid?: boolean;
50
- /** Whether invoice was partially paid (InvoiceExpired only). */
51
- partiallyPaid?: boolean;
52
- }
53
- /** Configuration for BTCPay Server integration. */
54
- export interface CryptoBillingConfig {
55
- /** BTCPay API key (from Account > API keys). */
56
- apiKey: string;
57
- /** BTCPay Server base URL. */
58
- baseUrl: string;
59
- /** BTCPay store ID. */
60
- storeId: string;
61
- }
62
26
  /** Result of processing a crypto webhook event. */
63
27
  export interface CryptoWebhookResult {
64
28
  handled: boolean;
@@ -68,10 +32,3 @@ export interface CryptoWebhookResult {
68
32
  reactivatedBots?: string[];
69
33
  duplicate?: boolean;
70
34
  }
71
- /**
72
- * Map BTCPay webhook event type string to a CryptoPaymentState.
73
- *
74
- * Shared between the core (billing) and consumer (monetization) webhook handlers.
75
- * Throws on unrecognized event types to surface integration errors early.
76
- */
77
- export declare function mapBtcPayEventToStatus(eventType: string): CryptoPaymentState;
@@ -1,24 +1 @@
1
- /**
2
- * Map BTCPay webhook event type string to a CryptoPaymentState.
3
- *
4
- * Shared between the core (billing) and consumer (monetization) webhook handlers.
5
- * Throws on unrecognized event types to surface integration errors early.
6
- */
7
- export function mapBtcPayEventToStatus(eventType) {
8
- switch (eventType) {
9
- case "InvoiceCreated":
10
- return "New";
11
- case "InvoiceReceivedPayment":
12
- case "InvoiceProcessing":
13
- return "Processing";
14
- case "InvoiceSettled":
15
- case "InvoicePaymentSettled":
16
- return "Settled";
17
- case "InvoiceExpired":
18
- return "Expired";
19
- case "InvoiceInvalid":
20
- return "Invalid";
21
- default:
22
- throw new Error(`Unknown BTCPay event type: ${eventType}`);
23
- }
24
- }
1
+ export {};
@@ -89,6 +89,17 @@ class ResendTransport {
89
89
  return result;
90
90
  }
91
91
  }
92
+ /** No-op transport that logs but does not send. Used when EMAIL_DISABLED=true. */
93
+ class NoopTransport {
94
+ async send(opts) {
95
+ logger.info("Email suppressed (EMAIL_DISABLED)", {
96
+ to: opts.to,
97
+ template: opts.templateName,
98
+ userId: opts.userId,
99
+ });
100
+ return { id: "noop", success: true };
101
+ }
102
+ }
92
103
  /**
93
104
  * Create a lazily-initialized singleton EmailClient from environment variables.
94
105
  *
@@ -126,6 +137,11 @@ let _client = null;
126
137
  */
127
138
  export function getEmailClient(overrides) {
128
139
  if (!_client) {
140
+ if (process.env.EMAIL_DISABLED === "true") {
141
+ _client = new EmailClient(new NoopTransport());
142
+ logger.info("Email client disabled (EMAIL_DISABLED=true)");
143
+ return _client;
144
+ }
129
145
  const from = overrides?.from || process.env.EMAIL_FROM || process.env.RESEND_FROM || "noreply@wopr.bot";
130
146
  const replyTo = overrides?.replyTo || process.env.EMAIL_REPLY_TO || process.env.RESEND_REPLY_TO || "support@wopr.bot";
131
147
  const sesRegion = process.env.AWS_SES_REGION;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wopr-network/platform-core",
3
- "version": "1.67.0",
3
+ "version": "1.68.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -72,10 +72,6 @@
72
72
  "./api/routes/verify-email": "./dist/api/routes/verify-email.js",
73
73
  "./api/routes/ws-auth": "./dist/api/routes/ws-auth.js",
74
74
  "./trpc": "./dist/trpc/index.js",
75
- "./crypto-plugin": {
76
- "import": "./dist/billing/crypto/plugin/index.js",
77
- "types": "./dist/billing/crypto/plugin/index.d.ts"
78
- },
79
75
  "./*": "./dist/*.js"
80
76
  },
81
77
  "scripts": {
@@ -87,6 +83,7 @@
87
83
  "format": "biome format src/ --write"
88
84
  },
89
85
  "peerDependencies": {
86
+ "@aws-sdk/client-ses": ">=3",
90
87
  "@trpc/server": ">=11",
91
88
  "better-auth": ">=1.5",
92
89
  "dockerode": ">=4",
@@ -99,6 +96,7 @@
99
96
  "zod": ">=3"
100
97
  },
101
98
  "devDependencies": {
99
+ "@aws-sdk/client-ses": "^3.1014.0",
102
100
  "@biomejs/biome": "^2.4.6",
103
101
  "@electric-sql/pglite": "^0.3.16",
104
102
  "@sentry/node": "^10.43.0",
@@ -133,14 +131,13 @@
133
131
  },
134
132
  "packageManager": "pnpm@10.31.0",
135
133
  "dependencies": {
136
- "@aws-sdk/client-ses": "^3.1014.0",
137
134
  "@hono/node-server": "^1.19.11",
138
135
  "@noble/curves": "^2.0.1",
139
136
  "@noble/hashes": "^2.0.1",
140
137
  "@scure/base": "^2.0.0",
141
138
  "@scure/bip32": "^2.0.1",
142
139
  "@scure/bip39": "^2.0.1",
143
- "@wopr-network/crypto-plugins": "^1.0.1",
140
+ "@wopr-network/crypto-plugins": "^1.1.0",
144
141
  "handlebars": "^4.7.8",
145
142
  "js-yaml": "^4.1.1",
146
143
  "postmark": "^4.0.7",
@@ -265,6 +265,14 @@ function authOptions(cfg: BetterAuthConfig): BetterAuthOptions {
265
265
 
266
266
  if (user.emailVerified) return;
267
267
 
268
+ if (process.env.SKIP_EMAIL_VERIFICATION === "true") {
269
+ // raw SQL: better-auth manages the "user" table schema; Drizzle schema is not available in this auth hook context
270
+ await pool.query('UPDATE "user" SET "emailVerified" = true WHERE id = $1', [user.id]);
271
+ user.emailVerified = true;
272
+ logger.info("Email verification skipped (SKIP_EMAIL_VERIFICATION=true)", { userId: user.id });
273
+ return;
274
+ }
275
+
268
276
  try {
269
277
  await initVerificationSchema(pool);
270
278
  const { token } = await generateVerificationToken(pool, user.id);
@@ -1,5 +1,4 @@
1
1
  import { Credit } from "../../../credits/credit.js";
2
- import { deriveAddress } from "../address-gen.js";
3
2
  import type { ICryptoChargeRepository } from "../charge-store.js";
4
3
  import type { BtcCheckoutOpts } from "./types.js";
5
4
 
@@ -7,6 +6,8 @@ export const MIN_BTC_USD = 10;
7
6
 
8
7
  export interface BtcCheckoutDeps {
9
8
  chargeStore: Pick<ICryptoChargeRepository, "getNextDerivationIndex" | "createStablecoinCharge">;
9
+ /** HD key derivation function — injected from @wopr-network/platform-crypto-server. */
10
+ deriveAddress: (xpub: string, index: number, encoding: string, params?: { hrp?: string }) => string;
10
11
  xpub: string;
11
12
  network?: "mainnet" | "testnet" | "regtest";
12
13
  }
@@ -36,7 +37,7 @@ export async function createBtcCheckout(deps: BtcCheckoutDeps, opts: BtcCheckout
36
37
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
37
38
  const derivationIndex = await deps.chargeStore.getNextDerivationIndex();
38
39
  const hrpMap = { mainnet: "bc", testnet: "tb", regtest: "bcrt" } as const;
39
- const depositAddress = deriveAddress(deps.xpub, derivationIndex, "bech32", {
40
+ const depositAddress = deps.deriveAddress(deps.xpub, derivationIndex, "bech32", {
40
41
  hrp: hrpMap[network],
41
42
  });
42
43
  const referenceId = `btc:${depositAddress}`;
@@ -1,10 +1,6 @@
1
- export type { EncodingParams } from "../address-gen.js";
2
- export { deriveAddress, deriveTreasury, isValidXpub } from "../address-gen.js";
3
1
  export type { BtcCheckoutDeps, BtcCheckoutResult } from "./checkout.js";
4
2
  export { createBtcCheckout, MIN_BTC_USD } from "./checkout.js";
5
3
  export { centsToSats, loadBitcoindConfig, satsToCents } from "./config.js";
6
4
  export type { BtcSettlerDeps } from "./settler.js";
7
5
  export { settleBtcPayment } from "./settler.js";
8
6
  export type { BitcoindConfig, BtcCheckoutOpts, BtcPaymentEvent } from "./types.js";
9
- export type { BtcWatcherOpts } from "./watcher.js";
10
- export { BtcWatcher, createBitcoindRpc } from "./watcher.js";
@@ -1,15 +1,13 @@
1
- import { HDKey } from "@scure/bip32";
2
1
  import { describe, expect, it, vi } from "vitest";
3
2
  import { createStablecoinCheckout } from "../checkout.js";
4
3
 
5
- function makeTestXpub(): string {
6
- const seed = new Uint8Array(32);
7
- seed[0] = 1;
8
- const master = HDKey.fromMasterSeed(seed);
9
- return master.derive("m/44'/60'/0'").publicExtendedKey;
10
- }
4
+ const TEST_XPUB =
5
+ "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8";
11
6
 
12
- const TEST_XPUB = makeTestXpub();
7
+ /** Deterministic mock — returns a valid-looking EVM address for any index. */
8
+ function mockDeriveAddress(_xpub: string, index: number, _encoding: string): string {
9
+ return `0x${index.toString(16).padStart(40, "0")}`;
10
+ }
13
11
 
14
12
  describe("createStablecoinCheckout", () => {
15
13
  it("derives address and creates charge", async () => {
@@ -19,7 +17,7 @@ describe("createStablecoinCheckout", () => {
19
17
  };
20
18
 
21
19
  const result = await createStablecoinCheckout(
22
- { chargeStore: mockChargeStore as never, xpub: TEST_XPUB },
20
+ { chargeStore: mockChargeStore as never, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB },
23
21
  { tenant: "t1", amountUsd: 10, chain: "base", token: "USDC" },
24
22
  );
25
23
 
@@ -43,7 +41,7 @@ describe("createStablecoinCheckout", () => {
43
41
 
44
42
  await expect(
45
43
  createStablecoinCheckout(
46
- { chargeStore: mockChargeStore as never, xpub: TEST_XPUB },
44
+ { chargeStore: mockChargeStore as never, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB },
47
45
  { tenant: "t1", amountUsd: 5, chain: "base", token: "USDC" },
48
46
  ),
49
47
  ).rejects.toThrow("Minimum");
@@ -56,7 +54,7 @@ describe("createStablecoinCheckout", () => {
56
54
  };
57
55
 
58
56
  await createStablecoinCheckout(
59
- { chargeStore: mockChargeStore as never, xpub: TEST_XPUB },
57
+ { chargeStore: mockChargeStore as never, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB },
60
58
  { tenant: "t1", amountUsd: 10, chain: "base", token: "USDC" },
61
59
  );
62
60
 
@@ -71,7 +69,7 @@ describe("createStablecoinCheckout", () => {
71
69
  };
72
70
 
73
71
  const result = await createStablecoinCheckout(
74
- { chargeStore: mockChargeStore as never, xpub: TEST_XPUB },
72
+ { chargeStore: mockChargeStore as never, deriveAddress: mockDeriveAddress, xpub: TEST_XPUB },
75
73
  { tenant: "t1", amountUsd: 25, chain: "base", token: "USDC" },
76
74
  );
77
75
 
@@ -3,6 +3,20 @@ import { createEthCheckout, MIN_ETH_USD } from "../eth-checkout.js";
3
3
 
4
4
  const mockOracle = { getPrice: vi.fn().mockResolvedValue({ priceMicros: 3_500_000_000, updatedAt: new Date() }) };
5
5
 
6
+ /** Deterministic mock — returns a valid-looking EVM address for any index. */
7
+ function mockDeriveAddress(_xpub: string, index: number, _encoding: string): string {
8
+ return `0x${index.toString(16).padStart(40, "0")}`;
9
+ }
10
+
11
+ /**
12
+ * centsToNative: Convert USD cents to native token base units.
13
+ * Formula: (cents * 10_000 * 10^decimals) / priceMicros
14
+ * This mirrors the real oracle/convert.ts logic.
15
+ */
16
+ function mockCentsToNative(cents: number, priceMicros: number, decimals: number): bigint {
17
+ return (BigInt(cents) * 10_000n * 10n ** BigInt(decimals)) / BigInt(priceMicros);
18
+ }
19
+
6
20
  function makeDeps(derivationIndex = 0) {
7
21
  return {
8
22
  chargeStore: {
@@ -10,6 +24,8 @@ function makeDeps(derivationIndex = 0) {
10
24
  createStablecoinCharge: vi.fn().mockResolvedValue(undefined),
11
25
  },
12
26
  oracle: mockOracle,
27
+ deriveAddress: mockDeriveAddress,
28
+ centsToNative: mockCentsToNative,
13
29
  xpub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
14
30
  };
15
31
  }
@@ -22,7 +38,7 @@ describe("createEthCheckout", () => {
22
38
  expect(result.amountUsd).toBe(50);
23
39
  expect(result.priceMicros).toBe(3_500_000_000);
24
40
  expect(result.chain).toBe("base");
25
- // $50 = 5000 cents × 10000 micros/cent × 10^18 / 3_500_000_000 micros = 14285714285714285n
41
+ // $50 = 5000 cents * 10000 micros/cent * 10^18 / 3_500_000_000 micros = 14285714285714285n
26
42
  expect(result.expectedWei).toBe("14285714285714285");
27
43
  expect(result.depositAddress).toMatch(/^0x/);
28
44
  expect(result.referenceId).toMatch(/^eth:base:0x/);
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
2
  import { settleEthPayment } from "../eth-settler.js";
3
- import type { EthPaymentEvent } from "../eth-watcher.js";
3
+ import type { EthPaymentEvent } from "../types.js";
4
4
 
5
5
  function makeEvent(overrides: Partial<EthPaymentEvent> = {}): EthPaymentEvent {
6
6
  return {