@arkade-os/sdk 0.5.3 → 0.5.4
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 +36 -34
- package/dist/adapters/expo.cjs +9 -5
- package/dist/adapters/expo.d.cts +11 -7
- package/dist/adapters/expo.d.ts +11 -7
- package/dist/adapters/expo.js +3 -3
- package/dist/{asyncStorageTaskQueue-B3U5gQ-i.d.ts → asyncStorageTaskQueue-DHMIxY04.d.ts} +2 -2
- package/dist/{asyncStorageTaskQueue-C9PkPcW_.d.cts → asyncStorageTaskQueue-DTBa8EH7.d.cts} +2 -2
- package/dist/{chunk-P7B4LQ3H.js → chunk-6CUP6ZIF.js} +4 -4
- package/dist/{chunk-P7B4LQ3H.js.map → chunk-6CUP6ZIF.js.map} +1 -1
- package/dist/{chunk-OPX2HRWM.js → chunk-AG4TFD6F.js} +137 -59
- package/dist/chunk-AG4TFD6F.js.map +1 -0
- package/dist/{chunk-5WRA66RV.cjs → chunk-B6VNKGIH.cjs} +10 -10
- package/dist/chunk-B6VNKGIH.cjs.map +1 -0
- package/dist/{chunk-6FL4N4S2.js → chunk-BTRCN4JJ.js} +22 -19
- package/dist/chunk-BTRCN4JJ.js.map +1 -0
- package/dist/{chunk-ZPF4I3K2.cjs → chunk-DNITZVNG.cjs} +28 -47
- package/dist/chunk-DNITZVNG.cjs.map +1 -0
- package/dist/{chunk-BYPBVHVA.cjs → chunk-E6OOJEHL.cjs} +49 -49
- package/dist/{chunk-BYPBVHVA.cjs.map → chunk-E6OOJEHL.cjs.map} +1 -1
- package/dist/{chunk-OUTWUYJ4.cjs → chunk-F3FAE7VJ.cjs} +769 -619
- package/dist/chunk-F3FAE7VJ.cjs.map +1 -0
- package/dist/{chunk-KW7ZEWYS.cjs → chunk-GHUUT54D.cjs} +140 -58
- package/dist/chunk-GHUUT54D.cjs.map +1 -0
- package/dist/{chunk-Y4BL3YYX.js → chunk-MWVAWFX6.js} +4 -4
- package/dist/chunk-MWVAWFX6.js.map +1 -0
- package/dist/{chunk-T7C3E2HL.js → chunk-TUOLZBNC.js} +19 -39
- package/dist/chunk-TUOLZBNC.js.map +1 -0
- package/dist/{chunk-ZMSM3NOH.cjs → chunk-WXNSISXK.cjs} +37 -34
- package/dist/chunk-WXNSISXK.cjs.map +1 -0
- package/dist/{chunk-HAQAWBYG.js → chunk-ZJHLLDBP.js} +283 -136
- package/dist/chunk-ZJHLLDBP.js.map +1 -0
- package/dist/contracts/handlers/index.cjs +9 -9
- package/dist/contracts/handlers/index.d.cts +3 -3
- package/dist/contracts/handlers/index.d.ts +3 -3
- package/dist/contracts/handlers/index.js +2 -2
- package/dist/{delegate-ByfKszb6.d.cts → delegate-f4_t864Z.d.cts} +1 -1
- package/dist/{delegate-Cd28gxpM.d.ts → delegate-xrSBNybC.d.ts} +1 -1
- package/dist/{index-DgH_0j14.d.cts → index-BJDz15ms.d.ts} +5 -5
- package/dist/{index-B6X2E7W_.d.ts → index-BjiVGtp8.d.cts} +5 -5
- package/dist/{index-BURzbRup.d.ts → index-DRwe0UDN.d.cts} +182 -114
- package/dist/{index-BURzbRup.d.cts → index-DRwe0UDN.d.ts} +182 -114
- package/dist/index.cjs +333 -313
- package/dist/index.d.cts +66 -44
- package/dist/index.d.ts +66 -44
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +65 -36
- package/dist/repositories/realm/index.cjs.map +1 -1
- package/dist/repositories/realm/index.d.cts +7 -3
- package/dist/repositories/realm/index.d.ts +7 -3
- package/dist/repositories/realm/index.js +35 -6
- package/dist/repositories/realm/index.js.map +1 -1
- package/dist/repositories/sqlite/index.cjs +176 -110
- package/dist/repositories/sqlite/index.cjs.map +1 -1
- package/dist/repositories/sqlite/index.d.cts +23 -13
- package/dist/repositories/sqlite/index.d.ts +23 -13
- package/dist/repositories/sqlite/index.js +148 -83
- package/dist/repositories/sqlite/index.js.map +1 -1
- package/dist/{taskRunner-i56-drQV.d.cts → taskRunner-BPPU-YHG.d.cts} +4 -4
- package/dist/{taskRunner-BaNCSxqK.d.ts → taskRunner-CDlNeth0.d.ts} +4 -4
- package/dist/wallet/expo/background.cjs +14 -14
- package/dist/wallet/expo/background.cjs.map +1 -1
- package/dist/wallet/expo/background.d.cts +3 -3
- package/dist/wallet/expo/background.d.ts +3 -3
- package/dist/wallet/expo/background.js +7 -7
- package/dist/wallet/expo/background.js.map +1 -1
- package/dist/wallet/expo/index.cjs +15 -15
- package/dist/wallet/expo/index.cjs.map +1 -1
- package/dist/wallet/expo/index.d.cts +6 -6
- package/dist/wallet/expo/index.d.ts +6 -6
- package/dist/wallet/expo/index.js +6 -6
- package/dist/wallet/expo/index.js.map +1 -1
- package/dist/{wallet-BjQugVUt.d.cts → wallet-Oc3Wd5gv.d.ts} +22 -18
- package/dist/{wallet-BnmhohgZ.d.ts → wallet-jVBDQl6R.d.cts} +22 -18
- package/dist/worker/expo/index.cjs +9 -9
- package/dist/worker/expo/index.d.cts +4 -4
- package/dist/worker/expo/index.d.ts +4 -4
- package/dist/worker/expo/index.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-5WRA66RV.cjs.map +0 -1
- package/dist/chunk-6FL4N4S2.js.map +0 -1
- package/dist/chunk-HAQAWBYG.js.map +0 -1
- package/dist/chunk-KW7ZEWYS.cjs.map +0 -1
- package/dist/chunk-OPX2HRWM.js.map +0 -1
- package/dist/chunk-OUTWUYJ4.cjs.map +0 -1
- package/dist/chunk-T7C3E2HL.js.map +0 -1
- package/dist/chunk-Y4BL3YYX.js.map +0 -1
- package/dist/chunk-ZMSM3NOH.cjs.map +0 -1
- package/dist/chunk-ZPF4I3K2.cjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { W as WalletRepository, P as PageRequest,
|
|
2
|
-
export {
|
|
1
|
+
import { W as WalletRepository, X as AtomicWalletState, P as PageRequest, F as Outpoint, H as PageResult, D as ExtendedVirtualCoin, J as ScriptVtxoCursor, K as ScriptVtxoPageOptions, L as StoredVtxo, M as VtxoRepositoryKey, E as ExtendedCoin, Q as TransactionHistoryPageFilter, U as TransactionHistoryPageCursor, h as ArkTransaction, Y as WalletState, C as ContractRepository, Z as ContractFilter, B as Contract, _ as IntentRepository, $ as ArkIntent, a0 as IntentPageFilter, a1 as VirtualTxRepository, a2 as VirtualTx, a3 as VtxoBranch } from '../../index-DRwe0UDN.js';
|
|
2
|
+
export { a4 as ChainedTxType } from '../../index-DRwe0UDN.js';
|
|
3
3
|
import '@scure/btc-signer/utils.js';
|
|
4
4
|
import '@scure/btc-signer/psbt.js';
|
|
5
5
|
import '@scure/btc-signer';
|
|
@@ -8,6 +8,8 @@ import '@scure/btc-signer/transaction.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Minimal SQL execution interface that consumers implement
|
|
10
10
|
* to connect their SQLite (or any SQL) database to the SDK.
|
|
11
|
+
* Share one executor object per connection across SDK repositories; separate wrappers
|
|
12
|
+
* and direct raw-driver calls bypass the SDK operation queue.
|
|
11
13
|
*
|
|
12
14
|
* Example for expo-sqlite:
|
|
13
15
|
* ```
|
|
@@ -27,6 +29,12 @@ interface SQLExecutor {
|
|
|
27
29
|
interface SQLiteWalletRepositoryOptions {
|
|
28
30
|
/** Table name prefix (default: "ark_") */
|
|
29
31
|
prefix?: string;
|
|
32
|
+
/** Opt in only with a dedicated connection or all operations coordinated through
|
|
33
|
+
* getSerializedExecutor/runInTransaction on the same executor object. Default: false.
|
|
34
|
+
* All read-modify-write callers must use atomic updates; queued legacy updates can still race. */
|
|
35
|
+
walletStateTransactions?: boolean;
|
|
36
|
+
/** Caller asserts durable backing; requires walletStateTransactions. No storage detection. */
|
|
37
|
+
persistentWalletState?: boolean;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* SQLite-based implementation of WalletRepository.
|
|
@@ -38,8 +46,9 @@ interface SQLiteWalletRepositoryOptions {
|
|
|
38
46
|
* The consumer owns the SQLExecutor lifecycle — `[Symbol.asyncDispose]` is a no-op.
|
|
39
47
|
*/
|
|
40
48
|
declare class SQLiteWalletRepository implements WalletRepository {
|
|
41
|
-
private readonly db;
|
|
42
49
|
readonly version: 2;
|
|
50
|
+
readonly atomicWalletState?: AtomicWalletState;
|
|
51
|
+
private readonly db;
|
|
43
52
|
private initPromise;
|
|
44
53
|
private readonly prefix;
|
|
45
54
|
private readonly tables;
|
|
@@ -103,6 +112,7 @@ declare class SQLiteWalletRepository implements WalletRepository {
|
|
|
103
112
|
getTransactionHistoryPage(filter: TransactionHistoryPageFilter, page: PageRequest<TransactionHistoryPageCursor>): Promise<PageResult<ArkTransaction, TransactionHistoryPageCursor>>;
|
|
104
113
|
saveTransactions(address: string, txs: ArkTransaction[]): Promise<void>;
|
|
105
114
|
deleteTransactions(address: string): Promise<void>;
|
|
115
|
+
private readonly atomicState;
|
|
106
116
|
getWalletState(): Promise<WalletState | null>;
|
|
107
117
|
saveWalletState(state: WalletState): Promise<void>;
|
|
108
118
|
}
|
|
@@ -121,8 +131,8 @@ interface SQLiteContractRepositoryOptions {
|
|
|
121
131
|
* The consumer owns the SQLExecutor lifecycle — `[Symbol.asyncDispose]` is a no-op.
|
|
122
132
|
*/
|
|
123
133
|
declare class SQLiteContractRepository implements ContractRepository {
|
|
124
|
-
private readonly db;
|
|
125
134
|
readonly version: 3;
|
|
135
|
+
private readonly db;
|
|
126
136
|
private initPromise;
|
|
127
137
|
private readonly prefix;
|
|
128
138
|
private readonly table;
|
|
@@ -139,8 +149,8 @@ declare class SQLiteContractRepository implements ContractRepository {
|
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
declare class SQLiteIntentRepository implements IntentRepository {
|
|
142
|
-
private readonly db;
|
|
143
152
|
readonly version: 1;
|
|
153
|
+
private readonly db;
|
|
144
154
|
private initPromise;
|
|
145
155
|
private readonly prefix;
|
|
146
156
|
private readonly t;
|
|
@@ -157,8 +167,8 @@ declare class SQLiteIntentRepository implements IntentRepository {
|
|
|
157
167
|
}
|
|
158
168
|
|
|
159
169
|
declare class SQLiteVirtualTxRepository implements VirtualTxRepository {
|
|
160
|
-
private readonly db;
|
|
161
170
|
readonly version: 1;
|
|
171
|
+
private readonly db;
|
|
162
172
|
private initPromise;
|
|
163
173
|
private readonly prefix;
|
|
164
174
|
private readonly tTx;
|
|
@@ -178,14 +188,14 @@ declare class SQLiteVirtualTxRepository implements VirtualTxRepository {
|
|
|
178
188
|
[Symbol.asyncDispose](): Promise<void>;
|
|
179
189
|
}
|
|
180
190
|
|
|
191
|
+
/** SDK reads and writes share the transaction queue; direct raw-driver calls do not. */
|
|
192
|
+
declare function getSerializedExecutor(db: SQLExecutor): SQLExecutor;
|
|
181
193
|
/**
|
|
182
|
-
* Run `fn` inside
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* again on the same `db` from within `fn` would wait on the chain it is part of
|
|
186
|
-
* and deadlock.
|
|
194
|
+
* Run `fn` inside `BEGIN IMMEDIATE` / `COMMIT`, excluding queued SDK reads and writes.
|
|
195
|
+
* Use only the supplied raw executor inside `fn`; repository calls or nested transactions deadlock.
|
|
196
|
+
* Existing zero-argument callbacks closing over the original raw executor remain supported.
|
|
187
197
|
*/
|
|
188
|
-
declare function runInTransaction(db: SQLExecutor, fn: () => Promise<void>): Promise<void>;
|
|
198
|
+
declare function runInTransaction(db: SQLExecutor, fn: (tx: SQLExecutor) => Promise<void>): Promise<void>;
|
|
189
199
|
|
|
190
200
|
/**
|
|
191
201
|
* Validate a SQLite table prefix and return it unchanged.
|
|
@@ -195,4 +205,4 @@ declare function runInTransaction(db: SQLExecutor, fn: () => Promise<void>): Pro
|
|
|
195
205
|
*/
|
|
196
206
|
declare function sanitizeTablePrefix(p: string): string;
|
|
197
207
|
|
|
198
|
-
export { type SQLExecutor, SQLiteContractRepository, SQLiteIntentRepository, SQLiteVirtualTxRepository, SQLiteWalletRepository, VirtualTx, VirtualTxRepository, VtxoBranch, runInTransaction, sanitizeTablePrefix };
|
|
208
|
+
export { type SQLExecutor, SQLiteContractRepository, SQLiteIntentRepository, SQLiteVirtualTxRepository, SQLiteWalletRepository, VirtualTx, VirtualTxRepository, VtxoBranch, getSerializedExecutor, runInTransaction, sanitizeTablePrefix };
|
|
@@ -1,32 +1,69 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { ChainedTxType } from '../../chunk-
|
|
3
|
-
import '../../chunk-
|
|
4
|
-
import '../../chunk-
|
|
5
|
-
import { isVtxoSpent } from '../../chunk-
|
|
1
|
+
import { legacyVtxoFacts, serializeVtxo, createdAtToIso, assertPageRequest, pageResult, checkSaveVtxosForScript, utxoEntries, serializeUtxo, assertHistoryPageFilter, serializeAssets, scriptFromArkAddress, deserializeVtxo, deserializeUtxo, deserializeAssets, contractFilterMatchesNothing, intentMatchesFilter, isTerminalIntentState, applyWalletStateUpdate, mergeChainedTxType } from '../../chunk-ZJHLLDBP.js';
|
|
2
|
+
export { ChainedTxType } from '../../chunk-ZJHLLDBP.js';
|
|
3
|
+
import '../../chunk-BTRCN4JJ.js';
|
|
4
|
+
import '../../chunk-6CUP6ZIF.js';
|
|
5
|
+
import { isVtxoSpent } from '../../chunk-AG4TFD6F.js';
|
|
6
6
|
|
|
7
7
|
// src/repositories/sqlite/transaction.ts
|
|
8
|
-
var
|
|
8
|
+
var executorQueues = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
var STALL_WARN_MS = 1e4;
|
|
10
|
+
function enqueue(queue, operation) {
|
|
11
|
+
let stall;
|
|
12
|
+
if (queue.inTransaction) {
|
|
13
|
+
const site = new Error(
|
|
14
|
+
`SQLite operation waited ${STALL_WARN_MS / 1e3}s behind a transaction. A repository, getSerializedExecutor or runInTransaction call inside a runInTransaction callback deadlocks; use the callback's tx.`
|
|
15
|
+
);
|
|
16
|
+
stall = setTimeout(() => console.warn(site), STALL_WARN_MS);
|
|
17
|
+
}
|
|
18
|
+
const run = queue.tail.then(() => {
|
|
19
|
+
clearTimeout(stall);
|
|
20
|
+
return operation();
|
|
21
|
+
});
|
|
22
|
+
queue.tail = run.catch(() => void 0);
|
|
23
|
+
return run;
|
|
24
|
+
}
|
|
25
|
+
function queueFor(db) {
|
|
26
|
+
const existing = executorQueues.get(db);
|
|
27
|
+
if (existing) return existing;
|
|
28
|
+
const facade = {
|
|
29
|
+
run: (sql, params) => enqueue(queue, () => db.run(sql, params)),
|
|
30
|
+
get: (sql, params) => enqueue(queue, () => db.get(sql, params)),
|
|
31
|
+
all: (sql, params) => enqueue(queue, () => db.all(sql, params))
|
|
32
|
+
};
|
|
33
|
+
const queue = {
|
|
34
|
+
raw: db,
|
|
35
|
+
facade,
|
|
36
|
+
tail: Promise.resolve(),
|
|
37
|
+
inTransaction: false
|
|
38
|
+
};
|
|
39
|
+
executorQueues.set(db, queue);
|
|
40
|
+
executorQueues.set(facade, queue);
|
|
41
|
+
return queue;
|
|
42
|
+
}
|
|
43
|
+
function getSerializedExecutor(db) {
|
|
44
|
+
return queueFor(db).facade;
|
|
45
|
+
}
|
|
9
46
|
function runInTransaction(db, fn) {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
47
|
+
const queue = queueFor(db);
|
|
48
|
+
return enqueue(queue, async () => {
|
|
49
|
+
const tx = queue.raw;
|
|
50
|
+
queue.inTransaction = true;
|
|
13
51
|
try {
|
|
14
|
-
await
|
|
15
|
-
await db.run("COMMIT");
|
|
16
|
-
} catch (e) {
|
|
52
|
+
await tx.run("BEGIN IMMEDIATE");
|
|
17
53
|
try {
|
|
18
|
-
await
|
|
19
|
-
|
|
54
|
+
await fn(tx);
|
|
55
|
+
await tx.run("COMMIT");
|
|
56
|
+
} catch (e) {
|
|
57
|
+
try {
|
|
58
|
+
await tx.run("ROLLBACK");
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
throw e;
|
|
20
62
|
}
|
|
21
|
-
|
|
63
|
+
} finally {
|
|
64
|
+
queue.inTransaction = false;
|
|
22
65
|
}
|
|
23
66
|
});
|
|
24
|
-
writeChains.set(
|
|
25
|
-
db,
|
|
26
|
-
run.catch(() => {
|
|
27
|
-
})
|
|
28
|
-
);
|
|
29
|
-
return run;
|
|
30
67
|
}
|
|
31
68
|
|
|
32
69
|
// src/repositories/sqlite/prefix.ts
|
|
@@ -39,8 +76,17 @@ function sanitizeTablePrefix(p) {
|
|
|
39
76
|
// src/repositories/sqlite/walletRepository.ts
|
|
40
77
|
var MAX_BOUND_PARAMETERS = 999;
|
|
41
78
|
var SQLiteWalletRepository = class {
|
|
79
|
+
version = 2;
|
|
80
|
+
atomicWalletState;
|
|
81
|
+
db;
|
|
82
|
+
initPromise = null;
|
|
83
|
+
prefix;
|
|
84
|
+
tables;
|
|
42
85
|
constructor(db, options) {
|
|
43
|
-
this.db = db;
|
|
86
|
+
this.db = getSerializedExecutor(db);
|
|
87
|
+
if (options?.walletStateTransactions === true) {
|
|
88
|
+
this.atomicWalletState = options.persistentWalletState === true ? { ...this.atomicState, persistent: true } : this.atomicState;
|
|
89
|
+
}
|
|
44
90
|
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
45
91
|
this.tables = {
|
|
46
92
|
vtxos: `${this.prefix}vtxos`,
|
|
@@ -49,11 +95,6 @@ var SQLiteWalletRepository = class {
|
|
|
49
95
|
walletState: `${this.prefix}wallet_state`
|
|
50
96
|
};
|
|
51
97
|
}
|
|
52
|
-
db;
|
|
53
|
-
version = 2;
|
|
54
|
-
initPromise = null;
|
|
55
|
-
prefix;
|
|
56
|
-
tables;
|
|
57
98
|
// ── Lifecycle ──────────────────────────────────────────────────────
|
|
58
99
|
ensureInit() {
|
|
59
100
|
if (!this.initPromise) {
|
|
@@ -156,16 +197,16 @@ var SQLiteWalletRepository = class {
|
|
|
156
197
|
* leave the next startup seeing no `vtxos` table.
|
|
157
198
|
*/
|
|
158
199
|
async migrateVtxosTable() {
|
|
159
|
-
await runInTransaction(this.db, async () => {
|
|
160
|
-
const tableExists = await
|
|
200
|
+
await runInTransaction(this.db, async (tx) => {
|
|
201
|
+
const tableExists = await tx.get(
|
|
161
202
|
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
|
|
162
203
|
[this.tables.vtxos]
|
|
163
204
|
);
|
|
164
205
|
if (!tableExists) {
|
|
165
|
-
await
|
|
206
|
+
await tx.run(this.vtxosCreateSql(this.tables.vtxos));
|
|
166
207
|
return;
|
|
167
208
|
}
|
|
168
|
-
const cols = await
|
|
209
|
+
const cols = await tx.all(
|
|
169
210
|
`PRAGMA table_info(${this.tables.vtxos})`
|
|
170
211
|
);
|
|
171
212
|
const scriptCol = cols.find((c) => c.name === "script");
|
|
@@ -179,33 +220,31 @@ var SQLiteWalletRepository = class {
|
|
|
179
220
|
let addedCanonicalColumns = false;
|
|
180
221
|
for (const [name, type] of nullableCanonicalColumns) {
|
|
181
222
|
if (!cols.some((c) => c.name === name)) {
|
|
182
|
-
await this.
|
|
183
|
-
`ALTER TABLE ${this.tables.vtxos} ADD COLUMN ${name} ${type}`
|
|
184
|
-
);
|
|
223
|
+
await tx.run(`ALTER TABLE ${this.tables.vtxos} ADD COLUMN ${name} ${type}`);
|
|
185
224
|
addedCanonicalColumns = true;
|
|
186
225
|
}
|
|
187
226
|
}
|
|
188
227
|
const hasLegacyBlob = cols.some((c) => c.name === "virtual_status_json");
|
|
189
228
|
if (addedCanonicalColumns && hasLegacyBlob) {
|
|
190
|
-
await this.backfillCanonicalVtxoColumns();
|
|
229
|
+
await this.backfillCanonicalVtxoColumns(tx);
|
|
191
230
|
}
|
|
192
231
|
if (scriptCol && scriptCol.notnull === 1 && !hasLegacyBlob) {
|
|
193
232
|
return;
|
|
194
233
|
}
|
|
195
234
|
if (!scriptCol) {
|
|
196
|
-
await
|
|
235
|
+
await tx.run(`ALTER TABLE ${this.tables.vtxos} ADD COLUMN script TEXT`);
|
|
197
236
|
}
|
|
198
|
-
const nullRows = await
|
|
237
|
+
const nullRows = await tx.all(`SELECT txid, vout, address FROM ${this.tables.vtxos} WHERE script IS NULL`);
|
|
199
238
|
for (const row of nullRows) {
|
|
200
|
-
await
|
|
239
|
+
await tx.run(
|
|
201
240
|
`UPDATE ${this.tables.vtxos} SET script = ? WHERE txid = ? AND vout = ?`,
|
|
202
241
|
[scriptFromArkAddress(row.address), row.txid, row.vout]
|
|
203
242
|
);
|
|
204
243
|
}
|
|
205
244
|
const tempName = `${this.tables.vtxos}__migrate_tmp`;
|
|
206
|
-
await
|
|
207
|
-
await
|
|
208
|
-
await
|
|
245
|
+
await tx.run(`DROP TABLE IF EXISTS ${tempName}`);
|
|
246
|
+
await tx.run(this.vtxosCreateSql(tempName));
|
|
247
|
+
await tx.run(`
|
|
209
248
|
INSERT INTO ${tempName}
|
|
210
249
|
(txid, vout, value, address, tap_tree,
|
|
211
250
|
forfeit_cb, forfeit_s, intent_cb, intent_s,
|
|
@@ -221,8 +260,8 @@ var SQLiteWalletRepository = class {
|
|
|
221
260
|
spent_by, settled_by, ark_tx_id, extra_witness_json, assets_json, script
|
|
222
261
|
FROM ${this.tables.vtxos}
|
|
223
262
|
`);
|
|
224
|
-
await
|
|
225
|
-
await
|
|
263
|
+
await tx.run(`DROP TABLE ${this.tables.vtxos}`);
|
|
264
|
+
await tx.run(`ALTER TABLE ${tempName} RENAME TO ${this.tables.vtxos}`);
|
|
226
265
|
});
|
|
227
266
|
}
|
|
228
267
|
/**
|
|
@@ -234,15 +273,15 @@ var SQLiteWalletRepository = class {
|
|
|
234
273
|
* is missing or corrupt are left alone: a migration must not be stopped by one bad row, and
|
|
235
274
|
* the next sync repairs it.
|
|
236
275
|
*/
|
|
237
|
-
async backfillCanonicalVtxoColumns() {
|
|
238
|
-
const rows = await
|
|
276
|
+
async backfillCanonicalVtxoColumns(tx) {
|
|
277
|
+
const rows = await tx.all(
|
|
239
278
|
`SELECT txid, vout, virtual_status_json FROM ${this.tables.vtxos}
|
|
240
279
|
WHERE virtual_status_json IS NOT NULL AND is_swept IS NULL`
|
|
241
280
|
);
|
|
242
281
|
for (const row of rows) {
|
|
243
282
|
const facts = legacyVtxoFacts(row.virtual_status_json);
|
|
244
283
|
if (!facts) continue;
|
|
245
|
-
await
|
|
284
|
+
await tx.run(
|
|
246
285
|
`UPDATE ${this.tables.vtxos}
|
|
247
286
|
SET is_swept = ?, is_preconfirmed = ?, commitment_txids_json = ?,
|
|
248
287
|
expires_at = ?, expires_at_height = ?,
|
|
@@ -502,6 +541,32 @@ var SQLiteWalletRepository = class {
|
|
|
502
541
|
await this.db.run(`DELETE FROM ${this.tables.transactions} WHERE address = ?`, [address]);
|
|
503
542
|
}
|
|
504
543
|
// ── Wallet state ───────────────────────────────────────────────────
|
|
544
|
+
atomicState = {
|
|
545
|
+
version: 1,
|
|
546
|
+
update: async (updater) => {
|
|
547
|
+
await this.ensureInit();
|
|
548
|
+
await runInTransaction(this.db, async (tx) => {
|
|
549
|
+
const row = await tx.get(
|
|
550
|
+
`SELECT * FROM ${this.tables.walletState} WHERE key = ?`,
|
|
551
|
+
["state"]
|
|
552
|
+
);
|
|
553
|
+
const current = row ? {
|
|
554
|
+
settings: row.settings_json ? JSON.parse(row.settings_json) : void 0,
|
|
555
|
+
lastSyncTime: row.last_sync_time ?? void 0
|
|
556
|
+
} : {};
|
|
557
|
+
const state = applyWalletStateUpdate(current, updater);
|
|
558
|
+
await tx.run(
|
|
559
|
+
`INSERT OR REPLACE INTO ${this.tables.walletState}
|
|
560
|
+
(key, settings_json, last_sync_time) VALUES (?, ?, ?)`,
|
|
561
|
+
[
|
|
562
|
+
"state",
|
|
563
|
+
state.settings ? JSON.stringify(state.settings) : null,
|
|
564
|
+
state.lastSyncTime ?? null
|
|
565
|
+
]
|
|
566
|
+
);
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
};
|
|
505
570
|
async getWalletState() {
|
|
506
571
|
await this.ensureInit();
|
|
507
572
|
const row = await this.db.get(
|
|
@@ -606,16 +671,16 @@ function txRowToDomain(row) {
|
|
|
606
671
|
// src/repositories/sqlite/contractRepository.ts
|
|
607
672
|
var WATCH_STATE = "IFNULL(watch, 'watched')";
|
|
608
673
|
var SQLiteContractRepository = class {
|
|
609
|
-
constructor(db, options) {
|
|
610
|
-
this.db = db;
|
|
611
|
-
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
612
|
-
this.table = `${this.prefix}contracts`;
|
|
613
|
-
}
|
|
614
|
-
db;
|
|
615
674
|
version = 3;
|
|
675
|
+
db;
|
|
616
676
|
initPromise = null;
|
|
617
677
|
prefix;
|
|
618
678
|
table;
|
|
679
|
+
constructor(db, options) {
|
|
680
|
+
this.db = getSerializedExecutor(db);
|
|
681
|
+
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
682
|
+
this.table = `${this.prefix}contracts`;
|
|
683
|
+
}
|
|
619
684
|
// ── Lifecycle ──────────────────────────────────────────────────────
|
|
620
685
|
ensureInit() {
|
|
621
686
|
if (!this.initPromise) {
|
|
@@ -750,16 +815,16 @@ function contractRowToDomain(row) {
|
|
|
750
815
|
|
|
751
816
|
// src/repositories/sqlite/intentRepository.ts
|
|
752
817
|
var SQLiteIntentRepository = class {
|
|
753
|
-
constructor(db, options) {
|
|
754
|
-
this.db = db;
|
|
755
|
-
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
756
|
-
this.t = `${this.prefix}intents`;
|
|
757
|
-
}
|
|
758
|
-
db;
|
|
759
818
|
version = 1;
|
|
819
|
+
db;
|
|
760
820
|
initPromise = null;
|
|
761
821
|
prefix;
|
|
762
822
|
t;
|
|
823
|
+
constructor(db, options) {
|
|
824
|
+
this.db = getSerializedExecutor(db);
|
|
825
|
+
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
826
|
+
this.t = `${this.prefix}intents`;
|
|
827
|
+
}
|
|
763
828
|
ensureInit() {
|
|
764
829
|
if (!this.initPromise) this.initPromise = this.init();
|
|
765
830
|
return this.initPromise;
|
|
@@ -793,15 +858,15 @@ var SQLiteIntentRepository = class {
|
|
|
793
858
|
}
|
|
794
859
|
async clear() {
|
|
795
860
|
await this.ensureInit();
|
|
796
|
-
await runInTransaction(this.db, async () => {
|
|
797
|
-
await
|
|
861
|
+
await runInTransaction(this.db, async (tx) => {
|
|
862
|
+
await tx.run(`DELETE FROM ${this.t}`);
|
|
798
863
|
});
|
|
799
864
|
}
|
|
800
865
|
async saveIntent(intent) {
|
|
801
866
|
await this.ensureInit();
|
|
802
867
|
const now = Date.now();
|
|
803
|
-
await runInTransaction(this.db, async () => {
|
|
804
|
-
await
|
|
868
|
+
await runInTransaction(this.db, async (tx) => {
|
|
869
|
+
await tx.run(
|
|
805
870
|
`INSERT INTO ${this.t}
|
|
806
871
|
(intent_tx_id, intent_id, state, valid_from, valid_until,
|
|
807
872
|
created_at, updated_at, register_proof, register_proof_message,
|
|
@@ -910,18 +975,18 @@ function rowToIntent(r) {
|
|
|
910
975
|
|
|
911
976
|
// src/repositories/sqlite/virtualTxRepository.ts
|
|
912
977
|
var SQLiteVirtualTxRepository = class {
|
|
913
|
-
constructor(db, options) {
|
|
914
|
-
this.db = db;
|
|
915
|
-
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
916
|
-
this.tTx = `${this.prefix}virtual_txs`;
|
|
917
|
-
this.tBranch = `${this.prefix}vtxo_branches`;
|
|
918
|
-
}
|
|
919
|
-
db;
|
|
920
978
|
version = 1;
|
|
979
|
+
db;
|
|
921
980
|
initPromise = null;
|
|
922
981
|
prefix;
|
|
923
982
|
tTx;
|
|
924
983
|
tBranch;
|
|
984
|
+
constructor(db, options) {
|
|
985
|
+
this.db = getSerializedExecutor(db);
|
|
986
|
+
this.prefix = sanitizeTablePrefix(options?.prefix ?? "ark_");
|
|
987
|
+
this.tTx = `${this.prefix}virtual_txs`;
|
|
988
|
+
this.tBranch = `${this.prefix}vtxo_branches`;
|
|
989
|
+
}
|
|
925
990
|
ensureInit() {
|
|
926
991
|
if (!this.initPromise) this.initPromise = this.init();
|
|
927
992
|
return this.initPromise;
|
|
@@ -946,17 +1011,17 @@ var SQLiteVirtualTxRepository = class {
|
|
|
946
1011
|
}
|
|
947
1012
|
async clear() {
|
|
948
1013
|
await this.ensureInit();
|
|
949
|
-
await runInTransaction(this.db, async () => {
|
|
950
|
-
await
|
|
951
|
-
await
|
|
1014
|
+
await runInTransaction(this.db, async (tx) => {
|
|
1015
|
+
await tx.run(`DELETE FROM ${this.tTx}`);
|
|
1016
|
+
await tx.run(`DELETE FROM ${this.tBranch}`);
|
|
952
1017
|
});
|
|
953
1018
|
}
|
|
954
1019
|
async upsertVirtualTxs(txs) {
|
|
955
1020
|
if (txs.length === 0) return;
|
|
956
1021
|
await this.ensureInit();
|
|
957
|
-
await runInTransaction(this.db, async () => {
|
|
1022
|
+
await runInTransaction(this.db, async (tx) => {
|
|
958
1023
|
const placeholders = txs.map(() => "?").join(", ");
|
|
959
|
-
const existing = await
|
|
1024
|
+
const existing = await tx.all(
|
|
960
1025
|
`SELECT * FROM ${this.tTx} WHERE txid IN (${placeholders})`,
|
|
961
1026
|
txs.map((t) => t.txid)
|
|
962
1027
|
);
|
|
@@ -966,7 +1031,7 @@ var SQLiteVirtualTxRepository = class {
|
|
|
966
1031
|
const psbt = t.psbt ?? prev?.psbt ?? null;
|
|
967
1032
|
const expires = t.expiresAt ?? prev?.expires_at ?? null;
|
|
968
1033
|
const type = mergeChainedTxType(t.type, prev?.type);
|
|
969
|
-
await
|
|
1034
|
+
await tx.run(
|
|
970
1035
|
`INSERT OR REPLACE INTO ${this.tTx} (txid, psbt, expires_at, type) VALUES (?, ?, ?, ?)`,
|
|
971
1036
|
[t.txid, psbt, expires, type]
|
|
972
1037
|
);
|
|
@@ -981,13 +1046,13 @@ var SQLiteVirtualTxRepository = class {
|
|
|
981
1046
|
}
|
|
982
1047
|
async setBranch(vtxo, branch) {
|
|
983
1048
|
await this.ensureInit();
|
|
984
|
-
await runInTransaction(this.db, async () => {
|
|
985
|
-
await
|
|
1049
|
+
await runInTransaction(this.db, async (tx) => {
|
|
1050
|
+
await tx.run(`DELETE FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`, [
|
|
986
1051
|
vtxo.txid,
|
|
987
1052
|
vtxo.vout
|
|
988
1053
|
]);
|
|
989
1054
|
for (const b of branch) {
|
|
990
|
-
await
|
|
1055
|
+
await tx.run(
|
|
991
1056
|
`INSERT OR REPLACE INTO ${this.tBranch} (vtxo_txid, vtxo_vout, virtual_txid, position) VALUES (?, ?, ?, ?)`,
|
|
992
1057
|
[b.vtxoTxid, b.vtxoVout, b.virtualTxid, b.position]
|
|
993
1058
|
);
|
|
@@ -1016,18 +1081,18 @@ var SQLiteVirtualTxRepository = class {
|
|
|
1016
1081
|
}
|
|
1017
1082
|
async pruneForSpentVtxo(vtxo) {
|
|
1018
1083
|
await this.ensureInit();
|
|
1019
|
-
await runInTransaction(this.db, async () => {
|
|
1020
|
-
const removed = await
|
|
1084
|
+
await runInTransaction(this.db, async (tx) => {
|
|
1085
|
+
const removed = await tx.all(
|
|
1021
1086
|
`SELECT DISTINCT virtual_txid FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`,
|
|
1022
1087
|
[vtxo.txid, vtxo.vout]
|
|
1023
1088
|
);
|
|
1024
|
-
await
|
|
1089
|
+
await tx.run(`DELETE FROM ${this.tBranch} WHERE vtxo_txid = ? AND vtxo_vout = ?`, [
|
|
1025
1090
|
vtxo.txid,
|
|
1026
1091
|
vtxo.vout
|
|
1027
1092
|
]);
|
|
1028
1093
|
if (removed.length === 0) return;
|
|
1029
1094
|
const placeholders = removed.map(() => "?").join(", ");
|
|
1030
|
-
await
|
|
1095
|
+
await tx.run(
|
|
1031
1096
|
`DELETE FROM ${this.tTx}
|
|
1032
1097
|
WHERE txid IN (${placeholders})
|
|
1033
1098
|
AND NOT EXISTS (
|
|
@@ -1049,6 +1114,6 @@ function rowToTx(r) {
|
|
|
1049
1114
|
};
|
|
1050
1115
|
}
|
|
1051
1116
|
|
|
1052
|
-
export { SQLiteContractRepository, SQLiteIntentRepository, SQLiteVirtualTxRepository, SQLiteWalletRepository, runInTransaction, sanitizeTablePrefix };
|
|
1117
|
+
export { SQLiteContractRepository, SQLiteIntentRepository, SQLiteVirtualTxRepository, SQLiteWalletRepository, getSerializedExecutor, runInTransaction, sanitizeTablePrefix };
|
|
1053
1118
|
//# sourceMappingURL=index.js.map
|
|
1054
1119
|
//# sourceMappingURL=index.js.map
|