@imtbl/minting-backend 2.23.0 → 2.23.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
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; } async function _asyncOptionalChain(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 = await fn(value); } else if (op === 'call' || op === 'optionalCall') { value = await fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _blockchaindata = require('@imtbl/blockchain-data');var _webhook = require('@imtbl/webhook');var _metrics = require('@imtbl/metrics');var u="minting_backend_sdk",M=()=>{try{_metrics.track.call(void 0, u,"initializePersistencePG")}catch (e2){}},h=()=>{try{_metrics.track.call(void 0, u,"initializePersistencePrismaSqlite")}catch (e3){}},I=()=>{try{_metrics.track.call(void 0, u,"submitMintingRequests")}catch (e4){}},A=()=>{try{_metrics.track.call(void 0, u,"processMint")}catch (e5){}},S=()=>{try{_metrics.track.call(void 0, u,"recordMint")}catch (e6){}},w=e=>{try{_metrics.track.call(void 0, u,"error",{name:e.name,message:e.message})}catch (e7){}},E=(e,t)=>{try{_metrics.track.call(void 0, u,"error",{name:e.name,message:e.message,origin:t})}catch (e8){}};var q=e=>(M(),{recordMint:async t=>{if((await e.query(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@imtbl/blockchain-data"),t=require("@imtbl/webhook"),n=require("@imtbl/metrics");const r=`minting_backend_sdk`,i=()=>{try{(0,n.track)(r,`initializePersistencePG`)}catch{}},a=()=>{try{(0,n.track)(r,`initializePersistencePrismaSqlite`)}catch{}},o=()=>{try{(0,n.track)(r,`submitMintingRequests`)}catch{}},s=()=>{try{(0,n.track)(r,`processMint`)}catch{}},c=()=>{try{(0,n.track)(r,`recordMint`)}catch{}},l=e=>{try{(0,n.track)(r,`error`,{name:e.name,message:e.message})}catch{}},u=(e,t)=>{try{(0,n.track)(r,`error`,{name:e.name,message:e.message,origin:t})}catch{}},d=e=>(i(),{recordMint:async t=>{if((await e.query(`
2
2
  INSERT INTO im_assets (asset_id, contract_address, owner_address, metadata, amount, token_id)
3
3
  VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (asset_id, contract_address) DO NOTHING;
4
- `,[t.asset_id,t.contract_address,t.owner_address,t.metadata,t.amount,t.token_id])).rowCount===0)throw new Error("Duplicated mint")},getNextBatchForSubmission:async t=>(await e.query(`
4
+ `,[t.asset_id,t.contract_address,t.owner_address,t.metadata,t.amount,t.token_id])).rowCount===0)throw Error(`Duplicated mint`)},getNextBatchForSubmission:async t=>(await e.query(`
5
5
  WITH limited_assets AS (
6
6
  SELECT id
7
7
  FROM im_assets
@@ -16,7 +16,7 @@
16
16
  RETURNING *;
17
17
  `,[t])).rows,updateMintingStatusToSubmitted:async t=>{await e.query(`
18
18
  UPDATE im_assets SET minting_status = $2 WHERE id = ANY($1);
19
- `,[t,"submitted"])},syncMintingStatus:async t=>{await e.query(`
19
+ `,[t,`submitted`])},syncMintingStatus:async t=>{await e.query(`
20
20
  INSERT INTO im_assets (
21
21
  asset_id,
22
22
  contract_address,
@@ -39,18 +39,18 @@
39
39
  im_assets.last_imtbl_zkevm_mint_request_updated_id < $7 OR
40
40
  im_assets.last_imtbl_zkevm_mint_request_updated_id is null
41
41
  );
42
- `,[t.assetId,t.contractAddress,t.ownerAddress,t.tokenId,t.status,t.metadataId,t.imtblZkevmMintRequestUpdatedId,t.error,t.amount])},markAsConflict:async(t,s)=>{await e.query(`
42
+ `,[t.assetId,t.contractAddress,t.ownerAddress,t.tokenId,t.status,t.metadataId,t.imtblZkevmMintRequestUpdatedId,t.error,t.amount])},markAsConflict:async(t,n)=>{await e.query(`
43
43
  UPDATE im_assets
44
44
  SET minting_status = 'conflicting'
45
45
  WHERE asset_id = ANY($1)
46
46
  AND contract_address = $2;
47
- `,[t,s])},resetMintingStatus:async t=>{await e.query(`
47
+ `,[t,n])},resetMintingStatus:async t=>{await e.query(`
48
48
  UPDATE im_assets SET minting_status = null WHERE id = ANY($1);
49
49
  `,[t])},markForRetry:async t=>{await e.query(`
50
50
  UPDATE im_assets
51
51
  SET minting_status = null, tried_count = tried_count + 1 WHERE id = ANY($1);
52
52
  `,[t])},updateMintingStatusToSubmissionFailed:async t=>{await e.query(`
53
53
  UPDATE im_assets SET minting_status = 'submission_failed' WHERE id = ANY($1);
54
- `,[t])},getMintingRequest:async(t,s)=>(await e.query(`
54
+ `,[t])},getMintingRequest:async(t,n)=>(await e.query(`
55
55
  SELECT * FROM im_assets WHERE contract_address = $1 and asset_id = $2;
56
- `,[t,s])).rows[0]||null});var U=e=>(h(),{recordMint:async t=>{if(!await e.imAssets.upsert({where:{im_assets_uindex:{assetId:t.asset_id,contractAddress:t.contract_address}},update:{},create:{assetId:t.asset_id,contractAddress:t.contract_address,ownerAddress:t.owner_address,metadata:JSON.stringify(t.metadata),amount:t.amount||null,tokenId:t.token_id||null}}))throw new Error("Duplicated mint")},getNextBatchForSubmission:async t=>{let a=(await e.imAssets.findMany({where:{mintingStatus:null},take:t})).map(n=>n.id);return await e.imAssets.updateMany({where:{id:{in:a}},data:{mintingStatus:"submitting"}}),(await e.imAssets.findMany({where:{id:{in:a}}})).map(n=>({id:n.id,contract_address:n.contractAddress,wallet_address:n.ownerAddress,asset_id:n.assetId,metadata:n.metadata?JSON.parse(n.metadata):null,owner_address:n.ownerAddress,tried_count:n.triedCount,amount:n.amount||null,token_id:n.tokenId||null}))},updateMintingStatusToSubmitted:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:"submitted"}})},syncMintingStatus:async t=>{let s=await e.imAssets.findUnique({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}}});s&&(s.lastImtblZkevmMintRequestUpdatedId===null||s.lastImtblZkevmMintRequestUpdatedId<t.imtblZkevmMintRequestUpdatedId)?await e.imAssets.update({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}},data:{ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}}):s||await e.imAssets.create({data:{assetId:t.assetId,contractAddress:t.contractAddress,ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}})},updateMintingStatusToSubmissionFailed:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:"submission_failed"}})},markAsConflict:async(t,s)=>{await e.imAssets.updateMany({where:{assetId:{in:t},contractAddress:s},data:{mintingStatus:"conflicting"}})},resetMintingStatus:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:null}})},markForRetry:async t=>{let s=await e.imAssets.findMany({where:{id:{in:t}},select:{id:!0,triedCount:!0}});for(let a of s)await e.imAssets.update({where:{id:a.id},data:{mintingStatus:null,triedCount:a.triedCount+1}})},getMintingRequest:async(t,s)=>{let a=await e.imAssets.findFirst({where:{contractAddress:t,assetId:s}});return a?{asset_id:a.assetId,contract_address:a.contractAddress,id:a.id,metadata:a.metadata?JSON.parse(a.metadata):null,owner_address:a.ownerAddress,tried_count:a.triedCount,wallet_address:a.ownerAddress,amount:a.amount||null}:null}});var R=async(e,t)=>{S(),e.recordMint(t)},O=1e3,b= exports.submitMintingRequests =async(e,t,{defaultBatchSize:s=1e3,chainName:a="imtbl-zkevm-testnet",maxNumberOfTries:l=3},n=console,g=1/0)=>{I();let m,P=0;for(;P++<g;){await new Promise(r=>{setTimeout(r,O)});let p=Math.min(_optionalChain([m, 'optionalAccess', _2 => _2.imx_remaining_mint_requests])?parseInt(m.imx_remaining_mint_requests,10):s,s);if(p===0&&m&&new Date(m.imx_mint_requests_limit_reset)>new Date){n.info(`minting limit reached, waiting for reset at ${_optionalChain([m, 'optionalAccess', _3 => _3.imx_mint_requests_limit_reset])}`);continue}p===0&&(n.info(`minting limit has been reset, use default batch size: ${s}`),m=void 0,p=s);let y=await e.getNextBatchForSubmission(p);if(y.length===0){n.info("no assets to mint");continue}let N=y.sort((r,d)=>r.contract_address>d.contract_address?1:-1).reduce((r,d)=>{if(r.length===0)return[{contractAddress:d.contract_address,assets:[d]}];let _=r[r.length-1];return _.contractAddress===d.contract_address&&_.assets.length<100?[...r.slice(0,-1),{..._,assets:[..._.assets,d]}]:[...r,{contractAddress:d.contract_address,assets:[d]}]},[]);m=await _asyncOptionalChain([(await Promise.allSettled(N.map(async({contractAddress:r,assets:d})=>{let _={chainName:a,contractAddress:r,createMintRequestRequest:{assets:d.map(i=>({reference_id:i.asset_id,owner_address:i.owner_address,metadata:i.metadata,token_id:i.token_id,amount:i.amount?`${i.amount}`:null}))}};try{let i=await t.createMintRequest(_);return n.info(`mintingResponse: ${JSON.stringify(i,null,2)}`),await e.updateMintingStatusToSubmitted(d.map(({id:o})=>o)),i}catch(i){if(n.error(i),w(i),i.code==="CONFLICT_ERROR"&&_optionalChain([i, 'access', _4 => _4.details, 'optionalAccess', _5 => _5.id])==="reference_id")try{await e.markAsConflict(i.details.values,r),await e.resetMintingStatus(d.map(({id:o})=>o).filter(o=>!i.details.values.includes(o)))}catch(o){n.error(o),w(i)}else{let{assetsToRetry:o,assetsExceededMaxNumberOfTries:x}=d.reduce((f,{tried_count:$=0,id:k})=>($<l?f.assetsToRetry.push(k):f.assetsExceededMaxNumberOfTries.push(k),f),{assetsToRetry:[],assetsExceededMaxNumberOfTries:[]});await e.markForRetry(o),await e.updateMintingStatusToSubmissionFailed(x)}return i}}))), 'access', async _6 => _6.reverse, 'call', async _7 => _7(), 'access', async _8 => _8.find, 'call', async _9 => _9(r=>r.status==="fulfilled"), 'optionalAccess', async _10 => _10.value])}},T= exports.processMint =async(e,t,s=console)=>{if(A(),t.event_name!=="imtbl_zkevm_mint_request_updated"){s.info(`${t.event_name} is not imtbl_zkevm_mint_request_updated, skip.`);return}let a=t.data.reference_id;if(!a)throw new Error("reference_id not found in webhook event");let l=t.data.contract_address;if(!l)throw new Error("contract_address not found in webhook event");t.data.status==="failed"&&s.error(`mint failed: ${JSON.stringify(t.data,null,2)}`);let n=await e.getMintingRequest(l,a);n||s.info(`minting request not found in the database, ${JSON.stringify(t.data)}`);let g=_optionalChain([n, 'optionalAccess', _11 => _11.wallet_address])||t.data.owner_address;if(!g)throw s.error("owner_address missing"),new Error("owner_address missing");await e.syncMintingStatus({tokenId:t.data.token_id,status:t.data.status,assetId:a,contractAddress:l,ownerAddress:g,metadataId:t.data.metadata_id,imtblZkevmMintRequestUpdatedId:t.event_id,error:t.data.error?JSON.stringify(t.data.error):null,amount:t.data.amount||null})};var z={zkevmMintRequestUpdated:async e=>{}},C= exports.MintingBackendModule =class{constructor(t){this.baseConfig=t.baseConfig,this.persistence=t.persistence,this.logger=t.logger||console,this.blockchainDataClient=new (0, _blockchaindata.BlockchainData)({baseConfig:t.baseConfig}),_metrics.setEnvironment.call(void 0, this.baseConfig.environment),this.baseConfig.publishableKey&&_metrics.setPublishableApiKey.call(void 0, this.baseConfig.publishableKey)}async recordMint(t){await R(this.persistence,t)}async submitMintingRequests(t){await b(this.persistence,this.blockchainDataClient,t)}async processMint(t,s=z){await _webhook.handle.call(void 0, t,this.baseConfig.environment,{zkevmMintRequestUpdated:async a=>{await T(this.persistence,a,this.logger),s.zkevmMintRequestUpdated&&s.zkevmMintRequestUpdated(a)}})}};if(typeof process<"u"&&process.on)try{process.on("uncaughtExceptionMonitor",E)}catch (e9){}exports.MintingBackendModule = C; exports.mintingPersistencePg = q; exports.mintingPersistencePrismaSqlite = U; exports.processMint = T; exports.recordMint = R; exports.submitMintingRequests = b;
56
+ `,[t,n])).rows[0]||null}),f=e=>(a(),{recordMint:async t=>{if(!await e.imAssets.upsert({where:{im_assets_uindex:{assetId:t.asset_id,contractAddress:t.contract_address}},update:{},create:{assetId:t.asset_id,contractAddress:t.contract_address,ownerAddress:t.owner_address,metadata:JSON.stringify(t.metadata),amount:t.amount||null,tokenId:t.token_id||null}}))throw Error(`Duplicated mint`)},getNextBatchForSubmission:async t=>{let n=(await e.imAssets.findMany({where:{mintingStatus:null},take:t})).map(e=>e.id);return await e.imAssets.updateMany({where:{id:{in:n}},data:{mintingStatus:`submitting`}}),(await e.imAssets.findMany({where:{id:{in:n}}})).map(e=>({id:e.id,contract_address:e.contractAddress,wallet_address:e.ownerAddress,asset_id:e.assetId,metadata:e.metadata?JSON.parse(e.metadata):null,owner_address:e.ownerAddress,tried_count:e.triedCount,amount:e.amount||null,token_id:e.tokenId||null}))},updateMintingStatusToSubmitted:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:`submitted`}})},syncMintingStatus:async t=>{let n=await e.imAssets.findUnique({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}}});n&&(n.lastImtblZkevmMintRequestUpdatedId===null||n.lastImtblZkevmMintRequestUpdatedId<t.imtblZkevmMintRequestUpdatedId)?await e.imAssets.update({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}},data:{ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}}):n||await e.imAssets.create({data:{assetId:t.assetId,contractAddress:t.contractAddress,ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}})},updateMintingStatusToSubmissionFailed:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:`submission_failed`}})},markAsConflict:async(t,n)=>{await e.imAssets.updateMany({where:{assetId:{in:t},contractAddress:n},data:{mintingStatus:`conflicting`}})},resetMintingStatus:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:null}})},markForRetry:async t=>{let n=await e.imAssets.findMany({where:{id:{in:t}},select:{id:!0,triedCount:!0}});for(let t of n)await e.imAssets.update({where:{id:t.id},data:{mintingStatus:null,triedCount:t.triedCount+1}})},getMintingRequest:async(t,n)=>{let r=await e.imAssets.findFirst({where:{contractAddress:t,assetId:n}});return r?{asset_id:r.assetId,contract_address:r.contractAddress,id:r.id,metadata:r.metadata?JSON.parse(r.metadata):null,owner_address:r.ownerAddress,tried_count:r.triedCount,wallet_address:r.ownerAddress,amount:r.amount||null}:null}}),p=async(e,t)=>{c(),e.recordMint(t)},m=async(e,t,{defaultBatchSize:n=1e3,chainName:r=`imtbl-zkevm-testnet`,maxNumberOfTries:i=3},a=console,s=1/0)=>{o();let c,u=0;for(;u++<s;){await new Promise(e=>{setTimeout(e,1e3)});let o=Math.min(c?.imx_remaining_mint_requests?parseInt(c.imx_remaining_mint_requests,10):n,n);if(o===0&&c&&new Date(c.imx_mint_requests_limit_reset)>new Date){a.info(`minting limit reached, waiting for reset at ${c?.imx_mint_requests_limit_reset}`);continue}o===0&&(a.info(`minting limit has been reset, use default batch size: ${n}`),c=void 0,o=n);let s=await e.getNextBatchForSubmission(o);if(s.length===0){a.info(`no assets to mint`);continue}let u=s.sort((e,t)=>e.contract_address>t.contract_address?1:-1).reduce((e,t)=>{if(e.length===0)return[{contractAddress:t.contract_address,assets:[t]}];let n=e[e.length-1];return n.contractAddress===t.contract_address&&n.assets.length<100?[...e.slice(0,-1),{...n,assets:[...n.assets,t]}]:[...e,{contractAddress:t.contract_address,assets:[t]}]},[]);c=(await Promise.allSettled(u.map(async({contractAddress:n,assets:o})=>{let s={chainName:r,contractAddress:n,createMintRequestRequest:{assets:o.map(e=>({reference_id:e.asset_id,owner_address:e.owner_address,metadata:e.metadata,token_id:e.token_id,amount:e.amount?`${e.amount}`:null}))}};try{let n=await t.createMintRequest(s);return a.info(`mintingResponse: ${JSON.stringify(n,null,2)}`),await e.updateMintingStatusToSubmitted(o.map(({id:e})=>e)),n}catch(t){if(a.error(t),l(t),t.code===`CONFLICT_ERROR`&&t.details?.id===`reference_id`)try{await e.markAsConflict(t.details.values,n),await e.resetMintingStatus(o.map(({id:e})=>e).filter(e=>!t.details.values.includes(e)))}catch(e){a.error(e),l(t)}else{let{assetsToRetry:t,assetsExceededMaxNumberOfTries:n}=o.reduce((e,{tried_count:t=0,id:n})=>(t<i?e.assetsToRetry.push(n):e.assetsExceededMaxNumberOfTries.push(n),e),{assetsToRetry:[],assetsExceededMaxNumberOfTries:[]});await e.markForRetry(t),await e.updateMintingStatusToSubmissionFailed(n)}return t}}))).reverse().find(e=>e.status===`fulfilled`)?.value}},h=async(e,t,n=console)=>{if(s(),t.event_name!==`imtbl_zkevm_mint_request_updated`){n.info(`${t.event_name} is not imtbl_zkevm_mint_request_updated, skip.`);return}let r=t.data.reference_id;if(!r)throw Error(`reference_id not found in webhook event`);let i=t.data.contract_address;if(!i)throw Error(`contract_address not found in webhook event`);t.data.status===`failed`&&n.error(`mint failed: ${JSON.stringify(t.data,null,2)}`);let a=await e.getMintingRequest(i,r);a||n.info(`minting request not found in the database, ${JSON.stringify(t.data)}`);let o=a?.wallet_address||t.data.owner_address;if(!o)throw n.error(`owner_address missing`),Error(`owner_address missing`);await e.syncMintingStatus({tokenId:t.data.token_id,status:t.data.status,assetId:r,contractAddress:i,ownerAddress:o,metadataId:t.data.metadata_id,imtblZkevmMintRequestUpdatedId:t.event_id,error:t.data.error?JSON.stringify(t.data.error):null,amount:t.data.amount||null})},g={zkevmMintRequestUpdated:async e=>{}};var _=class{baseConfig;persistence;blockchainDataClient;logger;constructor(t){this.baseConfig=t.baseConfig,this.persistence=t.persistence,this.logger=t.logger||console,this.blockchainDataClient=new e.BlockchainData({baseConfig:t.baseConfig}),(0,n.setEnvironment)(this.baseConfig.environment),this.baseConfig.publishableKey&&(0,n.setPublishableApiKey)(this.baseConfig.publishableKey)}async recordMint(e){await p(this.persistence,e)}async submitMintingRequests(e){await m(this.persistence,this.blockchainDataClient,e)}async processMint(e,n=g){await(0,t.handle)(e,this.baseConfig.environment,{zkevmMintRequestUpdated:async e=>{await h(this.persistence,e,this.logger),n.zkevmMintRequestUpdated&&n.zkevmMintRequestUpdated(e)}})}};if(typeof process<`u`&&process.on)try{process.on(`uncaughtExceptionMonitor`,u)}catch{}exports.MintingBackendModule=_,exports.mintingPersistencePg=d,exports.mintingPersistencePrismaSqlite=f,exports.processMint=h,exports.recordMint=p,exports.submitMintingRequests=m;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import{BlockchainData as v}from"@imtbl/blockchain-data";import{handle as D}from"@imtbl/webhook";import{setEnvironment as L,setPublishableApiKey as F}from"@imtbl/metrics";import{track as c}from"@imtbl/metrics";var u="minting_backend_sdk",M=()=>{try{c(u,"initializePersistencePG")}catch{}},h=()=>{try{c(u,"initializePersistencePrismaSqlite")}catch{}},I=()=>{try{c(u,"submitMintingRequests")}catch{}},A=()=>{try{c(u,"processMint")}catch{}},S=()=>{try{c(u,"recordMint")}catch{}},w=e=>{try{c(u,"error",{name:e.name,message:e.message})}catch{}},E=(e,t)=>{try{c(u,"error",{name:e.name,message:e.message,origin:t})}catch{}};var q=e=>(M(),{recordMint:async t=>{if((await e.query(`
1
+ import{BlockchainData as e}from"@imtbl/blockchain-data";import{handle as t}from"@imtbl/webhook";import{setEnvironment as n,setPublishableApiKey as r,track as i}from"@imtbl/metrics";const a=`minting_backend_sdk`,o=()=>{try{i(a,`initializePersistencePG`)}catch{}},s=()=>{try{i(a,`initializePersistencePrismaSqlite`)}catch{}},c=()=>{try{i(a,`submitMintingRequests`)}catch{}},l=()=>{try{i(a,`processMint`)}catch{}},u=()=>{try{i(a,`recordMint`)}catch{}},d=e=>{try{i(a,`error`,{name:e.name,message:e.message})}catch{}},f=(e,t)=>{try{i(a,`error`,{name:e.name,message:e.message,origin:t})}catch{}},p=e=>(o(),{recordMint:async t=>{if((await e.query(`
2
2
  INSERT INTO im_assets (asset_id, contract_address, owner_address, metadata, amount, token_id)
3
3
  VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (asset_id, contract_address) DO NOTHING;
4
- `,[t.asset_id,t.contract_address,t.owner_address,t.metadata,t.amount,t.token_id])).rowCount===0)throw new Error("Duplicated mint")},getNextBatchForSubmission:async t=>(await e.query(`
4
+ `,[t.asset_id,t.contract_address,t.owner_address,t.metadata,t.amount,t.token_id])).rowCount===0)throw Error(`Duplicated mint`)},getNextBatchForSubmission:async t=>(await e.query(`
5
5
  WITH limited_assets AS (
6
6
  SELECT id
7
7
  FROM im_assets
@@ -16,7 +16,7 @@ import{BlockchainData as v}from"@imtbl/blockchain-data";import{handle as D}from"
16
16
  RETURNING *;
17
17
  `,[t])).rows,updateMintingStatusToSubmitted:async t=>{await e.query(`
18
18
  UPDATE im_assets SET minting_status = $2 WHERE id = ANY($1);
19
- `,[t,"submitted"])},syncMintingStatus:async t=>{await e.query(`
19
+ `,[t,`submitted`])},syncMintingStatus:async t=>{await e.query(`
20
20
  INSERT INTO im_assets (
21
21
  asset_id,
22
22
  contract_address,
@@ -39,18 +39,18 @@ import{BlockchainData as v}from"@imtbl/blockchain-data";import{handle as D}from"
39
39
  im_assets.last_imtbl_zkevm_mint_request_updated_id < $7 OR
40
40
  im_assets.last_imtbl_zkevm_mint_request_updated_id is null
41
41
  );
42
- `,[t.assetId,t.contractAddress,t.ownerAddress,t.tokenId,t.status,t.metadataId,t.imtblZkevmMintRequestUpdatedId,t.error,t.amount])},markAsConflict:async(t,s)=>{await e.query(`
42
+ `,[t.assetId,t.contractAddress,t.ownerAddress,t.tokenId,t.status,t.metadataId,t.imtblZkevmMintRequestUpdatedId,t.error,t.amount])},markAsConflict:async(t,n)=>{await e.query(`
43
43
  UPDATE im_assets
44
44
  SET minting_status = 'conflicting'
45
45
  WHERE asset_id = ANY($1)
46
46
  AND contract_address = $2;
47
- `,[t,s])},resetMintingStatus:async t=>{await e.query(`
47
+ `,[t,n])},resetMintingStatus:async t=>{await e.query(`
48
48
  UPDATE im_assets SET minting_status = null WHERE id = ANY($1);
49
49
  `,[t])},markForRetry:async t=>{await e.query(`
50
50
  UPDATE im_assets
51
51
  SET minting_status = null, tried_count = tried_count + 1 WHERE id = ANY($1);
52
52
  `,[t])},updateMintingStatusToSubmissionFailed:async t=>{await e.query(`
53
53
  UPDATE im_assets SET minting_status = 'submission_failed' WHERE id = ANY($1);
54
- `,[t])},getMintingRequest:async(t,s)=>(await e.query(`
54
+ `,[t])},getMintingRequest:async(t,n)=>(await e.query(`
55
55
  SELECT * FROM im_assets WHERE contract_address = $1 and asset_id = $2;
56
- `,[t,s])).rows[0]||null});var U=e=>(h(),{recordMint:async t=>{if(!await e.imAssets.upsert({where:{im_assets_uindex:{assetId:t.asset_id,contractAddress:t.contract_address}},update:{},create:{assetId:t.asset_id,contractAddress:t.contract_address,ownerAddress:t.owner_address,metadata:JSON.stringify(t.metadata),amount:t.amount||null,tokenId:t.token_id||null}}))throw new Error("Duplicated mint")},getNextBatchForSubmission:async t=>{let a=(await e.imAssets.findMany({where:{mintingStatus:null},take:t})).map(n=>n.id);return await e.imAssets.updateMany({where:{id:{in:a}},data:{mintingStatus:"submitting"}}),(await e.imAssets.findMany({where:{id:{in:a}}})).map(n=>({id:n.id,contract_address:n.contractAddress,wallet_address:n.ownerAddress,asset_id:n.assetId,metadata:n.metadata?JSON.parse(n.metadata):null,owner_address:n.ownerAddress,tried_count:n.triedCount,amount:n.amount||null,token_id:n.tokenId||null}))},updateMintingStatusToSubmitted:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:"submitted"}})},syncMintingStatus:async t=>{let s=await e.imAssets.findUnique({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}}});s&&(s.lastImtblZkevmMintRequestUpdatedId===null||s.lastImtblZkevmMintRequestUpdatedId<t.imtblZkevmMintRequestUpdatedId)?await e.imAssets.update({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}},data:{ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}}):s||await e.imAssets.create({data:{assetId:t.assetId,contractAddress:t.contractAddress,ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}})},updateMintingStatusToSubmissionFailed:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:"submission_failed"}})},markAsConflict:async(t,s)=>{await e.imAssets.updateMany({where:{assetId:{in:t},contractAddress:s},data:{mintingStatus:"conflicting"}})},resetMintingStatus:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:null}})},markForRetry:async t=>{let s=await e.imAssets.findMany({where:{id:{in:t}},select:{id:!0,triedCount:!0}});for(let a of s)await e.imAssets.update({where:{id:a.id},data:{mintingStatus:null,triedCount:a.triedCount+1}})},getMintingRequest:async(t,s)=>{let a=await e.imAssets.findFirst({where:{contractAddress:t,assetId:s}});return a?{asset_id:a.assetId,contract_address:a.contractAddress,id:a.id,metadata:a.metadata?JSON.parse(a.metadata):null,owner_address:a.ownerAddress,tried_count:a.triedCount,wallet_address:a.ownerAddress,amount:a.amount||null}:null}});var R=async(e,t)=>{S(),e.recordMint(t)},O=1e3,b=async(e,t,{defaultBatchSize:s=1e3,chainName:a="imtbl-zkevm-testnet",maxNumberOfTries:l=3},n=console,g=1/0)=>{I();let m,P=0;for(;P++<g;){await new Promise(r=>{setTimeout(r,O)});let p=Math.min(m?.imx_remaining_mint_requests?parseInt(m.imx_remaining_mint_requests,10):s,s);if(p===0&&m&&new Date(m.imx_mint_requests_limit_reset)>new Date){n.info(`minting limit reached, waiting for reset at ${m?.imx_mint_requests_limit_reset}`);continue}p===0&&(n.info(`minting limit has been reset, use default batch size: ${s}`),m=void 0,p=s);let y=await e.getNextBatchForSubmission(p);if(y.length===0){n.info("no assets to mint");continue}let N=y.sort((r,d)=>r.contract_address>d.contract_address?1:-1).reduce((r,d)=>{if(r.length===0)return[{contractAddress:d.contract_address,assets:[d]}];let _=r[r.length-1];return _.contractAddress===d.contract_address&&_.assets.length<100?[...r.slice(0,-1),{..._,assets:[..._.assets,d]}]:[...r,{contractAddress:d.contract_address,assets:[d]}]},[]);m=(await Promise.allSettled(N.map(async({contractAddress:r,assets:d})=>{let _={chainName:a,contractAddress:r,createMintRequestRequest:{assets:d.map(i=>({reference_id:i.asset_id,owner_address:i.owner_address,metadata:i.metadata,token_id:i.token_id,amount:i.amount?`${i.amount}`:null}))}};try{let i=await t.createMintRequest(_);return n.info(`mintingResponse: ${JSON.stringify(i,null,2)}`),await e.updateMintingStatusToSubmitted(d.map(({id:o})=>o)),i}catch(i){if(n.error(i),w(i),i.code==="CONFLICT_ERROR"&&i.details?.id==="reference_id")try{await e.markAsConflict(i.details.values,r),await e.resetMintingStatus(d.map(({id:o})=>o).filter(o=>!i.details.values.includes(o)))}catch(o){n.error(o),w(i)}else{let{assetsToRetry:o,assetsExceededMaxNumberOfTries:x}=d.reduce((f,{tried_count:$=0,id:k})=>($<l?f.assetsToRetry.push(k):f.assetsExceededMaxNumberOfTries.push(k),f),{assetsToRetry:[],assetsExceededMaxNumberOfTries:[]});await e.markForRetry(o),await e.updateMintingStatusToSubmissionFailed(x)}return i}}))).reverse().find(r=>r.status==="fulfilled")?.value}},T=async(e,t,s=console)=>{if(A(),t.event_name!=="imtbl_zkevm_mint_request_updated"){s.info(`${t.event_name} is not imtbl_zkevm_mint_request_updated, skip.`);return}let a=t.data.reference_id;if(!a)throw new Error("reference_id not found in webhook event");let l=t.data.contract_address;if(!l)throw new Error("contract_address not found in webhook event");t.data.status==="failed"&&s.error(`mint failed: ${JSON.stringify(t.data,null,2)}`);let n=await e.getMintingRequest(l,a);n||s.info(`minting request not found in the database, ${JSON.stringify(t.data)}`);let g=n?.wallet_address||t.data.owner_address;if(!g)throw s.error("owner_address missing"),new Error("owner_address missing");await e.syncMintingStatus({tokenId:t.data.token_id,status:t.data.status,assetId:a,contractAddress:l,ownerAddress:g,metadataId:t.data.metadata_id,imtblZkevmMintRequestUpdatedId:t.event_id,error:t.data.error?JSON.stringify(t.data.error):null,amount:t.data.amount||null})};var z={zkevmMintRequestUpdated:async e=>{}},C=class{baseConfig;persistence;blockchainDataClient;logger;constructor(t){this.baseConfig=t.baseConfig,this.persistence=t.persistence,this.logger=t.logger||console,this.blockchainDataClient=new v({baseConfig:t.baseConfig}),L(this.baseConfig.environment),this.baseConfig.publishableKey&&F(this.baseConfig.publishableKey)}async recordMint(t){await R(this.persistence,t)}async submitMintingRequests(t){await b(this.persistence,this.blockchainDataClient,t)}async processMint(t,s=z){await D(t,this.baseConfig.environment,{zkevmMintRequestUpdated:async a=>{await T(this.persistence,a,this.logger),s.zkevmMintRequestUpdated&&s.zkevmMintRequestUpdated(a)}})}};if(typeof process<"u"&&process.on)try{process.on("uncaughtExceptionMonitor",E)}catch{}export{C as MintingBackendModule,q as mintingPersistencePg,U as mintingPersistencePrismaSqlite,T as processMint,R as recordMint,b as submitMintingRequests};
56
+ `,[t,n])).rows[0]||null}),m=e=>(s(),{recordMint:async t=>{if(!await e.imAssets.upsert({where:{im_assets_uindex:{assetId:t.asset_id,contractAddress:t.contract_address}},update:{},create:{assetId:t.asset_id,contractAddress:t.contract_address,ownerAddress:t.owner_address,metadata:JSON.stringify(t.metadata),amount:t.amount||null,tokenId:t.token_id||null}}))throw Error(`Duplicated mint`)},getNextBatchForSubmission:async t=>{let n=(await e.imAssets.findMany({where:{mintingStatus:null},take:t})).map(e=>e.id);return await e.imAssets.updateMany({where:{id:{in:n}},data:{mintingStatus:`submitting`}}),(await e.imAssets.findMany({where:{id:{in:n}}})).map(e=>({id:e.id,contract_address:e.contractAddress,wallet_address:e.ownerAddress,asset_id:e.assetId,metadata:e.metadata?JSON.parse(e.metadata):null,owner_address:e.ownerAddress,tried_count:e.triedCount,amount:e.amount||null,token_id:e.tokenId||null}))},updateMintingStatusToSubmitted:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:`submitted`}})},syncMintingStatus:async t=>{let n=await e.imAssets.findUnique({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}}});n&&(n.lastImtblZkevmMintRequestUpdatedId===null||n.lastImtblZkevmMintRequestUpdatedId<t.imtblZkevmMintRequestUpdatedId)?await e.imAssets.update({where:{im_assets_uindex:{assetId:t.assetId,contractAddress:t.contractAddress}},data:{ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}}):n||await e.imAssets.create({data:{assetId:t.assetId,contractAddress:t.contractAddress,ownerAddress:t.ownerAddress,tokenId:t.tokenId,mintingStatus:t.status,metadataId:t.metadataId,lastImtblZkevmMintRequestUpdatedId:t.imtblZkevmMintRequestUpdatedId,error:t.error,amount:t.amount||null}})},updateMintingStatusToSubmissionFailed:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:`submission_failed`}})},markAsConflict:async(t,n)=>{await e.imAssets.updateMany({where:{assetId:{in:t},contractAddress:n},data:{mintingStatus:`conflicting`}})},resetMintingStatus:async t=>{await e.imAssets.updateMany({where:{id:{in:t}},data:{mintingStatus:null}})},markForRetry:async t=>{let n=await e.imAssets.findMany({where:{id:{in:t}},select:{id:!0,triedCount:!0}});for(let t of n)await e.imAssets.update({where:{id:t.id},data:{mintingStatus:null,triedCount:t.triedCount+1}})},getMintingRequest:async(t,n)=>{let r=await e.imAssets.findFirst({where:{contractAddress:t,assetId:n}});return r?{asset_id:r.assetId,contract_address:r.contractAddress,id:r.id,metadata:r.metadata?JSON.parse(r.metadata):null,owner_address:r.ownerAddress,tried_count:r.triedCount,wallet_address:r.ownerAddress,amount:r.amount||null}:null}}),h=async(e,t)=>{u(),e.recordMint(t)},g=async(e,t,{defaultBatchSize:n=1e3,chainName:r=`imtbl-zkevm-testnet`,maxNumberOfTries:i=3},a=console,o=1/0)=>{c();let s,l=0;for(;l++<o;){await new Promise(e=>{setTimeout(e,1e3)});let o=Math.min(s?.imx_remaining_mint_requests?parseInt(s.imx_remaining_mint_requests,10):n,n);if(o===0&&s&&new Date(s.imx_mint_requests_limit_reset)>new Date){a.info(`minting limit reached, waiting for reset at ${s?.imx_mint_requests_limit_reset}`);continue}o===0&&(a.info(`minting limit has been reset, use default batch size: ${n}`),s=void 0,o=n);let c=await e.getNextBatchForSubmission(o);if(c.length===0){a.info(`no assets to mint`);continue}let l=c.sort((e,t)=>e.contract_address>t.contract_address?1:-1).reduce((e,t)=>{if(e.length===0)return[{contractAddress:t.contract_address,assets:[t]}];let n=e[e.length-1];return n.contractAddress===t.contract_address&&n.assets.length<100?[...e.slice(0,-1),{...n,assets:[...n.assets,t]}]:[...e,{contractAddress:t.contract_address,assets:[t]}]},[]);s=(await Promise.allSettled(l.map(async({contractAddress:n,assets:o})=>{let s={chainName:r,contractAddress:n,createMintRequestRequest:{assets:o.map(e=>({reference_id:e.asset_id,owner_address:e.owner_address,metadata:e.metadata,token_id:e.token_id,amount:e.amount?`${e.amount}`:null}))}};try{let n=await t.createMintRequest(s);return a.info(`mintingResponse: ${JSON.stringify(n,null,2)}`),await e.updateMintingStatusToSubmitted(o.map(({id:e})=>e)),n}catch(t){if(a.error(t),d(t),t.code===`CONFLICT_ERROR`&&t.details?.id===`reference_id`)try{await e.markAsConflict(t.details.values,n),await e.resetMintingStatus(o.map(({id:e})=>e).filter(e=>!t.details.values.includes(e)))}catch(e){a.error(e),d(t)}else{let{assetsToRetry:t,assetsExceededMaxNumberOfTries:n}=o.reduce((e,{tried_count:t=0,id:n})=>(t<i?e.assetsToRetry.push(n):e.assetsExceededMaxNumberOfTries.push(n),e),{assetsToRetry:[],assetsExceededMaxNumberOfTries:[]});await e.markForRetry(t),await e.updateMintingStatusToSubmissionFailed(n)}return t}}))).reverse().find(e=>e.status===`fulfilled`)?.value}},_=async(e,t,n=console)=>{if(l(),t.event_name!==`imtbl_zkevm_mint_request_updated`){n.info(`${t.event_name} is not imtbl_zkevm_mint_request_updated, skip.`);return}let r=t.data.reference_id;if(!r)throw Error(`reference_id not found in webhook event`);let i=t.data.contract_address;if(!i)throw Error(`contract_address not found in webhook event`);t.data.status===`failed`&&n.error(`mint failed: ${JSON.stringify(t.data,null,2)}`);let a=await e.getMintingRequest(i,r);a||n.info(`minting request not found in the database, ${JSON.stringify(t.data)}`);let o=a?.wallet_address||t.data.owner_address;if(!o)throw n.error(`owner_address missing`),Error(`owner_address missing`);await e.syncMintingStatus({tokenId:t.data.token_id,status:t.data.status,assetId:r,contractAddress:i,ownerAddress:o,metadataId:t.data.metadata_id,imtblZkevmMintRequestUpdatedId:t.event_id,error:t.data.error?JSON.stringify(t.data.error):null,amount:t.data.amount||null})},v={zkevmMintRequestUpdated:async e=>{}};var y=class{baseConfig;persistence;blockchainDataClient;logger;constructor(t){this.baseConfig=t.baseConfig,this.persistence=t.persistence,this.logger=t.logger||console,this.blockchainDataClient=new e({baseConfig:t.baseConfig}),n(this.baseConfig.environment),this.baseConfig.publishableKey&&r(this.baseConfig.publishableKey)}async recordMint(e){await h(this.persistence,e)}async submitMintingRequests(e){await g(this.persistence,this.blockchainDataClient,e)}async processMint(e,n=v){await t(e,this.baseConfig.environment,{zkevmMintRequestUpdated:async e=>{await _(this.persistence,e,this.logger),n.zkevmMintRequestUpdated&&n.zkevmMintRequestUpdated(e)}})}};if(typeof process<`u`&&process.on)try{process.on(`uncaughtExceptionMonitor`,f)}catch{}export{y as MintingBackendModule,p as mintingPersistencePg,m as mintingPersistencePrismaSqlite,_ as processMint,h as recordMint,g as submitMintingRequests};
@@ -4,8 +4,8 @@ import { CreateMintRequest, MintingPersistence } from './persistence/type';
4
4
  import { Logger } from './logger/type';
5
5
  export declare const recordMint: (mintingPersistence: MintingPersistence, mintRequest: CreateMintRequest) => Promise<void>;
6
6
  export declare const submitMintingRequests: (mintingPersistence: MintingPersistence, blockchainDataSDKClient: BlockchainData, { defaultBatchSize, chainName, maxNumberOfTries, }: {
7
- defaultBatchSize?: number | undefined;
8
7
  chainName?: string | undefined;
8
+ defaultBatchSize?: number | undefined;
9
9
  maxNumberOfTries?: number | undefined;
10
10
  }, logger?: Logger, maxLoops?: number) => Promise<void>;
11
11
  export declare const processMint: (mintingPersistence: MintingPersistence, event: ZkevmMintRequestUpdated, logger?: Logger) => Promise<void>;
package/package.json CHANGED
@@ -1,30 +1,28 @@
1
1
  {
2
2
  "name": "@imtbl/minting-backend",
3
3
  "description": "minting backend utilising Immutable Minting API",
4
- "version": "2.23.0",
4
+ "version": "2.23.1-0",
5
5
  "author": "Immutable",
6
6
  "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
7
7
  "dependencies": {
8
- "@imtbl/blockchain-data": "2.23.0",
9
- "@imtbl/config": "2.23.0",
10
- "@imtbl/generated-clients": "2.23.0",
11
- "@imtbl/metrics": "2.23.0",
12
- "@imtbl/webhook": "2.23.0",
13
- "uuid": "^9.0.1"
8
+ "uuid": "^9.0.1",
9
+ "@imtbl/blockchain-data": "2.23.1-0",
10
+ "@imtbl/config": "2.23.1-0",
11
+ "@imtbl/generated-clients": "2.23.1-0",
12
+ "@imtbl/metrics": "2.23.1-0",
13
+ "@imtbl/webhook": "2.23.1-0"
14
14
  },
15
15
  "devDependencies": {
16
- "@swc/core": "^1.4.2",
16
+ "@swc/core": "^1.15.46",
17
17
  "@swc/jest": "^0.2.37",
18
18
  "@testcontainers/postgresql": "^10.9.0",
19
19
  "@types/jest": "^29.5.12",
20
20
  "@types/pg": "^8.11.5",
21
21
  "@types/uuid": "^8.3.4",
22
- "eslint": "^8.56.0",
22
+ "@typescript/native": "npm:typescript@^7.0.2",
23
23
  "jest": "^29.7.0",
24
- "jest-environment-jsdom": "^29.4.3",
25
24
  "testcontainers": "^10.9.0",
26
- "typescript": "^5.6.2",
27
- "tsup": "^8.3.0"
25
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
28
26
  },
29
27
  "exports": {
30
28
  "development": {
@@ -52,17 +50,19 @@
52
50
  "publishConfig": {
53
51
  "access": "public"
54
52
  },
55
- "repository": "immutable/ts-immutable-sdk.git",
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "immutable/ts-immutable-sdk.git"
56
+ },
56
57
  "type": "module",
57
58
  "types": "./dist/types/index.d.ts",
58
59
  "scripts": {
59
60
  "build": "pnpm transpile && pnpm typegen",
60
- "transpile": "tsup src/index.ts --config ./tsup.config.js",
61
- "typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types",
62
61
  "pack:root": "pnpm pack --pack-destination $(dirname $(pnpm root -w))",
63
- "lint": "eslint ./src --ext .ts,.jsx,.tsx --max-warnings=0",
64
62
  "test": "jest --passWithNoTests",
65
63
  "test:watch": "jest --watch",
66
- "typecheck": "tsc --customConditions default --noEmit --jsx preserve"
64
+ "transpile": "tsdown",
65
+ "typecheck": "tsc --customConditions default --noEmit --jsx preserve",
66
+ "typegen": "tsc --customConditions default --emitDeclarationOnly --outDir dist/types"
67
67
  }
68
68
  }
@@ -1 +0,0 @@
1
- export {};