@filoz/repair-cli 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/cli.js +4 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/datasets.d.ts +1 -0
- package/dist/src/commands/datasets.d.ts.map +1 -1
- package/dist/src/commands/datasets.js +5 -5
- package/dist/src/commands/datasets.js.map +1 -1
- package/dist/src/commands/providers.d.ts +1 -0
- package/dist/src/commands/providers.d.ts.map +1 -1
- package/dist/src/commands/repair.d.ts +1 -0
- package/dist/src/commands/repair.d.ts.map +1 -1
- package/dist/src/commands/repair.js +7 -3
- package/dist/src/commands/repair.js.map +1 -1
- package/dist/src/commands/replicate.d.ts +1 -0
- package/dist/src/commands/replicate.d.ts.map +1 -1
- package/dist/src/commands/replicate.js +7 -3
- package/dist/src/commands/replicate.js.map +1 -1
- package/dist/src/commands/second-copy.d.ts +25 -0
- package/dist/src/commands/second-copy.d.ts.map +1 -0
- package/dist/src/commands/second-copy.js +175 -0
- package/dist/src/commands/second-copy.js.map +1 -0
- package/dist/src/commands/session-key.d.ts +25 -0
- package/dist/src/commands/session-key.d.ts.map +1 -0
- package/dist/src/commands/session-key.js +114 -0
- package/dist/src/commands/session-key.js.map +1 -0
- package/dist/src/commands/wallet.d.ts +1 -0
- package/dist/src/commands/wallet.d.ts.map +1 -1
- package/dist/src/commands/wallet.js +75 -26
- package/dist/src/commands/wallet.js.map +1 -1
- package/dist/src/db/dedupe-cids.d.ts +1 -1
- package/dist/src/db/repair-create.d.ts.map +1 -1
- package/dist/src/db/repair-create.js +2 -0
- package/dist/src/db/repair-create.js.map +1 -1
- package/dist/src/db/replicate-create.d.ts.map +1 -1
- package/dist/src/db/replicate-create.js +2 -0
- package/dist/src/db/replicate-create.js.map +1 -1
- package/dist/src/db/second-copy-create.d.ts +10 -0
- package/dist/src/db/second-copy-create.d.ts.map +1 -0
- package/dist/src/db/second-copy-create.js +104 -0
- package/dist/src/db/second-copy-create.js.map +1 -0
- package/dist/src/db/update-operation.d.ts +2 -2
- package/dist/src/db/update-operation.d.ts.map +1 -1
- package/dist/src/db/update-operation.js +2 -2
- package/dist/src/db/upsert-operations.js +1 -1
- package/dist/src/local-schema.d.ts +48 -11
- package/dist/src/local-schema.d.ts.map +1 -1
- package/dist/src/local-schema.js +3 -1
- package/dist/src/local-schema.js.map +1 -1
- package/dist/src/middleware.d.ts +2 -0
- package/dist/src/middleware.d.ts.map +1 -1
- package/dist/src/middleware.js +2 -0
- package/dist/src/middleware.js.map +1 -1
- package/dist/src/pipeline/add-pieces.d.ts.map +1 -1
- package/dist/src/pipeline/add-pieces.js +17 -3
- package/dist/src/pipeline/add-pieces.js.map +1 -1
- package/dist/src/pipeline/create-datasets.d.ts +4 -2
- package/dist/src/pipeline/create-datasets.d.ts.map +1 -1
- package/dist/src/pipeline/create-datasets.js +5 -5
- package/dist/src/pipeline/create-datasets.js.map +1 -1
- package/dist/src/utils.d.ts +34 -30
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +68 -3
- package/dist/src/utils.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +123 -4
- package/src/cli.ts +4 -0
- package/src/commands/datasets.ts +7 -5
- package/src/commands/repair.ts +7 -3
- package/src/commands/replicate.ts +7 -3
- package/src/commands/second-copy.ts +187 -0
- package/src/commands/session-key.ts +121 -0
- package/src/commands/wallet.ts +75 -26
- package/src/db/repair-create.ts +2 -0
- package/src/db/replicate-create.ts +2 -0
- package/src/db/second-copy-create.ts +147 -0
- package/src/db/update-operation.ts +3 -3
- package/src/db/upsert-operations.ts +1 -1
- package/src/local-schema.ts +4 -7
- package/src/middleware.ts +2 -0
- package/src/pipeline/add-pieces.ts +20 -4
- package/src/pipeline/create-datasets.ts +20 -5
- package/src/utils.ts +95 -5
|
@@ -6,19 +6,19 @@ export type UpdateOperationOptions = {
|
|
|
6
6
|
localDb: LocalDatabase
|
|
7
7
|
operationId: number
|
|
8
8
|
status: localSchema.OperationStatus
|
|
9
|
-
|
|
9
|
+
txHash?: string | null
|
|
10
10
|
error?: string | null
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Updates an operation in the database.
|
|
15
15
|
*/
|
|
16
|
-
export async function updateOperation({ localDb, operationId, status,
|
|
16
|
+
export async function updateOperation({ localDb, operationId, status, txHash, error }: UpdateOperationOptions) {
|
|
17
17
|
await localDb
|
|
18
18
|
.update(localSchema.operations)
|
|
19
19
|
.set({
|
|
20
20
|
status,
|
|
21
|
-
|
|
21
|
+
txHash,
|
|
22
22
|
error: error ?? null,
|
|
23
23
|
updatedAt: Date.now(),
|
|
24
24
|
})
|
|
@@ -18,6 +18,6 @@ export async function upsertOperations({ localDb, operations }: UpsertOperations
|
|
|
18
18
|
.values(operations.map((operation) => ({ ...operation, updatedAt: now })))
|
|
19
19
|
.onConflictDoUpdate({
|
|
20
20
|
target: localDb._.fullSchema.operations.id,
|
|
21
|
-
set: buildConflictUpdateColumns(localSchema.operations, ['status', 'error', 'updatedAt', '
|
|
21
|
+
set: buildConflictUpdateColumns(localSchema.operations, ['status', 'error', 'updatedAt', 'txHash']),
|
|
22
22
|
})
|
|
23
23
|
}
|
package/src/local-schema.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { MetadataObject } from '@filoz/synapse-core'
|
|
2
|
-
import type * as SP from '@filoz/synapse-core/sp'
|
|
3
2
|
import { relations } from 'drizzle-orm'
|
|
4
3
|
import type { AnySQLiteColumn } from 'drizzle-orm/sqlite-core'
|
|
5
4
|
import * as t from 'drizzle-orm/sqlite-core'
|
|
@@ -7,14 +6,10 @@ import { customType, sqliteTable as table } from 'drizzle-orm/sqlite-core'
|
|
|
7
6
|
import * as Json from 'iso-base/json'
|
|
8
7
|
|
|
9
8
|
export type RepairStatus = 'pending' | 'completed' | 'failed'
|
|
9
|
+
export type RepairKind = 'repair' | 'replicate' | 'second_copy'
|
|
10
10
|
export type OperationStatus = 'pending' | 'completed' | 'failed' | 'skipped'
|
|
11
11
|
export type OperationType = 'create_dataset' | 'add_piece'
|
|
12
12
|
|
|
13
|
-
export type OperationResult = Omit<
|
|
14
|
-
SP.AddPiecesSuccess,
|
|
15
|
-
'txStatus' | 'addMessageOk' | 'piecesAdded' | 'pieceCount' | 'confirmedPieceIds'
|
|
16
|
-
>
|
|
17
|
-
|
|
18
13
|
/**
|
|
19
14
|
* Custom type for JSON
|
|
20
15
|
* It will be used to store JSON data in the database
|
|
@@ -50,8 +45,10 @@ export type RepairUpdate = Partial<RepairInsert>
|
|
|
50
45
|
export const repairs = table('repairs', {
|
|
51
46
|
id: t.int().primaryKey({ autoIncrement: true }),
|
|
52
47
|
status: t.text().$type<RepairStatus>().notNull().default('pending'),
|
|
48
|
+
kind: t.text().$type<RepairKind>().notNull().default('repair'),
|
|
53
49
|
repairProviderId: bigintType('repair_provider_id').notNull(),
|
|
54
50
|
repairDataSetId: bigintType('repair_data_set_id'),
|
|
51
|
+
sourceProviderUrl: t.text('source_provider_url'),
|
|
55
52
|
targetProviderId: bigintType('target_provider_id').notNull(),
|
|
56
53
|
targetProviderUrl: t.text('target_provider_url').notNull(),
|
|
57
54
|
targetDataSetId: bigintType('target_data_set_id'),
|
|
@@ -74,7 +71,7 @@ export const operations = table('operations', {
|
|
|
74
71
|
cid: t.text().notNull(),
|
|
75
72
|
metadata: jsonType().$type<MetadataObject>().notNull(),
|
|
76
73
|
alternateProvider: t.text('alternate_provider').notNull(),
|
|
77
|
-
|
|
74
|
+
txHash: t.text('tx_hash'),
|
|
78
75
|
error: t.text(),
|
|
79
76
|
createdAt: t.integer('created_at').notNull(),
|
|
80
77
|
updatedAt: t.integer('updated_at').notNull(),
|
package/src/middleware.ts
CHANGED
|
@@ -13,6 +13,7 @@ export const contextSchema = z.object({
|
|
|
13
13
|
client: z.custom<Client<Transport, Chain, Account>>(),
|
|
14
14
|
chain: z.custom<Chain>(),
|
|
15
15
|
source: z.string(),
|
|
16
|
+
isInteractive: z.boolean(),
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
export const contextMiddleware = middleware<typeof contextSchema>(async (c, next) => {
|
|
@@ -38,6 +39,7 @@ export const contextMiddleware = middleware<typeof contextSchema>(async (c, next
|
|
|
38
39
|
c.set('client', client)
|
|
39
40
|
c.set('chain', chain)
|
|
40
41
|
c.set('source', source)
|
|
42
|
+
c.set('isInteractive', !c.agent && !c.formatExplicit)
|
|
41
43
|
await next()
|
|
42
44
|
|
|
43
45
|
localDb.$client.close()
|
|
@@ -9,7 +9,7 @@ import { repairUpdate } from '../db/repair-update.ts'
|
|
|
9
9
|
import { upsertOperations } from '../db/upsert-operations.ts'
|
|
10
10
|
import type { OperationSelect, RepairSelect } from '../local-schema.ts'
|
|
11
11
|
import type { IndexerDatabase, LocalDatabase, WalletClient } from '../types.ts'
|
|
12
|
-
import { excludeOperationsByCid, hashLink, operationsToPullPieces } from '../utils.ts'
|
|
12
|
+
import { completeConfirmedOperations, excludeOperationsByCid, hashLink, operationsToPullPieces } from '../utils.ts'
|
|
13
13
|
|
|
14
14
|
export type RunPullPiecesPhaseOptions = {
|
|
15
15
|
localDb: LocalDatabase
|
|
@@ -58,6 +58,15 @@ function createAddPiecesWorker({ localDb, indexerDb, repair, client, state, log
|
|
|
58
58
|
if (isRepair) {
|
|
59
59
|
operations = await dedupeCids({ indexerDb, localDb, dataSetId: dataset.dataSetId, operations })
|
|
60
60
|
}
|
|
61
|
+
// A previous run may have submitted a transaction and crashed before marking rows completed.
|
|
62
|
+
const operationsBeforeConfirmationCheck = operations.length
|
|
63
|
+
operations = await completeConfirmedOperations({ localDb, client, operations })
|
|
64
|
+
const confirmedOperations = operationsBeforeConfirmationCheck - operations.length
|
|
65
|
+
if (confirmedOperations > 0) {
|
|
66
|
+
state.completedOperations += confirmedOperations
|
|
67
|
+
completedOps += confirmedOperations
|
|
68
|
+
}
|
|
69
|
+
|
|
61
70
|
group.message(`Pulling ${operations.length} pieces...`)
|
|
62
71
|
// pull pieces
|
|
63
72
|
if (operations.length > 0) {
|
|
@@ -66,7 +75,7 @@ function createAddPiecesWorker({ localDb, indexerDb, repair, client, state, log
|
|
|
66
75
|
dataSetId: dataset.dataSetId,
|
|
67
76
|
clientDataSetId: dataset.clientDataSetId,
|
|
68
77
|
pieces: operationsToPullPieces(operations),
|
|
69
|
-
timeout: 1000 * 60 * 30,
|
|
78
|
+
timeout: 1000 * 60 * 30, // 30 minutes
|
|
70
79
|
onStatus: (status) => {
|
|
71
80
|
const completed = status.pieces.filter((piece) => piece.status === 'complete').length
|
|
72
81
|
const failed = status.pieces.filter((piece) => piece.status === 'failed').length
|
|
@@ -105,9 +114,16 @@ function createAddPiecesWorker({ localDb, indexerDb, repair, client, state, log
|
|
|
105
114
|
metadata: isRepair ? undefined : operation.metadata,
|
|
106
115
|
})),
|
|
107
116
|
})
|
|
117
|
+
await upsertOperations({
|
|
118
|
+
localDb,
|
|
119
|
+
operations: operations.map((operation) => ({
|
|
120
|
+
...operation,
|
|
121
|
+
txHash: addPiecesResult.txHash,
|
|
122
|
+
})),
|
|
123
|
+
})
|
|
108
124
|
|
|
109
125
|
group.message(`Waiting for add pieces ${hashLink(addPiecesResult.txHash, client.chain)}...`)
|
|
110
|
-
const
|
|
126
|
+
const waitForAddPieces = await SP.waitForAddPieces(addPiecesResult)
|
|
111
127
|
state.completedOperations += operations.length
|
|
112
128
|
completedOps += operations.length
|
|
113
129
|
await upsertOperations({
|
|
@@ -116,7 +132,7 @@ function createAddPiecesWorker({ localDb, indexerDb, repair, client, state, log
|
|
|
116
132
|
...operation,
|
|
117
133
|
status: 'completed',
|
|
118
134
|
error: null,
|
|
119
|
-
|
|
135
|
+
txHash: waitForAddPieces.txHash,
|
|
120
136
|
})),
|
|
121
137
|
})
|
|
122
138
|
}
|
|
@@ -2,6 +2,7 @@ import * as p from '@clack/prompts'
|
|
|
2
2
|
import * as SP from '@filoz/synapse-core/sp'
|
|
3
3
|
import { getPDPProvider } from '@filoz/synapse-core/sp-registry'
|
|
4
4
|
import { eq } from 'drizzle-orm'
|
|
5
|
+
import type { Address } from 'viem'
|
|
5
6
|
import { findRepairDataset } from '../db/find-repair-dataset.ts'
|
|
6
7
|
import { repairUpdate } from '../db/repair-update.ts'
|
|
7
8
|
import type { RepairSelect } from '../local-schema.ts'
|
|
@@ -14,6 +15,7 @@ export type EnsureRepairDatasetOptions = {
|
|
|
14
15
|
indexerDb: IndexerDatabase
|
|
15
16
|
client: WalletClient
|
|
16
17
|
repair: RepairSelect
|
|
18
|
+
payer: Address
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/**
|
|
@@ -21,7 +23,14 @@ export type EnsureRepairDatasetOptions = {
|
|
|
21
23
|
*
|
|
22
24
|
* @param options - The options for ensuring the repair dataset.
|
|
23
25
|
*/
|
|
24
|
-
export async function ensureRepairDataset({
|
|
26
|
+
export async function ensureRepairDataset({
|
|
27
|
+
source,
|
|
28
|
+
localDb,
|
|
29
|
+
indexerDb,
|
|
30
|
+
client,
|
|
31
|
+
repair,
|
|
32
|
+
payer,
|
|
33
|
+
}: EnsureRepairDatasetOptions) {
|
|
25
34
|
const log = p.taskLog({
|
|
26
35
|
title: 'Ensuring repair dataset',
|
|
27
36
|
})
|
|
@@ -36,7 +45,7 @@ export async function ensureRepairDataset({ source, localDb, indexerDb, client,
|
|
|
36
45
|
const existingDatasetId = await findRepairDataset({
|
|
37
46
|
indexerDb,
|
|
38
47
|
providerId: repair.targetProviderId,
|
|
39
|
-
payer
|
|
48
|
+
payer,
|
|
40
49
|
source,
|
|
41
50
|
})
|
|
42
51
|
|
|
@@ -47,7 +56,7 @@ export async function ensureRepairDataset({ source, localDb, indexerDb, client,
|
|
|
47
56
|
const { txHash, statusUrl } = await SP.createDataSet(client, {
|
|
48
57
|
payee: provider.payee,
|
|
49
58
|
serviceURL: provider.pdp.serviceURL,
|
|
50
|
-
payer
|
|
59
|
+
payer,
|
|
51
60
|
cdn: false,
|
|
52
61
|
metadata: {
|
|
53
62
|
source,
|
|
@@ -74,7 +83,13 @@ export async function ensureRepairDataset({ source, localDb, indexerDb, client,
|
|
|
74
83
|
*
|
|
75
84
|
* @param options - The options for ensuring the replication dataset.
|
|
76
85
|
*/
|
|
77
|
-
export async function ensureReplicateDataset({
|
|
86
|
+
export async function ensureReplicateDataset({
|
|
87
|
+
localDb,
|
|
88
|
+
indexerDb,
|
|
89
|
+
client,
|
|
90
|
+
repair,
|
|
91
|
+
payer,
|
|
92
|
+
}: EnsureRepairDatasetOptions) {
|
|
78
93
|
const log = p.taskLog({
|
|
79
94
|
title: 'Ensuring replication dataset',
|
|
80
95
|
})
|
|
@@ -110,7 +125,7 @@ export async function ensureReplicateDataset({ localDb, indexerDb, client, repai
|
|
|
110
125
|
const { txHash, statusUrl } = await SP.createDataSet(client, {
|
|
111
126
|
payee: provider.payee,
|
|
112
127
|
serviceURL: provider.pdp.serviceURL,
|
|
113
|
-
payer
|
|
128
|
+
payer,
|
|
114
129
|
cdn: sourceDataSet.withCdn,
|
|
115
130
|
metadata: sourceDataSet.metadata ?? undefined,
|
|
116
131
|
})
|
package/src/utils.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { MetadataObject } from '@filoz/synapse-core'
|
|
2
1
|
import { type Chain, getChain } from '@filoz/synapse-core/chains'
|
|
3
2
|
import * as Piece from '@filoz/synapse-core/piece'
|
|
4
3
|
import type * as SP from '@filoz/synapse-core/sp'
|
|
5
|
-
import { getTableColumns, type SQL, sql } from 'drizzle-orm'
|
|
4
|
+
import { getTableColumns, inArray, type SQL, sql } from 'drizzle-orm'
|
|
6
5
|
import { drizzle } from 'drizzle-orm/libsql'
|
|
7
6
|
import type { PgTable } from 'drizzle-orm/pg-core'
|
|
8
7
|
import type { SQLiteTable } from 'drizzle-orm/sqlite-core'
|
|
@@ -11,12 +10,13 @@ import { Conf } from 'iso-conf'
|
|
|
11
10
|
import { request } from 'iso-web/http'
|
|
12
11
|
import pLocate from 'p-locate'
|
|
13
12
|
import terminalLink from 'terminal-link'
|
|
14
|
-
import { createWalletClient, type Hex, http } from 'viem'
|
|
13
|
+
import { createWalletClient, type Hash, type Hex, http, TransactionReceiptNotFoundError } from 'viem'
|
|
15
14
|
import { privateKeyToAccount } from 'viem/accounts'
|
|
15
|
+
import { getTransactionReceipt } from 'viem/actions'
|
|
16
16
|
import packageJson from '../package.json' with { type: 'json' }
|
|
17
17
|
import type { OperationSelect } from './local-schema.ts'
|
|
18
18
|
import * as schema from './local-schema.ts'
|
|
19
|
-
import type { LocalDatabase } from './types.ts'
|
|
19
|
+
import type { LocalDatabase, WalletClient } from './types.ts'
|
|
20
20
|
|
|
21
21
|
export const configSchema = z.object({
|
|
22
22
|
privateKey: z.string().optional(),
|
|
@@ -81,6 +81,7 @@ export async function createLocalDatabase(dbPath: string): Promise<LocalDatabase
|
|
|
81
81
|
}) as LocalDatabase
|
|
82
82
|
|
|
83
83
|
await localDb.$client.execute('PRAGMA journal_mode = WAL')
|
|
84
|
+
await migrateLocalDatabase(localDb)
|
|
84
85
|
|
|
85
86
|
return localDb
|
|
86
87
|
}
|
|
@@ -109,6 +110,25 @@ export async function migrateLocalDatabase(db: LocalDatabase) {
|
|
|
109
110
|
} catch {
|
|
110
111
|
// Column already exists on databases created with the updated schema.
|
|
111
112
|
}
|
|
113
|
+
try {
|
|
114
|
+
await db.$client.execute(`
|
|
115
|
+
ALTER TABLE repairs ADD COLUMN kind text NOT NULL DEFAULT 'repair'
|
|
116
|
+
`)
|
|
117
|
+
} catch {
|
|
118
|
+
// Column already exists on databases created with the updated schema.
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
await db.$client.execute(`
|
|
122
|
+
ALTER TABLE repairs ADD COLUMN source_provider_url text
|
|
123
|
+
`)
|
|
124
|
+
} catch {
|
|
125
|
+
// Column already exists on databases created with the updated schema.
|
|
126
|
+
}
|
|
127
|
+
await db.$client.execute(`
|
|
128
|
+
UPDATE repairs
|
|
129
|
+
SET kind = 'replicate'
|
|
130
|
+
WHERE repair_data_set_id IS NOT NULL AND (kind IS NULL OR kind = 'repair')
|
|
131
|
+
`)
|
|
112
132
|
await db.$client.execute(`
|
|
113
133
|
CREATE TABLE IF NOT EXISTS operations (
|
|
114
134
|
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
|
@@ -118,13 +138,27 @@ export async function migrateLocalDatabase(db: LocalDatabase) {
|
|
|
118
138
|
cid text NOT NULL,
|
|
119
139
|
metadata text NOT NULL,
|
|
120
140
|
alternate_provider text NOT NULL,
|
|
121
|
-
|
|
141
|
+
tx_hash text,
|
|
122
142
|
error text,
|
|
123
143
|
created_at integer NOT NULL,
|
|
124
144
|
updated_at integer NOT NULL,
|
|
125
145
|
FOREIGN KEY (repair_id) REFERENCES repairs(id)
|
|
126
146
|
)
|
|
127
147
|
`)
|
|
148
|
+
try {
|
|
149
|
+
await db.$client.execute(`
|
|
150
|
+
ALTER TABLE operations ADD COLUMN tx_hash text
|
|
151
|
+
`)
|
|
152
|
+
} catch {
|
|
153
|
+
// Column already exists on databases created with the updated schema.
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
await db.$client.execute(`
|
|
157
|
+
ALTER TABLE operations DROP COLUMN result
|
|
158
|
+
`)
|
|
159
|
+
} catch {
|
|
160
|
+
// Column does not exist on databases created with the updated schema.
|
|
161
|
+
}
|
|
128
162
|
}
|
|
129
163
|
|
|
130
164
|
/**
|
|
@@ -139,6 +173,62 @@ export function hashLink(hash: string, chain: Chain) {
|
|
|
139
173
|
return link
|
|
140
174
|
}
|
|
141
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Mark operations with successful mined transactions as completed.
|
|
178
|
+
*
|
|
179
|
+
* @returns Operations that are not completed yet.
|
|
180
|
+
*/
|
|
181
|
+
export async function completeConfirmedOperations({
|
|
182
|
+
localDb,
|
|
183
|
+
client,
|
|
184
|
+
operations,
|
|
185
|
+
}: {
|
|
186
|
+
localDb: LocalDatabase
|
|
187
|
+
client: WalletClient
|
|
188
|
+
operations: OperationSelect[]
|
|
189
|
+
}): Promise<OperationSelect[]> {
|
|
190
|
+
const hashes = new Set(
|
|
191
|
+
operations.map((operation) => operation.txHash).filter((txHash): txHash is Hash => txHash != null)
|
|
192
|
+
)
|
|
193
|
+
const completedHashes = new Set<Hash>()
|
|
194
|
+
|
|
195
|
+
for (const hash of hashes) {
|
|
196
|
+
try {
|
|
197
|
+
const receipt = await getTransactionReceipt(client, { hash })
|
|
198
|
+
if (receipt.status === 'success') {
|
|
199
|
+
completedHashes.add(hash)
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (!(error instanceof TransactionReceiptNotFoundError)) {
|
|
203
|
+
throw error
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const completedOperations = operations.filter(
|
|
209
|
+
(operation) => operation.txHash != null && completedHashes.has(operation.txHash as Hash)
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
if (completedOperations.length > 0) {
|
|
213
|
+
await localDb
|
|
214
|
+
.update(schema.operations)
|
|
215
|
+
.set({
|
|
216
|
+
status: 'completed',
|
|
217
|
+
error: null,
|
|
218
|
+
updatedAt: Date.now(),
|
|
219
|
+
})
|
|
220
|
+
.where(
|
|
221
|
+
inArray(
|
|
222
|
+
schema.operations.id,
|
|
223
|
+
completedOperations.map((operation) => operation.id)
|
|
224
|
+
)
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
const completedOperationIds = new Set(completedOperations.map((operation) => operation.id))
|
|
228
|
+
|
|
229
|
+
return operations.filter((operation) => operation.status !== 'completed' && !completedOperationIds.has(operation.id))
|
|
230
|
+
}
|
|
231
|
+
|
|
142
232
|
/**
|
|
143
233
|
* Get a piece from a service URL
|
|
144
234
|
*/
|