@imtbl/sdk 1.36.2 → 1.36.3-alpha.1
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/blockchain_data.js +2 -2
- package/dist/browser/checkout/sdk.js +4 -4
- package/dist/checkout.js +5 -10
- package/dist/config.js +1 -1
- package/dist/index.browser.js +25 -25
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +609 -21
- package/dist/index.d.ts +139 -7
- package/dist/index.js +608 -22
- package/dist/minting_backend.d.ts +3528 -0
- package/dist/minting_backend.js +6596 -0
- package/dist/orderbook.js +2 -7
- package/dist/passport.js +4 -4
- package/dist/webhook.d.ts +11 -0
- package/dist/webhook.js +388 -0
- package/dist/x.js +3 -3
- package/package.json +9 -1
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,7 @@ var solidity = require('@ethersproject/solidity');
|
|
|
34
34
|
var routerSdk = require('@uniswap/router-sdk');
|
|
35
35
|
var units = require('@ethersproject/units');
|
|
36
36
|
var bignumber = require('@ethersproject/bignumber');
|
|
37
|
+
var MessageValidator = require('sns-validator');
|
|
37
38
|
|
|
38
39
|
function _interopNamespaceDefault(e) {
|
|
39
40
|
var n = Object.create(null);
|
|
@@ -183,7 +184,7 @@ const flattenProperties$1 = (properties) => {
|
|
|
183
184
|
};
|
|
184
185
|
|
|
185
186
|
// WARNING: DO NOT CHANGE THE STRING BELOW. IT GETS REPLACED AT BUILD TIME.
|
|
186
|
-
const SDK_VERSION$1 = '1.36.
|
|
187
|
+
const SDK_VERSION$1 = '1.36.3-alpha.1';
|
|
187
188
|
const getFrameParentDomain$1 = () => {
|
|
188
189
|
if (isNode$1()) {
|
|
189
190
|
return '';
|
|
@@ -14210,7 +14211,7 @@ class MultiRollupApiClients {
|
|
|
14210
14211
|
}
|
|
14211
14212
|
|
|
14212
14213
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
14213
|
-
const defaultHeaders$2 = { 'x-sdk-version': 'ts-immutable-sdk-1.36.
|
|
14214
|
+
const defaultHeaders$2 = { 'x-sdk-version': 'ts-immutable-sdk-1.36.3-alpha.1' };
|
|
14214
14215
|
const createConfig$1 = ({ basePath, headers, }) => {
|
|
14215
14216
|
if (!basePath.trim()) {
|
|
14216
14217
|
throw Error('basePath can not be empty');
|
|
@@ -14282,7 +14283,7 @@ class APIError extends Error {
|
|
|
14282
14283
|
|
|
14283
14284
|
/* eslint-disable implicit-arrow-linebreak */
|
|
14284
14285
|
const defaultHeaders$1 = {
|
|
14285
|
-
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-1.36.
|
|
14286
|
+
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-1.36.3-alpha.1',
|
|
14286
14287
|
};
|
|
14287
14288
|
/**
|
|
14288
14289
|
* createAPIConfiguration to create a custom Configuration
|
|
@@ -14756,7 +14757,7 @@ var blockchain_data = /*#__PURE__*/Object.freeze({
|
|
|
14756
14757
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
14757
14758
|
class ApiConfiguration extends index$2.Configuration {
|
|
14758
14759
|
}
|
|
14759
|
-
const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-1.36.
|
|
14760
|
+
const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-1.36.3-alpha.1' };
|
|
14760
14761
|
/**
|
|
14761
14762
|
* @dev use createImmutableXConfiguration instead
|
|
14762
14763
|
*/
|
|
@@ -14795,7 +14796,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
|
|
|
14795
14796
|
chainID,
|
|
14796
14797
|
coreContractAddress,
|
|
14797
14798
|
registrationContractAddress,
|
|
14798
|
-
sdkVersion: 'ts-immutable-sdk-1.36.
|
|
14799
|
+
sdkVersion: 'ts-immutable-sdk-1.36.3-alpha.1',
|
|
14799
14800
|
baseConfig,
|
|
14800
14801
|
});
|
|
14801
14802
|
const production = ({ baseConfig }) => createImmutableXConfiguration({
|
|
@@ -23617,12 +23618,12 @@ function assertOptions$1(options, schema, allowUnknown) {
|
|
|
23617
23618
|
}
|
|
23618
23619
|
}
|
|
23619
23620
|
|
|
23620
|
-
var validator$
|
|
23621
|
+
var validator$2 = {
|
|
23621
23622
|
assertOptions: assertOptions$1,
|
|
23622
23623
|
validators: validators$1$1
|
|
23623
23624
|
};
|
|
23624
23625
|
|
|
23625
|
-
const validators$2 = validator$
|
|
23626
|
+
const validators$2 = validator$2.validators;
|
|
23626
23627
|
|
|
23627
23628
|
/**
|
|
23628
23629
|
* Create a new instance of Axios
|
|
@@ -23663,7 +23664,7 @@ let Axios$2 = class Axios {
|
|
|
23663
23664
|
const {transitional, paramsSerializer, headers} = config;
|
|
23664
23665
|
|
|
23665
23666
|
if (transitional !== undefined) {
|
|
23666
|
-
validator$
|
|
23667
|
+
validator$2.assertOptions(transitional, {
|
|
23667
23668
|
silentJSONParsing: validators$2.transitional(validators$2.boolean),
|
|
23668
23669
|
forcedJSONParsing: validators$2.transitional(validators$2.boolean),
|
|
23669
23670
|
clarifyTimeoutError: validators$2.transitional(validators$2.boolean)
|
|
@@ -23676,7 +23677,7 @@ let Axios$2 = class Axios {
|
|
|
23676
23677
|
serialize: paramsSerializer
|
|
23677
23678
|
};
|
|
23678
23679
|
} else {
|
|
23679
|
-
validator$
|
|
23680
|
+
validator$2.assertOptions(paramsSerializer, {
|
|
23680
23681
|
encode: validators$2.function,
|
|
23681
23682
|
serialize: validators$2.function
|
|
23682
23683
|
}, true);
|
|
@@ -29269,8 +29270,6 @@ function getOrderbookConfig(config) {
|
|
|
29269
29270
|
case Environment$1.SANDBOX:
|
|
29270
29271
|
return {
|
|
29271
29272
|
seaportContractAddress: '0x7d117aA8BD6D31c4fa91722f246388f38ab1942c',
|
|
29272
|
-
// eslint-disable-next-line max-len
|
|
29273
|
-
// zoneContractAddress: '0x8831867E347AB87FA30199C5B695F0A31604Bb52', // ImmutableSignedZoneV1
|
|
29274
29273
|
zoneContractAddress: '0x1004f9615E79462c711Ff05a386BdbA91a7628C3',
|
|
29275
29274
|
apiEndpoint: 'https://api.sandbox.immutable.com',
|
|
29276
29275
|
chainName: TESTNET_CHAIN_NAME,
|
|
@@ -29280,10 +29279,7 @@ function getOrderbookConfig(config) {
|
|
|
29280
29279
|
case Environment$1.PRODUCTION:
|
|
29281
29280
|
return {
|
|
29282
29281
|
seaportContractAddress: '0x6c12aD6F0bD274191075Eb2E78D7dA5ba6453424',
|
|
29283
|
-
|
|
29284
|
-
zoneContractAddress: '0x00338b92Bec262078B3e49BF12bbEA058916BF91',
|
|
29285
|
-
// eslint-disable-next-line max-len
|
|
29286
|
-
// zoneContractAddress: '0x1004f9615E79462c711Ff05a386BdbA91a7628C3', // ImmutableSignedZoneV2
|
|
29282
|
+
zoneContractAddress: '0x1004f9615E79462c711Ff05a386BdbA91a7628C3',
|
|
29287
29283
|
apiEndpoint: 'https://api.immutable.com',
|
|
29288
29284
|
chainName: MAINNET_CHAIN_NAME,
|
|
29289
29285
|
provider: getConfiguredProvider('https://rpc.immutable.com', config.baseConfig.rateLimitingKey),
|
|
@@ -32377,12 +32373,12 @@ function assertOptions(options, schema, allowUnknown) {
|
|
|
32377
32373
|
}
|
|
32378
32374
|
}
|
|
32379
32375
|
|
|
32380
|
-
var validator = {
|
|
32376
|
+
var validator$1 = {
|
|
32381
32377
|
assertOptions,
|
|
32382
32378
|
validators: validators$1
|
|
32383
32379
|
};
|
|
32384
32380
|
|
|
32385
|
-
const validators = validator.validators;
|
|
32381
|
+
const validators = validator$1.validators;
|
|
32386
32382
|
|
|
32387
32383
|
/**
|
|
32388
32384
|
* Create a new instance of Axios
|
|
@@ -32423,7 +32419,7 @@ class Axios {
|
|
|
32423
32419
|
const {transitional, paramsSerializer, headers} = config;
|
|
32424
32420
|
|
|
32425
32421
|
if (transitional !== undefined) {
|
|
32426
|
-
validator.assertOptions(transitional, {
|
|
32422
|
+
validator$1.assertOptions(transitional, {
|
|
32427
32423
|
silentJSONParsing: validators.transitional(validators.boolean),
|
|
32428
32424
|
forcedJSONParsing: validators.transitional(validators.boolean),
|
|
32429
32425
|
clarifyTimeoutError: validators.transitional(validators.boolean)
|
|
@@ -32436,7 +32432,7 @@ class Axios {
|
|
|
32436
32432
|
serialize: paramsSerializer
|
|
32437
32433
|
};
|
|
32438
32434
|
} else {
|
|
32439
|
-
validator.assertOptions(paramsSerializer, {
|
|
32435
|
+
validator$1.assertOptions(paramsSerializer, {
|
|
32440
32436
|
encode: validators.function,
|
|
32441
32437
|
serialize: validators.function
|
|
32442
32438
|
}, true);
|
|
@@ -58195,7 +58191,7 @@ const flattenProperties = (properties) => {
|
|
|
58195
58191
|
};
|
|
58196
58192
|
|
|
58197
58193
|
// WARNING: DO NOT CHANGE THE STRING BELOW. IT GETS REPLACED AT BUILD TIME.
|
|
58198
|
-
const SDK_VERSION = '1.36.
|
|
58194
|
+
const SDK_VERSION = '1.36.3-alpha.1';
|
|
58199
58195
|
const getFrameParentDomain = () => {
|
|
58200
58196
|
if (isNode()) {
|
|
58201
58197
|
return '';
|
|
@@ -63488,7 +63484,7 @@ const IMMUTABLE_ZKVEM_GAS_OVERRIDES = {
|
|
|
63488
63484
|
maxPriorityFeePerGas: ethers.BigNumber.from(10e9),
|
|
63489
63485
|
};
|
|
63490
63486
|
|
|
63491
|
-
const SDK_VERSION_MARKER = '1.36.
|
|
63487
|
+
const SDK_VERSION_MARKER = '1.36.3-alpha.1';
|
|
63492
63488
|
// This SDK version is replaced by the `yarn build` command ran on the root level
|
|
63493
63489
|
const globalPackageVersion = () => SDK_VERSION_MARKER;
|
|
63494
63490
|
|
|
@@ -69154,9 +69150,601 @@ var x = /*#__PURE__*/Object.freeze({
|
|
|
69154
69150
|
sandbox: sandbox
|
|
69155
69151
|
});
|
|
69156
69152
|
|
|
69153
|
+
const validator = new MessageValidator();
|
|
69154
|
+
const allowedTopicArnPrefix = {
|
|
69155
|
+
[Environment$1.PRODUCTION]: 'arn:aws:sns:us-east-2:362750628221:',
|
|
69156
|
+
[Environment$1.SANDBOX]: 'arn:aws:sns:us-east-2:783421985614:'
|
|
69157
|
+
};
|
|
69158
|
+
const init = async (body, env, handlers) => {
|
|
69159
|
+
const msg = await new Promise((resolve, reject) => {
|
|
69160
|
+
validator.validate(body, (err, message) => {
|
|
69161
|
+
if (err) {
|
|
69162
|
+
return reject(err);
|
|
69163
|
+
}
|
|
69164
|
+
// check for topic arn prefix
|
|
69165
|
+
if (!message.TopicArn.startsWith(allowedTopicArnPrefix[env])) {
|
|
69166
|
+
throw new Error('Invalid topic arn');
|
|
69167
|
+
}
|
|
69168
|
+
if (message?.Type === 'SubscriptionConfirmation') {
|
|
69169
|
+
fetch(message.SubscribeURL).then(() => {
|
|
69170
|
+
resolve(message);
|
|
69171
|
+
}).catch((e) => {
|
|
69172
|
+
reject(e);
|
|
69173
|
+
});
|
|
69174
|
+
}
|
|
69175
|
+
return resolve(message);
|
|
69176
|
+
});
|
|
69177
|
+
});
|
|
69178
|
+
if (msg.Type === 'Notification') {
|
|
69179
|
+
const event = JSON.parse(msg.Message);
|
|
69180
|
+
switch (event.event_name) {
|
|
69181
|
+
case 'imtbl_zkevm_mint_request_updated':
|
|
69182
|
+
await handlers.zkevmMintRequestUpdated(event);
|
|
69183
|
+
break;
|
|
69184
|
+
default:
|
|
69185
|
+
if (handlers.others) {
|
|
69186
|
+
await handlers.others(event);
|
|
69187
|
+
}
|
|
69188
|
+
break;
|
|
69189
|
+
}
|
|
69190
|
+
}
|
|
69191
|
+
};
|
|
69192
|
+
|
|
69193
|
+
var webhook = /*#__PURE__*/Object.freeze({
|
|
69194
|
+
__proto__: null,
|
|
69195
|
+
init: init
|
|
69196
|
+
});
|
|
69197
|
+
|
|
69198
|
+
const moduleName = 'minting_backend_sdk';
|
|
69199
|
+
const trackInitializePersistencePG = () => {
|
|
69200
|
+
try {
|
|
69201
|
+
track(moduleName, 'initializePersistencePG');
|
|
69202
|
+
}
|
|
69203
|
+
catch {
|
|
69204
|
+
// ignore
|
|
69205
|
+
}
|
|
69206
|
+
};
|
|
69207
|
+
const trackInitializePersistencePrismaSqlite = () => {
|
|
69208
|
+
try {
|
|
69209
|
+
track(moduleName, 'initializePersistencePrismaSqlite');
|
|
69210
|
+
}
|
|
69211
|
+
catch {
|
|
69212
|
+
// ignore
|
|
69213
|
+
}
|
|
69214
|
+
};
|
|
69215
|
+
const trackSubmitMintingRequests = () => {
|
|
69216
|
+
try {
|
|
69217
|
+
track(moduleName, 'submitMintingRequests');
|
|
69218
|
+
}
|
|
69219
|
+
catch {
|
|
69220
|
+
// ignore
|
|
69221
|
+
}
|
|
69222
|
+
};
|
|
69223
|
+
const trackProcessMint = () => {
|
|
69224
|
+
try {
|
|
69225
|
+
track(moduleName, 'processMint');
|
|
69226
|
+
}
|
|
69227
|
+
catch {
|
|
69228
|
+
// ignore
|
|
69229
|
+
}
|
|
69230
|
+
};
|
|
69231
|
+
const trackRecordMint = () => {
|
|
69232
|
+
try {
|
|
69233
|
+
track(moduleName, 'recordMint');
|
|
69234
|
+
}
|
|
69235
|
+
catch {
|
|
69236
|
+
// ignore
|
|
69237
|
+
}
|
|
69238
|
+
};
|
|
69239
|
+
|
|
69240
|
+
const mintingPersistence$1 = (client) => {
|
|
69241
|
+
trackInitializePersistencePG();
|
|
69242
|
+
return {
|
|
69243
|
+
recordMint: async (request) => {
|
|
69244
|
+
const r = await client.query(`
|
|
69245
|
+
INSERT INTO im_assets (asset_id, contract_address, owner_address, metadata)
|
|
69246
|
+
VALUES ($1, $2, $3, $4) ON CONFLICT (asset_id, contract_address) DO NOTHING;
|
|
69247
|
+
`, [request.asset_id, request.contract_address, request.owner_address, request.metadata]);
|
|
69248
|
+
if (r.rowCount === 0) {
|
|
69249
|
+
throw new Error('Duplicated mint');
|
|
69250
|
+
}
|
|
69251
|
+
},
|
|
69252
|
+
getNextBatchForSubmission: async (limit) => {
|
|
69253
|
+
const res = await client.query(`
|
|
69254
|
+
UPDATE im_assets SET minting_status = 'submitting' WHERE minting_status IS NULL and id in (
|
|
69255
|
+
select id from im_assets where minting_status is null limit $1 for update skip locked
|
|
69256
|
+
) returning *;
|
|
69257
|
+
`, [limit]);
|
|
69258
|
+
return res.rows;
|
|
69259
|
+
},
|
|
69260
|
+
updateMintingStatusToSubmitted: async (ids) => {
|
|
69261
|
+
await client.query(`
|
|
69262
|
+
UPDATE im_assets SET minting_status = $2 WHERE id = ANY($1);
|
|
69263
|
+
`, [ids, 'submitted']);
|
|
69264
|
+
},
|
|
69265
|
+
syncMintingStatus: async (submittedMintRequest) => {
|
|
69266
|
+
// doing a upsert just in case the row has not been created yet
|
|
69267
|
+
await client.query(`
|
|
69268
|
+
INSERT INTO im_assets (
|
|
69269
|
+
asset_id,
|
|
69270
|
+
contract_address,
|
|
69271
|
+
owner_address,
|
|
69272
|
+
token_id,
|
|
69273
|
+
minting_status,
|
|
69274
|
+
metadata_id,
|
|
69275
|
+
last_imtbl_zkevm_mint_request_updated_id,
|
|
69276
|
+
error
|
|
69277
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (asset_id, contract_address)
|
|
69278
|
+
DO UPDATE SET
|
|
69279
|
+
owner_address = $3,
|
|
69280
|
+
token_id = $4,
|
|
69281
|
+
minting_status = $5,
|
|
69282
|
+
metadata_id = $6,
|
|
69283
|
+
last_imtbl_zkevm_mint_request_updated_id = $7,
|
|
69284
|
+
error = $8
|
|
69285
|
+
where (
|
|
69286
|
+
im_assets.last_imtbl_zkevm_mint_request_updated_id < $7 OR
|
|
69287
|
+
im_assets.last_imtbl_zkevm_mint_request_updated_id is null
|
|
69288
|
+
);
|
|
69289
|
+
`, [
|
|
69290
|
+
submittedMintRequest.assetId,
|
|
69291
|
+
submittedMintRequest.contractAddress,
|
|
69292
|
+
submittedMintRequest.ownerAddress,
|
|
69293
|
+
submittedMintRequest.tokenId,
|
|
69294
|
+
submittedMintRequest.status,
|
|
69295
|
+
submittedMintRequest.metadataId,
|
|
69296
|
+
submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
69297
|
+
submittedMintRequest.error
|
|
69298
|
+
]);
|
|
69299
|
+
},
|
|
69300
|
+
markAsConflict: async (assetIds, contractAddress) => {
|
|
69301
|
+
await client.query(`
|
|
69302
|
+
UPDATE im_assets
|
|
69303
|
+
SET minting_status = 'conflicting'
|
|
69304
|
+
WHERE asset_id = ANY($1)
|
|
69305
|
+
AND contract_address = $2;
|
|
69306
|
+
`, [assetIds, contractAddress]);
|
|
69307
|
+
},
|
|
69308
|
+
resetMintingStatus: async (ids) => {
|
|
69309
|
+
await client.query(`
|
|
69310
|
+
UPDATE im_assets SET minting_status = null WHERE id = ANY($1);
|
|
69311
|
+
`, [ids]);
|
|
69312
|
+
},
|
|
69313
|
+
markForRetry: async (ids) => {
|
|
69314
|
+
await client.query(`
|
|
69315
|
+
UPDATE im_assets
|
|
69316
|
+
SET minting_status = null, tried_count = tried_count + 1 WHERE id = ANY($1);
|
|
69317
|
+
`, [ids]);
|
|
69318
|
+
},
|
|
69319
|
+
updateMintingStatusToSubmissionFailed: async (ids) => {
|
|
69320
|
+
await client.query(`
|
|
69321
|
+
UPDATE im_assets SET minting_status = 'submission_failed' WHERE id = ANY($1);
|
|
69322
|
+
`, [ids]);
|
|
69323
|
+
},
|
|
69324
|
+
getMintingRequest: async (contractAddress, referenceId) => {
|
|
69325
|
+
const res = await client.query(`
|
|
69326
|
+
SELECT * FROM im_assets WHERE contract_address = $1 and asset_id = $2;
|
|
69327
|
+
`, [contractAddress, referenceId]);
|
|
69328
|
+
return res.rows[0] || null;
|
|
69329
|
+
}
|
|
69330
|
+
};
|
|
69331
|
+
};
|
|
69332
|
+
|
|
69333
|
+
/* eslint-disable no-await-in-loop */
|
|
69334
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
69335
|
+
// client is a PrismaClient instance. it needs to be generated with
|
|
69336
|
+
// additional schema defined inside (TODO: point to repo) file.
|
|
69337
|
+
const mintingPersistence = (client) => {
|
|
69338
|
+
trackInitializePersistencePrismaSqlite();
|
|
69339
|
+
return {
|
|
69340
|
+
recordMint: async (request) => {
|
|
69341
|
+
const result = await client.imAssets.upsert({
|
|
69342
|
+
where: {
|
|
69343
|
+
im_assets_uindex: {
|
|
69344
|
+
assetId: request.asset_id, contractAddress: request.contract_address
|
|
69345
|
+
}
|
|
69346
|
+
},
|
|
69347
|
+
update: {},
|
|
69348
|
+
create: {
|
|
69349
|
+
assetId: request.asset_id,
|
|
69350
|
+
contractAddress: request.contract_address,
|
|
69351
|
+
ownerAddress: request.owner_address,
|
|
69352
|
+
metadata: JSON.stringify(request.metadata), // Serialize JSON metadata
|
|
69353
|
+
},
|
|
69354
|
+
});
|
|
69355
|
+
// Since upsert does not throw on update and does not tell directly if it updated or inserted,
|
|
69356
|
+
// we need to add additional logic to handle this if "result" does not provide enough info.
|
|
69357
|
+
if (!result) {
|
|
69358
|
+
throw new Error('Duplicated mint');
|
|
69359
|
+
}
|
|
69360
|
+
},
|
|
69361
|
+
// WARNING: this is NOT concurrency safe. Please only call this method one at a time.
|
|
69362
|
+
getNextBatchForSubmission: async (limit) => {
|
|
69363
|
+
const assets = await client.imAssets.findMany({
|
|
69364
|
+
where: {
|
|
69365
|
+
mintingStatus: null
|
|
69366
|
+
},
|
|
69367
|
+
take: limit
|
|
69368
|
+
});
|
|
69369
|
+
const assetIds = assets.map((asset) => asset.id);
|
|
69370
|
+
await client.imAssets.updateMany({
|
|
69371
|
+
where: {
|
|
69372
|
+
id: {
|
|
69373
|
+
in: assetIds
|
|
69374
|
+
}
|
|
69375
|
+
},
|
|
69376
|
+
data: {
|
|
69377
|
+
mintingStatus: 'submitting'
|
|
69378
|
+
}
|
|
69379
|
+
});
|
|
69380
|
+
const updatedAssets = await client.imAssets.findMany({
|
|
69381
|
+
where: {
|
|
69382
|
+
id: {
|
|
69383
|
+
in: assetIds
|
|
69384
|
+
}
|
|
69385
|
+
}
|
|
69386
|
+
});
|
|
69387
|
+
return updatedAssets.map((asset) => ({
|
|
69388
|
+
id: asset.id,
|
|
69389
|
+
contract_address: asset.contractAddress,
|
|
69390
|
+
wallet_address: asset.ownerAddress,
|
|
69391
|
+
asset_id: asset.assetId,
|
|
69392
|
+
metadata: asset.metadata ? JSON.parse(asset.metadata) : null,
|
|
69393
|
+
owner_address: asset.ownerAddress,
|
|
69394
|
+
tried_count: asset.triedCount,
|
|
69395
|
+
}));
|
|
69396
|
+
},
|
|
69397
|
+
updateMintingStatusToSubmitted: async (ids) => {
|
|
69398
|
+
await client.imAssets.updateMany({
|
|
69399
|
+
where: {
|
|
69400
|
+
id: {
|
|
69401
|
+
in: ids
|
|
69402
|
+
}
|
|
69403
|
+
},
|
|
69404
|
+
data: {
|
|
69405
|
+
mintingStatus: 'submitted'
|
|
69406
|
+
}
|
|
69407
|
+
});
|
|
69408
|
+
},
|
|
69409
|
+
syncMintingStatus: async (submittedMintRequest) => {
|
|
69410
|
+
// First, attempt to retrieve the existing asset
|
|
69411
|
+
const existingAsset = await client.imAssets.findUnique({
|
|
69412
|
+
where: {
|
|
69413
|
+
im_assets_uindex: {
|
|
69414
|
+
assetId: submittedMintRequest.assetId,
|
|
69415
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
69416
|
+
},
|
|
69417
|
+
}
|
|
69418
|
+
});
|
|
69419
|
+
// Check if the asset exists and the condition for updating is met
|
|
69420
|
+
if (existingAsset && (existingAsset.lastImtblZkevmMintRequestUpdatedId === null
|
|
69421
|
+
|| existingAsset.lastImtblZkevmMintRequestUpdatedId < submittedMintRequest.imtblZkevmMintRequestUpdatedId)) {
|
|
69422
|
+
// Perform update if the existing record's lastImtblZkevmMintRequestUpdatedId is less than the new one or is null
|
|
69423
|
+
await client.imAssets.update({
|
|
69424
|
+
where: {
|
|
69425
|
+
im_assets_uindex: {
|
|
69426
|
+
assetId: submittedMintRequest.assetId,
|
|
69427
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
69428
|
+
},
|
|
69429
|
+
},
|
|
69430
|
+
data: {
|
|
69431
|
+
ownerAddress: submittedMintRequest.ownerAddress,
|
|
69432
|
+
tokenId: submittedMintRequest.tokenId,
|
|
69433
|
+
mintingStatus: submittedMintRequest.status,
|
|
69434
|
+
metadataId: submittedMintRequest.metadataId,
|
|
69435
|
+
lastImtblZkevmMintRequestUpdatedId: submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
69436
|
+
error: submittedMintRequest.error,
|
|
69437
|
+
}
|
|
69438
|
+
});
|
|
69439
|
+
}
|
|
69440
|
+
else if (!existingAsset) {
|
|
69441
|
+
// Perform insert if no existing record is found
|
|
69442
|
+
await client.imAssets.create({
|
|
69443
|
+
data: {
|
|
69444
|
+
assetId: submittedMintRequest.assetId,
|
|
69445
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
69446
|
+
ownerAddress: submittedMintRequest.ownerAddress,
|
|
69447
|
+
tokenId: submittedMintRequest.tokenId,
|
|
69448
|
+
mintingStatus: submittedMintRequest.status,
|
|
69449
|
+
metadataId: submittedMintRequest.metadataId,
|
|
69450
|
+
lastImtblZkevmMintRequestUpdatedId: submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
69451
|
+
error: submittedMintRequest.error,
|
|
69452
|
+
}
|
|
69453
|
+
});
|
|
69454
|
+
}
|
|
69455
|
+
// If existing asset does not meet the update condition, do nothing
|
|
69456
|
+
},
|
|
69457
|
+
updateMintingStatusToSubmissionFailed: async (ids) => {
|
|
69458
|
+
await client.imAssets.updateMany({
|
|
69459
|
+
where: {
|
|
69460
|
+
id: {
|
|
69461
|
+
in: ids
|
|
69462
|
+
}
|
|
69463
|
+
},
|
|
69464
|
+
data: {
|
|
69465
|
+
mintingStatus: 'submission_failed'
|
|
69466
|
+
}
|
|
69467
|
+
});
|
|
69468
|
+
},
|
|
69469
|
+
markAsConflict: async (assetIds, contractAddress) => {
|
|
69470
|
+
await client.imAssets.updateMany({
|
|
69471
|
+
where: {
|
|
69472
|
+
assetId: {
|
|
69473
|
+
in: assetIds // Targets assets where assetId is in the provided list
|
|
69474
|
+
},
|
|
69475
|
+
contractAddress // Additional condition for contract address
|
|
69476
|
+
},
|
|
69477
|
+
data: {
|
|
69478
|
+
mintingStatus: 'conflicting' // Set the new status
|
|
69479
|
+
}
|
|
69480
|
+
});
|
|
69481
|
+
},
|
|
69482
|
+
resetMintingStatus: async (ids) => {
|
|
69483
|
+
await client.imAssets.updateMany({
|
|
69484
|
+
where: {
|
|
69485
|
+
id: {
|
|
69486
|
+
in: ids // Condition to match ids
|
|
69487
|
+
}
|
|
69488
|
+
},
|
|
69489
|
+
data: {
|
|
69490
|
+
mintingStatus: null // Setting minting_status to null
|
|
69491
|
+
}
|
|
69492
|
+
});
|
|
69493
|
+
},
|
|
69494
|
+
// this method is not concurrency safe
|
|
69495
|
+
markForRetry: async (ids) => {
|
|
69496
|
+
// Retrieve the current values of tried_count for the specified ids
|
|
69497
|
+
const assets = await client.imAssets.findMany({
|
|
69498
|
+
where: {
|
|
69499
|
+
id: {
|
|
69500
|
+
in: ids
|
|
69501
|
+
}
|
|
69502
|
+
},
|
|
69503
|
+
select: {
|
|
69504
|
+
id: true,
|
|
69505
|
+
triedCount: true // Assuming the field is named triedCount
|
|
69506
|
+
}
|
|
69507
|
+
});
|
|
69508
|
+
// Update each asset with the new tried_count and nullify minting_status
|
|
69509
|
+
for (const asset of assets) {
|
|
69510
|
+
await client.imAssets.update({
|
|
69511
|
+
where: {
|
|
69512
|
+
id: asset.id
|
|
69513
|
+
},
|
|
69514
|
+
data: {
|
|
69515
|
+
mintingStatus: null,
|
|
69516
|
+
triedCount: asset.triedCount + 1
|
|
69517
|
+
}
|
|
69518
|
+
});
|
|
69519
|
+
}
|
|
69520
|
+
},
|
|
69521
|
+
getMintingRequest: async (contractAddress, referenceId) => {
|
|
69522
|
+
// Retrieve the asset from the database based on contract_address and asset_id
|
|
69523
|
+
const asset = await client.imAssets.findFirst({
|
|
69524
|
+
where: {
|
|
69525
|
+
contractAddress,
|
|
69526
|
+
assetId: referenceId
|
|
69527
|
+
}
|
|
69528
|
+
});
|
|
69529
|
+
if (!asset) {
|
|
69530
|
+
return null;
|
|
69531
|
+
}
|
|
69532
|
+
return {
|
|
69533
|
+
asset_id: asset.assetId,
|
|
69534
|
+
contract_address: asset.contractAddress,
|
|
69535
|
+
id: asset.id,
|
|
69536
|
+
metadata: asset.metadata ? JSON.parse(asset.metadata) : null,
|
|
69537
|
+
owner_address: asset.ownerAddress,
|
|
69538
|
+
tried_count: asset.triedCount,
|
|
69539
|
+
wallet_address: asset.ownerAddress
|
|
69540
|
+
};
|
|
69541
|
+
}
|
|
69542
|
+
};
|
|
69543
|
+
};
|
|
69544
|
+
|
|
69545
|
+
// TODO: expose metrics
|
|
69546
|
+
// - submitting status count, conflicting status count
|
|
69547
|
+
// - failed events count
|
|
69548
|
+
const recordMint = async (mintingPersistence, mintRequest) => {
|
|
69549
|
+
trackRecordMint();
|
|
69550
|
+
mintingPersistence.recordMint(mintRequest);
|
|
69551
|
+
};
|
|
69552
|
+
const defaultMintingDelay = 1000;
|
|
69553
|
+
// This function can be called in different node process and will run in parallel to mint assets.
|
|
69554
|
+
// Each process will NOT mint the same asset.
|
|
69555
|
+
// Monitor your database to see if parallel processes are saturating the database CPU and triggering excessive vacuuming.
|
|
69556
|
+
// default batch size will be treated as 100 when it exceeds 100 because minting API has a limit of 100 assets per request.
|
|
69557
|
+
const submitMintingRequests = async (mintingPersistence, blockchainDataSDKClient, { defaultBatchSize = 1000, chainName = 'imtbl-zkevm-testnet', maxNumberOfTries = 3, }, logger = console) => {
|
|
69558
|
+
trackSubmitMintingRequests();
|
|
69559
|
+
let mintingResponse;
|
|
69560
|
+
// eslint-disable-next-line no-constant-condition
|
|
69561
|
+
while (true) {
|
|
69562
|
+
await new Promise((resolve) => {
|
|
69563
|
+
setTimeout(resolve, defaultMintingDelay);
|
|
69564
|
+
});
|
|
69565
|
+
let batchSize = Math.min(mintingResponse?.imx_remaining_mint_requests
|
|
69566
|
+
? parseInt(mintingResponse.imx_remaining_mint_requests, 10)
|
|
69567
|
+
: defaultBatchSize, defaultBatchSize);
|
|
69568
|
+
if (batchSize === 0
|
|
69569
|
+
&& mintingResponse
|
|
69570
|
+
&& new Date(mintingResponse.imx_mint_requests_limit_reset) > new Date()) {
|
|
69571
|
+
logger.info(`minting limit reached, waiting for reset at ${mintingResponse?.imx_mint_requests_limit_reset}`);
|
|
69572
|
+
continue;
|
|
69573
|
+
}
|
|
69574
|
+
if (batchSize === 0) {
|
|
69575
|
+
logger.info(`minting limit has been reset, use default batch size: ${defaultBatchSize}`);
|
|
69576
|
+
mintingResponse = undefined;
|
|
69577
|
+
batchSize = defaultBatchSize;
|
|
69578
|
+
}
|
|
69579
|
+
// get mints to be submitted
|
|
69580
|
+
const pendingMints = await mintingPersistence.getNextBatchForSubmission(batchSize);
|
|
69581
|
+
if (pendingMints.length === 0) {
|
|
69582
|
+
logger.info('no assets to mint');
|
|
69583
|
+
continue;
|
|
69584
|
+
}
|
|
69585
|
+
// chunk assets by every 100 assets. every chunk should all be for the same contract address.
|
|
69586
|
+
const chunkedAssets = pendingMints.sort((a, b) => (a.contract_address > b.contract_address ? 1 : -1)).reduce((acc, row) => {
|
|
69587
|
+
if (acc.length === 0) {
|
|
69588
|
+
return [{ contractAddress: row.contract_address, assets: [row] }];
|
|
69589
|
+
}
|
|
69590
|
+
const lastBatch = acc[acc.length - 1];
|
|
69591
|
+
if (lastBatch.contractAddress === row.contract_address && lastBatch.assets.length < 100) {
|
|
69592
|
+
return [...acc.slice(0, -1), { ...lastBatch, assets: [...lastBatch.assets, row] }];
|
|
69593
|
+
}
|
|
69594
|
+
return [...acc, { contractAddress: row.contract_address, assets: [row] }];
|
|
69595
|
+
}, []);
|
|
69596
|
+
// submit minting request for each contract address in parallel
|
|
69597
|
+
const mintingResults = await Promise.allSettled(chunkedAssets.map(async ({ contractAddress, assets }) => {
|
|
69598
|
+
const mintingRequest = {
|
|
69599
|
+
chainName,
|
|
69600
|
+
contractAddress,
|
|
69601
|
+
createMintRequestRequest: {
|
|
69602
|
+
assets: assets.map((row) => ({
|
|
69603
|
+
reference_id: row.asset_id,
|
|
69604
|
+
owner_address: row.owner_address,
|
|
69605
|
+
metadata: row.metadata,
|
|
69606
|
+
})),
|
|
69607
|
+
},
|
|
69608
|
+
};
|
|
69609
|
+
try {
|
|
69610
|
+
const response = await blockchainDataSDKClient.createMintRequest(mintingRequest);
|
|
69611
|
+
logger.info(`mintingResponse: ${JSON.stringify(response, null, 2)}`);
|
|
69612
|
+
// update minting status to submitted
|
|
69613
|
+
await mintingPersistence.updateMintingStatusToSubmitted(assets.map(({ id }) => id));
|
|
69614
|
+
return response;
|
|
69615
|
+
}
|
|
69616
|
+
catch (e) {
|
|
69617
|
+
logger.error(e);
|
|
69618
|
+
if (e.code === 'CONFLICT_ERROR'
|
|
69619
|
+
&& e.details?.id === 'reference_id') {
|
|
69620
|
+
try {
|
|
69621
|
+
// mark the assets as conflicting, so that we don't send them again.
|
|
69622
|
+
await mintingPersistence.markAsConflict(e.details.values, contractAddress);
|
|
69623
|
+
// remove non conflicting assets status so that they can be retried.
|
|
69624
|
+
await mintingPersistence.resetMintingStatus(assets
|
|
69625
|
+
.map(({ id }) => id)
|
|
69626
|
+
.filter((id) => !e.details.values.includes(id)));
|
|
69627
|
+
}
|
|
69628
|
+
catch (e2) {
|
|
69629
|
+
logger.error(e2);
|
|
69630
|
+
}
|
|
69631
|
+
}
|
|
69632
|
+
else {
|
|
69633
|
+
// separate assets into "need to be retied" and "exceeded max number of tries."
|
|
69634
|
+
const { assetsToRetry, assetsExceededMaxNumberOfTries } = assets.reduce((acc, { tried_count = 0, id }) => {
|
|
69635
|
+
if (tried_count < maxNumberOfTries) {
|
|
69636
|
+
acc.assetsToRetry.push(id);
|
|
69637
|
+
}
|
|
69638
|
+
else {
|
|
69639
|
+
acc.assetsExceededMaxNumberOfTries.push(id);
|
|
69640
|
+
}
|
|
69641
|
+
return acc;
|
|
69642
|
+
}, {
|
|
69643
|
+
assetsToRetry: [],
|
|
69644
|
+
assetsExceededMaxNumberOfTries: [],
|
|
69645
|
+
});
|
|
69646
|
+
// remove all assets status so that they can be retried.
|
|
69647
|
+
await mintingPersistence.markForRetry(assetsToRetry);
|
|
69648
|
+
// mark assets that have exceeded the max number of tries as submission_failed
|
|
69649
|
+
await mintingPersistence.updateMintingStatusToSubmissionFailed(assetsExceededMaxNumberOfTries);
|
|
69650
|
+
}
|
|
69651
|
+
return e;
|
|
69652
|
+
}
|
|
69653
|
+
}));
|
|
69654
|
+
mintingResponse = mintingResults
|
|
69655
|
+
.reverse()
|
|
69656
|
+
.find((r) => r.status === 'fulfilled')?.value;
|
|
69657
|
+
}
|
|
69658
|
+
};
|
|
69659
|
+
const processMint = async (mintingPersistence, event, logger = console) => {
|
|
69660
|
+
trackProcessMint();
|
|
69661
|
+
if (event.event_name !== 'imtbl_zkevm_mint_request_updated') {
|
|
69662
|
+
logger.info(`${event.event_name} is not imtbl_zkevm_mint_request_updated, skip.`);
|
|
69663
|
+
return;
|
|
69664
|
+
}
|
|
69665
|
+
const referenceId = event.data.reference_id;
|
|
69666
|
+
if (!referenceId) {
|
|
69667
|
+
throw new Error('reference_id not found in webhook event');
|
|
69668
|
+
}
|
|
69669
|
+
const contractAddress = event.data.contract_address;
|
|
69670
|
+
if (!contractAddress) {
|
|
69671
|
+
throw new Error('contract_address not found in webhook event');
|
|
69672
|
+
}
|
|
69673
|
+
if (event.data.status === 'failed') {
|
|
69674
|
+
logger.error(`mint failed: ${JSON.stringify(event.data, null, 2)}`);
|
|
69675
|
+
}
|
|
69676
|
+
const mintReq = await mintingPersistence.getMintingRequest(contractAddress, referenceId);
|
|
69677
|
+
if (!mintReq) {
|
|
69678
|
+
logger.info(`minting request not found in the database, ${JSON.stringify(event.data)}`);
|
|
69679
|
+
}
|
|
69680
|
+
const ownerAddress = mintReq?.wallet_address || event.data.owner_address;
|
|
69681
|
+
if (!ownerAddress) {
|
|
69682
|
+
logger.error('owner_address missing');
|
|
69683
|
+
throw new Error('owner_address missing');
|
|
69684
|
+
}
|
|
69685
|
+
await mintingPersistence.syncMintingStatus({
|
|
69686
|
+
tokenId: event.data.token_id,
|
|
69687
|
+
status: event.data.status,
|
|
69688
|
+
assetId: referenceId,
|
|
69689
|
+
contractAddress,
|
|
69690
|
+
ownerAddress,
|
|
69691
|
+
metadataId: event.data.metadata_id,
|
|
69692
|
+
imtblZkevmMintRequestUpdatedId: event.event_id,
|
|
69693
|
+
error: event.data.error ? JSON.stringify(event.data.error) : null,
|
|
69694
|
+
});
|
|
69695
|
+
};
|
|
69696
|
+
|
|
69697
|
+
const noopHandlers = {
|
|
69698
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
69699
|
+
zkevmMintRequestUpdated: async (event) => { },
|
|
69700
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
69701
|
+
others: async (..._args) => { }
|
|
69702
|
+
};
|
|
69703
|
+
class MintingBackendModule {
|
|
69704
|
+
baseConfig;
|
|
69705
|
+
persistence;
|
|
69706
|
+
blockchainDataClient;
|
|
69707
|
+
logger;
|
|
69708
|
+
constructor(config) {
|
|
69709
|
+
this.baseConfig = config.baseConfig;
|
|
69710
|
+
this.persistence = config.persistence;
|
|
69711
|
+
this.logger = config.logger || console;
|
|
69712
|
+
this.blockchainDataClient = new BlockchainData({
|
|
69713
|
+
baseConfig: config.baseConfig
|
|
69714
|
+
});
|
|
69715
|
+
}
|
|
69716
|
+
async recordMint(mintRequest) {
|
|
69717
|
+
await recordMint(this.persistence, mintRequest);
|
|
69718
|
+
}
|
|
69719
|
+
async submitMintingRequests(config) {
|
|
69720
|
+
await submitMintingRequests(this.persistence, this.blockchainDataClient, config);
|
|
69721
|
+
}
|
|
69722
|
+
async processMint(body, otherHandlers = noopHandlers) {
|
|
69723
|
+
await init(body, this.baseConfig.environment, {
|
|
69724
|
+
zkevmMintRequestUpdated: async (event) => {
|
|
69725
|
+
await processMint(this.persistence, event, this.logger);
|
|
69726
|
+
otherHandlers.zkevmMintRequestUpdated(event);
|
|
69727
|
+
},
|
|
69728
|
+
others: otherHandlers.others
|
|
69729
|
+
});
|
|
69730
|
+
}
|
|
69731
|
+
}
|
|
69732
|
+
|
|
69733
|
+
var minting_backend = /*#__PURE__*/Object.freeze({
|
|
69734
|
+
__proto__: null,
|
|
69735
|
+
MintingBackendModule: MintingBackendModule,
|
|
69736
|
+
mintingPersistencePg: mintingPersistence$1,
|
|
69737
|
+
mintingPersistencePrismaSqlite: mintingPersistence,
|
|
69738
|
+
processMint: processMint,
|
|
69739
|
+
recordMint: recordMint,
|
|
69740
|
+
submitMintingRequests: submitMintingRequests
|
|
69741
|
+
});
|
|
69742
|
+
|
|
69157
69743
|
exports.blockchainData = blockchain_data;
|
|
69158
69744
|
exports.checkout = checkout;
|
|
69159
69745
|
exports.config = config;
|
|
69746
|
+
exports.mintingBackend = minting_backend;
|
|
69160
69747
|
exports.orderbook = orderbook;
|
|
69161
69748
|
exports.passport = passport;
|
|
69749
|
+
exports.webhook = webhook;
|
|
69162
69750
|
exports.x = x;
|