@imtbl/minting-backend 2.0.0-alpha.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/LICENSE.md +176 -0
- package/README.md +53 -0
- package/dist/index.cjs +618 -0
- package/dist/index.js +618 -0
- package/dist/types/analytics/index.d.ts +7 -0
- package/dist/types/config/index.d.ts +15 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/logger/type.d.ts +4 -0
- package/dist/types/minting.d.ts +11 -0
- package/dist/types/persistence/pg/postgres.d.ts +3 -0
- package/dist/types/persistence/prismaSqlite/sqlite.d.ts +2 -0
- package/dist/types/persistence/type.d.ts +41 -0
- package/dist/types/postgres.test.d.ts +1 -0
- package/package.json +67 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/index.ts
|
|
2
|
+
var _blockchaindata = require('@imtbl/blockchain-data');
|
|
3
|
+
var _webhook = require('@imtbl/webhook');
|
|
4
|
+
var _metrics = require('@imtbl/metrics');
|
|
5
|
+
|
|
6
|
+
// src/analytics/index.ts
|
|
7
|
+
|
|
8
|
+
var moduleName = "minting_backend_sdk";
|
|
9
|
+
var trackInitializePersistencePG = () => {
|
|
10
|
+
try {
|
|
11
|
+
_metrics.track.call(void 0, moduleName, "initializePersistencePG");
|
|
12
|
+
} catch (e3) {
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var trackInitializePersistencePrismaSqlite = () => {
|
|
16
|
+
try {
|
|
17
|
+
_metrics.track.call(void 0, moduleName, "initializePersistencePrismaSqlite");
|
|
18
|
+
} catch (e4) {
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var trackSubmitMintingRequests = () => {
|
|
22
|
+
try {
|
|
23
|
+
_metrics.track.call(void 0, moduleName, "submitMintingRequests");
|
|
24
|
+
} catch (e5) {
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var trackProcessMint = () => {
|
|
28
|
+
try {
|
|
29
|
+
_metrics.track.call(void 0, moduleName, "processMint");
|
|
30
|
+
} catch (e6) {
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var trackRecordMint = () => {
|
|
34
|
+
try {
|
|
35
|
+
_metrics.track.call(void 0, moduleName, "recordMint");
|
|
36
|
+
} catch (e7) {
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var trackError = (error) => {
|
|
40
|
+
try {
|
|
41
|
+
_metrics.track.call(void 0, moduleName, "error", {
|
|
42
|
+
name: error.name,
|
|
43
|
+
message: error.message
|
|
44
|
+
});
|
|
45
|
+
} catch (e8) {
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var trackUncaughtException = (error, origin) => {
|
|
49
|
+
try {
|
|
50
|
+
_metrics.track.call(void 0, moduleName, "error", {
|
|
51
|
+
name: error.name,
|
|
52
|
+
message: error.message,
|
|
53
|
+
origin
|
|
54
|
+
});
|
|
55
|
+
} catch (e9) {
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/persistence/pg/postgres.ts
|
|
60
|
+
var mintingPersistence = (client) => {
|
|
61
|
+
trackInitializePersistencePG();
|
|
62
|
+
return {
|
|
63
|
+
recordMint: async (request) => {
|
|
64
|
+
const r = await client.query(
|
|
65
|
+
`
|
|
66
|
+
INSERT INTO im_assets (asset_id, contract_address, owner_address, metadata, amount, token_id)
|
|
67
|
+
VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (asset_id, contract_address) DO NOTHING;
|
|
68
|
+
`,
|
|
69
|
+
[
|
|
70
|
+
request.asset_id,
|
|
71
|
+
request.contract_address,
|
|
72
|
+
request.owner_address,
|
|
73
|
+
request.metadata,
|
|
74
|
+
request.amount,
|
|
75
|
+
request.token_id
|
|
76
|
+
]
|
|
77
|
+
);
|
|
78
|
+
if (r.rowCount === 0) {
|
|
79
|
+
throw new Error("Duplicated mint");
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
getNextBatchForSubmission: async (limit) => {
|
|
83
|
+
const res = await client.query(`
|
|
84
|
+
WITH limited_assets AS (
|
|
85
|
+
SELECT id
|
|
86
|
+
FROM im_assets
|
|
87
|
+
WHERE minting_status IS NULL
|
|
88
|
+
LIMIT $1
|
|
89
|
+
FOR UPDATE SKIP LOCKED
|
|
90
|
+
)
|
|
91
|
+
UPDATE im_assets
|
|
92
|
+
SET minting_status = 'submitting'
|
|
93
|
+
WHERE minting_status IS NULL
|
|
94
|
+
AND id IN (SELECT id FROM limited_assets)
|
|
95
|
+
RETURNING *;
|
|
96
|
+
`, [limit]);
|
|
97
|
+
return res.rows;
|
|
98
|
+
},
|
|
99
|
+
updateMintingStatusToSubmitted: async (ids) => {
|
|
100
|
+
await client.query(`
|
|
101
|
+
UPDATE im_assets SET minting_status = $2 WHERE id = ANY($1);
|
|
102
|
+
`, [ids, "submitted"]);
|
|
103
|
+
},
|
|
104
|
+
syncMintingStatus: async (submittedMintRequest) => {
|
|
105
|
+
await client.query(`
|
|
106
|
+
INSERT INTO im_assets (
|
|
107
|
+
asset_id,
|
|
108
|
+
contract_address,
|
|
109
|
+
owner_address,
|
|
110
|
+
token_id,
|
|
111
|
+
minting_status,
|
|
112
|
+
metadata_id,
|
|
113
|
+
last_imtbl_zkevm_mint_request_updated_id,
|
|
114
|
+
error,
|
|
115
|
+
amount
|
|
116
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (asset_id, contract_address)
|
|
117
|
+
DO UPDATE SET
|
|
118
|
+
owner_address = $3,
|
|
119
|
+
token_id = $4,
|
|
120
|
+
minting_status = $5,
|
|
121
|
+
metadata_id = $6,
|
|
122
|
+
last_imtbl_zkevm_mint_request_updated_id = $7,
|
|
123
|
+
error = $8
|
|
124
|
+
where (
|
|
125
|
+
im_assets.last_imtbl_zkevm_mint_request_updated_id < $7 OR
|
|
126
|
+
im_assets.last_imtbl_zkevm_mint_request_updated_id is null
|
|
127
|
+
);
|
|
128
|
+
`, [
|
|
129
|
+
submittedMintRequest.assetId,
|
|
130
|
+
submittedMintRequest.contractAddress,
|
|
131
|
+
submittedMintRequest.ownerAddress,
|
|
132
|
+
submittedMintRequest.tokenId,
|
|
133
|
+
submittedMintRequest.status,
|
|
134
|
+
submittedMintRequest.metadataId,
|
|
135
|
+
submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
136
|
+
submittedMintRequest.error,
|
|
137
|
+
submittedMintRequest.amount
|
|
138
|
+
]);
|
|
139
|
+
},
|
|
140
|
+
markAsConflict: async (assetIds, contractAddress) => {
|
|
141
|
+
await client.query(`
|
|
142
|
+
UPDATE im_assets
|
|
143
|
+
SET minting_status = 'conflicting'
|
|
144
|
+
WHERE asset_id = ANY($1)
|
|
145
|
+
AND contract_address = $2;
|
|
146
|
+
`, [assetIds, contractAddress]);
|
|
147
|
+
},
|
|
148
|
+
resetMintingStatus: async (ids) => {
|
|
149
|
+
await client.query(`
|
|
150
|
+
UPDATE im_assets SET minting_status = null WHERE id = ANY($1);
|
|
151
|
+
`, [ids]);
|
|
152
|
+
},
|
|
153
|
+
markForRetry: async (ids) => {
|
|
154
|
+
await client.query(`
|
|
155
|
+
UPDATE im_assets
|
|
156
|
+
SET minting_status = null, tried_count = tried_count + 1 WHERE id = ANY($1);
|
|
157
|
+
`, [ids]);
|
|
158
|
+
},
|
|
159
|
+
updateMintingStatusToSubmissionFailed: async (ids) => {
|
|
160
|
+
await client.query(`
|
|
161
|
+
UPDATE im_assets SET minting_status = 'submission_failed' WHERE id = ANY($1);
|
|
162
|
+
`, [ids]);
|
|
163
|
+
},
|
|
164
|
+
getMintingRequest: async (contractAddress, referenceId) => {
|
|
165
|
+
const res = await client.query(`
|
|
166
|
+
SELECT * FROM im_assets WHERE contract_address = $1 and asset_id = $2;
|
|
167
|
+
`, [contractAddress, referenceId]);
|
|
168
|
+
return res.rows[0] || null;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/persistence/prismaSqlite/sqlite.ts
|
|
174
|
+
var mintingPersistence2 = (client) => {
|
|
175
|
+
trackInitializePersistencePrismaSqlite();
|
|
176
|
+
return {
|
|
177
|
+
recordMint: async (request) => {
|
|
178
|
+
const result = await client.imAssets.upsert({
|
|
179
|
+
where: {
|
|
180
|
+
im_assets_uindex: {
|
|
181
|
+
assetId: request.asset_id,
|
|
182
|
+
contractAddress: request.contract_address
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
update: {},
|
|
186
|
+
// Do nothing on conflict
|
|
187
|
+
create: {
|
|
188
|
+
assetId: request.asset_id,
|
|
189
|
+
contractAddress: request.contract_address,
|
|
190
|
+
ownerAddress: request.owner_address,
|
|
191
|
+
metadata: JSON.stringify(request.metadata),
|
|
192
|
+
// Serialize JSON metadata
|
|
193
|
+
amount: request.amount || null,
|
|
194
|
+
tokenId: request.token_id || null
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
if (!result) {
|
|
198
|
+
throw new Error("Duplicated mint");
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
// WARNING: this is NOT concurrency safe. Please only call this method one at a time.
|
|
202
|
+
getNextBatchForSubmission: async (limit) => {
|
|
203
|
+
const assets = await client.imAssets.findMany({
|
|
204
|
+
where: {
|
|
205
|
+
mintingStatus: null
|
|
206
|
+
},
|
|
207
|
+
take: limit
|
|
208
|
+
});
|
|
209
|
+
const assetIds = assets.map((asset) => asset.id);
|
|
210
|
+
await client.imAssets.updateMany({
|
|
211
|
+
where: {
|
|
212
|
+
id: {
|
|
213
|
+
in: assetIds
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
data: {
|
|
217
|
+
mintingStatus: "submitting"
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
const updatedAssets = await client.imAssets.findMany({
|
|
221
|
+
where: {
|
|
222
|
+
id: {
|
|
223
|
+
in: assetIds
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
return updatedAssets.map((asset) => ({
|
|
228
|
+
id: asset.id,
|
|
229
|
+
contract_address: asset.contractAddress,
|
|
230
|
+
wallet_address: asset.ownerAddress,
|
|
231
|
+
asset_id: asset.assetId,
|
|
232
|
+
metadata: asset.metadata ? JSON.parse(asset.metadata) : null,
|
|
233
|
+
owner_address: asset.ownerAddress,
|
|
234
|
+
tried_count: asset.triedCount,
|
|
235
|
+
amount: asset.amount || null,
|
|
236
|
+
token_id: asset.tokenId || null
|
|
237
|
+
}));
|
|
238
|
+
},
|
|
239
|
+
updateMintingStatusToSubmitted: async (ids) => {
|
|
240
|
+
await client.imAssets.updateMany({
|
|
241
|
+
where: {
|
|
242
|
+
id: {
|
|
243
|
+
in: ids
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
data: {
|
|
247
|
+
mintingStatus: "submitted"
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
},
|
|
251
|
+
syncMintingStatus: async (submittedMintRequest) => {
|
|
252
|
+
const existingAsset = await client.imAssets.findUnique({
|
|
253
|
+
where: {
|
|
254
|
+
im_assets_uindex: {
|
|
255
|
+
assetId: submittedMintRequest.assetId,
|
|
256
|
+
contractAddress: submittedMintRequest.contractAddress
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
if (existingAsset && (existingAsset.lastImtblZkevmMintRequestUpdatedId === null || existingAsset.lastImtblZkevmMintRequestUpdatedId < submittedMintRequest.imtblZkevmMintRequestUpdatedId)) {
|
|
261
|
+
await client.imAssets.update({
|
|
262
|
+
where: {
|
|
263
|
+
im_assets_uindex: {
|
|
264
|
+
assetId: submittedMintRequest.assetId,
|
|
265
|
+
contractAddress: submittedMintRequest.contractAddress
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
data: {
|
|
269
|
+
ownerAddress: submittedMintRequest.ownerAddress,
|
|
270
|
+
tokenId: submittedMintRequest.tokenId,
|
|
271
|
+
mintingStatus: submittedMintRequest.status,
|
|
272
|
+
metadataId: submittedMintRequest.metadataId,
|
|
273
|
+
lastImtblZkevmMintRequestUpdatedId: submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
274
|
+
error: submittedMintRequest.error,
|
|
275
|
+
amount: submittedMintRequest.amount || null
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
} else if (!existingAsset) {
|
|
279
|
+
await client.imAssets.create({
|
|
280
|
+
data: {
|
|
281
|
+
assetId: submittedMintRequest.assetId,
|
|
282
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
283
|
+
ownerAddress: submittedMintRequest.ownerAddress,
|
|
284
|
+
tokenId: submittedMintRequest.tokenId,
|
|
285
|
+
mintingStatus: submittedMintRequest.status,
|
|
286
|
+
metadataId: submittedMintRequest.metadataId,
|
|
287
|
+
lastImtblZkevmMintRequestUpdatedId: submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
288
|
+
error: submittedMintRequest.error,
|
|
289
|
+
amount: submittedMintRequest.amount || null
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
updateMintingStatusToSubmissionFailed: async (ids) => {
|
|
295
|
+
await client.imAssets.updateMany({
|
|
296
|
+
where: {
|
|
297
|
+
id: {
|
|
298
|
+
in: ids
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
data: {
|
|
302
|
+
mintingStatus: "submission_failed"
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
},
|
|
306
|
+
markAsConflict: async (assetIds, contractAddress) => {
|
|
307
|
+
await client.imAssets.updateMany({
|
|
308
|
+
where: {
|
|
309
|
+
assetId: {
|
|
310
|
+
in: assetIds
|
|
311
|
+
// Targets assets where assetId is in the provided list
|
|
312
|
+
},
|
|
313
|
+
contractAddress
|
|
314
|
+
// Additional condition for contract address
|
|
315
|
+
},
|
|
316
|
+
data: {
|
|
317
|
+
mintingStatus: "conflicting"
|
|
318
|
+
// Set the new status
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
resetMintingStatus: async (ids) => {
|
|
323
|
+
await client.imAssets.updateMany({
|
|
324
|
+
where: {
|
|
325
|
+
id: {
|
|
326
|
+
in: ids
|
|
327
|
+
// Condition to match ids
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
data: {
|
|
331
|
+
mintingStatus: null
|
|
332
|
+
// Setting minting_status to null
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
},
|
|
336
|
+
// this method is not concurrency safe
|
|
337
|
+
markForRetry: async (ids) => {
|
|
338
|
+
const assets = await client.imAssets.findMany({
|
|
339
|
+
where: {
|
|
340
|
+
id: {
|
|
341
|
+
in: ids
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
select: {
|
|
345
|
+
id: true,
|
|
346
|
+
triedCount: true
|
|
347
|
+
// Assuming the field is named triedCount
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
for (const asset of assets) {
|
|
351
|
+
await client.imAssets.update({
|
|
352
|
+
where: {
|
|
353
|
+
id: asset.id
|
|
354
|
+
},
|
|
355
|
+
data: {
|
|
356
|
+
mintingStatus: null,
|
|
357
|
+
triedCount: asset.triedCount + 1
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
getMintingRequest: async (contractAddress, referenceId) => {
|
|
363
|
+
const asset = await client.imAssets.findFirst({
|
|
364
|
+
where: {
|
|
365
|
+
contractAddress,
|
|
366
|
+
assetId: referenceId
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
if (!asset) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
asset_id: asset.assetId,
|
|
374
|
+
contract_address: asset.contractAddress,
|
|
375
|
+
id: asset.id,
|
|
376
|
+
metadata: asset.metadata ? JSON.parse(asset.metadata) : null,
|
|
377
|
+
owner_address: asset.ownerAddress,
|
|
378
|
+
tried_count: asset.triedCount,
|
|
379
|
+
wallet_address: asset.ownerAddress,
|
|
380
|
+
amount: asset.amount || null
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// src/minting.ts
|
|
387
|
+
var recordMint = async (mintingPersistence3, mintRequest) => {
|
|
388
|
+
trackRecordMint();
|
|
389
|
+
mintingPersistence3.recordMint(mintRequest);
|
|
390
|
+
};
|
|
391
|
+
var defaultMintingDelay = 1e3;
|
|
392
|
+
var submitMintingRequests = async (mintingPersistence3, blockchainDataSDKClient, {
|
|
393
|
+
defaultBatchSize = 1e3,
|
|
394
|
+
chainName = "imtbl-zkevm-testnet",
|
|
395
|
+
maxNumberOfTries = 3
|
|
396
|
+
}, logger = console, maxLoops = Infinity) => {
|
|
397
|
+
trackSubmitMintingRequests();
|
|
398
|
+
let mintingResponse;
|
|
399
|
+
let numberOfLoops = 0;
|
|
400
|
+
while (numberOfLoops++ < maxLoops) {
|
|
401
|
+
await new Promise((resolve) => {
|
|
402
|
+
setTimeout(resolve, defaultMintingDelay);
|
|
403
|
+
});
|
|
404
|
+
let batchSize = Math.min(
|
|
405
|
+
_optionalChain([mintingResponse, 'optionalAccess', _ => _.imx_remaining_mint_requests]) ? parseInt(mintingResponse.imx_remaining_mint_requests, 10) : defaultBatchSize,
|
|
406
|
+
defaultBatchSize
|
|
407
|
+
);
|
|
408
|
+
if (batchSize === 0 && mintingResponse && new Date(mintingResponse.imx_mint_requests_limit_reset) > /* @__PURE__ */ new Date()) {
|
|
409
|
+
logger.info(
|
|
410
|
+
`minting limit reached, waiting for reset at ${_optionalChain([mintingResponse, 'optionalAccess', _2 => _2.imx_mint_requests_limit_reset])}`
|
|
411
|
+
);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (batchSize === 0) {
|
|
415
|
+
logger.info(
|
|
416
|
+
`minting limit has been reset, use default batch size: ${defaultBatchSize}`
|
|
417
|
+
);
|
|
418
|
+
mintingResponse = void 0;
|
|
419
|
+
batchSize = defaultBatchSize;
|
|
420
|
+
}
|
|
421
|
+
const pendingMints = await mintingPersistence3.getNextBatchForSubmission(
|
|
422
|
+
batchSize
|
|
423
|
+
);
|
|
424
|
+
if (pendingMints.length === 0) {
|
|
425
|
+
logger.info("no assets to mint");
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
const chunkedAssets = pendingMints.sort(
|
|
429
|
+
(a, b) => a.contract_address > b.contract_address ? 1 : -1
|
|
430
|
+
).reduce((acc, row) => {
|
|
431
|
+
if (acc.length === 0) {
|
|
432
|
+
return [{ contractAddress: row.contract_address, assets: [row] }];
|
|
433
|
+
}
|
|
434
|
+
const lastBatch = acc[acc.length - 1];
|
|
435
|
+
if (lastBatch.contractAddress === row.contract_address && lastBatch.assets.length < 100) {
|
|
436
|
+
return [...acc.slice(0, -1), { ...lastBatch, assets: [...lastBatch.assets, row] }];
|
|
437
|
+
}
|
|
438
|
+
return [...acc, { contractAddress: row.contract_address, assets: [row] }];
|
|
439
|
+
}, []);
|
|
440
|
+
const mintingResults = await Promise.allSettled(
|
|
441
|
+
chunkedAssets.map(
|
|
442
|
+
async ({ contractAddress, assets }) => {
|
|
443
|
+
const mintingRequest = {
|
|
444
|
+
chainName,
|
|
445
|
+
contractAddress,
|
|
446
|
+
createMintRequestRequest: {
|
|
447
|
+
assets: assets.map((row) => ({
|
|
448
|
+
reference_id: row.asset_id,
|
|
449
|
+
owner_address: row.owner_address,
|
|
450
|
+
metadata: row.metadata,
|
|
451
|
+
token_id: row.token_id,
|
|
452
|
+
amount: row.amount ? `${row.amount}` : null
|
|
453
|
+
}))
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
try {
|
|
457
|
+
const response = await blockchainDataSDKClient.createMintRequest(
|
|
458
|
+
mintingRequest
|
|
459
|
+
);
|
|
460
|
+
logger.info(
|
|
461
|
+
`mintingResponse: ${JSON.stringify(response, null, 2)}`
|
|
462
|
+
);
|
|
463
|
+
await mintingPersistence3.updateMintingStatusToSubmitted(
|
|
464
|
+
assets.map(({ id }) => id)
|
|
465
|
+
);
|
|
466
|
+
return response;
|
|
467
|
+
} catch (e) {
|
|
468
|
+
logger.error(e);
|
|
469
|
+
trackError(e);
|
|
470
|
+
if (e.code === "CONFLICT_ERROR" && _optionalChain([e, 'access', _3 => _3.details, 'optionalAccess', _4 => _4.id]) === "reference_id") {
|
|
471
|
+
try {
|
|
472
|
+
await mintingPersistence3.markAsConflict(
|
|
473
|
+
e.details.values,
|
|
474
|
+
contractAddress
|
|
475
|
+
);
|
|
476
|
+
await mintingPersistence3.resetMintingStatus(
|
|
477
|
+
assets.map(({ id }) => id).filter((id) => !e.details.values.includes(id))
|
|
478
|
+
);
|
|
479
|
+
} catch (e2) {
|
|
480
|
+
logger.error(e2);
|
|
481
|
+
trackError(e);
|
|
482
|
+
}
|
|
483
|
+
} else {
|
|
484
|
+
const { assetsToRetry, assetsExceededMaxNumberOfTries } = assets.reduce(
|
|
485
|
+
(acc, { tried_count = 0, id }) => {
|
|
486
|
+
if (tried_count < maxNumberOfTries) {
|
|
487
|
+
acc.assetsToRetry.push(id);
|
|
488
|
+
} else {
|
|
489
|
+
acc.assetsExceededMaxNumberOfTries.push(id);
|
|
490
|
+
}
|
|
491
|
+
return acc;
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
assetsToRetry: [],
|
|
495
|
+
assetsExceededMaxNumberOfTries: []
|
|
496
|
+
}
|
|
497
|
+
);
|
|
498
|
+
await mintingPersistence3.markForRetry(
|
|
499
|
+
assetsToRetry
|
|
500
|
+
);
|
|
501
|
+
await mintingPersistence3.updateMintingStatusToSubmissionFailed(
|
|
502
|
+
assetsExceededMaxNumberOfTries
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
return e;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
)
|
|
509
|
+
);
|
|
510
|
+
mintingResponse = _optionalChain([mintingResults, 'access', _5 => _5.reverse, 'call', _6 => _6(), 'access', _7 => _7.find, 'call', _8 => _8(
|
|
511
|
+
(r) => r.status === "fulfilled"
|
|
512
|
+
), 'optionalAccess', _9 => _9.value]);
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
var processMint = async (mintingPersistence3, event, logger = console) => {
|
|
516
|
+
trackProcessMint();
|
|
517
|
+
if (event.event_name !== "imtbl_zkevm_mint_request_updated") {
|
|
518
|
+
logger.info(
|
|
519
|
+
`${event.event_name} is not imtbl_zkevm_mint_request_updated, skip.`
|
|
520
|
+
);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
const referenceId = event.data.reference_id;
|
|
524
|
+
if (!referenceId) {
|
|
525
|
+
throw new Error("reference_id not found in webhook event");
|
|
526
|
+
}
|
|
527
|
+
const contractAddress = event.data.contract_address;
|
|
528
|
+
if (!contractAddress) {
|
|
529
|
+
throw new Error("contract_address not found in webhook event");
|
|
530
|
+
}
|
|
531
|
+
if (event.data.status === "failed") {
|
|
532
|
+
logger.error(`mint failed: ${JSON.stringify(event.data, null, 2)}`);
|
|
533
|
+
}
|
|
534
|
+
const mintReq = await mintingPersistence3.getMintingRequest(
|
|
535
|
+
contractAddress,
|
|
536
|
+
referenceId
|
|
537
|
+
);
|
|
538
|
+
if (!mintReq) {
|
|
539
|
+
logger.info(
|
|
540
|
+
`minting request not found in the database, ${JSON.stringify(event.data)}`
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
const ownerAddress = _optionalChain([mintReq, 'optionalAccess', _10 => _10.wallet_address]) || event.data.owner_address;
|
|
544
|
+
if (!ownerAddress) {
|
|
545
|
+
logger.error("owner_address missing");
|
|
546
|
+
throw new Error("owner_address missing");
|
|
547
|
+
}
|
|
548
|
+
await mintingPersistence3.syncMintingStatus({
|
|
549
|
+
tokenId: event.data.token_id,
|
|
550
|
+
status: event.data.status,
|
|
551
|
+
assetId: referenceId,
|
|
552
|
+
contractAddress,
|
|
553
|
+
ownerAddress,
|
|
554
|
+
metadataId: event.data.metadata_id,
|
|
555
|
+
imtblZkevmMintRequestUpdatedId: event.event_id,
|
|
556
|
+
error: event.data.error ? JSON.stringify(event.data.error) : null,
|
|
557
|
+
amount: event.data.amount || null
|
|
558
|
+
});
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// src/index.ts
|
|
562
|
+
var noopHandlers = {
|
|
563
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
564
|
+
zkevmMintRequestUpdated: async (event) => {
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
var MintingBackendModule = class {
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
constructor(config) {
|
|
573
|
+
this.baseConfig = config.baseConfig;
|
|
574
|
+
this.persistence = config.persistence;
|
|
575
|
+
this.logger = config.logger || console;
|
|
576
|
+
this.blockchainDataClient = new (0, _blockchaindata.BlockchainData)({
|
|
577
|
+
baseConfig: config.baseConfig
|
|
578
|
+
});
|
|
579
|
+
_metrics.setEnvironment.call(void 0, this.baseConfig.environment);
|
|
580
|
+
if (this.baseConfig.publishableKey) {
|
|
581
|
+
_metrics.setPublishableApiKey.call(void 0, this.baseConfig.publishableKey);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
async recordMint(mintRequest) {
|
|
585
|
+
await recordMint(this.persistence, mintRequest);
|
|
586
|
+
}
|
|
587
|
+
async submitMintingRequests(config) {
|
|
588
|
+
await submitMintingRequests(
|
|
589
|
+
this.persistence,
|
|
590
|
+
this.blockchainDataClient,
|
|
591
|
+
config
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
async processMint(body, otherHandlers = noopHandlers) {
|
|
595
|
+
await _webhook.handle.call(void 0, body, this.baseConfig.environment, {
|
|
596
|
+
zkevmMintRequestUpdated: async (event) => {
|
|
597
|
+
await processMint(this.persistence, event, this.logger);
|
|
598
|
+
if (otherHandlers.zkevmMintRequestUpdated) {
|
|
599
|
+
otherHandlers.zkevmMintRequestUpdated(event);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
if (typeof process !== "undefined" && process.on) {
|
|
606
|
+
try {
|
|
607
|
+
process.on("uncaughtExceptionMonitor", trackUncaughtException);
|
|
608
|
+
} catch (e10) {
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
exports.MintingBackendModule = MintingBackendModule; exports.mintingPersistencePg = mintingPersistence; exports.mintingPersistencePrismaSqlite = mintingPersistence2; exports.processMint = processMint; exports.recordMint = recordMint; exports.submitMintingRequests = submitMintingRequests;
|