@wopr-network/platform-core 1.58.1 → 1.60.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.
- package/dist/billing/crypto/__tests__/key-server.test.js +3 -0
- package/dist/billing/crypto/key-server.js +1 -0
- package/dist/billing/crypto/oracle/coingecko.js +1 -0
- package/dist/billing/crypto/payment-method-store.d.ts +1 -0
- package/dist/billing/crypto/payment-method-store.js +3 -0
- package/dist/billing/crypto/tron/__tests__/address-convert.test.d.ts +1 -0
- package/dist/billing/crypto/tron/__tests__/address-convert.test.js +55 -0
- package/dist/billing/crypto/tron/address-convert.d.ts +14 -0
- package/dist/billing/crypto/tron/address-convert.js +83 -0
- package/dist/billing/crypto/watcher-service.js +21 -11
- package/dist/db/schema/crypto.d.ts +17 -0
- package/dist/db/schema/crypto.js +1 -0
- package/dist/db/schema/index.d.ts +2 -0
- package/dist/db/schema/index.js +2 -0
- package/dist/db/schema/product-config.d.ts +610 -0
- package/dist/db/schema/product-config.js +51 -0
- package/dist/db/schema/products.d.ts +565 -0
- package/dist/db/schema/products.js +43 -0
- package/dist/product-config/boot.d.ts +36 -0
- package/dist/product-config/boot.js +30 -0
- package/dist/product-config/drizzle-product-config-repository.d.ts +19 -0
- package/dist/product-config/drizzle-product-config-repository.js +200 -0
- package/dist/product-config/drizzle-product-config-repository.test.d.ts +1 -0
- package/dist/product-config/drizzle-product-config-repository.test.js +114 -0
- package/dist/product-config/index.d.ts +24 -0
- package/dist/product-config/index.js +37 -0
- package/dist/product-config/repository-types.d.ts +143 -0
- package/dist/product-config/repository-types.js +53 -0
- package/dist/product-config/service.d.ts +27 -0
- package/dist/product-config/service.js +74 -0
- package/dist/product-config/service.test.d.ts +1 -0
- package/dist/product-config/service.test.js +107 -0
- package/dist/trpc/index.d.ts +1 -0
- package/dist/trpc/index.js +1 -0
- package/dist/trpc/product-config-router.d.ts +117 -0
- package/dist/trpc/product-config-router.js +137 -0
- package/docs/specs/2026-03-23-product-config-db-migration-plan.md +2260 -0
- package/docs/specs/2026-03-23-product-config-db-migration.md +371 -0
- package/drizzle/migrations/0020_product_config_tables.sql +109 -0
- package/drizzle/migrations/0021_watcher_type_column.sql +3 -0
- package/drizzle/migrations/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/scripts/seed-products.ts +268 -0
- package/src/billing/crypto/__tests__/key-server.test.ts +3 -0
- package/src/billing/crypto/key-server.ts +2 -0
- package/src/billing/crypto/oracle/coingecko.ts +1 -0
- package/src/billing/crypto/payment-method-store.ts +4 -0
- package/src/billing/crypto/tron/__tests__/address-convert.test.ts +67 -0
- package/src/billing/crypto/tron/address-convert.ts +80 -0
- package/src/billing/crypto/watcher-service.ts +24 -16
- package/src/db/schema/crypto.ts +1 -0
- package/src/db/schema/index.ts +2 -0
- package/src/db/schema/product-config.ts +56 -0
- package/src/db/schema/products.ts +58 -0
- package/src/product-config/boot.ts +57 -0
- package/src/product-config/drizzle-product-config-repository.test.ts +132 -0
- package/src/product-config/drizzle-product-config-repository.ts +229 -0
- package/src/product-config/index.ts +62 -0
- package/src/product-config/repository-types.ts +222 -0
- package/src/product-config/service.test.ts +127 -0
- package/src/product-config/service.ts +105 -0
- package/src/trpc/index.ts +1 -0
- package/src/trpc/product-config-router.ts +161 -0
|
@@ -12,6 +12,7 @@ function createMockDb() {
|
|
|
12
12
|
decimals: 8,
|
|
13
13
|
addressType: "bech32",
|
|
14
14
|
encodingParams: '{"hrp":"bc"}',
|
|
15
|
+
watcherType: "utxo",
|
|
15
16
|
confirmations: 6,
|
|
16
17
|
};
|
|
17
18
|
const db = {
|
|
@@ -180,6 +181,7 @@ describe("key-server routes", () => {
|
|
|
180
181
|
decimals: 18,
|
|
181
182
|
addressType: "evm",
|
|
182
183
|
encodingParams: "{}",
|
|
184
|
+
watcherType: "evm",
|
|
183
185
|
confirmations: 1,
|
|
184
186
|
};
|
|
185
187
|
const db = {
|
|
@@ -239,6 +241,7 @@ describe("key-server routes", () => {
|
|
|
239
241
|
decimals: 18,
|
|
240
242
|
addressType: "evm",
|
|
241
243
|
encodingParams: "{}",
|
|
244
|
+
watcherType: "evm",
|
|
242
245
|
confirmations: 1,
|
|
243
246
|
};
|
|
244
247
|
const db = {
|
|
@@ -296,6 +296,7 @@ export function createKeyServerApp(deps) {
|
|
|
296
296
|
xpub: body.xpub,
|
|
297
297
|
addressType: body.address_type ?? "evm",
|
|
298
298
|
encodingParams: JSON.stringify(body.encoding_params ?? {}),
|
|
299
|
+
watcherType: body.watcher_type ?? "evm",
|
|
299
300
|
confirmations: body.confirmations ?? 6,
|
|
300
301
|
});
|
|
301
302
|
return c.json({ id: body.id, path: `m/44'/${body.coin_type}'/${body.account_index}'` }, 201);
|
|
@@ -48,6 +48,7 @@ export class DrizzlePaymentMethodStore {
|
|
|
48
48
|
xpub: method.xpub,
|
|
49
49
|
addressType: method.addressType,
|
|
50
50
|
encodingParams: method.encodingParams,
|
|
51
|
+
watcherType: method.watcherType,
|
|
51
52
|
confirmations: method.confirmations,
|
|
52
53
|
})
|
|
53
54
|
.onConflictDoUpdate({
|
|
@@ -67,6 +68,7 @@ export class DrizzlePaymentMethodStore {
|
|
|
67
68
|
xpub: method.xpub,
|
|
68
69
|
addressType: method.addressType,
|
|
69
70
|
encodingParams: method.encodingParams,
|
|
71
|
+
watcherType: method.watcherType,
|
|
70
72
|
confirmations: method.confirmations,
|
|
71
73
|
},
|
|
72
74
|
});
|
|
@@ -105,6 +107,7 @@ function toRecord(row) {
|
|
|
105
107
|
xpub: row.xpub,
|
|
106
108
|
addressType: row.addressType,
|
|
107
109
|
encodingParams: row.encodingParams,
|
|
110
|
+
watcherType: row.watcherType,
|
|
108
111
|
confirmations: row.confirmations,
|
|
109
112
|
};
|
|
110
113
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { hexToTron, isTronAddress, tronToHex } from "../address-convert.js";
|
|
3
|
+
// Known Tron address / hex pair (Tron foundation address)
|
|
4
|
+
const TRON_ADDR = "TJCnKsPa7y5okkXvQAidZBzqx3QyQ6sxMW";
|
|
5
|
+
const HEX_ADDR = "0x5a523b449890854c8fc460ab602df9f31fe4293f";
|
|
6
|
+
describe("tronToHex", () => {
|
|
7
|
+
it("converts T... to 0x hex", () => {
|
|
8
|
+
const hex = tronToHex(TRON_ADDR);
|
|
9
|
+
expect(hex).toBe(HEX_ADDR);
|
|
10
|
+
});
|
|
11
|
+
it("rejects non-Tron address", () => {
|
|
12
|
+
expect(() => tronToHex("0x1234")).toThrow("Not a Tron address");
|
|
13
|
+
});
|
|
14
|
+
it("rejects invalid checksum", () => {
|
|
15
|
+
// Flip last character
|
|
16
|
+
const bad = `${TRON_ADDR.slice(0, -1)}X`;
|
|
17
|
+
expect(() => tronToHex(bad)).toThrow();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe("hexToTron", () => {
|
|
21
|
+
it("converts 0x hex to T...", () => {
|
|
22
|
+
const tron = hexToTron(HEX_ADDR);
|
|
23
|
+
expect(tron).toBe(TRON_ADDR);
|
|
24
|
+
});
|
|
25
|
+
it("handles hex without 0x prefix", () => {
|
|
26
|
+
const tron = hexToTron(HEX_ADDR.slice(2));
|
|
27
|
+
expect(tron).toBe(TRON_ADDR);
|
|
28
|
+
});
|
|
29
|
+
it("rejects wrong length", () => {
|
|
30
|
+
expect(() => hexToTron("0x1234")).toThrow("Invalid hex address length");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe("roundtrip", () => {
|
|
34
|
+
it("tronToHex → hexToTron is identity", () => {
|
|
35
|
+
const hex = tronToHex(TRON_ADDR);
|
|
36
|
+
const back = hexToTron(hex);
|
|
37
|
+
expect(back).toBe(TRON_ADDR);
|
|
38
|
+
});
|
|
39
|
+
it("hexToTron → tronToHex is identity", () => {
|
|
40
|
+
const tron = hexToTron(HEX_ADDR);
|
|
41
|
+
const back = tronToHex(tron);
|
|
42
|
+
expect(back).toBe(HEX_ADDR);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("isTronAddress", () => {
|
|
46
|
+
it("returns true for T... address", () => {
|
|
47
|
+
expect(isTronAddress(TRON_ADDR)).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
it("returns false for 0x address", () => {
|
|
50
|
+
expect(isTronAddress(HEX_ADDR)).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
it("returns false for BTC address", () => {
|
|
53
|
+
expect(isTronAddress("bc1qtest")).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a Tron T... address to 0x hex (20 bytes, no 0x41 prefix).
|
|
3
|
+
* For feeding addresses to the EVM watcher JSON-RPC filters.
|
|
4
|
+
*/
|
|
5
|
+
export declare function tronToHex(tronAddr: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Convert a 0x hex address (20 bytes) back to Tron T... Base58Check.
|
|
8
|
+
* For converting watcher event addresses back to DB format.
|
|
9
|
+
*/
|
|
10
|
+
export declare function hexToTron(hexAddr: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Check if an address is a Tron T... address.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isTronAddress(addr: string): boolean;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tron address conversion — T... Base58Check ↔ 0x hex.
|
|
3
|
+
*
|
|
4
|
+
* Tron addresses are 21 bytes: 0x41 prefix + 20-byte address.
|
|
5
|
+
* The JSON-RPC layer strips the 0x41 and returns standard 0x-prefixed hex.
|
|
6
|
+
* We need to convert between the two at the watcher boundary.
|
|
7
|
+
*/
|
|
8
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
9
|
+
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
10
|
+
function base58decode(s) {
|
|
11
|
+
let num = 0n;
|
|
12
|
+
for (const ch of s) {
|
|
13
|
+
const idx = BASE58_ALPHABET.indexOf(ch);
|
|
14
|
+
if (idx < 0)
|
|
15
|
+
throw new Error(`Invalid base58 character: ${ch}`);
|
|
16
|
+
num = num * 58n + BigInt(idx);
|
|
17
|
+
}
|
|
18
|
+
const hex = num.toString(16).padStart(50, "0"); // 25 bytes = 50 hex chars
|
|
19
|
+
const bytes = new Uint8Array(25);
|
|
20
|
+
for (let i = 0; i < 25; i++)
|
|
21
|
+
bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
22
|
+
return bytes;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Convert a Tron T... address to 0x hex (20 bytes, no 0x41 prefix).
|
|
26
|
+
* For feeding addresses to the EVM watcher JSON-RPC filters.
|
|
27
|
+
*/
|
|
28
|
+
export function tronToHex(tronAddr) {
|
|
29
|
+
if (!tronAddr.startsWith("T"))
|
|
30
|
+
throw new Error(`Not a Tron address: ${tronAddr}`);
|
|
31
|
+
const decoded = base58decode(tronAddr);
|
|
32
|
+
// decoded: [0x41, ...20 bytes address..., ...4 bytes checksum]
|
|
33
|
+
// Verify checksum
|
|
34
|
+
const payload = decoded.slice(0, 21);
|
|
35
|
+
const checksum = sha256(sha256(payload)).slice(0, 4);
|
|
36
|
+
for (let i = 0; i < 4; i++) {
|
|
37
|
+
if (decoded[21 + i] !== checksum[i])
|
|
38
|
+
throw new Error(`Invalid checksum for Tron address: ${tronAddr}`);
|
|
39
|
+
}
|
|
40
|
+
// Strip 0x41 prefix, return 20-byte hex with 0x prefix
|
|
41
|
+
const addrBytes = payload.slice(1);
|
|
42
|
+
return `0x${Array.from(addrBytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Convert a 0x hex address (20 bytes) back to Tron T... Base58Check.
|
|
46
|
+
* For converting watcher event addresses back to DB format.
|
|
47
|
+
*/
|
|
48
|
+
export function hexToTron(hexAddr) {
|
|
49
|
+
const hex = hexAddr.startsWith("0x") ? hexAddr.slice(2) : hexAddr;
|
|
50
|
+
if (hex.length !== 40)
|
|
51
|
+
throw new Error(`Invalid hex address length: ${hex.length}`);
|
|
52
|
+
// Build payload: 0x41 + 20 bytes
|
|
53
|
+
const payload = new Uint8Array(21);
|
|
54
|
+
payload[0] = 0x41;
|
|
55
|
+
for (let i = 0; i < 20; i++)
|
|
56
|
+
payload[i + 1] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
57
|
+
// Compute checksum
|
|
58
|
+
const checksum = sha256(sha256(payload)).slice(0, 4);
|
|
59
|
+
const full = new Uint8Array(25);
|
|
60
|
+
full.set(payload);
|
|
61
|
+
full.set(checksum, 21);
|
|
62
|
+
// Base58 encode
|
|
63
|
+
let num = 0n;
|
|
64
|
+
for (const byte of full)
|
|
65
|
+
num = num * 256n + BigInt(byte);
|
|
66
|
+
let encoded = "";
|
|
67
|
+
while (num > 0n) {
|
|
68
|
+
encoded = BASE58_ALPHABET[Number(num % 58n)] + encoded;
|
|
69
|
+
num = num / 58n;
|
|
70
|
+
}
|
|
71
|
+
for (const byte of full) {
|
|
72
|
+
if (byte !== 0)
|
|
73
|
+
break;
|
|
74
|
+
encoded = `1${encoded}`;
|
|
75
|
+
}
|
|
76
|
+
return encoded;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if an address is a Tron T... address.
|
|
80
|
+
*/
|
|
81
|
+
export function isTronAddress(addr) {
|
|
82
|
+
return addr.startsWith("T") && addr.length >= 33 && addr.length <= 35;
|
|
83
|
+
}
|
|
@@ -16,6 +16,7 @@ import { cryptoCharges, webhookDeliveries } from "../../db/schema/crypto.js";
|
|
|
16
16
|
import { BtcWatcher, createBitcoindRpc } from "./btc/watcher.js";
|
|
17
17
|
import { EthWatcher } from "./evm/eth-watcher.js";
|
|
18
18
|
import { createRpcCaller, EvmWatcher } from "./evm/watcher.js";
|
|
19
|
+
import { hexToTron, isTronAddress, tronToHex } from "./tron/address-convert.js";
|
|
19
20
|
const MAX_DELIVERY_ATTEMPTS = 10;
|
|
20
21
|
const BACKOFF_BASE_MS = 5_000;
|
|
21
22
|
// --- SSRF validation ---
|
|
@@ -181,9 +182,10 @@ export async function startWatchers(opts) {
|
|
|
181
182
|
const serviceKey = opts.serviceKey;
|
|
182
183
|
const timers = [];
|
|
183
184
|
const methods = await methodStore.listEnabled();
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
// Route watchers by DB-driven watcherType — no hardcoded chain names.
|
|
186
|
+
// Adding a new chain is a DB INSERT with watcher_type = "utxo" or "evm".
|
|
187
|
+
const utxoMethods = methods.filter((m) => m.watcherType === "utxo");
|
|
188
|
+
const evmMethods = methods.filter((m) => m.watcherType === "evm");
|
|
187
189
|
// --- UTXO Watchers (BTC, LTC, DOGE) ---
|
|
188
190
|
for (const method of utxoMethods) {
|
|
189
191
|
if (!method.rpcUrl)
|
|
@@ -272,6 +274,12 @@ export async function startWatchers(opts) {
|
|
|
272
274
|
const nativeEvmMethods = evmMethods.filter((m) => m.type === "native");
|
|
273
275
|
const erc20Methods = evmMethods.filter((m) => m.type === "erc20" && m.contractAddress);
|
|
274
276
|
const BACKFILL_BLOCKS = 1000; // Scan ~30min of blocks on first deploy to catch missed deposits
|
|
277
|
+
// Address conversion helpers for chains with non-EVM address formats (e.g. Tron T...).
|
|
278
|
+
// The EVM watcher uses 0x hex addresses; the DB stores native format (T... for Tron).
|
|
279
|
+
// Determined by addressType from the DB — not by inspecting addresses at runtime.
|
|
280
|
+
const needsAddrConvert = (method) => method.addressType === "p2pkh";
|
|
281
|
+
const toWatcherAddr = (addr, method) => needsAddrConvert(method) && isTronAddress(addr) ? tronToHex(addr) : addr;
|
|
282
|
+
const fromWatcherAddr = (addr, method) => needsAddrConvert(method) ? hexToTron(addr) : addr;
|
|
275
283
|
for (const method of nativeEvmMethods) {
|
|
276
284
|
if (!method.rpcUrl)
|
|
277
285
|
continue;
|
|
@@ -289,19 +297,20 @@ export async function startWatchers(opts) {
|
|
|
289
297
|
rpcCall,
|
|
290
298
|
oracle,
|
|
291
299
|
fromBlock: backfillStart,
|
|
292
|
-
watchedAddresses: chainAddresses,
|
|
300
|
+
watchedAddresses: chainAddresses.map((a) => toWatcherAddr(a, method)),
|
|
293
301
|
cursorStore,
|
|
294
302
|
confirmations: method.confirmations,
|
|
295
303
|
onPayment: async (event) => {
|
|
304
|
+
const dbAddr = fromWatcherAddr(event.to, method);
|
|
296
305
|
log("ETH payment", {
|
|
297
306
|
chain: event.chain,
|
|
298
|
-
to:
|
|
307
|
+
to: dbAddr,
|
|
299
308
|
txHash: event.txHash,
|
|
300
309
|
valueWei: event.valueWei,
|
|
301
310
|
confirmations: event.confirmations,
|
|
302
311
|
confirmationsRequired: event.confirmationsRequired,
|
|
303
312
|
});
|
|
304
|
-
await handlePayment(db, chargeStore,
|
|
313
|
+
await handlePayment(db, chargeStore, dbAddr, event.valueWei, {
|
|
305
314
|
txHash: event.txHash,
|
|
306
315
|
confirmations: event.confirmations,
|
|
307
316
|
confirmationsRequired: event.confirmationsRequired,
|
|
@@ -321,7 +330,7 @@ export async function startWatchers(opts) {
|
|
|
321
330
|
const freshNative = fresh
|
|
322
331
|
.filter((a) => a.chain === method.chain && a.token === method.token)
|
|
323
332
|
.map((a) => a.address);
|
|
324
|
-
watcher.setWatchedAddresses(freshNative);
|
|
333
|
+
watcher.setWatchedAddresses(freshNative.map((a) => toWatcherAddr(a, method)));
|
|
325
334
|
await watcher.poll();
|
|
326
335
|
}
|
|
327
336
|
catch (err) {
|
|
@@ -346,21 +355,22 @@ export async function startWatchers(opts) {
|
|
|
346
355
|
token: method.token,
|
|
347
356
|
rpcCall,
|
|
348
357
|
fromBlock: latestBlock,
|
|
349
|
-
watchedAddresses: chainAddresses,
|
|
358
|
+
watchedAddresses: chainAddresses.map((a) => toWatcherAddr(a, method)),
|
|
350
359
|
contractAddress: method.contractAddress,
|
|
351
360
|
decimals: method.decimals,
|
|
352
361
|
confirmations: method.confirmations,
|
|
353
362
|
cursorStore,
|
|
354
363
|
onPayment: async (event) => {
|
|
364
|
+
const dbAddr = fromWatcherAddr(event.to, method);
|
|
355
365
|
log("EVM payment", {
|
|
356
366
|
chain: event.chain,
|
|
357
367
|
token: event.token,
|
|
358
|
-
to:
|
|
368
|
+
to: dbAddr,
|
|
359
369
|
txHash: event.txHash,
|
|
360
370
|
confirmations: event.confirmations,
|
|
361
371
|
confirmationsRequired: event.confirmationsRequired,
|
|
362
372
|
});
|
|
363
|
-
await handlePayment(db, chargeStore,
|
|
373
|
+
await handlePayment(db, chargeStore, dbAddr, event.rawAmount, {
|
|
364
374
|
txHash: event.txHash,
|
|
365
375
|
confirmations: event.confirmations,
|
|
366
376
|
confirmationsRequired: event.confirmationsRequired,
|
|
@@ -378,7 +388,7 @@ export async function startWatchers(opts) {
|
|
|
378
388
|
try {
|
|
379
389
|
const fresh = await chargeStore.listActiveDepositAddresses();
|
|
380
390
|
const freshChain = fresh.filter((a) => a.chain === method.chain).map((a) => a.address);
|
|
381
|
-
watcher.setWatchedAddresses(freshChain);
|
|
391
|
+
watcher.setWatchedAddresses(freshChain.map((a) => toWatcherAddr(a, method)));
|
|
382
392
|
await watcher.poll();
|
|
383
393
|
}
|
|
384
394
|
catch (err) {
|
|
@@ -699,6 +699,23 @@ export declare const paymentMethods: import("drizzle-orm/pg-core").PgTableWithCo
|
|
|
699
699
|
identity: undefined;
|
|
700
700
|
generated: undefined;
|
|
701
701
|
}, {}, {}>;
|
|
702
|
+
watcherType: import("drizzle-orm/pg-core").PgColumn<{
|
|
703
|
+
name: "watcher_type";
|
|
704
|
+
tableName: "payment_methods";
|
|
705
|
+
dataType: "string";
|
|
706
|
+
columnType: "PgText";
|
|
707
|
+
data: string;
|
|
708
|
+
driverParam: string;
|
|
709
|
+
notNull: true;
|
|
710
|
+
hasDefault: true;
|
|
711
|
+
isPrimaryKey: false;
|
|
712
|
+
isAutoincrement: false;
|
|
713
|
+
hasRuntimeDefault: false;
|
|
714
|
+
enumValues: [string, ...string[]];
|
|
715
|
+
baseColumn: never;
|
|
716
|
+
identity: undefined;
|
|
717
|
+
generated: undefined;
|
|
718
|
+
}, {}, {}>;
|
|
702
719
|
confirmations: import("drizzle-orm/pg-core").PgColumn<{
|
|
703
720
|
name: "confirmations";
|
|
704
721
|
tableName: "payment_methods";
|
package/dist/db/schema/crypto.js
CHANGED
|
@@ -77,6 +77,7 @@ export const paymentMethods = pgTable("payment_methods", {
|
|
|
77
77
|
xpub: text("xpub"), // HD wallet extended public key for deposit address derivation
|
|
78
78
|
addressType: text("address_type").notNull().default("evm"), // "bech32" (BTC/LTC), "p2pkh" (DOGE), "evm" (ETH/ERC20)
|
|
79
79
|
encodingParams: text("encoding_params").notNull().default("{}"), // JSON: {"hrp":"bc"}, {"version":"0x1e"}, etc.
|
|
80
|
+
watcherType: text("watcher_type").notNull().default("evm"), // "utxo" (BTC/LTC/DOGE) or "evm" (ETH/ERC20/TRX)
|
|
80
81
|
confirmations: integer("confirmations").notNull().default(1),
|
|
81
82
|
nextIndex: integer("next_index").notNull().default(0), // atomic derivation counter, never reuses
|
|
82
83
|
createdAt: text("created_at").notNull().default(sql `(now())`),
|
|
@@ -44,6 +44,8 @@ export * from "./page-contexts.js";
|
|
|
44
44
|
export * from "./platform-api-keys.js";
|
|
45
45
|
export * from "./plugin-configs.js";
|
|
46
46
|
export * from "./plugin-marketplace-content.js";
|
|
47
|
+
export * from "./product-config.js";
|
|
48
|
+
export * from "./products.js";
|
|
47
49
|
export * from "./promotion-redemptions.js";
|
|
48
50
|
export * from "./promotions.js";
|
|
49
51
|
export * from "./provider-credentials.js";
|
package/dist/db/schema/index.js
CHANGED
|
@@ -44,6 +44,8 @@ export * from "./page-contexts.js";
|
|
|
44
44
|
export * from "./platform-api-keys.js";
|
|
45
45
|
export * from "./plugin-configs.js";
|
|
46
46
|
export * from "./plugin-marketplace-content.js";
|
|
47
|
+
export * from "./product-config.js";
|
|
48
|
+
export * from "./products.js";
|
|
47
49
|
export * from "./promotion-redemptions.js";
|
|
48
50
|
export * from "./promotions.js";
|
|
49
51
|
export * from "./provider-credentials.js";
|