@imtbl/sdk 1.39.2 → 1.39.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 +4 -4
- package/dist/config.js +1 -1
- package/dist/index.browser.js +4 -4
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +627 -15
- package/dist/index.d.ts +145 -7
- package/dist/index.js +626 -16
- package/dist/minting_backend.d.ts +3534 -0
- package/dist/minting_backend.js +6615 -0
- package/dist/orderbook.js +1 -1
- 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 +10 -2
package/dist/index.js
CHANGED
|
@@ -34,6 +34,7 @@ import { keccak256 as keccak256$3 } from '@ethersproject/solidity';
|
|
|
34
34
|
import { SwapRouter, PaymentsExtended } from '@uniswap/router-sdk';
|
|
35
35
|
import { parseUnits as parseUnits$1 } from '@ethersproject/units';
|
|
36
36
|
import { BigNumber as BigNumber$2 } from '@ethersproject/bignumber';
|
|
37
|
+
import MessageValidator from 'sns-validator';
|
|
37
38
|
|
|
38
39
|
const isNode$1 = () => typeof window === 'undefined';
|
|
39
40
|
const isBrowser$1 = () => !isNode$1();
|
|
@@ -161,7 +162,7 @@ const flattenProperties$1 = (properties) => {
|
|
|
161
162
|
};
|
|
162
163
|
|
|
163
164
|
// WARNING: DO NOT CHANGE THE STRING BELOW. IT GETS REPLACED AT BUILD TIME.
|
|
164
|
-
const SDK_VERSION$1 = '1.39.
|
|
165
|
+
const SDK_VERSION$1 = '1.39.3-alpha.1';
|
|
165
166
|
const getFrameParentDomain$1 = () => {
|
|
166
167
|
if (isNode$1()) {
|
|
167
168
|
return '';
|
|
@@ -14188,7 +14189,7 @@ class MultiRollupApiClients {
|
|
|
14188
14189
|
}
|
|
14189
14190
|
|
|
14190
14191
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
14191
|
-
const defaultHeaders$2 = { 'x-sdk-version': 'ts-immutable-sdk-1.39.
|
|
14192
|
+
const defaultHeaders$2 = { 'x-sdk-version': 'ts-immutable-sdk-1.39.3-alpha.1' };
|
|
14192
14193
|
const createConfig$1 = ({ basePath, headers, }) => {
|
|
14193
14194
|
if (!basePath.trim()) {
|
|
14194
14195
|
throw Error('basePath can not be empty');
|
|
@@ -14260,7 +14261,7 @@ class APIError extends Error {
|
|
|
14260
14261
|
|
|
14261
14262
|
/* eslint-disable implicit-arrow-linebreak */
|
|
14262
14263
|
const defaultHeaders$1 = {
|
|
14263
|
-
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-1.39.
|
|
14264
|
+
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-1.39.3-alpha.1',
|
|
14264
14265
|
};
|
|
14265
14266
|
/**
|
|
14266
14267
|
* createAPIConfiguration to create a custom Configuration
|
|
@@ -14734,7 +14735,7 @@ var blockchain_data = /*#__PURE__*/Object.freeze({
|
|
|
14734
14735
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
14735
14736
|
class ApiConfiguration extends index$2.Configuration {
|
|
14736
14737
|
}
|
|
14737
|
-
const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-1.39.
|
|
14738
|
+
const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-1.39.3-alpha.1' };
|
|
14738
14739
|
/**
|
|
14739
14740
|
* @dev use createImmutableXConfiguration instead
|
|
14740
14741
|
*/
|
|
@@ -14775,7 +14776,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
|
|
|
14775
14776
|
coreContractAddress,
|
|
14776
14777
|
registrationContractAddress,
|
|
14777
14778
|
registrationV4ContractAddress,
|
|
14778
|
-
sdkVersion: 'ts-immutable-sdk-1.39.
|
|
14779
|
+
sdkVersion: 'ts-immutable-sdk-1.39.3-alpha.1',
|
|
14779
14780
|
baseConfig,
|
|
14780
14781
|
});
|
|
14781
14782
|
const production = ({ baseConfig }) => createImmutableXConfiguration({
|
|
@@ -26278,12 +26279,12 @@ function assertOptions$1(options, schema, allowUnknown) {
|
|
|
26278
26279
|
}
|
|
26279
26280
|
}
|
|
26280
26281
|
|
|
26281
|
-
var validator$
|
|
26282
|
+
var validator$2 = {
|
|
26282
26283
|
assertOptions: assertOptions$1,
|
|
26283
26284
|
validators: validators$1$1
|
|
26284
26285
|
};
|
|
26285
26286
|
|
|
26286
|
-
const validators$2 = validator$
|
|
26287
|
+
const validators$2 = validator$2.validators;
|
|
26287
26288
|
|
|
26288
26289
|
/**
|
|
26289
26290
|
* Create a new instance of Axios
|
|
@@ -26324,7 +26325,7 @@ let Axios$2 = class Axios {
|
|
|
26324
26325
|
const {transitional, paramsSerializer, headers} = config;
|
|
26325
26326
|
|
|
26326
26327
|
if (transitional !== undefined) {
|
|
26327
|
-
validator$
|
|
26328
|
+
validator$2.assertOptions(transitional, {
|
|
26328
26329
|
silentJSONParsing: validators$2.transitional(validators$2.boolean),
|
|
26329
26330
|
forcedJSONParsing: validators$2.transitional(validators$2.boolean),
|
|
26330
26331
|
clarifyTimeoutError: validators$2.transitional(validators$2.boolean)
|
|
@@ -26337,7 +26338,7 @@ let Axios$2 = class Axios {
|
|
|
26337
26338
|
serialize: paramsSerializer
|
|
26338
26339
|
};
|
|
26339
26340
|
} else {
|
|
26340
|
-
validator$
|
|
26341
|
+
validator$2.assertOptions(paramsSerializer, {
|
|
26341
26342
|
encode: validators$2.function,
|
|
26342
26343
|
serialize: validators$2.function
|
|
26343
26344
|
}, true);
|
|
@@ -35056,12 +35057,12 @@ function assertOptions(options, schema, allowUnknown) {
|
|
|
35056
35057
|
}
|
|
35057
35058
|
}
|
|
35058
35059
|
|
|
35059
|
-
var validator = {
|
|
35060
|
+
var validator$1 = {
|
|
35060
35061
|
assertOptions,
|
|
35061
35062
|
validators: validators$1
|
|
35062
35063
|
};
|
|
35063
35064
|
|
|
35064
|
-
const validators = validator.validators;
|
|
35065
|
+
const validators = validator$1.validators;
|
|
35065
35066
|
|
|
35066
35067
|
/**
|
|
35067
35068
|
* Create a new instance of Axios
|
|
@@ -35102,7 +35103,7 @@ class Axios {
|
|
|
35102
35103
|
const {transitional, paramsSerializer, headers} = config;
|
|
35103
35104
|
|
|
35104
35105
|
if (transitional !== undefined) {
|
|
35105
|
-
validator.assertOptions(transitional, {
|
|
35106
|
+
validator$1.assertOptions(transitional, {
|
|
35106
35107
|
silentJSONParsing: validators.transitional(validators.boolean),
|
|
35107
35108
|
forcedJSONParsing: validators.transitional(validators.boolean),
|
|
35108
35109
|
clarifyTimeoutError: validators.transitional(validators.boolean)
|
|
@@ -35115,7 +35116,7 @@ class Axios {
|
|
|
35115
35116
|
serialize: paramsSerializer
|
|
35116
35117
|
};
|
|
35117
35118
|
} else {
|
|
35118
|
-
validator.assertOptions(paramsSerializer, {
|
|
35119
|
+
validator$1.assertOptions(paramsSerializer, {
|
|
35119
35120
|
encode: validators.function,
|
|
35120
35121
|
serialize: validators.function
|
|
35121
35122
|
}, true);
|
|
@@ -60874,7 +60875,7 @@ const flattenProperties = (properties) => {
|
|
|
60874
60875
|
};
|
|
60875
60876
|
|
|
60876
60877
|
// WARNING: DO NOT CHANGE THE STRING BELOW. IT GETS REPLACED AT BUILD TIME.
|
|
60877
|
-
const SDK_VERSION = '1.39.
|
|
60878
|
+
const SDK_VERSION = '1.39.3-alpha.1';
|
|
60878
60879
|
const getFrameParentDomain = () => {
|
|
60879
60880
|
if (isNode()) {
|
|
60880
60881
|
return '';
|
|
@@ -66167,7 +66168,7 @@ const IMMUTABLE_ZKVEM_GAS_OVERRIDES = {
|
|
|
66167
66168
|
maxPriorityFeePerGas: BigNumber$1.from(10e9),
|
|
66168
66169
|
};
|
|
66169
66170
|
|
|
66170
|
-
const SDK_VERSION_MARKER = '1.39.
|
|
66171
|
+
const SDK_VERSION_MARKER = '1.39.3-alpha.1';
|
|
66171
66172
|
// This SDK version is replaced by the `yarn build` command ran on the root level
|
|
66172
66173
|
const globalPackageVersion = () => SDK_VERSION_MARKER;
|
|
66173
66174
|
|
|
@@ -71924,4 +71925,613 @@ var x = /*#__PURE__*/Object.freeze({
|
|
|
71924
71925
|
starkEcOrder: starkEcOrder
|
|
71925
71926
|
});
|
|
71926
71927
|
|
|
71927
|
-
|
|
71928
|
+
const validator = new MessageValidator();
|
|
71929
|
+
const allowedTopicArnPrefix = {
|
|
71930
|
+
[Environment$1.PRODUCTION]: 'arn:aws:sns:us-east-2:362750628221:',
|
|
71931
|
+
[Environment$1.SANDBOX]: 'arn:aws:sns:us-east-2:783421985614:'
|
|
71932
|
+
};
|
|
71933
|
+
const init = async (body, env, handlers) => {
|
|
71934
|
+
const msg = await new Promise((resolve, reject) => {
|
|
71935
|
+
validator.validate(body, (err, message) => {
|
|
71936
|
+
if (err) {
|
|
71937
|
+
return reject(err);
|
|
71938
|
+
}
|
|
71939
|
+
// check for topic arn prefix
|
|
71940
|
+
if (!message.TopicArn.startsWith(allowedTopicArnPrefix[env])) {
|
|
71941
|
+
throw new Error('Invalid topic arn');
|
|
71942
|
+
}
|
|
71943
|
+
if (message?.Type === 'SubscriptionConfirmation') {
|
|
71944
|
+
fetch(message.SubscribeURL).then(() => {
|
|
71945
|
+
resolve(message);
|
|
71946
|
+
}).catch((e) => {
|
|
71947
|
+
reject(e);
|
|
71948
|
+
});
|
|
71949
|
+
}
|
|
71950
|
+
return resolve(message);
|
|
71951
|
+
});
|
|
71952
|
+
});
|
|
71953
|
+
if (msg.Type === 'Notification') {
|
|
71954
|
+
const event = JSON.parse(msg.Message);
|
|
71955
|
+
switch (event.event_name) {
|
|
71956
|
+
case 'imtbl_zkevm_mint_request_updated':
|
|
71957
|
+
await handlers.zkevmMintRequestUpdated(event);
|
|
71958
|
+
break;
|
|
71959
|
+
default:
|
|
71960
|
+
if (handlers.others) {
|
|
71961
|
+
await handlers.others(event);
|
|
71962
|
+
}
|
|
71963
|
+
break;
|
|
71964
|
+
}
|
|
71965
|
+
}
|
|
71966
|
+
};
|
|
71967
|
+
|
|
71968
|
+
var webhook = /*#__PURE__*/Object.freeze({
|
|
71969
|
+
__proto__: null,
|
|
71970
|
+
init: init
|
|
71971
|
+
});
|
|
71972
|
+
|
|
71973
|
+
const moduleName = 'minting_backend_sdk';
|
|
71974
|
+
const trackInitializePersistencePG = () => {
|
|
71975
|
+
try {
|
|
71976
|
+
track(moduleName, 'initializePersistencePG');
|
|
71977
|
+
}
|
|
71978
|
+
catch {
|
|
71979
|
+
// ignore
|
|
71980
|
+
}
|
|
71981
|
+
};
|
|
71982
|
+
const trackInitializePersistencePrismaSqlite = () => {
|
|
71983
|
+
try {
|
|
71984
|
+
track(moduleName, 'initializePersistencePrismaSqlite');
|
|
71985
|
+
}
|
|
71986
|
+
catch {
|
|
71987
|
+
// ignore
|
|
71988
|
+
}
|
|
71989
|
+
};
|
|
71990
|
+
const trackSubmitMintingRequests = () => {
|
|
71991
|
+
try {
|
|
71992
|
+
track(moduleName, 'submitMintingRequests');
|
|
71993
|
+
}
|
|
71994
|
+
catch {
|
|
71995
|
+
// ignore
|
|
71996
|
+
}
|
|
71997
|
+
};
|
|
71998
|
+
const trackProcessMint = () => {
|
|
71999
|
+
try {
|
|
72000
|
+
track(moduleName, 'processMint');
|
|
72001
|
+
}
|
|
72002
|
+
catch {
|
|
72003
|
+
// ignore
|
|
72004
|
+
}
|
|
72005
|
+
};
|
|
72006
|
+
const trackRecordMint = () => {
|
|
72007
|
+
try {
|
|
72008
|
+
track(moduleName, 'recordMint');
|
|
72009
|
+
}
|
|
72010
|
+
catch {
|
|
72011
|
+
// ignore
|
|
72012
|
+
}
|
|
72013
|
+
};
|
|
72014
|
+
|
|
72015
|
+
const mintingPersistence$1 = (client) => {
|
|
72016
|
+
trackInitializePersistencePG();
|
|
72017
|
+
return {
|
|
72018
|
+
recordMint: async (request) => {
|
|
72019
|
+
const r = await client.query(`
|
|
72020
|
+
INSERT INTO im_assets (asset_id, contract_address, owner_address, metadata, amount, token_id)
|
|
72021
|
+
VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (asset_id, contract_address) DO NOTHING;
|
|
72022
|
+
`, [
|
|
72023
|
+
request.asset_id, request.contract_address, request.owner_address,
|
|
72024
|
+
request.metadata, request.amount, request.token_id
|
|
72025
|
+
]);
|
|
72026
|
+
if (r.rowCount === 0) {
|
|
72027
|
+
throw new Error('Duplicated mint');
|
|
72028
|
+
}
|
|
72029
|
+
},
|
|
72030
|
+
getNextBatchForSubmission: async (limit) => {
|
|
72031
|
+
const res = await client.query(`
|
|
72032
|
+
UPDATE im_assets SET minting_status = 'submitting' WHERE minting_status IS NULL and id in (
|
|
72033
|
+
select id from im_assets where minting_status is null limit $1 for update skip locked
|
|
72034
|
+
) returning *;
|
|
72035
|
+
`, [limit]);
|
|
72036
|
+
return res.rows;
|
|
72037
|
+
},
|
|
72038
|
+
updateMintingStatusToSubmitted: async (ids) => {
|
|
72039
|
+
await client.query(`
|
|
72040
|
+
UPDATE im_assets SET minting_status = $2 WHERE id = ANY($1);
|
|
72041
|
+
`, [ids, 'submitted']);
|
|
72042
|
+
},
|
|
72043
|
+
syncMintingStatus: async (submittedMintRequest) => {
|
|
72044
|
+
// doing a upsert just in case the row has not been created yet
|
|
72045
|
+
await client.query(`
|
|
72046
|
+
INSERT INTO im_assets (
|
|
72047
|
+
asset_id,
|
|
72048
|
+
contract_address,
|
|
72049
|
+
owner_address,
|
|
72050
|
+
token_id,
|
|
72051
|
+
minting_status,
|
|
72052
|
+
metadata_id,
|
|
72053
|
+
last_imtbl_zkevm_mint_request_updated_id,
|
|
72054
|
+
error,
|
|
72055
|
+
amount
|
|
72056
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT (asset_id, contract_address)
|
|
72057
|
+
DO UPDATE SET
|
|
72058
|
+
owner_address = $3,
|
|
72059
|
+
token_id = $4,
|
|
72060
|
+
minting_status = $5,
|
|
72061
|
+
metadata_id = $6,
|
|
72062
|
+
last_imtbl_zkevm_mint_request_updated_id = $7,
|
|
72063
|
+
error = $8
|
|
72064
|
+
where (
|
|
72065
|
+
im_assets.last_imtbl_zkevm_mint_request_updated_id < $7 OR
|
|
72066
|
+
im_assets.last_imtbl_zkevm_mint_request_updated_id is null
|
|
72067
|
+
);
|
|
72068
|
+
`, [
|
|
72069
|
+
submittedMintRequest.assetId,
|
|
72070
|
+
submittedMintRequest.contractAddress,
|
|
72071
|
+
submittedMintRequest.ownerAddress,
|
|
72072
|
+
submittedMintRequest.tokenId,
|
|
72073
|
+
submittedMintRequest.status,
|
|
72074
|
+
submittedMintRequest.metadataId,
|
|
72075
|
+
submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
72076
|
+
submittedMintRequest.error,
|
|
72077
|
+
submittedMintRequest.amount
|
|
72078
|
+
]);
|
|
72079
|
+
},
|
|
72080
|
+
markAsConflict: async (assetIds, contractAddress) => {
|
|
72081
|
+
await client.query(`
|
|
72082
|
+
UPDATE im_assets
|
|
72083
|
+
SET minting_status = 'conflicting'
|
|
72084
|
+
WHERE asset_id = ANY($1)
|
|
72085
|
+
AND contract_address = $2;
|
|
72086
|
+
`, [assetIds, contractAddress]);
|
|
72087
|
+
},
|
|
72088
|
+
resetMintingStatus: async (ids) => {
|
|
72089
|
+
await client.query(`
|
|
72090
|
+
UPDATE im_assets SET minting_status = null WHERE id = ANY($1);
|
|
72091
|
+
`, [ids]);
|
|
72092
|
+
},
|
|
72093
|
+
markForRetry: async (ids) => {
|
|
72094
|
+
await client.query(`
|
|
72095
|
+
UPDATE im_assets
|
|
72096
|
+
SET minting_status = null, tried_count = tried_count + 1 WHERE id = ANY($1);
|
|
72097
|
+
`, [ids]);
|
|
72098
|
+
},
|
|
72099
|
+
updateMintingStatusToSubmissionFailed: async (ids) => {
|
|
72100
|
+
await client.query(`
|
|
72101
|
+
UPDATE im_assets SET minting_status = 'submission_failed' WHERE id = ANY($1);
|
|
72102
|
+
`, [ids]);
|
|
72103
|
+
},
|
|
72104
|
+
getMintingRequest: async (contractAddress, referenceId) => {
|
|
72105
|
+
const res = await client.query(`
|
|
72106
|
+
SELECT * FROM im_assets WHERE contract_address = $1 and asset_id = $2;
|
|
72107
|
+
`, [contractAddress, referenceId]);
|
|
72108
|
+
return res.rows[0] || null;
|
|
72109
|
+
}
|
|
72110
|
+
};
|
|
72111
|
+
};
|
|
72112
|
+
|
|
72113
|
+
/* eslint-disable no-await-in-loop */
|
|
72114
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
72115
|
+
// client is a PrismaClient instance. it needs to be generated with
|
|
72116
|
+
// additional schema defined inside (TODO: point to repo) file.
|
|
72117
|
+
const mintingPersistence = (client) => {
|
|
72118
|
+
trackInitializePersistencePrismaSqlite();
|
|
72119
|
+
return {
|
|
72120
|
+
recordMint: async (request) => {
|
|
72121
|
+
const result = await client.imAssets.upsert({
|
|
72122
|
+
where: {
|
|
72123
|
+
im_assets_uindex: {
|
|
72124
|
+
assetId: request.asset_id, contractAddress: request.contract_address
|
|
72125
|
+
}
|
|
72126
|
+
},
|
|
72127
|
+
update: {},
|
|
72128
|
+
create: {
|
|
72129
|
+
assetId: request.asset_id,
|
|
72130
|
+
contractAddress: request.contract_address,
|
|
72131
|
+
ownerAddress: request.owner_address,
|
|
72132
|
+
metadata: JSON.stringify(request.metadata),
|
|
72133
|
+
amount: request.amount || null,
|
|
72134
|
+
tokenId: request.token_id || null,
|
|
72135
|
+
},
|
|
72136
|
+
});
|
|
72137
|
+
// Since upsert does not throw on update and does not tell directly if it updated or inserted,
|
|
72138
|
+
// we need to add additional logic to handle this if "result" does not provide enough info.
|
|
72139
|
+
if (!result) {
|
|
72140
|
+
throw new Error('Duplicated mint');
|
|
72141
|
+
}
|
|
72142
|
+
},
|
|
72143
|
+
// WARNING: this is NOT concurrency safe. Please only call this method one at a time.
|
|
72144
|
+
getNextBatchForSubmission: async (limit) => {
|
|
72145
|
+
const assets = await client.imAssets.findMany({
|
|
72146
|
+
where: {
|
|
72147
|
+
mintingStatus: null
|
|
72148
|
+
},
|
|
72149
|
+
take: limit
|
|
72150
|
+
});
|
|
72151
|
+
const assetIds = assets.map((asset) => asset.id);
|
|
72152
|
+
await client.imAssets.updateMany({
|
|
72153
|
+
where: {
|
|
72154
|
+
id: {
|
|
72155
|
+
in: assetIds
|
|
72156
|
+
}
|
|
72157
|
+
},
|
|
72158
|
+
data: {
|
|
72159
|
+
mintingStatus: 'submitting'
|
|
72160
|
+
}
|
|
72161
|
+
});
|
|
72162
|
+
const updatedAssets = await client.imAssets.findMany({
|
|
72163
|
+
where: {
|
|
72164
|
+
id: {
|
|
72165
|
+
in: assetIds
|
|
72166
|
+
}
|
|
72167
|
+
}
|
|
72168
|
+
});
|
|
72169
|
+
return updatedAssets.map((asset) => ({
|
|
72170
|
+
id: asset.id,
|
|
72171
|
+
contract_address: asset.contractAddress,
|
|
72172
|
+
wallet_address: asset.ownerAddress,
|
|
72173
|
+
asset_id: asset.assetId,
|
|
72174
|
+
metadata: asset.metadata ? JSON.parse(asset.metadata) : null,
|
|
72175
|
+
owner_address: asset.ownerAddress,
|
|
72176
|
+
tried_count: asset.triedCount,
|
|
72177
|
+
amount: asset.amount || null,
|
|
72178
|
+
token_id: asset.tokenId || null,
|
|
72179
|
+
}));
|
|
72180
|
+
},
|
|
72181
|
+
updateMintingStatusToSubmitted: async (ids) => {
|
|
72182
|
+
await client.imAssets.updateMany({
|
|
72183
|
+
where: {
|
|
72184
|
+
id: {
|
|
72185
|
+
in: ids
|
|
72186
|
+
}
|
|
72187
|
+
},
|
|
72188
|
+
data: {
|
|
72189
|
+
mintingStatus: 'submitted'
|
|
72190
|
+
}
|
|
72191
|
+
});
|
|
72192
|
+
},
|
|
72193
|
+
syncMintingStatus: async (submittedMintRequest) => {
|
|
72194
|
+
// First, attempt to retrieve the existing asset
|
|
72195
|
+
const existingAsset = await client.imAssets.findUnique({
|
|
72196
|
+
where: {
|
|
72197
|
+
im_assets_uindex: {
|
|
72198
|
+
assetId: submittedMintRequest.assetId,
|
|
72199
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
72200
|
+
},
|
|
72201
|
+
}
|
|
72202
|
+
});
|
|
72203
|
+
// Check if the asset exists and the condition for updating is met
|
|
72204
|
+
if (existingAsset && (existingAsset.lastImtblZkevmMintRequestUpdatedId === null
|
|
72205
|
+
|| existingAsset.lastImtblZkevmMintRequestUpdatedId < submittedMintRequest.imtblZkevmMintRequestUpdatedId)) {
|
|
72206
|
+
// Perform update if the existing record's lastImtblZkevmMintRequestUpdatedId is less than the new one or is null
|
|
72207
|
+
await client.imAssets.update({
|
|
72208
|
+
where: {
|
|
72209
|
+
im_assets_uindex: {
|
|
72210
|
+
assetId: submittedMintRequest.assetId,
|
|
72211
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
72212
|
+
},
|
|
72213
|
+
},
|
|
72214
|
+
data: {
|
|
72215
|
+
ownerAddress: submittedMintRequest.ownerAddress,
|
|
72216
|
+
tokenId: submittedMintRequest.tokenId,
|
|
72217
|
+
mintingStatus: submittedMintRequest.status,
|
|
72218
|
+
metadataId: submittedMintRequest.metadataId,
|
|
72219
|
+
lastImtblZkevmMintRequestUpdatedId: submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
72220
|
+
error: submittedMintRequest.error,
|
|
72221
|
+
amount: submittedMintRequest.amount || null
|
|
72222
|
+
}
|
|
72223
|
+
});
|
|
72224
|
+
}
|
|
72225
|
+
else if (!existingAsset) {
|
|
72226
|
+
// Perform insert if no existing record is found
|
|
72227
|
+
await client.imAssets.create({
|
|
72228
|
+
data: {
|
|
72229
|
+
assetId: submittedMintRequest.assetId,
|
|
72230
|
+
contractAddress: submittedMintRequest.contractAddress,
|
|
72231
|
+
ownerAddress: submittedMintRequest.ownerAddress,
|
|
72232
|
+
tokenId: submittedMintRequest.tokenId,
|
|
72233
|
+
mintingStatus: submittedMintRequest.status,
|
|
72234
|
+
metadataId: submittedMintRequest.metadataId,
|
|
72235
|
+
lastImtblZkevmMintRequestUpdatedId: submittedMintRequest.imtblZkevmMintRequestUpdatedId,
|
|
72236
|
+
error: submittedMintRequest.error,
|
|
72237
|
+
amount: submittedMintRequest.amount || null
|
|
72238
|
+
}
|
|
72239
|
+
});
|
|
72240
|
+
}
|
|
72241
|
+
// If existing asset does not meet the update condition, do nothing
|
|
72242
|
+
},
|
|
72243
|
+
updateMintingStatusToSubmissionFailed: async (ids) => {
|
|
72244
|
+
await client.imAssets.updateMany({
|
|
72245
|
+
where: {
|
|
72246
|
+
id: {
|
|
72247
|
+
in: ids
|
|
72248
|
+
}
|
|
72249
|
+
},
|
|
72250
|
+
data: {
|
|
72251
|
+
mintingStatus: 'submission_failed'
|
|
72252
|
+
}
|
|
72253
|
+
});
|
|
72254
|
+
},
|
|
72255
|
+
markAsConflict: async (assetIds, contractAddress) => {
|
|
72256
|
+
await client.imAssets.updateMany({
|
|
72257
|
+
where: {
|
|
72258
|
+
assetId: {
|
|
72259
|
+
in: assetIds // Targets assets where assetId is in the provided list
|
|
72260
|
+
},
|
|
72261
|
+
contractAddress // Additional condition for contract address
|
|
72262
|
+
},
|
|
72263
|
+
data: {
|
|
72264
|
+
mintingStatus: 'conflicting' // Set the new status
|
|
72265
|
+
}
|
|
72266
|
+
});
|
|
72267
|
+
},
|
|
72268
|
+
resetMintingStatus: async (ids) => {
|
|
72269
|
+
await client.imAssets.updateMany({
|
|
72270
|
+
where: {
|
|
72271
|
+
id: {
|
|
72272
|
+
in: ids // Condition to match ids
|
|
72273
|
+
}
|
|
72274
|
+
},
|
|
72275
|
+
data: {
|
|
72276
|
+
mintingStatus: null // Setting minting_status to null
|
|
72277
|
+
}
|
|
72278
|
+
});
|
|
72279
|
+
},
|
|
72280
|
+
// this method is not concurrency safe
|
|
72281
|
+
markForRetry: async (ids) => {
|
|
72282
|
+
// Retrieve the current values of tried_count for the specified ids
|
|
72283
|
+
const assets = await client.imAssets.findMany({
|
|
72284
|
+
where: {
|
|
72285
|
+
id: {
|
|
72286
|
+
in: ids
|
|
72287
|
+
}
|
|
72288
|
+
},
|
|
72289
|
+
select: {
|
|
72290
|
+
id: true,
|
|
72291
|
+
triedCount: true // Assuming the field is named triedCount
|
|
72292
|
+
}
|
|
72293
|
+
});
|
|
72294
|
+
// Update each asset with the new tried_count and nullify minting_status
|
|
72295
|
+
for (const asset of assets) {
|
|
72296
|
+
await client.imAssets.update({
|
|
72297
|
+
where: {
|
|
72298
|
+
id: asset.id
|
|
72299
|
+
},
|
|
72300
|
+
data: {
|
|
72301
|
+
mintingStatus: null,
|
|
72302
|
+
triedCount: asset.triedCount + 1
|
|
72303
|
+
}
|
|
72304
|
+
});
|
|
72305
|
+
}
|
|
72306
|
+
},
|
|
72307
|
+
getMintingRequest: async (contractAddress, referenceId) => {
|
|
72308
|
+
// Retrieve the asset from the database based on contract_address and asset_id
|
|
72309
|
+
const asset = await client.imAssets.findFirst({
|
|
72310
|
+
where: {
|
|
72311
|
+
contractAddress,
|
|
72312
|
+
assetId: referenceId
|
|
72313
|
+
}
|
|
72314
|
+
});
|
|
72315
|
+
if (!asset) {
|
|
72316
|
+
return null;
|
|
72317
|
+
}
|
|
72318
|
+
return {
|
|
72319
|
+
asset_id: asset.assetId,
|
|
72320
|
+
contract_address: asset.contractAddress,
|
|
72321
|
+
id: asset.id,
|
|
72322
|
+
metadata: asset.metadata ? JSON.parse(asset.metadata) : null,
|
|
72323
|
+
owner_address: asset.ownerAddress,
|
|
72324
|
+
tried_count: asset.triedCount,
|
|
72325
|
+
wallet_address: asset.ownerAddress,
|
|
72326
|
+
amount: asset.amount || null
|
|
72327
|
+
};
|
|
72328
|
+
}
|
|
72329
|
+
};
|
|
72330
|
+
};
|
|
72331
|
+
|
|
72332
|
+
// TODO: expose metrics
|
|
72333
|
+
// - submitting status count, conflicting status count
|
|
72334
|
+
// - failed events count
|
|
72335
|
+
const recordMint = async (mintingPersistence, mintRequest) => {
|
|
72336
|
+
trackRecordMint();
|
|
72337
|
+
mintingPersistence.recordMint(mintRequest);
|
|
72338
|
+
};
|
|
72339
|
+
const defaultMintingDelay = 1000;
|
|
72340
|
+
// This function can be called in different node process and will run in parallel to mint assets.
|
|
72341
|
+
// Each process will NOT mint the same asset.
|
|
72342
|
+
// Monitor your database to see if parallel processes are saturating the database CPU and triggering excessive vacuuming.
|
|
72343
|
+
// default batch size will be treated as 100 when it exceeds 100 because minting API has a limit of 100 assets per request.
|
|
72344
|
+
const submitMintingRequests = async (mintingPersistence, blockchainDataSDKClient, { defaultBatchSize = 1000, chainName = 'imtbl-zkevm-testnet', maxNumberOfTries = 3, }, logger = console) => {
|
|
72345
|
+
trackSubmitMintingRequests();
|
|
72346
|
+
let mintingResponse;
|
|
72347
|
+
// eslint-disable-next-line no-constant-condition
|
|
72348
|
+
while (true) {
|
|
72349
|
+
await new Promise((resolve) => {
|
|
72350
|
+
setTimeout(resolve, defaultMintingDelay);
|
|
72351
|
+
});
|
|
72352
|
+
let batchSize = Math.min(mintingResponse?.imx_remaining_mint_requests
|
|
72353
|
+
? parseInt(mintingResponse.imx_remaining_mint_requests, 10)
|
|
72354
|
+
: defaultBatchSize, defaultBatchSize);
|
|
72355
|
+
if (batchSize === 0
|
|
72356
|
+
&& mintingResponse
|
|
72357
|
+
&& new Date(mintingResponse.imx_mint_requests_limit_reset) > new Date()) {
|
|
72358
|
+
logger.info(`minting limit reached, waiting for reset at ${mintingResponse?.imx_mint_requests_limit_reset}`);
|
|
72359
|
+
continue;
|
|
72360
|
+
}
|
|
72361
|
+
if (batchSize === 0) {
|
|
72362
|
+
logger.info(`minting limit has been reset, use default batch size: ${defaultBatchSize}`);
|
|
72363
|
+
mintingResponse = undefined;
|
|
72364
|
+
batchSize = defaultBatchSize;
|
|
72365
|
+
}
|
|
72366
|
+
// get mints to be submitted
|
|
72367
|
+
const pendingMints = await mintingPersistence.getNextBatchForSubmission(batchSize);
|
|
72368
|
+
if (pendingMints.length === 0) {
|
|
72369
|
+
logger.info('no assets to mint');
|
|
72370
|
+
continue;
|
|
72371
|
+
}
|
|
72372
|
+
// chunk assets by every 100 assets. every chunk should all be for the same contract address.
|
|
72373
|
+
const chunkedAssets = pendingMints.sort((a, b) => (a.contract_address > b.contract_address ? 1 : -1)).reduce((acc, row) => {
|
|
72374
|
+
if (acc.length === 0) {
|
|
72375
|
+
return [{ contractAddress: row.contract_address, assets: [row] }];
|
|
72376
|
+
}
|
|
72377
|
+
const lastBatch = acc[acc.length - 1];
|
|
72378
|
+
if (lastBatch.contractAddress === row.contract_address && lastBatch.assets.length < 100) {
|
|
72379
|
+
return [...acc.slice(0, -1), { ...lastBatch, assets: [...lastBatch.assets, row] }];
|
|
72380
|
+
}
|
|
72381
|
+
return [...acc, { contractAddress: row.contract_address, assets: [row] }];
|
|
72382
|
+
}, []);
|
|
72383
|
+
// submit minting request for each contract address in parallel
|
|
72384
|
+
const mintingResults = await Promise.allSettled(chunkedAssets.map(async ({ contractAddress, assets }) => {
|
|
72385
|
+
const mintingRequest = {
|
|
72386
|
+
chainName,
|
|
72387
|
+
contractAddress,
|
|
72388
|
+
createMintRequestRequest: {
|
|
72389
|
+
assets: assets.map((row) => ({
|
|
72390
|
+
reference_id: row.asset_id,
|
|
72391
|
+
owner_address: row.owner_address,
|
|
72392
|
+
metadata: row.metadata,
|
|
72393
|
+
token_id: row.token_id,
|
|
72394
|
+
amount: row.amount ? `${row.amount}` : null,
|
|
72395
|
+
})),
|
|
72396
|
+
},
|
|
72397
|
+
};
|
|
72398
|
+
try {
|
|
72399
|
+
const response = await blockchainDataSDKClient.createMintRequest(mintingRequest);
|
|
72400
|
+
logger.info(`mintingResponse: ${JSON.stringify(response, null, 2)}`);
|
|
72401
|
+
// update minting status to submitted
|
|
72402
|
+
await mintingPersistence.updateMintingStatusToSubmitted(assets.map(({ id }) => id));
|
|
72403
|
+
return response;
|
|
72404
|
+
}
|
|
72405
|
+
catch (e) {
|
|
72406
|
+
logger.error(e);
|
|
72407
|
+
if (e.code === 'CONFLICT_ERROR'
|
|
72408
|
+
&& e.details?.id === 'reference_id') {
|
|
72409
|
+
try {
|
|
72410
|
+
// mark the assets as conflicting, so that we don't send them again.
|
|
72411
|
+
await mintingPersistence.markAsConflict(e.details.values, contractAddress);
|
|
72412
|
+
// remove non conflicting assets status so that they can be retried.
|
|
72413
|
+
await mintingPersistence.resetMintingStatus(assets
|
|
72414
|
+
.map(({ id }) => id)
|
|
72415
|
+
.filter((id) => !e.details.values.includes(id)));
|
|
72416
|
+
}
|
|
72417
|
+
catch (e2) {
|
|
72418
|
+
logger.error(e2);
|
|
72419
|
+
}
|
|
72420
|
+
}
|
|
72421
|
+
else {
|
|
72422
|
+
// separate assets into "need to be retied" and "exceeded max number of tries."
|
|
72423
|
+
const { assetsToRetry, assetsExceededMaxNumberOfTries } = assets.reduce((acc, { tried_count = 0, id }) => {
|
|
72424
|
+
if (tried_count < maxNumberOfTries) {
|
|
72425
|
+
acc.assetsToRetry.push(id);
|
|
72426
|
+
}
|
|
72427
|
+
else {
|
|
72428
|
+
acc.assetsExceededMaxNumberOfTries.push(id);
|
|
72429
|
+
}
|
|
72430
|
+
return acc;
|
|
72431
|
+
}, {
|
|
72432
|
+
assetsToRetry: [],
|
|
72433
|
+
assetsExceededMaxNumberOfTries: [],
|
|
72434
|
+
});
|
|
72435
|
+
// remove all assets status so that they can be retried.
|
|
72436
|
+
await mintingPersistence.markForRetry(assetsToRetry);
|
|
72437
|
+
// mark assets that have exceeded the max number of tries as submission_failed
|
|
72438
|
+
await mintingPersistence.updateMintingStatusToSubmissionFailed(assetsExceededMaxNumberOfTries);
|
|
72439
|
+
}
|
|
72440
|
+
return e;
|
|
72441
|
+
}
|
|
72442
|
+
}));
|
|
72443
|
+
mintingResponse = mintingResults
|
|
72444
|
+
.reverse()
|
|
72445
|
+
.find((r) => r.status === 'fulfilled')?.value;
|
|
72446
|
+
}
|
|
72447
|
+
};
|
|
72448
|
+
const processMint = async (mintingPersistence, event, logger = console) => {
|
|
72449
|
+
trackProcessMint();
|
|
72450
|
+
if (event.event_name !== 'imtbl_zkevm_mint_request_updated') {
|
|
72451
|
+
logger.info(`${event.event_name} is not imtbl_zkevm_mint_request_updated, skip.`);
|
|
72452
|
+
return;
|
|
72453
|
+
}
|
|
72454
|
+
const referenceId = event.data.reference_id;
|
|
72455
|
+
if (!referenceId) {
|
|
72456
|
+
throw new Error('reference_id not found in webhook event');
|
|
72457
|
+
}
|
|
72458
|
+
const contractAddress = event.data.contract_address;
|
|
72459
|
+
if (!contractAddress) {
|
|
72460
|
+
throw new Error('contract_address not found in webhook event');
|
|
72461
|
+
}
|
|
72462
|
+
if (event.data.status === 'failed') {
|
|
72463
|
+
logger.error(`mint failed: ${JSON.stringify(event.data, null, 2)}`);
|
|
72464
|
+
}
|
|
72465
|
+
const mintReq = await mintingPersistence.getMintingRequest(contractAddress, referenceId);
|
|
72466
|
+
if (!mintReq) {
|
|
72467
|
+
logger.info(`minting request not found in the database, ${JSON.stringify(event.data)}`);
|
|
72468
|
+
}
|
|
72469
|
+
const ownerAddress = mintReq?.wallet_address || event.data.owner_address;
|
|
72470
|
+
if (!ownerAddress) {
|
|
72471
|
+
logger.error('owner_address missing');
|
|
72472
|
+
throw new Error('owner_address missing');
|
|
72473
|
+
}
|
|
72474
|
+
await mintingPersistence.syncMintingStatus({
|
|
72475
|
+
tokenId: event.data.token_id,
|
|
72476
|
+
status: event.data.status,
|
|
72477
|
+
assetId: referenceId,
|
|
72478
|
+
contractAddress,
|
|
72479
|
+
ownerAddress,
|
|
72480
|
+
metadataId: event.data.metadata_id,
|
|
72481
|
+
imtblZkevmMintRequestUpdatedId: event.event_id,
|
|
72482
|
+
error: event.data.error ? JSON.stringify(event.data.error) : null,
|
|
72483
|
+
amount: event.data.amount || null,
|
|
72484
|
+
});
|
|
72485
|
+
};
|
|
72486
|
+
|
|
72487
|
+
const noopHandlers = {
|
|
72488
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
72489
|
+
zkevmMintRequestUpdated: async (event) => { },
|
|
72490
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
72491
|
+
others: async (..._args) => { }
|
|
72492
|
+
};
|
|
72493
|
+
class MintingBackendModule {
|
|
72494
|
+
baseConfig;
|
|
72495
|
+
persistence;
|
|
72496
|
+
blockchainDataClient;
|
|
72497
|
+
logger;
|
|
72498
|
+
constructor(config) {
|
|
72499
|
+
this.baseConfig = config.baseConfig;
|
|
72500
|
+
this.persistence = config.persistence;
|
|
72501
|
+
this.logger = config.logger || console;
|
|
72502
|
+
this.blockchainDataClient = new BlockchainData({
|
|
72503
|
+
baseConfig: config.baseConfig
|
|
72504
|
+
});
|
|
72505
|
+
setEnvironment(this.baseConfig.environment);
|
|
72506
|
+
if (this.baseConfig.publishableKey) {
|
|
72507
|
+
setPublishableApiKey(this.baseConfig.publishableKey);
|
|
72508
|
+
}
|
|
72509
|
+
}
|
|
72510
|
+
async recordMint(mintRequest) {
|
|
72511
|
+
await recordMint(this.persistence, mintRequest);
|
|
72512
|
+
}
|
|
72513
|
+
async submitMintingRequests(config) {
|
|
72514
|
+
await submitMintingRequests(this.persistence, this.blockchainDataClient, config);
|
|
72515
|
+
}
|
|
72516
|
+
async processMint(body, otherHandlers = noopHandlers) {
|
|
72517
|
+
await init(body, this.baseConfig.environment, {
|
|
72518
|
+
zkevmMintRequestUpdated: async (event) => {
|
|
72519
|
+
await processMint(this.persistence, event, this.logger);
|
|
72520
|
+
otherHandlers.zkevmMintRequestUpdated(event);
|
|
72521
|
+
},
|
|
72522
|
+
others: otherHandlers.others
|
|
72523
|
+
});
|
|
72524
|
+
}
|
|
72525
|
+
}
|
|
72526
|
+
|
|
72527
|
+
var minting_backend = /*#__PURE__*/Object.freeze({
|
|
72528
|
+
__proto__: null,
|
|
72529
|
+
MintingBackendModule: MintingBackendModule,
|
|
72530
|
+
mintingPersistencePg: mintingPersistence$1,
|
|
72531
|
+
mintingPersistencePrismaSqlite: mintingPersistence,
|
|
72532
|
+
processMint: processMint,
|
|
72533
|
+
recordMint: recordMint,
|
|
72534
|
+
submitMintingRequests: submitMintingRequests
|
|
72535
|
+
});
|
|
72536
|
+
|
|
72537
|
+
export { blockchain_data as blockchainData, checkout, config, minting_backend as mintingBackend, orderbook, passport, webhook, x };
|