@ocap/statedb-sqlite 1.29.5
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 +66 -0
- package/esm/_virtual/rolldown_runtime.mjs +21 -0
- package/esm/db.d.mts +92 -0
- package/esm/db.mjs +257 -0
- package/esm/index.d.mts +4 -0
- package/esm/index.mjs +7 -0
- package/esm/interfaces.d.mts +201 -0
- package/esm/interfaces.mjs +1 -0
- package/esm/kysely.d.mts +43 -0
- package/esm/kysely.mjs +62 -0
- package/esm/migrations/001-genesis.d.mts +14 -0
- package/esm/migrations/001-genesis.mjs +52 -0
- package/esm/migrations/index.d.mts +24 -0
- package/esm/migrations/index.mjs +60 -0
- package/esm/package.mjs +70 -0
- package/esm/table/account.d.mts +40 -0
- package/esm/table/account.mjs +99 -0
- package/esm/table/balance.d.mts +39 -0
- package/esm/table/balance.mjs +69 -0
- package/esm/table/base.d.mts +84 -0
- package/esm/table/base.mjs +217 -0
- package/esm/table/rollup.d.mts +22 -0
- package/esm/table/rollup.mjs +44 -0
- package/esm/table/token.d.mts +23 -0
- package/esm/table/token.mjs +42 -0
- package/lib/_virtual/rolldown_runtime.cjs +43 -0
- package/lib/db.cjs +259 -0
- package/lib/db.d.cts +92 -0
- package/lib/index.cjs +9 -0
- package/lib/index.d.cts +4 -0
- package/lib/interfaces.cjs +0 -0
- package/lib/interfaces.d.cts +201 -0
- package/lib/kysely.cjs +63 -0
- package/lib/kysely.d.cts +43 -0
- package/lib/migrations/001-genesis.cjs +59 -0
- package/lib/migrations/001-genesis.d.cts +14 -0
- package/lib/migrations/index.cjs +62 -0
- package/lib/migrations/index.d.cts +24 -0
- package/lib/package.cjs +76 -0
- package/lib/table/account.cjs +101 -0
- package/lib/table/account.d.cts +40 -0
- package/lib/table/balance.cjs +71 -0
- package/lib/table/balance.d.cts +39 -0
- package/lib/table/base.cjs +221 -0
- package/lib/table/base.d.cts +84 -0
- package/lib/table/rollup.cjs +45 -0
- package/lib/table/rollup.d.cts +22 -0
- package/lib/table/token.cjs +43 -0
- package/lib/table/token.d.cts +23 -0
- package/package.json +75 -0
package/lib/db.d.cts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Database } from "./interfaces.cjs";
|
|
2
|
+
import { SqliteConfig } from "./kysely.cjs";
|
|
3
|
+
import { StateDB } from "@ocap/statedb";
|
|
4
|
+
import { IAccountState, IAssetFactoryState, IAssetState, IBalanceTable, IChainState, IDelegateState, IEvidenceState, IRollupBlock, IRollupTable, IStakeState, IStateDB, IStateTable, ITokenFactoryState, ITokenTable, ITxState } from "@ocap/types";
|
|
5
|
+
import { Kysely, Transaction } from "kysely";
|
|
6
|
+
|
|
7
|
+
//#region src/db.d.ts
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* SQLite StateDB Implementation
|
|
11
|
+
* Uses SQLite via Kysely as the storage backend
|
|
12
|
+
*/
|
|
13
|
+
declare class SqliteStateDB extends StateDB implements IStateDB {
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
private db;
|
|
17
|
+
private config;
|
|
18
|
+
private initialized;
|
|
19
|
+
balance: IBalanceTable;
|
|
20
|
+
account: IStateTable<IAccountState>;
|
|
21
|
+
factory: IStateTable<IAssetFactoryState>;
|
|
22
|
+
stake: IStateTable<IStakeState>;
|
|
23
|
+
asset: IStateTable<IAssetState>;
|
|
24
|
+
delegation: IStateTable<IDelegateState>;
|
|
25
|
+
tx: IStateTable<ITxState>;
|
|
26
|
+
token: ITokenTable;
|
|
27
|
+
chain: IStateTable<IChainState>;
|
|
28
|
+
rollup: IRollupTable;
|
|
29
|
+
rollupBlock: IStateTable<IRollupBlock>;
|
|
30
|
+
evidence: IStateTable<IEvidenceState>;
|
|
31
|
+
tokenFactory: IStateTable<ITokenFactoryState>;
|
|
32
|
+
/**
|
|
33
|
+
* Creates an instance of SqliteStateDB
|
|
34
|
+
*
|
|
35
|
+
* @param config - SQLite configuration (defaults to in-memory)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // In-memory database for testing
|
|
40
|
+
* const db = new SqliteStateDB();
|
|
41
|
+
* await db.initialize();
|
|
42
|
+
*
|
|
43
|
+
* // File-based database for production
|
|
44
|
+
* const db = new SqliteStateDB({ filename: './data/state.sqlite' });
|
|
45
|
+
* await db.initialize();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
constructor(config?: SqliteConfig);
|
|
49
|
+
/**
|
|
50
|
+
* Synchronous initialization
|
|
51
|
+
* Called from constructor for immediate table availability
|
|
52
|
+
*/
|
|
53
|
+
private initSync;
|
|
54
|
+
/**
|
|
55
|
+
* Async initialization - runs migrations
|
|
56
|
+
* Call this after constructor to ensure database schema is ready
|
|
57
|
+
*/
|
|
58
|
+
initialize(): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Execute multiple operations within a database transaction
|
|
61
|
+
* Provides retry logic for SQLite BUSY errors (lock conflicts)
|
|
62
|
+
*
|
|
63
|
+
* @param fn - Function receiving Kysely transaction object
|
|
64
|
+
* @param options - Optional retry configuration
|
|
65
|
+
* @returns Result of the transaction function
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* await db.runAsLambda(async (txn) => {
|
|
70
|
+
* await txn.insertInto('account').values({ ... }).execute();
|
|
71
|
+
* await txn.updateTable('balance').set({ ... }).execute();
|
|
72
|
+
* });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
runAsLambda<T>(fn: (txn: Transaction<Database>) => T | Promise<T>, options?: {
|
|
76
|
+
retryLimit?: number;
|
|
77
|
+
}): Promise<T>;
|
|
78
|
+
/**
|
|
79
|
+
* Reset all tables (for testing)
|
|
80
|
+
*/
|
|
81
|
+
reset(): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Close database connection
|
|
84
|
+
*/
|
|
85
|
+
close(): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Get the underlying Kysely instance (for advanced operations)
|
|
88
|
+
*/
|
|
89
|
+
getKysely(): Kysely<Database>;
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { SqliteStateDB as default };
|
package/lib/index.cjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
const require_db = require('./db.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/index.ts
|
|
5
|
+
var src_default = require_db.default;
|
|
6
|
+
|
|
7
|
+
//#endregion
|
|
8
|
+
exports.SqliteStateDB = require_db.default;
|
|
9
|
+
exports.default = src_default;
|
package/lib/index.d.cts
ADDED
|
File without changes
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { IOperationContext } from "@ocap/types";
|
|
2
|
+
import { Transaction } from "kysely";
|
|
3
|
+
|
|
4
|
+
//#region src/interfaces.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* SQLite-specific operation context
|
|
8
|
+
* Extends base operation context with optional transaction
|
|
9
|
+
*/
|
|
10
|
+
interface SqliteOperationContext extends IOperationContext {
|
|
11
|
+
txn?: Transaction<Database>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Database schema types for Kysely
|
|
15
|
+
* Each table is defined with its column types
|
|
16
|
+
*/
|
|
17
|
+
interface Database {
|
|
18
|
+
account: AccountTable;
|
|
19
|
+
balance: BalanceTable;
|
|
20
|
+
chain: ChainTable;
|
|
21
|
+
tx: TxTable;
|
|
22
|
+
asset: AssetTable;
|
|
23
|
+
token: TokenTable;
|
|
24
|
+
factory: FactoryTable;
|
|
25
|
+
tokenFactory: TokenFactoryTable;
|
|
26
|
+
stake: StakeTable;
|
|
27
|
+
delegation: DelegationTable;
|
|
28
|
+
rollup: RollupTable;
|
|
29
|
+
rollupBlock: RollupBlockTable;
|
|
30
|
+
evidence: EvidenceTable;
|
|
31
|
+
}
|
|
32
|
+
interface AccountTable {
|
|
33
|
+
address: string;
|
|
34
|
+
balance: string;
|
|
35
|
+
gasBalance: string | null;
|
|
36
|
+
moniker: string | null;
|
|
37
|
+
pk: string | null;
|
|
38
|
+
nonce: number;
|
|
39
|
+
numTxs: number;
|
|
40
|
+
numAssets: number;
|
|
41
|
+
issuer: string | null;
|
|
42
|
+
migratedTo: string | null;
|
|
43
|
+
migratedFrom: string | null;
|
|
44
|
+
stake: string | null;
|
|
45
|
+
tokens: string | null;
|
|
46
|
+
data: string | null;
|
|
47
|
+
context: string | null;
|
|
48
|
+
_retrievedAt: string | null;
|
|
49
|
+
}
|
|
50
|
+
interface BalanceTable {
|
|
51
|
+
address: string;
|
|
52
|
+
tokenAddress: string;
|
|
53
|
+
balance: string;
|
|
54
|
+
context: string | null;
|
|
55
|
+
}
|
|
56
|
+
interface ChainTable {
|
|
57
|
+
address: string;
|
|
58
|
+
chainId: string | null;
|
|
59
|
+
version: string | null;
|
|
60
|
+
accounts: string | null;
|
|
61
|
+
moderator: string | null;
|
|
62
|
+
token: string | null;
|
|
63
|
+
transaction: string | null;
|
|
64
|
+
vaults: string | null;
|
|
65
|
+
context: string | null;
|
|
66
|
+
}
|
|
67
|
+
interface TxTable {
|
|
68
|
+
hash: string;
|
|
69
|
+
code: string | null;
|
|
70
|
+
height: number | null;
|
|
71
|
+
index_: number | null;
|
|
72
|
+
receipts: string | null;
|
|
73
|
+
receiptsVerified: number | null;
|
|
74
|
+
receiver: string | null;
|
|
75
|
+
sender: string | null;
|
|
76
|
+
time: string | null;
|
|
77
|
+
tx: string | null;
|
|
78
|
+
type: string | null;
|
|
79
|
+
finalized: number | null;
|
|
80
|
+
valid: number | null;
|
|
81
|
+
}
|
|
82
|
+
interface AssetTable {
|
|
83
|
+
address: string;
|
|
84
|
+
owner: string | null;
|
|
85
|
+
moniker: string | null;
|
|
86
|
+
readonly: number | null;
|
|
87
|
+
transferrable: number | null;
|
|
88
|
+
issuer: string | null;
|
|
89
|
+
parent: string | null;
|
|
90
|
+
ttl: number | null;
|
|
91
|
+
consumedTime: string | null;
|
|
92
|
+
endpoint: string | null;
|
|
93
|
+
display: string | null;
|
|
94
|
+
tags: string | null;
|
|
95
|
+
stake: string | null;
|
|
96
|
+
data: string | null;
|
|
97
|
+
context: string | null;
|
|
98
|
+
}
|
|
99
|
+
interface TokenTable {
|
|
100
|
+
address: string;
|
|
101
|
+
symbol: string | null;
|
|
102
|
+
name: string | null;
|
|
103
|
+
decimal: number | null;
|
|
104
|
+
unit: string | null;
|
|
105
|
+
description: string | null;
|
|
106
|
+
icon: string | null;
|
|
107
|
+
totalSupply: string | null;
|
|
108
|
+
initialSupply: string | null;
|
|
109
|
+
maxTotalSupply: string | null;
|
|
110
|
+
foreignToken: string | null;
|
|
111
|
+
issuer: string | null;
|
|
112
|
+
website: string | null;
|
|
113
|
+
metadata: string | null;
|
|
114
|
+
tokenFactoryAddress: string | null;
|
|
115
|
+
spenders: string | null;
|
|
116
|
+
minters: string | null;
|
|
117
|
+
type: string | null;
|
|
118
|
+
data: string | null;
|
|
119
|
+
context: string | null;
|
|
120
|
+
}
|
|
121
|
+
interface FactoryTable {
|
|
122
|
+
address: string;
|
|
123
|
+
owner: string | null;
|
|
124
|
+
name: string | null;
|
|
125
|
+
description: string | null;
|
|
126
|
+
settlement: string | null;
|
|
127
|
+
limit: number | null;
|
|
128
|
+
trustedIssuers: string | null;
|
|
129
|
+
tokens: string | null;
|
|
130
|
+
numMinted: number | null;
|
|
131
|
+
lastSettlement: string | null;
|
|
132
|
+
input: string | null;
|
|
133
|
+
output: string | null;
|
|
134
|
+
display: string | null;
|
|
135
|
+
hooks: string | null;
|
|
136
|
+
data: string | null;
|
|
137
|
+
context: string | null;
|
|
138
|
+
}
|
|
139
|
+
interface TokenFactoryTable {
|
|
140
|
+
address: string;
|
|
141
|
+
owner: string | null;
|
|
142
|
+
name: string | null;
|
|
143
|
+
description: string | null;
|
|
144
|
+
moniker: string | null;
|
|
145
|
+
status: string | null;
|
|
146
|
+
curve: string | null;
|
|
147
|
+
input: string | null;
|
|
148
|
+
output: string | null;
|
|
149
|
+
data: string | null;
|
|
150
|
+
context: string | null;
|
|
151
|
+
}
|
|
152
|
+
interface StakeTable {
|
|
153
|
+
address: string;
|
|
154
|
+
sender: string | null;
|
|
155
|
+
receiver: string | null;
|
|
156
|
+
tokens: string | null;
|
|
157
|
+
revokedTokens: string | null;
|
|
158
|
+
message: string | null;
|
|
159
|
+
data: string | null;
|
|
160
|
+
context: string | null;
|
|
161
|
+
}
|
|
162
|
+
interface DelegationTable {
|
|
163
|
+
address: string;
|
|
164
|
+
from_: string | null;
|
|
165
|
+
to_: string | null;
|
|
166
|
+
ops: string | null;
|
|
167
|
+
data: string | null;
|
|
168
|
+
context: string | null;
|
|
169
|
+
}
|
|
170
|
+
interface RollupTable {
|
|
171
|
+
address: string;
|
|
172
|
+
tokenAddress: string | null;
|
|
173
|
+
paused: number | null;
|
|
174
|
+
seedValidators: string | null;
|
|
175
|
+
validators: string | null;
|
|
176
|
+
vaultAddress: string | null;
|
|
177
|
+
blockHash: string | null;
|
|
178
|
+
issuer: string | null;
|
|
179
|
+
data: string | null;
|
|
180
|
+
context: string | null;
|
|
181
|
+
}
|
|
182
|
+
interface RollupBlockTable {
|
|
183
|
+
hash: string;
|
|
184
|
+
rollup: string | null;
|
|
185
|
+
height: number | null;
|
|
186
|
+
previousHash: string | null;
|
|
187
|
+
mintedAmount: string | null;
|
|
188
|
+
burnedAmount: string | null;
|
|
189
|
+
rewardAmount: string | null;
|
|
190
|
+
signatures: string | null;
|
|
191
|
+
data: string | null;
|
|
192
|
+
context: string | null;
|
|
193
|
+
}
|
|
194
|
+
interface EvidenceTable {
|
|
195
|
+
hash: string;
|
|
196
|
+
type: string | null;
|
|
197
|
+
data: string | null;
|
|
198
|
+
context: string | null;
|
|
199
|
+
}
|
|
200
|
+
//#endregion
|
|
201
|
+
export { AccountTable, AssetTable, BalanceTable, ChainTable, Database, DelegationTable, EvidenceTable, FactoryTable, RollupBlockTable, RollupTable, SqliteOperationContext, StakeTable, TokenFactoryTable, TokenTable, TxTable };
|
package/lib/kysely.cjs
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let kysely = require("kysely");
|
|
3
|
+
|
|
4
|
+
//#region src/kysely.ts
|
|
5
|
+
function isBunRuntime() {
|
|
6
|
+
return typeof globalThis.Bun !== "undefined";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Create a Kysely instance with SQLite dialect
|
|
10
|
+
* Automatically uses kysely-bun-sqlite in Bun or better-sqlite3 in Node.js
|
|
11
|
+
*
|
|
12
|
+
* @param config - SQLite configuration
|
|
13
|
+
* @returns Kysely instance configured for the database
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // In-memory database for testing
|
|
18
|
+
* const db = createKysely({ filename: ':memory:' });
|
|
19
|
+
*
|
|
20
|
+
* // File-based database for production
|
|
21
|
+
* const db = createKysely({ filename: './data/state.sqlite' });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
function createKysely(config) {
|
|
25
|
+
if (isBunRuntime()) {
|
|
26
|
+
const { BunSqliteDialect } = {}.require("kysely-bun-sqlite");
|
|
27
|
+
const { Database: BunDatabase } = {}.require("bun:sqlite");
|
|
28
|
+
const sqlite$1 = new BunDatabase(config.filename, {
|
|
29
|
+
create: config.create !== false,
|
|
30
|
+
readonly: config.readonly === true
|
|
31
|
+
});
|
|
32
|
+
if (config.walMode !== false && !config.readonly && config.filename !== ":memory:") {
|
|
33
|
+
sqlite$1.exec("PRAGMA journal_mode = WAL");
|
|
34
|
+
sqlite$1.exec("PRAGMA synchronous = NORMAL");
|
|
35
|
+
}
|
|
36
|
+
sqlite$1.exec("PRAGMA foreign_keys = ON");
|
|
37
|
+
sqlite$1.exec("PRAGMA busy_timeout = 5000");
|
|
38
|
+
return new kysely.Kysely({ dialect: new BunSqliteDialect({ database: sqlite$1 }) });
|
|
39
|
+
}
|
|
40
|
+
const sqlite = new (require("better-sqlite3"))(config.filename, {
|
|
41
|
+
readonly: config.readonly === true,
|
|
42
|
+
fileMustExist: config.create === false
|
|
43
|
+
});
|
|
44
|
+
if (config.walMode !== false && !config.readonly && config.filename !== ":memory:") {
|
|
45
|
+
sqlite.pragma("journal_mode = WAL");
|
|
46
|
+
sqlite.pragma("synchronous = NORMAL");
|
|
47
|
+
}
|
|
48
|
+
sqlite.pragma("foreign_keys = ON");
|
|
49
|
+
sqlite.pragma("busy_timeout = 5000");
|
|
50
|
+
return new kysely.Kysely({ dialect: new kysely.SqliteDialect({ database: sqlite }) });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the underlying SQLite database instance from Kysely
|
|
54
|
+
* Useful for executing raw SQL or pragmas
|
|
55
|
+
* Returns either bun:sqlite Database or better-sqlite3 Database depending on runtime
|
|
56
|
+
*/
|
|
57
|
+
function getRawDatabase(db) {
|
|
58
|
+
return db.getExecutor().adapter.db;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
exports.createKysely = createKysely;
|
|
63
|
+
exports.getRawDatabase = getRawDatabase;
|
package/lib/kysely.d.cts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Database } from "./interfaces.cjs";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
|
|
4
|
+
//#region src/kysely.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* SQLite configuration options
|
|
8
|
+
*/
|
|
9
|
+
interface SqliteConfig {
|
|
10
|
+
/** Database file path. Use ':memory:' for in-memory database */
|
|
11
|
+
filename: string;
|
|
12
|
+
/** Open database in readonly mode */
|
|
13
|
+
readonly?: boolean;
|
|
14
|
+
/** Throw error if file doesn't exist (default: false, creates new file) */
|
|
15
|
+
create?: boolean;
|
|
16
|
+
/** Enable WAL mode (default: true) */
|
|
17
|
+
walMode?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create a Kysely instance with SQLite dialect
|
|
21
|
+
* Automatically uses kysely-bun-sqlite in Bun or better-sqlite3 in Node.js
|
|
22
|
+
*
|
|
23
|
+
* @param config - SQLite configuration
|
|
24
|
+
* @returns Kysely instance configured for the database
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // In-memory database for testing
|
|
29
|
+
* const db = createKysely({ filename: ':memory:' });
|
|
30
|
+
*
|
|
31
|
+
* // File-based database for production
|
|
32
|
+
* const db = createKysely({ filename: './data/state.sqlite' });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare function createKysely(config: SqliteConfig): Kysely<Database>;
|
|
36
|
+
/**
|
|
37
|
+
* Get the underlying SQLite database instance from Kysely
|
|
38
|
+
* Useful for executing raw SQL or pragmas
|
|
39
|
+
* Returns either bun:sqlite Database or better-sqlite3 Database depending on runtime
|
|
40
|
+
*/
|
|
41
|
+
declare function getRawDatabase(db: Kysely<Database>): any;
|
|
42
|
+
//#endregion
|
|
43
|
+
export { SqliteConfig, createKysely, getRawDatabase };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let kysely = require("kysely");
|
|
3
|
+
|
|
4
|
+
//#region src/migrations/001-genesis.ts
|
|
5
|
+
var _001_genesis_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
|
|
6
|
+
down: () => down,
|
|
7
|
+
up: () => up
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* Genesis migration - creates all StateDB tables
|
|
11
|
+
*/
|
|
12
|
+
async function up(db) {
|
|
13
|
+
await db.schema.createTable("account").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("balance", "text", (col) => col.notNull().defaultTo("0")).addColumn("gasBalance", "text", (col) => col.defaultTo("0")).addColumn("moniker", "text").addColumn("pk", "text").addColumn("nonce", "integer", (col) => col.defaultTo(0)).addColumn("numTxs", "integer", (col) => col.defaultTo(0)).addColumn("numAssets", "integer", (col) => col.defaultTo(0)).addColumn("issuer", "text").addColumn("migratedTo", "text").addColumn("migratedFrom", "text").addColumn("stake", "text").addColumn("tokens", "text").addColumn("data", "text").addColumn("context", "text").addColumn("poke", "text").addColumn("_retrievedAt", "text").execute();
|
|
14
|
+
await db.schema.createTable("balance").ifNotExists().addColumn("address", "text", (col) => col.notNull()).addColumn("tokenAddress", "text", (col) => col.notNull()).addColumn("balance", "text", (col) => col.notNull().defaultTo("0")).addColumn("context", "text").addPrimaryKeyConstraint("balance_pk", ["address", "tokenAddress"]).execute();
|
|
15
|
+
await db.schema.createTable("chain").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("chainId", "text").addColumn("version", "text").addColumn("accounts", "text").addColumn("moderator", "text").addColumn("token", "text").addColumn("transaction", "text").addColumn("vaults", "text").addColumn("context", "text").execute();
|
|
16
|
+
await db.schema.createTable("tx").ifNotExists().addColumn("hash", "text", (col) => col.primaryKey()).addColumn("code", "text").addColumn("height", "integer").addColumn("index_", "integer").addColumn("receipts", "text").addColumn("receiptsVerified", "integer").addColumn("receiver", "text").addColumn("sender", "text").addColumn("time", "text").addColumn("tx", "text").addColumn("type", "text").addColumn("finalized", "integer").addColumn("valid", "integer").execute();
|
|
17
|
+
await db.schema.createTable("asset").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("owner", "text").addColumn("moniker", "text").addColumn("readonly", "integer").addColumn("transferrable", "integer").addColumn("issuer", "text").addColumn("parent", "text").addColumn("ttl", "integer").addColumn("consumedTime", "text").addColumn("endpoint", "text").addColumn("display", "text").addColumn("tags", "text").addColumn("stake", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
18
|
+
await db.schema.createTable("token").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("symbol", "text").addColumn("name", "text").addColumn("decimal", "integer").addColumn("unit", "text").addColumn("description", "text").addColumn("icon", "text").addColumn("totalSupply", "text").addColumn("initialSupply", "text").addColumn("maxTotalSupply", "text").addColumn("foreignToken", "text").addColumn("issuer", "text").addColumn("website", "text").addColumn("metadata", "text").addColumn("tokenFactoryAddress", "text").addColumn("spenders", "text").addColumn("minters", "text").addColumn("type", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
19
|
+
await kysely.sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_token_symbol ON token(symbol) WHERE symbol IS NOT NULL`.execute(db);
|
|
20
|
+
await db.schema.createTable("factory").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("owner", "text").addColumn("name", "text").addColumn("description", "text").addColumn("settlement", "text").addColumn("limit", "integer").addColumn("trustedIssuers", "text").addColumn("tokens", "text").addColumn("numMinted", "integer").addColumn("lastSettlement", "text").addColumn("input", "text").addColumn("output", "text").addColumn("display", "text").addColumn("hooks", "text").addColumn("data", "text").addColumn("context", "text").addColumn("balance", "text").addColumn("stake", "text").execute();
|
|
21
|
+
await db.schema.createTable("tokenFactory").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("owner", "text").addColumn("name", "text").addColumn("description", "text").addColumn("moniker", "text").addColumn("tokenAddress", "text").addColumn("reserveAddress", "text").addColumn("currentSupply", "text").addColumn("reserveBalance", "text").addColumn("feeRate", "integer").addColumn("status", "text").addColumn("curve", "text").addColumn("input", "text").addColumn("output", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
22
|
+
await db.schema.createTable("stake").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("sender", "text").addColumn("receiver", "text").addColumn("tokens", "text").addColumn("assets", "text").addColumn("slashers", "text").addColumn("revocable", "integer").addColumn("message", "text").addColumn("revokeWaitingPeriod", "integer").addColumn("revokedTokens", "text").addColumn("revokedAssets", "text").addColumn("nonce", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
23
|
+
await db.schema.createTable("delegation").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("from_", "text").addColumn("to_", "text").addColumn("ops", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
24
|
+
await db.schema.createTable("rollup").ifNotExists().addColumn("address", "text", (col) => col.primaryKey()).addColumn("tokenAddress", "text").addColumn("vaultAddress", "text").addColumn("contractAddress", "text").addColumn("paused", "integer").addColumn("closed", "integer").addColumn("seedValidators", "text").addColumn("validators", "text").addColumn("minStakeAmount", "text").addColumn("maxStakeAmount", "text").addColumn("minSignerCount", "integer").addColumn("maxSignerCount", "integer").addColumn("minBlockSize", "integer").addColumn("maxBlockSize", "integer").addColumn("minBlockInterval", "integer").addColumn("minBlockConfirmation", "integer").addColumn("minDepositAmount", "text").addColumn("maxDepositAmount", "text").addColumn("minWithdrawAmount", "text").addColumn("maxWithdrawAmount", "text").addColumn("depositFeeRate", "integer").addColumn("withdrawFeeRate", "integer").addColumn("proposerFeeShare", "integer").addColumn("publisherFeeShare", "integer").addColumn("minDepositFee", "text").addColumn("maxDepositFee", "text").addColumn("minWithdrawFee", "text").addColumn("maxWithdrawFee", "text").addColumn("issuer", "text").addColumn("blockHeight", "integer").addColumn("blockHash", "text").addColumn("leaveWaitingPeriod", "integer").addColumn("publishWaitingPeriod", "integer").addColumn("publishSlashRate", "integer").addColumn("revokeWaitingPeriod", "integer").addColumn("erc20TokenAddress", "text").addColumn("foreignChainId", "text").addColumn("foreignChainType", "text").addColumn("migrateHistory", "text").addColumn("vaultHistory", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
25
|
+
await kysely.sql`DROP INDEX IF EXISTS idx_rollup_token`.execute(db);
|
|
26
|
+
await kysely.sql`CREATE INDEX IF NOT EXISTS idx_rollup_token ON rollup(tokenAddress) WHERE tokenAddress IS NOT NULL`.execute(db);
|
|
27
|
+
await db.schema.createTable("rollupBlock").ifNotExists().addColumn("hash", "text", (col) => col.primaryKey()).addColumn("rollup", "text").addColumn("height", "integer").addColumn("merkleRoot", "text").addColumn("previousHash", "text").addColumn("txsHash", "text").addColumn("txs", "text").addColumn("proposer", "text").addColumn("mintedAmount", "text").addColumn("burnedAmount", "text").addColumn("rewardAmount", "text").addColumn("minReward", "text").addColumn("blockReward", "text").addColumn("governance", "integer").addColumn("checkpoint", "text").addColumn("txHash", "text").addColumn("signatures", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
28
|
+
await db.schema.createTable("evidence").ifNotExists().addColumn("hash", "text", (col) => col.primaryKey()).addColumn("type", "text").addColumn("data", "text").addColumn("context", "text").execute();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Rollback migration - drops all tables
|
|
32
|
+
*/
|
|
33
|
+
async function down(db) {
|
|
34
|
+
for (const table of [
|
|
35
|
+
"evidence",
|
|
36
|
+
"rollupBlock",
|
|
37
|
+
"rollup",
|
|
38
|
+
"delegation",
|
|
39
|
+
"stake",
|
|
40
|
+
"tokenFactory",
|
|
41
|
+
"factory",
|
|
42
|
+
"token",
|
|
43
|
+
"asset",
|
|
44
|
+
"tx",
|
|
45
|
+
"chain",
|
|
46
|
+
"balance",
|
|
47
|
+
"account"
|
|
48
|
+
]) await db.schema.dropTable(table).ifExists().execute();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
Object.defineProperty(exports, '_001_genesis_exports', {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () {
|
|
55
|
+
return _001_genesis_exports;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
exports.down = down;
|
|
59
|
+
exports.up = up;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
//#region src/migrations/001-genesis.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Genesis migration - creates all StateDB tables
|
|
7
|
+
*/
|
|
8
|
+
declare function up(db: Kysely<unknown>): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Rollback migration - drops all tables
|
|
11
|
+
*/
|
|
12
|
+
declare function down(db: Kysely<unknown>): Promise<void>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { down, up };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_migrations_001_genesis = require('./001-genesis.cjs');
|
|
3
|
+
let kysely = require("kysely");
|
|
4
|
+
|
|
5
|
+
//#region src/migrations/index.ts
|
|
6
|
+
/**
|
|
7
|
+
* In-memory migration provider
|
|
8
|
+
* Provides migrations directly without filesystem access
|
|
9
|
+
*/
|
|
10
|
+
var InMemoryMigrationProvider = class {
|
|
11
|
+
constructor(migrations) {
|
|
12
|
+
this.migrations = migrations;
|
|
13
|
+
}
|
|
14
|
+
async getMigrations() {
|
|
15
|
+
return this.migrations;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Run all pending migrations
|
|
20
|
+
*
|
|
21
|
+
* @param db - Kysely database instance
|
|
22
|
+
* @throws Error if any migration fails
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const db = createKysely({ filename: ':memory:' });
|
|
27
|
+
* await runMigrations(db);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
async function runMigrations(db) {
|
|
31
|
+
const { error, results } = await new kysely.Migrator({
|
|
32
|
+
db,
|
|
33
|
+
provider: new InMemoryMigrationProvider({ "001-genesis": require_migrations_001_genesis._001_genesis_exports })
|
|
34
|
+
}).migrateToLatest();
|
|
35
|
+
results?.forEach((it) => {
|
|
36
|
+
if (it.status === "Success") {} else if (it.status === "Error") console.error(`Migration "${it.migrationName}" failed`);
|
|
37
|
+
});
|
|
38
|
+
if (error) {
|
|
39
|
+
console.error("Migration failed:", error);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Roll back all migrations
|
|
45
|
+
* WARNING: This will drop all tables and data
|
|
46
|
+
*/
|
|
47
|
+
async function rollbackMigrations(db) {
|
|
48
|
+
const migrator = new kysely.Migrator({
|
|
49
|
+
db,
|
|
50
|
+
provider: new InMemoryMigrationProvider({ "001-genesis": require_migrations_001_genesis._001_genesis_exports })
|
|
51
|
+
});
|
|
52
|
+
let hasMore = true;
|
|
53
|
+
while (hasMore) {
|
|
54
|
+
const { error, results } = await migrator.migrateDown();
|
|
55
|
+
if (error) throw error;
|
|
56
|
+
hasMore = results !== void 0 && results.length > 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
exports.rollbackMigrations = rollbackMigrations;
|
|
62
|
+
exports.runMigrations = runMigrations;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
//#region src/migrations/index.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Run all pending migrations
|
|
7
|
+
*
|
|
8
|
+
* @param db - Kysely database instance
|
|
9
|
+
* @throws Error if any migration fails
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const db = createKysely({ filename: ':memory:' });
|
|
14
|
+
* await runMigrations(db);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
declare function runMigrations(db: Kysely<unknown>): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Roll back all migrations
|
|
20
|
+
* WARNING: This will drop all tables and data
|
|
21
|
+
*/
|
|
22
|
+
declare function rollbackMigrations(db: Kysely<unknown>): Promise<void>;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { rollbackMigrations, runMigrations };
|
package/lib/package.cjs
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
|
|
2
|
+
//#region package.json
|
|
3
|
+
var package_default = {
|
|
4
|
+
name: "@ocap/statedb-sqlite",
|
|
5
|
+
description: "OCAP statedb adapter that uses SQLite as backend",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
author: "wangshijun <shijun@arcblock.io> (https://www.arcblock.io)",
|
|
8
|
+
bugs: {
|
|
9
|
+
"url": "https://github.com/ArcBlock/blockchain/issues",
|
|
10
|
+
"email": "shijun@arcblock.io"
|
|
11
|
+
},
|
|
12
|
+
publishConfig: { "access": "public" },
|
|
13
|
+
contributors: ["wangshijun <shijun@arcblock.io> (https://www.arcblock.io)"],
|
|
14
|
+
devDependencies: { "@ocap/statedb-test": "workspace:*" },
|
|
15
|
+
homepage: "https://github.com/ArcBlock/blockchain/tree/master/statedb/sqlite",
|
|
16
|
+
keywords: [
|
|
17
|
+
"ocap",
|
|
18
|
+
"statedb",
|
|
19
|
+
"sqlite",
|
|
20
|
+
"kysely"
|
|
21
|
+
],
|
|
22
|
+
license: "Apache-2.0",
|
|
23
|
+
type: "module",
|
|
24
|
+
main: "./lib/index.cjs",
|
|
25
|
+
module: "./esm/index.mjs",
|
|
26
|
+
types: "./esm/index.d.mts",
|
|
27
|
+
exports: {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./esm/index.d.mts",
|
|
30
|
+
"import": "./esm/index.mjs",
|
|
31
|
+
"default": "./lib/index.cjs"
|
|
32
|
+
},
|
|
33
|
+
"./lib/*.js": {
|
|
34
|
+
"types": "./esm/*.d.mts",
|
|
35
|
+
"import": "./esm/*.mjs",
|
|
36
|
+
"default": "./lib/*.cjs"
|
|
37
|
+
},
|
|
38
|
+
"./lib/*": {
|
|
39
|
+
"types": "./esm/*.d.mts",
|
|
40
|
+
"import": "./esm/*.mjs",
|
|
41
|
+
"default": "./lib/*.cjs"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
files: ["lib", "esm"],
|
|
45
|
+
repository: {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "https://github.com/ArcBlock/blockchain/tree/master/statedb/sqlite"
|
|
48
|
+
},
|
|
49
|
+
scripts: {
|
|
50
|
+
"build": "tsdown",
|
|
51
|
+
"prebuild": "rm -rf lib esm",
|
|
52
|
+
"lint": "biome check",
|
|
53
|
+
"lint:fix": "biome check --write",
|
|
54
|
+
"test": "bun test",
|
|
55
|
+
"coverage": "npm run test -- --coverage"
|
|
56
|
+
},
|
|
57
|
+
dependencies: {
|
|
58
|
+
"@ocap/state": "workspace:*",
|
|
59
|
+
"@ocap/statedb": "workspace:*",
|
|
60
|
+
"@ocap/types": "workspace:*",
|
|
61
|
+
"@ocap/util": "workspace:*",
|
|
62
|
+
"debug": "^4.4.3",
|
|
63
|
+
"better-sqlite3": "^11.8.1",
|
|
64
|
+
"kysely": "^0.27.0",
|
|
65
|
+
"kysely-bun-sqlite": "^0.4.0",
|
|
66
|
+
"lodash": "^4.17.23"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
Object.defineProperty(exports, 'default', {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
get: function () {
|
|
74
|
+
return package_default;
|
|
75
|
+
}
|
|
76
|
+
});
|