@pafi-dev/issuer-postgres 0.1.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/README.md +178 -0
- package/dist/entities/index.cjs +303 -0
- package/dist/entities/index.cjs.map +1 -0
- package/dist/entities/index.d.cts +122 -0
- package/dist/entities/index.d.ts +122 -0
- package/dist/entities/index.js +292 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/index.cjs +764 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +97 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +749 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/index.cjs +138 -0
- package/dist/migrations/index.cjs.map +1 -0
- package/dist/migrations/index.d.cts +41 -0
- package/dist/migrations/index.d.ts +41 -0
- package/dist/migrations/index.js +110 -0
- package/dist/migrations/index.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/postgresPointLedger.ts","../src/entities/locked-mint.entity.ts","../src/entities/pending-credit.entity.ts","../src/entities/user-balance.entity.ts","../src/entities/ledger-journal.entity.ts","../src/entities/indexer-cursor.entity.ts","../src/postgresCursorStore.ts","../src/entities/index.ts","../src/migrations/1700000000000-InitialSchema.ts","../src/migrations/index.ts"],"sourcesContent":["import type { DataSource } from \"typeorm\";\nimport { getAddress, type Address, type Hex } from \"viem\";\nimport type {\n IPointLedger,\n LockedMintRequest,\n MintingStatus,\n PendingCredit,\n} from \"@pafi-dev/issuer\";\n\nimport { LockedMintEntity } from \"./entities/locked-mint.entity\";\nimport { PendingCreditEntity } from \"./entities/pending-credit.entity\";\nimport { UserBalanceEntity } from \"./entities/user-balance.entity\";\nimport { LedgerJournalEntity } from \"./entities/ledger-journal.entity\";\n\nexport interface PostgresPointLedgerOptions {\n /**\n * Optional logger. When omitted, the service is silent. Pass a Nest\n * `Logger` / pino instance / `console` to surface debug + info\n * lines.\n */\n logger?: {\n debug?: (msg: string) => void;\n log?: (msg: string) => void;\n warn?: (msg: string) => void;\n };\n}\n\n/**\n * Postgres-backed `IPointLedger` — the reference impl every issuer\n * starts from. Framework-agnostic: takes a TypeORM `DataSource` in the\n * constructor, no NestJS decorators or DI tokens. Wrap in your\n * favorite injector.\n *\n * Implements every required + optional method from `IPointLedger`,\n * including the v1.4 reverse flow (`reservePendingCredit`,\n * `resolveCreditByBurnTx`) and the bundler-receipt fallback hooks\n * (`bindMintUserOpHash`, `bindCreditUserOpHash`, `getMintLock`,\n * `getPendingCredit`).\n *\n * Multi-token: every method requires `tokenAddress` — there is no\n * \"default token\" bucket. Single-token issuers pass the same address\n * everywhere.\n */\nexport class PostgresPointLedger implements IPointLedger {\n private readonly logger: PostgresPointLedgerOptions[\"logger\"];\n\n constructor(\n private readonly dataSource: DataSource,\n options: PostgresPointLedgerOptions = {},\n ) {\n this.logger = options.logger;\n }\n\n // ---------------------------------------------------------------------\n // Read\n // ---------------------------------------------------------------------\n\n async getBalance(\n userAddress: Address,\n tokenAddress?: Address,\n ): Promise<bigint> {\n const { user, token } = normalize(userAddress, tokenAddress);\n\n // Lazy sweep: mark any expired PENDING lock as EXPIRED before\n // computing available. Keeps the lock table self-cleaning without\n // needing a background cron.\n await this.dataSource\n .getRepository(LockedMintEntity)\n .createQueryBuilder()\n .update()\n .set({ status: \"EXPIRED\" })\n .where(\"status = :pending\", { pending: \"PENDING\" })\n .andWhere(\"expires_at <= :now\", { now: new Date() })\n .execute();\n\n const balanceRow = await this.dataSource\n .getRepository(UserBalanceEntity)\n .findOne({ where: { userAddress: user, tokenAddress: token } });\n const total = balanceRow?.balance ?? 0n;\n const locked = await this.sumPendingLocks(user, token);\n const available = total - locked;\n return available < 0n ? 0n : available;\n }\n\n async getLockedRequests(\n userAddress: Address,\n tokenAddress?: Address,\n ): Promise<LockedMintRequest[]> {\n const { user, token } = normalize(userAddress, tokenAddress);\n const rows = await this.dataSource\n .getRepository(LockedMintEntity)\n .find({\n where: { userAddress: user, tokenAddress: token, status: \"PENDING\" },\n order: { createdAt: \"ASC\" },\n });\n return rows.map((row) => this.toSdkLock(row));\n }\n\n async getMintLock(\n lockId: string,\n userAddress?: Address,\n ): Promise<LockedMintRequest | null> {\n const row = await this.dataSource\n .getRepository(LockedMintEntity)\n .findOne({ where: { id: lockId } });\n if (!row) return null;\n if (\n userAddress &&\n row.userAddress.toLowerCase() !== userAddress.toLowerCase()\n ) {\n return null;\n }\n return this.toSdkLock(row);\n }\n\n /** Raw TypeORM row — escape hatch for callers that need entity fields. */\n async getMintLockEntity(lockId: string): Promise<LockedMintEntity | null> {\n return this.dataSource\n .getRepository(LockedMintEntity)\n .findOne({ where: { id: lockId } });\n }\n\n async getPendingCredit(\n lockId: string,\n userAddress?: Address,\n ): Promise<PendingCredit | null> {\n const row = await this.dataSource\n .getRepository(PendingCreditEntity)\n .findOne({ where: { id: lockId } });\n if (!row) return null;\n if (\n userAddress &&\n row.userAddress.toLowerCase() !== userAddress.toLowerCase()\n ) {\n return null;\n }\n return {\n lockId: row.id,\n userAddress: getAddress(row.userAddress) as Address,\n amount: row.amount,\n tokenAddress: row.tokenAddress\n ? (getAddress(row.tokenAddress) as Address)\n : undefined,\n status: row.status as PendingCredit[\"status\"],\n createdAt: row.createdAt.getTime(),\n expiresAt: row.expiresAt.getTime(),\n txHash: (row.txHash as Hex | null) ?? undefined,\n resolvedAt: row.resolvedAt?.getTime(),\n userOpHash: (row.userOpHash as Hex | null) ?? undefined,\n };\n }\n\n /** Raw TypeORM row escape hatch for credits. */\n async getPendingCreditEntity(\n lockId: string,\n ): Promise<PendingCreditEntity | null> {\n return this.dataSource\n .getRepository(PendingCreditEntity)\n .findOne({ where: { id: lockId } });\n }\n\n /**\n * Paginated list of a user's mint requests across all statuses and\n * all tokens — used by `GET /user/transactions` reference endpoint.\n */\n async listUserTransactions(\n userAddress: Address,\n limit: number,\n offset: number,\n ): Promise<{ rows: LockedMintEntity[]; total: number }> {\n const user = getAddress(userAddress);\n const [rows, total] = await this.dataSource\n .getRepository(LockedMintEntity)\n .findAndCount({\n where: { userAddress: user },\n order: { createdAt: \"DESC\" },\n take: limit,\n skip: offset,\n });\n return { rows, total };\n }\n\n // ---------------------------------------------------------------------\n // Write\n // ---------------------------------------------------------------------\n\n async creditBalance(\n userAddress: Address,\n amount: bigint,\n reason: string,\n tokenAddress?: Address,\n ): Promise<void> {\n if (amount <= 0n) {\n throw new Error(\"creditBalance: amount must be positive\");\n }\n const { user, token } = normalize(userAddress, tokenAddress);\n\n await this.dataSource.transaction(async (tx) => {\n const existing = await tx\n .getRepository(UserBalanceEntity)\n .findOne({ where: { userAddress: user, tokenAddress: token } });\n const next = (existing?.balance ?? 0n) + amount;\n\n await tx\n .getRepository(UserBalanceEntity)\n .upsert(\n { userAddress: user, tokenAddress: token, balance: next },\n { conflictPaths: [\"userAddress\", \"tokenAddress\"] },\n );\n\n await tx.getRepository(LedgerJournalEntity).insert({\n userAddress: user,\n tokenAddress: token,\n delta: amount,\n reason,\n });\n });\n\n this.logger?.debug?.(`credit ${user}[${token}] +${amount} (${reason})`);\n }\n\n async lockForMinting(\n userAddress: Address,\n amount: bigint,\n lockDurationMs: number,\n tokenAddress?: Address,\n ): Promise<string> {\n if (amount <= 0n) {\n throw new Error(\"lockForMinting: amount must be positive\");\n }\n if (lockDurationMs <= 0) {\n throw new Error(\"lockForMinting: lockDurationMs must be positive\");\n }\n const { user, token } = normalize(userAddress, tokenAddress);\n\n return this.dataSource.transaction(async (tx) => {\n const balanceRow = await tx\n .getRepository(UserBalanceEntity)\n .findOne({ where: { userAddress: user, tokenAddress: token } });\n const total = balanceRow?.balance ?? 0n;\n\n const pendingTotal = await tx\n .getRepository(LockedMintEntity)\n .createQueryBuilder(\"lock\")\n .select(\"COALESCE(SUM(CAST(lock.amount AS NUMERIC)), 0)\", \"sum\")\n .where(\"lock.user_address = :user\", { user })\n .andWhere(\"lock.token_address = :token\", { token })\n .andWhere(\"lock.status = :pending\", { pending: \"PENDING\" })\n .andWhere(\"lock.expires_at > :now\", { now: new Date() })\n .getRawOne<{ sum: string }>();\n\n const locked = pendingTotal ? BigInt(pendingTotal.sum) : 0n;\n const available = total - locked;\n if (available < amount) {\n throw new Error(\n `Insufficient balance: available=${available}, requested=${amount}`,\n );\n }\n\n const lock = await tx.getRepository(LockedMintEntity).save({\n userAddress: user,\n tokenAddress: token,\n amount,\n status: \"PENDING\",\n expiresAt: new Date(Date.now() + lockDurationMs),\n });\n\n this.logger?.debug?.(\n `lock ${lock.id} ${user}[${token}] amount=${amount}`,\n );\n return lock.id;\n });\n }\n\n async releaseLock(lockId: string): Promise<void> {\n const result = await this.dataSource\n .getRepository(LockedMintEntity)\n .delete({ id: lockId, status: \"PENDING\" });\n\n if ((result.affected ?? 0) > 0) {\n this.logger?.debug?.(`release lock ${lockId}`);\n }\n }\n\n async deductBalance(\n userAddress: Address,\n amount: bigint,\n txHash: Hex,\n tokenAddress?: Address,\n ): Promise<void> {\n if (amount <= 0n) {\n throw new Error(\"deductBalance: amount must be positive\");\n }\n const { user, token } = normalize(userAddress, tokenAddress);\n\n await this.dataSource.transaction(async (tx) => {\n const balance = await tx\n .getRepository(UserBalanceEntity)\n .findOne({ where: { userAddress: user, tokenAddress: token } });\n if (!balance || balance.balance < amount) {\n throw new Error(\n `Cannot deduct ${amount} from balance ${balance?.balance ?? 0n}`,\n );\n }\n\n await tx.getRepository(UserBalanceEntity).update(\n { userAddress: user, tokenAddress: token },\n { balance: balance.balance - amount },\n );\n\n await tx.getRepository(LedgerJournalEntity).insert({\n userAddress: user,\n tokenAddress: token,\n delta: -amount,\n reason: \"MINT_CONFIRMED\",\n txHash,\n });\n\n // Resolve the oldest matching PENDING lock atomically.\n const match = await tx.getRepository(LockedMintEntity).findOne({\n where: {\n userAddress: user,\n tokenAddress: token,\n amount,\n status: \"PENDING\",\n },\n order: { createdAt: \"ASC\" },\n });\n if (match) {\n await tx\n .getRepository(LockedMintEntity)\n .update({ id: match.id }, { status: \"MINTED\", txHash });\n }\n });\n\n this.logger?.log?.(`deduct ${user}[${token}] -${amount} tx=${txHash}`);\n }\n\n async updateMintStatus(\n lockId: string,\n status: MintingStatus,\n txHash?: Hex,\n ): Promise<void> {\n const update: Partial<LockedMintEntity> = { status };\n if (txHash) update.txHash = txHash;\n\n await this.dataSource\n .getRepository(LockedMintEntity)\n .update({ id: lockId }, update);\n }\n\n async bindMintUserOpHash(lockId: string, userOpHash: Hex): Promise<void> {\n await this.dataSource\n .getRepository(LockedMintEntity)\n .update({ id: lockId }, { userOpHash });\n }\n\n async bindCreditUserOpHash(lockId: string, userOpHash: Hex): Promise<void> {\n await this.dataSource\n .getRepository(PendingCreditEntity)\n .update({ id: lockId }, { userOpHash });\n }\n\n // ---------------------------------------------------------------------\n // Reverse flow (burn → off-chain credit)\n // ---------------------------------------------------------------------\n\n async reservePendingCredit(\n userAddress: Address,\n amount: bigint,\n durationMs: number,\n tokenAddress?: Address,\n ): Promise<string> {\n if (amount <= 0n) {\n throw new Error(\"reservePendingCredit: amount must be positive\");\n }\n if (durationMs <= 0) {\n throw new Error(\"reservePendingCredit: durationMs must be positive\");\n }\n const { user, token } = normalize(userAddress, tokenAddress);\n\n const row = await this.dataSource\n .getRepository(PendingCreditEntity)\n .save({\n userAddress: user,\n tokenAddress: token,\n amount,\n status: \"PENDING\",\n expiresAt: new Date(Date.now() + durationMs),\n });\n\n this.logger?.debug?.(\n `reserve pending credit ${row.id} ${user}[${token}] +${amount}`,\n );\n return row.id;\n }\n\n async resolveCreditByBurnTx(lockId: string, txHash: Hex): Promise<void> {\n await this.dataSource.transaction(async (tx) => {\n const credit = await tx\n .getRepository(PendingCreditEntity)\n .findOne({ where: { id: lockId } });\n\n if (!credit) {\n throw new Error(\n `resolveCreditByBurnTx: unknown pending credit ${lockId}`,\n );\n }\n\n if (credit.status === \"RESOLVED\") {\n if (credit.txHash === txHash) return; // idempotent replay\n throw new Error(\n `resolveCreditByBurnTx: credit ${lockId} already resolved with a different txHash`,\n );\n }\n\n if (credit.status === \"EXPIRED\") {\n throw new Error(\n `resolveCreditByBurnTx: credit ${lockId} already expired — burn landed too late`,\n );\n }\n\n const user = credit.userAddress as Address;\n const token = credit.tokenAddress as Address;\n\n // Defense-in-depth — same `txHash` already credited a sibling\n // credit for the same (user, token). Mark this credit resolved\n // without re-applying balance.\n const alreadyResolved = await tx\n .getRepository(PendingCreditEntity)\n .findOne({\n where: {\n userAddress: user,\n tokenAddress: token,\n txHash,\n status: \"RESOLVED\",\n },\n });\n if (alreadyResolved) {\n await tx\n .getRepository(PendingCreditEntity)\n .update(\n { id: lockId },\n { status: \"RESOLVED\", txHash, resolvedAt: new Date() },\n );\n return;\n }\n\n const balance = await tx\n .getRepository(UserBalanceEntity)\n .findOne({ where: { userAddress: user, tokenAddress: token } });\n const next = (balance?.balance ?? 0n) + credit.amount;\n\n await tx\n .getRepository(UserBalanceEntity)\n .upsert(\n { userAddress: user, tokenAddress: token, balance: next },\n { conflictPaths: [\"userAddress\", \"tokenAddress\"] },\n );\n\n await tx.getRepository(LedgerJournalEntity).insert({\n userAddress: user,\n tokenAddress: token,\n delta: credit.amount,\n reason: \"BURN_FOR_CREDIT\",\n txHash,\n });\n\n await tx\n .getRepository(PendingCreditEntity)\n .update(\n { id: lockId },\n { status: \"RESOLVED\", txHash, resolvedAt: new Date() },\n );\n });\n\n this.logger?.log?.(`resolve pending credit ${lockId} tx=${txHash}`);\n }\n\n /**\n * Used by `BurnIndexer.matchLockId` to resolve an on-chain burn\n * event back to a pending credit row. Returns the oldest matching\n * `(user, token, amount, status: PENDING)` lockId, or undefined\n * when no match exists (unsolicited burn — indexer skips).\n */\n async findPendingCreditLockId(\n userAddress: Address,\n amount: bigint,\n tokenAddress: Address,\n ): Promise<string | undefined> {\n const { user, token } = normalize(userAddress, tokenAddress);\n const row = await this.dataSource\n .getRepository(PendingCreditEntity)\n .findOne({\n where: {\n userAddress: user,\n tokenAddress: token,\n amount,\n status: \"PENDING\",\n },\n order: { createdAt: \"ASC\" },\n });\n return row?.id;\n }\n\n // ---------------------------------------------------------------------\n // Internals\n // ---------------------------------------------------------------------\n\n private async sumPendingLocks(\n userAddress: Address,\n tokenAddress: Address,\n ): Promise<bigint> {\n const row = await this.dataSource\n .getRepository(LockedMintEntity)\n .createQueryBuilder(\"lock\")\n .select(\"COALESCE(SUM(CAST(lock.amount AS NUMERIC)), 0)\", \"sum\")\n .where(\"lock.user_address = :user\", { user: userAddress })\n .andWhere(\"lock.token_address = :token\", { token: tokenAddress })\n .andWhere(\"lock.status = :pending\", { pending: \"PENDING\" })\n .andWhere(\"lock.expires_at > :now\", { now: new Date() })\n .getRawOne<{ sum: string }>();\n return row ? BigInt(row.sum) : 0n;\n }\n\n private toSdkLock(row: LockedMintEntity): LockedMintRequest {\n const out: LockedMintRequest = {\n lockId: row.id,\n userAddress: row.userAddress as Address,\n tokenAddress: row.tokenAddress as Address,\n amount: row.amount,\n status: row.status,\n createdAt: row.createdAt.getTime(),\n expiresAt: row.expiresAt.getTime(),\n };\n if (row.txHash) out.txHash = row.txHash as Hex;\n if (row.userOpHash) out.userOpHash = row.userOpHash as Hex;\n return out;\n }\n}\n\n/**\n * Multi-token guard — throw if `tokenAddress` is missing on any\n * mutating call. Single-token issuers must still pass their token\n * address explicitly so reads + writes never fall into a \"default\"\n * bucket the application never queries.\n */\nfunction normalize(\n userAddress: Address,\n tokenAddress: Address | undefined,\n): { user: Address; token: Address } {\n if (!tokenAddress) {\n throw new Error(\n \"PostgresPointLedger: tokenAddress is required on every call (multi-token ledger)\",\n );\n }\n return {\n user: getAddress(userAddress),\n token: getAddress(tokenAddress),\n };\n}\n","import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n PrimaryGeneratedColumn,\n} from \"typeorm\";\nimport type { MintingStatus } from \"@pafi-dev/issuer\";\n\n/**\n * A reservation against a user's off-chain balance.\n *\n * Lifecycle:\n * PENDING ── PointIndexer matches Mint event ──▶ MINTED\n * │\n * ├── deadline elapsed ────────────────────▶ EXPIRED\n * │\n * └── tx reverted ─────────────────────────▶ FAILED\n *\n * The `(userAddress, status)` composite index keeps the \"sum all\n * PENDING locks\" hot path of `lockForMinting()` fast under load.\n */\n@Entity({ name: \"locked_mint_requests\" })\n@Index([\"userAddress\", \"status\"])\nexport class LockedMintEntity {\n @PrimaryGeneratedColumn(\"uuid\")\n id!: string;\n\n @Column({ name: \"user_address\", type: \"varchar\", length: 42 })\n userAddress!: string;\n\n @Column({ name: \"token_address\", type: \"varchar\", length: 42 })\n tokenAddress!: string;\n\n @Column({\n name: \"amount\",\n type: \"numeric\",\n precision: 78,\n scale: 0,\n transformer: {\n to: (value: bigint) => value.toString(),\n from: (value: string) => BigInt(value),\n },\n })\n amount!: bigint;\n\n @Column({\n name: \"status\",\n type: \"varchar\",\n length: 16,\n default: \"PENDING\",\n })\n status!: MintingStatus;\n\n @CreateDateColumn({ name: \"created_at\" })\n createdAt!: Date;\n\n @Column({ name: \"expires_at\", type: \"timestamp with time zone\" })\n expiresAt!: Date;\n\n @Column({ name: \"tx_hash\", type: \"varchar\", length: 66, nullable: true })\n txHash?: string | null;\n\n /**\n * ERC-4337 userOpHash returned by the bundler at /claim/submit.\n * Bound to the lock so `/claim/status` can fall back to the bundler\n * receipt — required when multiple PENDING locks share the same\n * `amount` (PointIndexer matches by amount and can pick the wrong\n * sibling lock).\n */\n @Column({\n name: \"user_op_hash\",\n type: \"varchar\",\n length: 66,\n nullable: true,\n })\n userOpHash?: string | null;\n}\n","import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n PrimaryGeneratedColumn,\n} from \"typeorm\";\n\nexport type PendingCreditStatus = \"PENDING\" | \"RESOLVED\" | \"EXPIRED\";\n\n/**\n * Reverse flow — user burns on-chain PT, `BurnIndexer` observes\n * `Transfer(user → 0x0)`, the credit is settled to the off-chain ledger.\n *\n * Lifecycle:\n * PENDING ── Burn tx observed by indexer ──▶ RESOLVED\n * │\n * └── deadline elapsed ────────────────▶ EXPIRED\n *\n * The credit is reserved BEFORE the UserOp is submitted so the\n * indexer can correlate `(user, amount, token)` back to the off-chain\n * row when the burn lands.\n */\n@Entity({ name: \"pending_credits\" })\n@Index([\"userAddress\", \"status\"])\n@Index([\"txHash\"])\nexport class PendingCreditEntity {\n @PrimaryGeneratedColumn(\"uuid\")\n id!: string;\n\n @Column({ name: \"user_address\", type: \"varchar\", length: 42 })\n userAddress!: string;\n\n @Column({ name: \"token_address\", type: \"varchar\", length: 42 })\n tokenAddress!: string;\n\n @Column({\n name: \"amount\",\n type: \"numeric\",\n precision: 78,\n scale: 0,\n transformer: {\n to: (value: bigint) => value.toString(),\n from: (value: string) => BigInt(value),\n },\n })\n amount!: bigint;\n\n @Column({\n name: \"status\",\n type: \"varchar\",\n length: 16,\n default: \"PENDING\",\n })\n status!: PendingCreditStatus;\n\n /** On-chain burn tx that settled this credit. Null until indexer resolves. */\n @Column({ name: \"tx_hash\", type: \"varchar\", length: 66, nullable: true })\n txHash?: string | null;\n\n /** ERC-4337 userOpHash bound at /redeem/submit. See `LockedMintEntity`. */\n @Column({\n name: \"user_op_hash\",\n type: \"varchar\",\n length: 66,\n nullable: true,\n })\n userOpHash?: string | null;\n\n @CreateDateColumn({ name: \"created_at\" })\n createdAt!: Date;\n\n @Column({ name: \"expires_at\", type: \"timestamp with time zone\" })\n expiresAt!: Date;\n\n @Column({\n name: \"resolved_at\",\n type: \"timestamp with time zone\",\n nullable: true,\n })\n resolvedAt?: Date | null;\n}\n","import { Column, Entity, PrimaryColumn, UpdateDateColumn } from \"typeorm\";\n\n/**\n * Off-chain point balance per `(userAddress, tokenAddress)`.\n *\n * `balance` is the **total** owned; pending reservations live in\n * `LockedMintEntity`. Available balance = total − sum(PENDING locks)\n * — `getBalance` in `PostgresPointLedger` does this subtraction\n * inside a transaction so reads are race-free.\n *\n * All amounts are `numeric(78, 0)` for full bigint precision (uint256\n * fits in 78 decimal digits). TypeORM transforms bigint ↔ string at\n * the boundary; in JS/TS code we always deal with `bigint`.\n */\n@Entity({ name: \"user_balances\" })\nexport class UserBalanceEntity {\n @PrimaryColumn({ name: \"user_address\", type: \"varchar\", length: 42 })\n userAddress!: string;\n\n @PrimaryColumn({ name: \"token_address\", type: \"varchar\", length: 42 })\n tokenAddress!: string;\n\n @Column({\n name: \"balance\",\n type: \"numeric\",\n precision: 78,\n scale: 0,\n default: 0,\n transformer: {\n to: (value: bigint) => value.toString(),\n from: (value: string) => BigInt(value),\n },\n })\n balance!: bigint;\n\n @UpdateDateColumn({ name: \"updated_at\" })\n updatedAt!: Date;\n}\n","import {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n PrimaryGeneratedColumn,\n} from \"typeorm\";\n\n/**\n * Append-only audit trail for every balance mutation. Used for\n * reconciliation, customer support, and regulatory reporting.\n *\n * Sign convention:\n * - positive `delta` — credit (merchant award, refund, manual top-up)\n * - negative `delta` — debit (mint confirmation against the off-chain\n * balance; `txHash` references the on-chain Mint event)\n */\n@Entity({ name: \"ledger_journal\" })\n@Index([\"userAddress\", \"createdAt\"])\nexport class LedgerJournalEntity {\n @PrimaryGeneratedColumn(\"uuid\")\n id!: string;\n\n @Column({ name: \"user_address\", type: \"varchar\", length: 42 })\n userAddress!: string;\n\n @Column({ name: \"token_address\", type: \"varchar\", length: 42 })\n tokenAddress!: string;\n\n @Column({\n name: \"delta\",\n type: \"numeric\",\n precision: 78,\n scale: 0,\n transformer: {\n to: (value: bigint) => value.toString(),\n from: (value: string) => BigInt(value),\n },\n })\n delta!: bigint;\n\n @Column({ name: \"reason\", type: \"varchar\", length: 128 })\n reason!: string;\n\n @Column({ name: \"tx_hash\", type: \"varchar\", length: 66, nullable: true })\n txHash?: string | null;\n\n @CreateDateColumn({ name: \"created_at\" })\n createdAt!: Date;\n}\n","import { Column, Entity, PrimaryColumn, UpdateDateColumn } from \"typeorm\";\n\n/**\n * Persistent cursor for `PointIndexer` / `BurnIndexer`. Multiple rows\n * coexist keyed by `id` (e.g. `default` for the mint indexer,\n * `burn:0x...` for each per-token burn indexer).\n *\n * Stores the **next** block to scan, not the last processed one.\n * Indexer reads on startup and resumes from there.\n */\n@Entity({ name: \"indexer_cursors\" })\nexport class IndexerCursorEntity {\n @PrimaryColumn({ type: \"varchar\", length: 64 })\n id!: string;\n\n @Column({\n name: \"next_block\",\n type: \"numeric\",\n precision: 78,\n scale: 0,\n transformer: {\n to: (value: bigint) => value.toString(),\n from: (value: string) => BigInt(value),\n },\n })\n nextBlock!: bigint;\n\n @UpdateDateColumn({ name: \"updated_at\" })\n updatedAt!: Date;\n}\n","import type { DataSource } from \"typeorm\";\nimport type { IIndexerCursorStore } from \"@pafi-dev/issuer\";\n\nimport { IndexerCursorEntity } from \"./entities/indexer-cursor.entity\";\n\n/**\n * Postgres-backed indexer cursor store. Lets indexers survive\n * restarts — on boot, the indexer reads the last persisted block and\n * resumes scanning from there.\n *\n * Multiple indexers (e.g. `PointIndexer` for Mint events +\n * `BurnIndexer` per token for Transfer→0x0) share the same table via\n * different `cursorId`s. Construct with `cursorId = \"default\"` for\n * the primary mint indexer, or call `forKey(id)` to derive a sibling\n * store for a secondary indexer.\n */\nexport class PostgresCursorStore implements IIndexerCursorStore {\n constructor(\n private readonly dataSource: DataSource,\n private readonly cursorId: string = \"default\",\n ) {}\n\n async load(): Promise<bigint | undefined> {\n const row = await this.dataSource\n .getRepository(IndexerCursorEntity)\n .findOne({ where: { id: this.cursorId } });\n return row?.nextBlock;\n }\n\n async save(blockNumber: bigint): Promise<void> {\n await this.dataSource\n .getRepository(IndexerCursorEntity)\n .upsert(\n { id: this.cursorId, nextBlock: blockNumber },\n { conflictPaths: [\"id\"] },\n );\n }\n\n /** Derived store keyed by a different `id` — for sibling indexers. */\n forKey(cursorId: string): IIndexerCursorStore {\n return new PostgresCursorStore(this.dataSource, cursorId);\n }\n}\n","export { LockedMintEntity } from \"./locked-mint.entity\";\nexport {\n PendingCreditEntity,\n type PendingCreditStatus,\n} from \"./pending-credit.entity\";\nexport { UserBalanceEntity } from \"./user-balance.entity\";\nexport { LedgerJournalEntity } from \"./ledger-journal.entity\";\nexport { IndexerCursorEntity } from \"./indexer-cursor.entity\";\n\nimport { LockedMintEntity } from \"./locked-mint.entity\";\nimport { PendingCreditEntity } from \"./pending-credit.entity\";\nimport { UserBalanceEntity } from \"./user-balance.entity\";\nimport { LedgerJournalEntity } from \"./ledger-journal.entity\";\nimport { IndexerCursorEntity } from \"./indexer-cursor.entity\";\n\n/**\n * All entities in one array — drop into TypeORM's `entities` config or\n * NestJS's `TypeOrmModule.forFeature(PAFI_ENTITIES)`.\n */\nexport const PAFI_ENTITIES = [\n LockedMintEntity,\n PendingCreditEntity,\n UserBalanceEntity,\n LedgerJournalEntity,\n IndexerCursorEntity,\n] as const;\n","import type { MigrationInterface, QueryRunner } from \"typeorm\";\n\n/**\n * Single consolidated initial schema for `@pafi-dev/issuer-postgres`.\n *\n * Combines what gg56 split into two migrations (`InitialSchema` +\n * `AddPendingCredits`) plus the `user_op_hash` column, since this is\n * the v1.4-and-after baseline. Issuers adopting the SDK from scratch\n * apply this once.\n *\n * Tables:\n * user_balances — off-chain point balance per (user, token)\n * locked_mint_requests — reservations during mint flow\n * pending_credits — reserved credits during burn/redeem flow\n * ledger_journal — append-only audit trail of every delta\n * indexer_cursors — PointIndexer / BurnIndexer block cursors\n *\n * Issuer-specific extensions (campaign rules, KYC tables, custom\n * scenarios) belong in a follow-up migration — never edit this file\n * in place once it ships.\n */\nexport class InitialSchema1700000000000 implements MigrationInterface {\n name = \"InitialSchema1700000000000\";\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS \"pgcrypto\"`);\n\n // ─── user_balances ──────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"user_balances\" (\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"balance\" numeric(78, 0) NOT NULL DEFAULT 0,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_user_balances\" PRIMARY KEY (\"user_address\", \"token_address\")\n )\n `);\n\n // ─── locked_mint_requests ───────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"locked_mint_requests\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"amount\" numeric(78, 0) NOT NULL,\n \"status\" varchar(16) NOT NULL DEFAULT 'PENDING',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n \"expires_at\" TIMESTAMP WITH TIME ZONE NOT NULL,\n \"tx_hash\" varchar(66),\n \"user_op_hash\" varchar(66),\n CONSTRAINT \"PK_locked_mint_requests\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_locked_mint_user_status\"\n ON \"locked_mint_requests\" (\"user_address\", \"token_address\", \"status\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_locked_mint_user_op_hash\"\n ON \"locked_mint_requests\" (\"user_op_hash\")\n `);\n\n // ─── pending_credits ────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"pending_credits\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"amount\" numeric(78, 0) NOT NULL,\n \"status\" varchar(16) NOT NULL DEFAULT 'PENDING',\n \"tx_hash\" varchar(66),\n \"user_op_hash\" varchar(66),\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n \"expires_at\" TIMESTAMP WITH TIME ZONE NOT NULL,\n \"resolved_at\" TIMESTAMP WITH TIME ZONE,\n CONSTRAINT \"PK_pending_credits\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_user_status\"\n ON \"pending_credits\" (\"user_address\", \"token_address\", \"status\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_tx_hash\"\n ON \"pending_credits\" (\"tx_hash\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_user_op_hash\"\n ON \"pending_credits\" (\"user_op_hash\")\n `);\n\n // ─── ledger_journal ─────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"ledger_journal\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"delta\" numeric(78, 0) NOT NULL,\n \"reason\" varchar(128) NOT NULL,\n \"tx_hash\" varchar(66),\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_ledger_journal\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_ledger_journal_user_created\"\n ON \"ledger_journal\" (\"user_address\", \"token_address\", \"created_at\")\n `);\n\n // ─── indexer_cursors ────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"indexer_cursors\" (\n \"id\" varchar(64) NOT NULL,\n \"next_block\" numeric(78, 0) NOT NULL,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_indexer_cursors\" PRIMARY KEY (\"id\")\n )\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`DROP TABLE \"indexer_cursors\"`);\n await queryRunner.query(`DROP INDEX \"IDX_ledger_journal_user_created\"`);\n await queryRunner.query(`DROP TABLE \"ledger_journal\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_user_op_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_tx_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_user_status\"`);\n await queryRunner.query(`DROP TABLE \"pending_credits\"`);\n await queryRunner.query(`DROP INDEX \"IDX_locked_mint_user_op_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_locked_mint_user_status\"`);\n await queryRunner.query(`DROP TABLE \"locked_mint_requests\"`);\n await queryRunner.query(`DROP TABLE \"user_balances\"`);\n }\n}\n","export { InitialSchema1700000000000 } from \"./1700000000000-InitialSchema\";\n\nimport { InitialSchema1700000000000 } from \"./1700000000000-InitialSchema\";\n\n/**\n * All shipped migrations in chronological order. Drop into TypeORM's\n * `migrations` config:\n *\n * import { PAFI_MIGRATIONS } from \"@pafi-dev/issuer-postgres/migrations\";\n *\n * new DataSource({\n * entities: [...PAFI_ENTITIES, ...yourCustomEntities],\n * migrations: [...PAFI_MIGRATIONS, ...yourCustomMigrations],\n * });\n */\nexport const PAFI_MIGRATIONS = [InitialSchema1700000000000] as const;\n"],"mappings":"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","names":["Column","CreateDateColumn","Entity","Index","PrimaryGeneratedColumn","PrimaryGeneratedColumn","Column","CreateDateColumn","Entity","Index","Column","Entity","Column","Entity","Column","CreateDateColumn","Entity","Index","PrimaryGeneratedColumn","PrimaryGeneratedColumn","Column","CreateDateColumn","Entity","Index","Column","Entity","PrimaryColumn","UpdateDateColumn","PrimaryColumn","Column","UpdateDateColumn","Entity"]}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/migrations/index.ts
|
|
21
|
+
var migrations_exports = {};
|
|
22
|
+
__export(migrations_exports, {
|
|
23
|
+
InitialSchema1700000000000: () => InitialSchema1700000000000,
|
|
24
|
+
PAFI_MIGRATIONS: () => PAFI_MIGRATIONS
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(migrations_exports);
|
|
27
|
+
|
|
28
|
+
// src/migrations/1700000000000-InitialSchema.ts
|
|
29
|
+
var InitialSchema1700000000000 = class {
|
|
30
|
+
name = "InitialSchema1700000000000";
|
|
31
|
+
async up(queryRunner) {
|
|
32
|
+
await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS "pgcrypto"`);
|
|
33
|
+
await queryRunner.query(`
|
|
34
|
+
CREATE TABLE "user_balances" (
|
|
35
|
+
"user_address" varchar(42) NOT NULL,
|
|
36
|
+
"token_address" varchar(42) NOT NULL,
|
|
37
|
+
"balance" numeric(78, 0) NOT NULL DEFAULT 0,
|
|
38
|
+
"updated_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
39
|
+
CONSTRAINT "PK_user_balances" PRIMARY KEY ("user_address", "token_address")
|
|
40
|
+
)
|
|
41
|
+
`);
|
|
42
|
+
await queryRunner.query(`
|
|
43
|
+
CREATE TABLE "locked_mint_requests" (
|
|
44
|
+
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
45
|
+
"user_address" varchar(42) NOT NULL,
|
|
46
|
+
"token_address" varchar(42) NOT NULL,
|
|
47
|
+
"amount" numeric(78, 0) NOT NULL,
|
|
48
|
+
"status" varchar(16) NOT NULL DEFAULT 'PENDING',
|
|
49
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
50
|
+
"expires_at" TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
51
|
+
"tx_hash" varchar(66),
|
|
52
|
+
"user_op_hash" varchar(66),
|
|
53
|
+
CONSTRAINT "PK_locked_mint_requests" PRIMARY KEY ("id")
|
|
54
|
+
)
|
|
55
|
+
`);
|
|
56
|
+
await queryRunner.query(`
|
|
57
|
+
CREATE INDEX "IDX_locked_mint_user_status"
|
|
58
|
+
ON "locked_mint_requests" ("user_address", "token_address", "status")
|
|
59
|
+
`);
|
|
60
|
+
await queryRunner.query(`
|
|
61
|
+
CREATE INDEX "IDX_locked_mint_user_op_hash"
|
|
62
|
+
ON "locked_mint_requests" ("user_op_hash")
|
|
63
|
+
`);
|
|
64
|
+
await queryRunner.query(`
|
|
65
|
+
CREATE TABLE "pending_credits" (
|
|
66
|
+
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
67
|
+
"user_address" varchar(42) NOT NULL,
|
|
68
|
+
"token_address" varchar(42) NOT NULL,
|
|
69
|
+
"amount" numeric(78, 0) NOT NULL,
|
|
70
|
+
"status" varchar(16) NOT NULL DEFAULT 'PENDING',
|
|
71
|
+
"tx_hash" varchar(66),
|
|
72
|
+
"user_op_hash" varchar(66),
|
|
73
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
74
|
+
"expires_at" TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
75
|
+
"resolved_at" TIMESTAMP WITH TIME ZONE,
|
|
76
|
+
CONSTRAINT "PK_pending_credits" PRIMARY KEY ("id")
|
|
77
|
+
)
|
|
78
|
+
`);
|
|
79
|
+
await queryRunner.query(`
|
|
80
|
+
CREATE INDEX "IDX_pending_credits_user_status"
|
|
81
|
+
ON "pending_credits" ("user_address", "token_address", "status")
|
|
82
|
+
`);
|
|
83
|
+
await queryRunner.query(`
|
|
84
|
+
CREATE INDEX "IDX_pending_credits_tx_hash"
|
|
85
|
+
ON "pending_credits" ("tx_hash")
|
|
86
|
+
`);
|
|
87
|
+
await queryRunner.query(`
|
|
88
|
+
CREATE INDEX "IDX_pending_credits_user_op_hash"
|
|
89
|
+
ON "pending_credits" ("user_op_hash")
|
|
90
|
+
`);
|
|
91
|
+
await queryRunner.query(`
|
|
92
|
+
CREATE TABLE "ledger_journal" (
|
|
93
|
+
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
94
|
+
"user_address" varchar(42) NOT NULL,
|
|
95
|
+
"token_address" varchar(42) NOT NULL,
|
|
96
|
+
"delta" numeric(78, 0) NOT NULL,
|
|
97
|
+
"reason" varchar(128) NOT NULL,
|
|
98
|
+
"tx_hash" varchar(66),
|
|
99
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
100
|
+
CONSTRAINT "PK_ledger_journal" PRIMARY KEY ("id")
|
|
101
|
+
)
|
|
102
|
+
`);
|
|
103
|
+
await queryRunner.query(`
|
|
104
|
+
CREATE INDEX "IDX_ledger_journal_user_created"
|
|
105
|
+
ON "ledger_journal" ("user_address", "token_address", "created_at")
|
|
106
|
+
`);
|
|
107
|
+
await queryRunner.query(`
|
|
108
|
+
CREATE TABLE "indexer_cursors" (
|
|
109
|
+
"id" varchar(64) NOT NULL,
|
|
110
|
+
"next_block" numeric(78, 0) NOT NULL,
|
|
111
|
+
"updated_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
112
|
+
CONSTRAINT "PK_indexer_cursors" PRIMARY KEY ("id")
|
|
113
|
+
)
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
async down(queryRunner) {
|
|
117
|
+
await queryRunner.query(`DROP TABLE "indexer_cursors"`);
|
|
118
|
+
await queryRunner.query(`DROP INDEX "IDX_ledger_journal_user_created"`);
|
|
119
|
+
await queryRunner.query(`DROP TABLE "ledger_journal"`);
|
|
120
|
+
await queryRunner.query(`DROP INDEX "IDX_pending_credits_user_op_hash"`);
|
|
121
|
+
await queryRunner.query(`DROP INDEX "IDX_pending_credits_tx_hash"`);
|
|
122
|
+
await queryRunner.query(`DROP INDEX "IDX_pending_credits_user_status"`);
|
|
123
|
+
await queryRunner.query(`DROP TABLE "pending_credits"`);
|
|
124
|
+
await queryRunner.query(`DROP INDEX "IDX_locked_mint_user_op_hash"`);
|
|
125
|
+
await queryRunner.query(`DROP INDEX "IDX_locked_mint_user_status"`);
|
|
126
|
+
await queryRunner.query(`DROP TABLE "locked_mint_requests"`);
|
|
127
|
+
await queryRunner.query(`DROP TABLE "user_balances"`);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// src/migrations/index.ts
|
|
132
|
+
var PAFI_MIGRATIONS = [InitialSchema1700000000000];
|
|
133
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
134
|
+
0 && (module.exports = {
|
|
135
|
+
InitialSchema1700000000000,
|
|
136
|
+
PAFI_MIGRATIONS
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/migrations/index.ts","../../src/migrations/1700000000000-InitialSchema.ts"],"sourcesContent":["export { InitialSchema1700000000000 } from \"./1700000000000-InitialSchema\";\n\nimport { InitialSchema1700000000000 } from \"./1700000000000-InitialSchema\";\n\n/**\n * All shipped migrations in chronological order. Drop into TypeORM's\n * `migrations` config:\n *\n * import { PAFI_MIGRATIONS } from \"@pafi-dev/issuer-postgres/migrations\";\n *\n * new DataSource({\n * entities: [...PAFI_ENTITIES, ...yourCustomEntities],\n * migrations: [...PAFI_MIGRATIONS, ...yourCustomMigrations],\n * });\n */\nexport const PAFI_MIGRATIONS = [InitialSchema1700000000000] as const;\n","import type { MigrationInterface, QueryRunner } from \"typeorm\";\n\n/**\n * Single consolidated initial schema for `@pafi-dev/issuer-postgres`.\n *\n * Combines what gg56 split into two migrations (`InitialSchema` +\n * `AddPendingCredits`) plus the `user_op_hash` column, since this is\n * the v1.4-and-after baseline. Issuers adopting the SDK from scratch\n * apply this once.\n *\n * Tables:\n * user_balances — off-chain point balance per (user, token)\n * locked_mint_requests — reservations during mint flow\n * pending_credits — reserved credits during burn/redeem flow\n * ledger_journal — append-only audit trail of every delta\n * indexer_cursors — PointIndexer / BurnIndexer block cursors\n *\n * Issuer-specific extensions (campaign rules, KYC tables, custom\n * scenarios) belong in a follow-up migration — never edit this file\n * in place once it ships.\n */\nexport class InitialSchema1700000000000 implements MigrationInterface {\n name = \"InitialSchema1700000000000\";\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS \"pgcrypto\"`);\n\n // ─── user_balances ──────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"user_balances\" (\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"balance\" numeric(78, 0) NOT NULL DEFAULT 0,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_user_balances\" PRIMARY KEY (\"user_address\", \"token_address\")\n )\n `);\n\n // ─── locked_mint_requests ───────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"locked_mint_requests\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"amount\" numeric(78, 0) NOT NULL,\n \"status\" varchar(16) NOT NULL DEFAULT 'PENDING',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n \"expires_at\" TIMESTAMP WITH TIME ZONE NOT NULL,\n \"tx_hash\" varchar(66),\n \"user_op_hash\" varchar(66),\n CONSTRAINT \"PK_locked_mint_requests\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_locked_mint_user_status\"\n ON \"locked_mint_requests\" (\"user_address\", \"token_address\", \"status\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_locked_mint_user_op_hash\"\n ON \"locked_mint_requests\" (\"user_op_hash\")\n `);\n\n // ─── pending_credits ────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"pending_credits\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"amount\" numeric(78, 0) NOT NULL,\n \"status\" varchar(16) NOT NULL DEFAULT 'PENDING',\n \"tx_hash\" varchar(66),\n \"user_op_hash\" varchar(66),\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n \"expires_at\" TIMESTAMP WITH TIME ZONE NOT NULL,\n \"resolved_at\" TIMESTAMP WITH TIME ZONE,\n CONSTRAINT \"PK_pending_credits\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_user_status\"\n ON \"pending_credits\" (\"user_address\", \"token_address\", \"status\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_tx_hash\"\n ON \"pending_credits\" (\"tx_hash\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_user_op_hash\"\n ON \"pending_credits\" (\"user_op_hash\")\n `);\n\n // ─── ledger_journal ─────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"ledger_journal\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"delta\" numeric(78, 0) NOT NULL,\n \"reason\" varchar(128) NOT NULL,\n \"tx_hash\" varchar(66),\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_ledger_journal\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_ledger_journal_user_created\"\n ON \"ledger_journal\" (\"user_address\", \"token_address\", \"created_at\")\n `);\n\n // ─── indexer_cursors ────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"indexer_cursors\" (\n \"id\" varchar(64) NOT NULL,\n \"next_block\" numeric(78, 0) NOT NULL,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_indexer_cursors\" PRIMARY KEY (\"id\")\n )\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`DROP TABLE \"indexer_cursors\"`);\n await queryRunner.query(`DROP INDEX \"IDX_ledger_journal_user_created\"`);\n await queryRunner.query(`DROP TABLE \"ledger_journal\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_user_op_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_tx_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_user_status\"`);\n await queryRunner.query(`DROP TABLE \"pending_credits\"`);\n await queryRunner.query(`DROP INDEX \"IDX_locked_mint_user_op_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_locked_mint_user_status\"`);\n await queryRunner.query(`DROP TABLE \"locked_mint_requests\"`);\n await queryRunner.query(`DROP TABLE \"user_balances\"`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqBO,IAAM,6BAAN,MAA+D;AAAA,EACpE,OAAO;AAAA,EAEP,MAAa,GAAG,aAAyC;AACvD,UAAM,YAAY,MAAM,2CAA2C;AAGnE,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAQvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAavB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAcvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAWvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAOvB;AAAA,EACH;AAAA,EAEA,MAAa,KAAK,aAAyC;AACzD,UAAM,YAAY,MAAM,8BAA8B;AACtD,UAAM,YAAY,MAAM,8CAA8C;AACtE,UAAM,YAAY,MAAM,6BAA6B;AACrD,UAAM,YAAY,MAAM,+CAA+C;AACvE,UAAM,YAAY,MAAM,0CAA0C;AAClE,UAAM,YAAY,MAAM,8CAA8C;AACtE,UAAM,YAAY,MAAM,8BAA8B;AACtD,UAAM,YAAY,MAAM,2CAA2C;AACnE,UAAM,YAAY,MAAM,0CAA0C;AAClE,UAAM,YAAY,MAAM,mCAAmC;AAC3D,UAAM,YAAY,MAAM,4BAA4B;AAAA,EACtD;AACF;;;ADtHO,IAAM,kBAAkB,CAAC,0BAA0B;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Single consolidated initial schema for `@pafi-dev/issuer-postgres`.
|
|
5
|
+
*
|
|
6
|
+
* Combines what gg56 split into two migrations (`InitialSchema` +
|
|
7
|
+
* `AddPendingCredits`) plus the `user_op_hash` column, since this is
|
|
8
|
+
* the v1.4-and-after baseline. Issuers adopting the SDK from scratch
|
|
9
|
+
* apply this once.
|
|
10
|
+
*
|
|
11
|
+
* Tables:
|
|
12
|
+
* user_balances — off-chain point balance per (user, token)
|
|
13
|
+
* locked_mint_requests — reservations during mint flow
|
|
14
|
+
* pending_credits — reserved credits during burn/redeem flow
|
|
15
|
+
* ledger_journal — append-only audit trail of every delta
|
|
16
|
+
* indexer_cursors — PointIndexer / BurnIndexer block cursors
|
|
17
|
+
*
|
|
18
|
+
* Issuer-specific extensions (campaign rules, KYC tables, custom
|
|
19
|
+
* scenarios) belong in a follow-up migration — never edit this file
|
|
20
|
+
* in place once it ships.
|
|
21
|
+
*/
|
|
22
|
+
declare class InitialSchema1700000000000 implements MigrationInterface {
|
|
23
|
+
name: string;
|
|
24
|
+
up(queryRunner: QueryRunner): Promise<void>;
|
|
25
|
+
down(queryRunner: QueryRunner): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* All shipped migrations in chronological order. Drop into TypeORM's
|
|
30
|
+
* `migrations` config:
|
|
31
|
+
*
|
|
32
|
+
* import { PAFI_MIGRATIONS } from "@pafi-dev/issuer-postgres/migrations";
|
|
33
|
+
*
|
|
34
|
+
* new DataSource({
|
|
35
|
+
* entities: [...PAFI_ENTITIES, ...yourCustomEntities],
|
|
36
|
+
* migrations: [...PAFI_MIGRATIONS, ...yourCustomMigrations],
|
|
37
|
+
* });
|
|
38
|
+
*/
|
|
39
|
+
declare const PAFI_MIGRATIONS: readonly [typeof InitialSchema1700000000000];
|
|
40
|
+
|
|
41
|
+
export { InitialSchema1700000000000, PAFI_MIGRATIONS };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Single consolidated initial schema for `@pafi-dev/issuer-postgres`.
|
|
5
|
+
*
|
|
6
|
+
* Combines what gg56 split into two migrations (`InitialSchema` +
|
|
7
|
+
* `AddPendingCredits`) plus the `user_op_hash` column, since this is
|
|
8
|
+
* the v1.4-and-after baseline. Issuers adopting the SDK from scratch
|
|
9
|
+
* apply this once.
|
|
10
|
+
*
|
|
11
|
+
* Tables:
|
|
12
|
+
* user_balances — off-chain point balance per (user, token)
|
|
13
|
+
* locked_mint_requests — reservations during mint flow
|
|
14
|
+
* pending_credits — reserved credits during burn/redeem flow
|
|
15
|
+
* ledger_journal — append-only audit trail of every delta
|
|
16
|
+
* indexer_cursors — PointIndexer / BurnIndexer block cursors
|
|
17
|
+
*
|
|
18
|
+
* Issuer-specific extensions (campaign rules, KYC tables, custom
|
|
19
|
+
* scenarios) belong in a follow-up migration — never edit this file
|
|
20
|
+
* in place once it ships.
|
|
21
|
+
*/
|
|
22
|
+
declare class InitialSchema1700000000000 implements MigrationInterface {
|
|
23
|
+
name: string;
|
|
24
|
+
up(queryRunner: QueryRunner): Promise<void>;
|
|
25
|
+
down(queryRunner: QueryRunner): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* All shipped migrations in chronological order. Drop into TypeORM's
|
|
30
|
+
* `migrations` config:
|
|
31
|
+
*
|
|
32
|
+
* import { PAFI_MIGRATIONS } from "@pafi-dev/issuer-postgres/migrations";
|
|
33
|
+
*
|
|
34
|
+
* new DataSource({
|
|
35
|
+
* entities: [...PAFI_ENTITIES, ...yourCustomEntities],
|
|
36
|
+
* migrations: [...PAFI_MIGRATIONS, ...yourCustomMigrations],
|
|
37
|
+
* });
|
|
38
|
+
*/
|
|
39
|
+
declare const PAFI_MIGRATIONS: readonly [typeof InitialSchema1700000000000];
|
|
40
|
+
|
|
41
|
+
export { InitialSchema1700000000000, PAFI_MIGRATIONS };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// src/migrations/1700000000000-InitialSchema.ts
|
|
2
|
+
var InitialSchema1700000000000 = class {
|
|
3
|
+
name = "InitialSchema1700000000000";
|
|
4
|
+
async up(queryRunner) {
|
|
5
|
+
await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS "pgcrypto"`);
|
|
6
|
+
await queryRunner.query(`
|
|
7
|
+
CREATE TABLE "user_balances" (
|
|
8
|
+
"user_address" varchar(42) NOT NULL,
|
|
9
|
+
"token_address" varchar(42) NOT NULL,
|
|
10
|
+
"balance" numeric(78, 0) NOT NULL DEFAULT 0,
|
|
11
|
+
"updated_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
12
|
+
CONSTRAINT "PK_user_balances" PRIMARY KEY ("user_address", "token_address")
|
|
13
|
+
)
|
|
14
|
+
`);
|
|
15
|
+
await queryRunner.query(`
|
|
16
|
+
CREATE TABLE "locked_mint_requests" (
|
|
17
|
+
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
18
|
+
"user_address" varchar(42) NOT NULL,
|
|
19
|
+
"token_address" varchar(42) NOT NULL,
|
|
20
|
+
"amount" numeric(78, 0) NOT NULL,
|
|
21
|
+
"status" varchar(16) NOT NULL DEFAULT 'PENDING',
|
|
22
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
23
|
+
"expires_at" TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
24
|
+
"tx_hash" varchar(66),
|
|
25
|
+
"user_op_hash" varchar(66),
|
|
26
|
+
CONSTRAINT "PK_locked_mint_requests" PRIMARY KEY ("id")
|
|
27
|
+
)
|
|
28
|
+
`);
|
|
29
|
+
await queryRunner.query(`
|
|
30
|
+
CREATE INDEX "IDX_locked_mint_user_status"
|
|
31
|
+
ON "locked_mint_requests" ("user_address", "token_address", "status")
|
|
32
|
+
`);
|
|
33
|
+
await queryRunner.query(`
|
|
34
|
+
CREATE INDEX "IDX_locked_mint_user_op_hash"
|
|
35
|
+
ON "locked_mint_requests" ("user_op_hash")
|
|
36
|
+
`);
|
|
37
|
+
await queryRunner.query(`
|
|
38
|
+
CREATE TABLE "pending_credits" (
|
|
39
|
+
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
40
|
+
"user_address" varchar(42) NOT NULL,
|
|
41
|
+
"token_address" varchar(42) NOT NULL,
|
|
42
|
+
"amount" numeric(78, 0) NOT NULL,
|
|
43
|
+
"status" varchar(16) NOT NULL DEFAULT 'PENDING',
|
|
44
|
+
"tx_hash" varchar(66),
|
|
45
|
+
"user_op_hash" varchar(66),
|
|
46
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
47
|
+
"expires_at" TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
48
|
+
"resolved_at" TIMESTAMP WITH TIME ZONE,
|
|
49
|
+
CONSTRAINT "PK_pending_credits" PRIMARY KEY ("id")
|
|
50
|
+
)
|
|
51
|
+
`);
|
|
52
|
+
await queryRunner.query(`
|
|
53
|
+
CREATE INDEX "IDX_pending_credits_user_status"
|
|
54
|
+
ON "pending_credits" ("user_address", "token_address", "status")
|
|
55
|
+
`);
|
|
56
|
+
await queryRunner.query(`
|
|
57
|
+
CREATE INDEX "IDX_pending_credits_tx_hash"
|
|
58
|
+
ON "pending_credits" ("tx_hash")
|
|
59
|
+
`);
|
|
60
|
+
await queryRunner.query(`
|
|
61
|
+
CREATE INDEX "IDX_pending_credits_user_op_hash"
|
|
62
|
+
ON "pending_credits" ("user_op_hash")
|
|
63
|
+
`);
|
|
64
|
+
await queryRunner.query(`
|
|
65
|
+
CREATE TABLE "ledger_journal" (
|
|
66
|
+
"id" uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
67
|
+
"user_address" varchar(42) NOT NULL,
|
|
68
|
+
"token_address" varchar(42) NOT NULL,
|
|
69
|
+
"delta" numeric(78, 0) NOT NULL,
|
|
70
|
+
"reason" varchar(128) NOT NULL,
|
|
71
|
+
"tx_hash" varchar(66),
|
|
72
|
+
"created_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
73
|
+
CONSTRAINT "PK_ledger_journal" PRIMARY KEY ("id")
|
|
74
|
+
)
|
|
75
|
+
`);
|
|
76
|
+
await queryRunner.query(`
|
|
77
|
+
CREATE INDEX "IDX_ledger_journal_user_created"
|
|
78
|
+
ON "ledger_journal" ("user_address", "token_address", "created_at")
|
|
79
|
+
`);
|
|
80
|
+
await queryRunner.query(`
|
|
81
|
+
CREATE TABLE "indexer_cursors" (
|
|
82
|
+
"id" varchar(64) NOT NULL,
|
|
83
|
+
"next_block" numeric(78, 0) NOT NULL,
|
|
84
|
+
"updated_at" TIMESTAMP NOT NULL DEFAULT now(),
|
|
85
|
+
CONSTRAINT "PK_indexer_cursors" PRIMARY KEY ("id")
|
|
86
|
+
)
|
|
87
|
+
`);
|
|
88
|
+
}
|
|
89
|
+
async down(queryRunner) {
|
|
90
|
+
await queryRunner.query(`DROP TABLE "indexer_cursors"`);
|
|
91
|
+
await queryRunner.query(`DROP INDEX "IDX_ledger_journal_user_created"`);
|
|
92
|
+
await queryRunner.query(`DROP TABLE "ledger_journal"`);
|
|
93
|
+
await queryRunner.query(`DROP INDEX "IDX_pending_credits_user_op_hash"`);
|
|
94
|
+
await queryRunner.query(`DROP INDEX "IDX_pending_credits_tx_hash"`);
|
|
95
|
+
await queryRunner.query(`DROP INDEX "IDX_pending_credits_user_status"`);
|
|
96
|
+
await queryRunner.query(`DROP TABLE "pending_credits"`);
|
|
97
|
+
await queryRunner.query(`DROP INDEX "IDX_locked_mint_user_op_hash"`);
|
|
98
|
+
await queryRunner.query(`DROP INDEX "IDX_locked_mint_user_status"`);
|
|
99
|
+
await queryRunner.query(`DROP TABLE "locked_mint_requests"`);
|
|
100
|
+
await queryRunner.query(`DROP TABLE "user_balances"`);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// src/migrations/index.ts
|
|
105
|
+
var PAFI_MIGRATIONS = [InitialSchema1700000000000];
|
|
106
|
+
export {
|
|
107
|
+
InitialSchema1700000000000,
|
|
108
|
+
PAFI_MIGRATIONS
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/migrations/1700000000000-InitialSchema.ts","../../src/migrations/index.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from \"typeorm\";\n\n/**\n * Single consolidated initial schema for `@pafi-dev/issuer-postgres`.\n *\n * Combines what gg56 split into two migrations (`InitialSchema` +\n * `AddPendingCredits`) plus the `user_op_hash` column, since this is\n * the v1.4-and-after baseline. Issuers adopting the SDK from scratch\n * apply this once.\n *\n * Tables:\n * user_balances — off-chain point balance per (user, token)\n * locked_mint_requests — reservations during mint flow\n * pending_credits — reserved credits during burn/redeem flow\n * ledger_journal — append-only audit trail of every delta\n * indexer_cursors — PointIndexer / BurnIndexer block cursors\n *\n * Issuer-specific extensions (campaign rules, KYC tables, custom\n * scenarios) belong in a follow-up migration — never edit this file\n * in place once it ships.\n */\nexport class InitialSchema1700000000000 implements MigrationInterface {\n name = \"InitialSchema1700000000000\";\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS \"pgcrypto\"`);\n\n // ─── user_balances ──────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"user_balances\" (\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"balance\" numeric(78, 0) NOT NULL DEFAULT 0,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_user_balances\" PRIMARY KEY (\"user_address\", \"token_address\")\n )\n `);\n\n // ─── locked_mint_requests ───────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"locked_mint_requests\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"amount\" numeric(78, 0) NOT NULL,\n \"status\" varchar(16) NOT NULL DEFAULT 'PENDING',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n \"expires_at\" TIMESTAMP WITH TIME ZONE NOT NULL,\n \"tx_hash\" varchar(66),\n \"user_op_hash\" varchar(66),\n CONSTRAINT \"PK_locked_mint_requests\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_locked_mint_user_status\"\n ON \"locked_mint_requests\" (\"user_address\", \"token_address\", \"status\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_locked_mint_user_op_hash\"\n ON \"locked_mint_requests\" (\"user_op_hash\")\n `);\n\n // ─── pending_credits ────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"pending_credits\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"amount\" numeric(78, 0) NOT NULL,\n \"status\" varchar(16) NOT NULL DEFAULT 'PENDING',\n \"tx_hash\" varchar(66),\n \"user_op_hash\" varchar(66),\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n \"expires_at\" TIMESTAMP WITH TIME ZONE NOT NULL,\n \"resolved_at\" TIMESTAMP WITH TIME ZONE,\n CONSTRAINT \"PK_pending_credits\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_user_status\"\n ON \"pending_credits\" (\"user_address\", \"token_address\", \"status\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_tx_hash\"\n ON \"pending_credits\" (\"tx_hash\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_pending_credits_user_op_hash\"\n ON \"pending_credits\" (\"user_op_hash\")\n `);\n\n // ─── ledger_journal ─────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"ledger_journal\" (\n \"id\" uuid NOT NULL DEFAULT gen_random_uuid(),\n \"user_address\" varchar(42) NOT NULL,\n \"token_address\" varchar(42) NOT NULL,\n \"delta\" numeric(78, 0) NOT NULL,\n \"reason\" varchar(128) NOT NULL,\n \"tx_hash\" varchar(66),\n \"created_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_ledger_journal\" PRIMARY KEY (\"id\")\n )\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_ledger_journal_user_created\"\n ON \"ledger_journal\" (\"user_address\", \"token_address\", \"created_at\")\n `);\n\n // ─── indexer_cursors ────────────────────────────────────────────\n await queryRunner.query(`\n CREATE TABLE \"indexer_cursors\" (\n \"id\" varchar(64) NOT NULL,\n \"next_block\" numeric(78, 0) NOT NULL,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT now(),\n CONSTRAINT \"PK_indexer_cursors\" PRIMARY KEY (\"id\")\n )\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`DROP TABLE \"indexer_cursors\"`);\n await queryRunner.query(`DROP INDEX \"IDX_ledger_journal_user_created\"`);\n await queryRunner.query(`DROP TABLE \"ledger_journal\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_user_op_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_tx_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_pending_credits_user_status\"`);\n await queryRunner.query(`DROP TABLE \"pending_credits\"`);\n await queryRunner.query(`DROP INDEX \"IDX_locked_mint_user_op_hash\"`);\n await queryRunner.query(`DROP INDEX \"IDX_locked_mint_user_status\"`);\n await queryRunner.query(`DROP TABLE \"locked_mint_requests\"`);\n await queryRunner.query(`DROP TABLE \"user_balances\"`);\n }\n}\n","export { InitialSchema1700000000000 } from \"./1700000000000-InitialSchema\";\n\nimport { InitialSchema1700000000000 } from \"./1700000000000-InitialSchema\";\n\n/**\n * All shipped migrations in chronological order. Drop into TypeORM's\n * `migrations` config:\n *\n * import { PAFI_MIGRATIONS } from \"@pafi-dev/issuer-postgres/migrations\";\n *\n * new DataSource({\n * entities: [...PAFI_ENTITIES, ...yourCustomEntities],\n * migrations: [...PAFI_MIGRATIONS, ...yourCustomMigrations],\n * });\n */\nexport const PAFI_MIGRATIONS = [InitialSchema1700000000000] as const;\n"],"mappings":";AAqBO,IAAM,6BAAN,MAA+D;AAAA,EACpE,OAAO;AAAA,EAEP,MAAa,GAAG,aAAyC;AACvD,UAAM,YAAY,MAAM,2CAA2C;AAGnE,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAQvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAavB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAcvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAWvB;AACD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA,KAGvB;AAGD,UAAM,YAAY,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAOvB;AAAA,EACH;AAAA,EAEA,MAAa,KAAK,aAAyC;AACzD,UAAM,YAAY,MAAM,8BAA8B;AACtD,UAAM,YAAY,MAAM,8CAA8C;AACtE,UAAM,YAAY,MAAM,6BAA6B;AACrD,UAAM,YAAY,MAAM,+CAA+C;AACvE,UAAM,YAAY,MAAM,0CAA0C;AAClE,UAAM,YAAY,MAAM,8CAA8C;AACtE,UAAM,YAAY,MAAM,8BAA8B;AACtD,UAAM,YAAY,MAAM,2CAA2C;AACnE,UAAM,YAAY,MAAM,0CAA0C;AAClE,UAAM,YAAY,MAAM,mCAAmC;AAC3D,UAAM,YAAY,MAAM,4BAA4B;AAAA,EACtD;AACF;;;ACtHO,IAAM,kBAAkB,CAAC,0BAA0B;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pafi-dev/issuer-postgres",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Postgres-backed IPointLedger implementation for @pafi-dev/issuer — TypeORM entities + migrations + base service issuers can drop in directly",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"./entities": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/entities/index.d.ts",
|
|
23
|
+
"default": "./dist/entities/index.js"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/entities/index.d.cts",
|
|
27
|
+
"default": "./dist/entities/index.cjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./migrations": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/migrations/index.d.ts",
|
|
33
|
+
"default": "./dist/migrations/index.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/migrations/index.d.cts",
|
|
37
|
+
"default": "./dist/migrations/index.cjs"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist"
|
|
43
|
+
],
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@pafi-dev/issuer": "0.5.34"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"typeorm": "^0.3.0",
|
|
49
|
+
"viem": "^2.0.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"tsup": "^8.0.0",
|
|
53
|
+
"typescript": "^5.5.0",
|
|
54
|
+
"typeorm": "^0.3.20",
|
|
55
|
+
"viem": "^2.21.0",
|
|
56
|
+
"vitest": "^2.0.0",
|
|
57
|
+
"reflect-metadata": "^0.1.14"
|
|
58
|
+
},
|
|
59
|
+
"license": "Apache-2.0",
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsup",
|
|
62
|
+
"test": "vitest run --passWithNoTests",
|
|
63
|
+
"test:watch": "vitest",
|
|
64
|
+
"typecheck": "tsc --noEmit"
|
|
65
|
+
}
|
|
66
|
+
}
|