aiia-vault-sdk 1.1.26 → 1.1.27

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/utils.d.ts CHANGED
@@ -8,6 +8,22 @@ export declare const LOG_PREFIXES: {
8
8
  DEBUG: string;
9
9
  };
10
10
  export declare const sleep: (ms: number) => Promise<void>;
11
+ /**
12
+ * Splits an array into chunks of the specified size
13
+ * @param array The array to split into chunks
14
+ * @param chunkSize The maximum size of each chunk
15
+ * @returns An array of chunks
16
+ */
17
+ export declare const chunks: <T>(array: T[], chunkSize: number) => T[][];
18
+ /**
19
+ * Process items in batches with a delay between batches to avoid rate limiting
20
+ * @param items Array of items to process
21
+ * @param processFn Function to process each batch of items
22
+ * @param batchSize Maximum number of items per batch
23
+ * @param delayMs Delay in milliseconds between batches
24
+ * @returns The combined results from all batches
25
+ */
26
+ export declare const processBatches: <T, R>(items: T[], processFn: (batch: T[]) => Promise<R[]>, batchSize?: number, delayMs?: number) => Promise<R[]>;
11
27
  export declare const getRandomProvider: (providers: ethers.Provider[]) => ethers.Provider;
12
28
  export declare const checkRpcHealth: (provider: ethers.Provider, index?: number) => Promise<boolean>;
13
29
  export declare const getTransactionStatus: (provider: ethers.Provider, txHash: string, maxRetries?: number) => Promise<{
package/dist/utils.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getNetworkFromRpc=exports.signAndSendTransaction=exports.streamEvents=exports.getAllEvents=exports.resolveContractAddress=exports.getRewardWeight=exports.buildApproveERC20Tx=exports.getTokenAllowance=exports.getTokenSymbol=exports.getTokenDecimals=exports.getTransactionStatus=exports.checkRpcHealth=exports.getRandomProvider=exports.sleep=exports.LOG_PREFIXES=void 0;const e=require("ethers");exports.LOG_PREFIXES={INFO:"[STREAM-INFO]",BLOCK:"[STREAM-BLOCK]",EVENT:"[STREAM-EVENT]",ERROR:"[STREAM-ERROR]",SAVE:"[STREAM-SAVE]",DEBUG:"[STREAM-DEBUG]"};exports.sleep=async e=>new Promise((t=>setTimeout(t,e)));exports.getRandomProvider=e=>e[Math.floor(Math.random()*e.length)];exports.checkRpcHealth=async(e,t=0)=>{try{const t=new Promise(((e,t)=>{setTimeout((()=>t(new Error("RPC request timeout"))),5e3)}));return await Promise.race([e.getBlockNumber(),t]),!0}catch(e){return console.error(`${exports.LOG_PREFIXES.ERROR} RPC health check failed:`,e,t),!1}};exports.getTransactionStatus=async(e,t,o=10)=>{let r=0,s=1e3;for(;r<o;)try{const a=await e.getTransactionReceipt(t);if(!a){if(r++,r===o)return{hash:t,status:null,confirmations:0,isCompleted:!1,attempts:r};await(0,exports.sleep)(s),s*=2;continue}const n=Number(await a.confirmations()||0);return{hash:a.hash,status:1===a.status,confirmations:n,isCompleted:!0,attempts:r+1}}catch(e){throw new Error(`Failed to get transaction status: ${e.message}`)}throw new Error("Failed to get transaction status after maximum retries")};exports.getTokenDecimals=async(t,o)=>{const r=new e.ethers.Contract(t,["function decimals() view returns (uint8)"],o);return Number(await r.decimals())};exports.getTokenSymbol=async(t,o)=>{const r=new e.ethers.Contract(t,["function symbol() view returns (string)"],o);return await r.symbol()};exports.getTokenAllowance=async(t,o,r,s)=>{if(t===e.ethers.ZeroAddress||t.toLowerCase()===e.ethers.ZeroAddress)return BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");const a=new e.ethers.Contract(t,["function allowance(address owner, address spender) view returns (uint256)"],s);return await a.allowance(o,r)};exports.buildApproveERC20Tx=async(t,o,r,s)=>{const a=new e.ethers.Contract(t,["function approve(address spender, uint256 amount) returns (bool)"],s);return await a.approve.populateTransaction(o,r)};exports.getRewardWeight=(e,t)=>{let o=0;const r=[...t].sort(((e,t)=>e.duration-t.duration));for(const t of r)e>=t.duration&&(o=t.weight);return o};exports.resolveContractAddress=(e,t,o,r)=>{if(r)return r;const s=(0,exports.getNetworkFromRpc)(e);return o?.[s]?.[t]};exports.getAllEvents=async(e,t,o,r,s,a)=>{let n=[];e.interface.forEachEvent((e=>{n.push(e.name)})),a&&a.length>0&&(n=n.filter((e=>a.includes(e))));const i=n.map((async t=>{const a=o(),n=a.filters[t]();return(await a.queryFilter(n,r,s)).map((o=>{const r=e.interface.parseLog({topics:o.topics,data:o.data});return{eventName:t,blockNumber:o.blockNumber,transactionHash:o.transactionHash,args:r?.args.toObject(),timestamp:null}}))})),c=(await Promise.all(i)).flat();c.sort(((e,t)=>e.blockNumber-t.blockNumber));const l=[...new Set(c.map((e=>e.blockNumber)))].map((e=>t().getBlock(e))),m=await Promise.all(l),p=new Map(m.map((e=>[e.number,e.timestamp])));return c.map((e=>({eventName:e.eventName,blockNumber:e.blockNumber,transactionHash:e.transactionHash,args:Object.fromEntries(Object.entries(e.args||{}).filter((([e])=>isNaN(Number(e))))),timestamp:p.get(e.blockNumber)??null})))};exports.streamEvents=async({getProvider:e,getAllEvents:t,formatEvent:o,onEvent:r,saveLatestBlock:s,fromBlock:a,batchSize:n=1e3,sleepTime:i=5e3,whitelistEvents:c})=>{const l="1"===process.env.DEBUG_STREAM_EVENTS;let m=a;for(l&&(console.log(`${exports.LOG_PREFIXES.INFO} StreamEvents Debug Mode Enabled`),console.log(`${exports.LOG_PREFIXES.INFO} Initial fromBlock: ${m}`),console.log(`${exports.LOG_PREFIXES.INFO} Batch size: ${n}`),console.log(`${exports.LOG_PREFIXES.INFO} Sleep time: ${i}ms`),c&&c.length>0&&console.log(`${exports.LOG_PREFIXES.INFO} Whitelist events: ${c.join(", ")}`));;)try{const a=await e().getBlockNumber();l&&console.log(`${exports.LOG_PREFIXES.BLOCK} Latest block: ${a}`);const p=Math.min(m+n,a);if(l&&console.log(`${exports.LOG_PREFIXES.BLOCK} Processing blocks from ${m} to ${p}`),m>=a){l&&console.log(`${exports.LOG_PREFIXES.DEBUG} Caught up to latest block, waiting ${i}ms...`),await(0,exports.sleep)(i);continue}const f=await t(m,p,c);if(l&&f.length>0){const e=f.reduce(((e,t)=>{const o=t.eventName||"Unknown";return e[o]=(e[o]||0)+1,e}),{});console.log(`${exports.LOG_PREFIXES.EVENT} Found ${f.length} events:`),Object.entries(e).forEach((([e,t])=>{console.log(`${exports.LOG_PREFIXES.EVENT} - ${e}: ${t}`)}))}for(const e of f)l&&console.log(`${exports.LOG_PREFIXES.EVENT} Processing: ${e.eventName||"Event"}`),await r(o(e));await s(p),l&&console.log(`${exports.LOG_PREFIXES.SAVE} Saved latest block: ${p}`),m=p+1}catch(e){l?(console.error(`${exports.LOG_PREFIXES.ERROR} Error in streamEvents:`,e),console.error(`${exports.LOG_PREFIXES.ERROR} Stack trace:`,e instanceof Error?e.stack:"")):console.error(`${exports.LOG_PREFIXES.ERROR} Error in streamEvents:`,e),await(0,exports.sleep)(1e3)}};exports.signAndSendTransaction=async(e,t,o,{onSubmit:r,onFinally:s,onError:a}={},n)=>{try{const a={...e};let n;if("object"==typeof t&&null!==t&&"sendTransaction"in t){const e=t.connect(o());n=(await e.sendTransaction(a)).hash}else n=await t(a);r&&await r(n);const i=await(0,exports.getTransactionStatus)(o(),n);if(null===i.status)throw new Error("Transaction may not be minted on-chain yet or has failed. Please check the blockchain explorer.");if(!1===i.status)throw new Error("Transaction failed. Please check the blockchain explorer for details.");return s&&await s({...i,txHash:n}),{transaction:{hash:n},status:i}}catch(e){if(n&&e)try{if("CALL_EXCEPTION"===e.code&&e.data){const t=e.data;for(const o of Object.values(n.interface.fragments).filter((e=>"error"===e.type)))if("name"in o){const r=n.interface.getError(o.name);if(r&&r.selector){if(r.selector===t){const t=o.name,r=e.errorArgs||[],s=new Error(`Transaction failed with custom error: ${t}(${r.join(", ")})`);throw Object.assign(s,e),a&&await a(s),s}}}console.log(`${exports.LOG_PREFIXES.DEBUG} Unknown custom error with selector: ${t}`)}}catch(e){console.error(`${exports.LOG_PREFIXES.ERROR} Error decoding transaction error:`,e)}throw a&&await a(e instanceof Error?e:new Error(String(e))),e}};exports.getNetworkFromRpc=e=>{const t=e.toLowerCase();let o=t;try{if(t.includes("://")){o=new URL(t).hostname}else t.includes("@")&&(o=t.split("@")[1].split("/")[0])}catch(e){console.warn(`${exports.LOG_PREFIXES.ERROR} Failed to parse RPC URL: ${t}`)}const r=[[/sepolia\.base|base-sepolia/,"base-sepolia"],[/goerli\.base|base-goerli/,"base-goerli"],[/base-mainnet/,"base"],[/polygon-mumbai|mumbai\.polygon/,"polygon-mumbai"],[/polygon-amoy|amoy\.polygon/,"polygon-amoy"],[/polygon-zkevm|zkevm|zkevm[-.]polygon/,"polygon-zkevm"],[/arbitrum.*sepolia|sepolia.*arbitrum/,"arbitrum-sepolia"],[/arbitrum.*goerli|goerli.*arbitrum/,"arbitrum-goerli"],[/arbitrum-nova|nova[-.]arbitrum/,"arbitrum-nova"],[/optimism-sepolia|sepolia[-.]optimism/,"optimism-sepolia"],[/optimism-goerli|goerli[-.]optimism/,"optimism-goerli"],[/avalanche-fuji|fuji[-.]avalanche|avax-test/,"avalanche-fuji"],[/bsc-testnet|testnet[-.]bsc|data-seed-prebsc/,"bsc-testnet"],[/base(?![-.]sepolia|[-.]goerli)/,"base"],[/polygon(?![-.]mumbai|[-.]amoy)/,"polygon"],[/arbitrum(?![-.]nova)/,"arbitrum"],[/optimism(?![-.]sepolia|[-.]goerli)/,"optimism"],[/avalanche|avax(?![-.]test|[-.]fuji)/,"avalanche"],[/bsc|binance(?![-.]testnet)/,"bsc"],[/eth-sepolia|sepolia(?![-.]base|[-.]arbitrum|[-.]optimism)/,"sepolia"],[/eth-goerli|goerli(?![-.]base|[-.]arbitrum|[-.]optimism)/,"goerli"],[/eth-mainnet|ethereum|eth\.rpc/,"ethereum"],[/mainnet/,"ethereum"]];for(const[e,o]of r)if(e.test(t))return o;for(const[e,t]of r)if(e.test(o))return t;throw new Error("Failed to get network from RPC URL")};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getNetworkFromRpc=exports.signAndSendTransaction=exports.streamEvents=exports.getAllEvents=exports.resolveContractAddress=exports.getRewardWeight=exports.buildApproveERC20Tx=exports.getTokenAllowance=exports.getTokenSymbol=exports.getTokenDecimals=exports.getTransactionStatus=exports.checkRpcHealth=exports.getRandomProvider=exports.processBatches=exports.chunks=exports.sleep=exports.LOG_PREFIXES=void 0;const e=require("ethers");exports.LOG_PREFIXES={INFO:"[STREAM-INFO]",BLOCK:"[STREAM-BLOCK]",EVENT:"[STREAM-EVENT]",ERROR:"[STREAM-ERROR]",SAVE:"[STREAM-SAVE]",DEBUG:"[STREAM-DEBUG]"};exports.sleep=async e=>new Promise((t=>setTimeout(t,e)));exports.chunks=(e,t)=>{const o=[];for(let r=0;r<e.length;r+=t)o.push(e.slice(r,r+t));return o};exports.processBatches=async(e,t,o=3,r=500)=>{let s=[];const n=(0,exports.chunks)(e,o);for(let e=0;e<n.length;e++){const o=await t(n[e]);s=[...s,...o],e<n.length-1&&await(0,exports.sleep)(r)}return s};exports.getRandomProvider=e=>e[Math.floor(Math.random()*e.length)];exports.checkRpcHealth=async(e,t=0)=>{try{const t=new Promise(((e,t)=>{setTimeout((()=>t(new Error("RPC request timeout"))),5e3)}));return await Promise.race([e.getBlockNumber(),t]),!0}catch(e){return console.error(`${exports.LOG_PREFIXES.ERROR} RPC health check failed:`,e,t),!1}};exports.getTransactionStatus=async(e,t,o=10)=>{let r=0,s=1e3;for(;r<o;)try{const n=await e.getTransactionReceipt(t);if(!n){if(r++,r===o)return{hash:t,status:null,confirmations:0,isCompleted:!1,attempts:r};await(0,exports.sleep)(s),s*=2;continue}const a=Number(await n.confirmations()||0);return{hash:n.hash,status:1===n.status,confirmations:a,isCompleted:!0,attempts:r+1}}catch(e){throw new Error(`Failed to get transaction status: ${e.message}`)}throw new Error("Failed to get transaction status after maximum retries")};exports.getTokenDecimals=async(t,o)=>{const r=new e.ethers.Contract(t,["function decimals() view returns (uint8)"],o);return Number(await r.decimals())};exports.getTokenSymbol=async(t,o)=>{const r=new e.ethers.Contract(t,["function symbol() view returns (string)"],o);return await r.symbol()};exports.getTokenAllowance=async(t,o,r,s)=>{if(t===e.ethers.ZeroAddress||t.toLowerCase()===e.ethers.ZeroAddress)return BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");const n=new e.ethers.Contract(t,["function allowance(address owner, address spender) view returns (uint256)"],s);return await n.allowance(o,r)};exports.buildApproveERC20Tx=async(t,o,r,s)=>{const n=new e.ethers.Contract(t,["function approve(address spender, uint256 amount) returns (bool)"],s);return await n.approve.populateTransaction(o,r)};exports.getRewardWeight=(e,t)=>{let o=0;const r=[...t].sort(((e,t)=>e.duration-t.duration));for(const t of r)e>=t.duration&&(o=t.weight);return o};exports.resolveContractAddress=(e,t,o,r)=>{if(r)return r;const s=(0,exports.getNetworkFromRpc)(e);return o?.[s]?.[t]};exports.getAllEvents=async(e,t,o,r,s,n)=>{let a=[];e.interface.forEachEvent((e=>{a.push(e.name)})),n&&n.length>0&&(a=a.filter((e=>n.includes(e))));const i=await(0,exports.processBatches)(a,(async t=>{const n=t.map((async t=>{const n=o(),a=n.filters[t]();return(await n.queryFilter(a,r,s)).map((o=>{const r=e.interface.parseLog({topics:o.topics,data:o.data});return{eventName:t,blockNumber:o.blockNumber,transactionHash:o.transactionHash,args:r?.args.toObject(),timestamp:null}}))}));return(await Promise.all(n)).flat()}));i.sort(((e,t)=>e.blockNumber-t.blockNumber));const c=[...new Set(i.map((e=>e.blockNumber)))],l=new Map;return await(0,exports.processBatches)(c,(async e=>{const o=e.map((e=>t().getBlock(e)));return(await Promise.all(o)).forEach((e=>{e&&l.set(e.number,e.timestamp)})),[]})),i.map((e=>({eventName:e.eventName,blockNumber:e.blockNumber,transactionHash:e.transactionHash,args:Object.fromEntries(Object.entries(e.args||{}).filter((([e])=>isNaN(Number(e))))),timestamp:l.get(e.blockNumber)??null})))};exports.streamEvents=async({getProvider:e,getAllEvents:t,formatEvent:o,onEvent:r,saveLatestBlock:s,fromBlock:n,batchSize:a=1e3,sleepTime:i=5e3,whitelistEvents:c})=>{const l="1"===process.env.DEBUG_STREAM_EVENTS;let p=n,m=0,f=Date.now();const u=()=>{m++;const e=Date.now();e-f>=1e4&&(console.log(`${exports.LOG_PREFIXES.INFO} RPC Requests in last 10s: ${m}`),m=0,f=e)},E=()=>{const t=e();if(!t.__requestTracking){if("send"in t){const e=t.send.bind(t);t.send=async(t,o)=>(u(),e(t,o))}else if("_send"in t){const e=t._send.bind(t);t._send=async(t,o)=>(u(),e(t,o))}else{const e=t.getBlockNumber.bind(t);t.getBlockNumber=async()=>(u(),e());const o=t.getBlock.bind(t);t.getBlock=async e=>(u(),o(e));const r=t.getTransactionReceipt.bind(t);t.getTransactionReceipt=async e=>(u(),r(e))}t.__requestTracking=!0}return t},g=async(e,o,r)=>(u(),await t(e,o,r));for(l&&(console.log(`${exports.LOG_PREFIXES.INFO} StreamEvents Debug Mode Enabled`),console.log(`${exports.LOG_PREFIXES.INFO} Initial fromBlock: ${p}`),console.log(`${exports.LOG_PREFIXES.INFO} Batch size: ${a}`),console.log(`${exports.LOG_PREFIXES.INFO} Sleep time: ${i}ms`),console.log(`${exports.LOG_PREFIXES.INFO} RPC request tracking enabled (10s intervals)`),c&&c.length>0&&console.log(`${exports.LOG_PREFIXES.INFO} Whitelist events: ${c.join(", ")}`));;)try{const e=await E().getBlockNumber();l&&console.log(`${exports.LOG_PREFIXES.BLOCK} Latest block: ${e}`);const t=Math.min(p+a,e);if(l&&console.log(`${exports.LOG_PREFIXES.BLOCK} Processing blocks from ${p} to ${t}`),p>=e){l&&console.log(`${exports.LOG_PREFIXES.DEBUG} Caught up to latest block, waiting ${i}ms...`),await(0,exports.sleep)(i);continue}const n=await g(p,t,c);if(l&&n.length>0){const e=n.reduce(((e,t)=>{const o=t.eventName||"Unknown";return e[o]=(e[o]||0)+1,e}),{});console.log(`${exports.LOG_PREFIXES.EVENT} Found ${n.length} events:`),Object.entries(e).forEach((([e,t])=>{console.log(`${exports.LOG_PREFIXES.EVENT} - ${e}: ${t}`)}))}for(const e of n)l&&console.log(`${exports.LOG_PREFIXES.EVENT} Processing: ${e.eventName||"Event"}`),await r(o(e));await s(t),l&&console.log(`${exports.LOG_PREFIXES.SAVE} Saved latest block: ${t}`),p=t+1}catch(e){l?(console.error(`${exports.LOG_PREFIXES.ERROR} Error in streamEvents:`,e),console.error(`${exports.LOG_PREFIXES.ERROR} Stack trace:`,e instanceof Error?e.stack:"")):console.error(`${exports.LOG_PREFIXES.ERROR} Error in streamEvents:`,e),await(0,exports.sleep)(1e3)}};exports.signAndSendTransaction=async(e,t,o,{onSubmit:r,onFinally:s,onError:n}={},a)=>{try{const n={...e};let a;if("object"==typeof t&&null!==t&&"sendTransaction"in t){const e=t.connect(o());a=(await e.sendTransaction(n)).hash}else a=await t(n);r&&await r(a);const i=await(0,exports.getTransactionStatus)(o(),a);if(null===i.status)throw new Error("Transaction may not be minted on-chain yet or has failed. Please check the blockchain explorer.");if(!1===i.status)throw new Error("Transaction failed. Please check the blockchain explorer for details.");return s&&await s({...i,txHash:a}),{transaction:{hash:a},status:i}}catch(e){if(a&&e)try{if("CALL_EXCEPTION"===e.code&&e.data){const t=e.data;for(const o of Object.values(a.interface.fragments).filter((e=>"error"===e.type)))if("name"in o){const r=a.interface.getError(o.name);if(r&&r.selector){if(r.selector===t){const t=o.name,r=e.errorArgs||[],s=new Error(`Transaction failed with custom error: ${t}(${r.join(", ")})`);throw Object.assign(s,e),n&&await n(s),s}}}console.log(`${exports.LOG_PREFIXES.DEBUG} Unknown custom error with selector: ${t}`)}}catch(e){console.error(`${exports.LOG_PREFIXES.ERROR} Error decoding transaction error:`,e)}throw n&&await n(e instanceof Error?e:new Error(String(e))),e}};exports.getNetworkFromRpc=e=>{const t=e.toLowerCase();let o=t;try{if(t.includes("://")){o=new URL(t).hostname}else t.includes("@")&&(o=t.split("@")[1].split("/")[0])}catch(e){console.warn(`${exports.LOG_PREFIXES.ERROR} Failed to parse RPC URL: ${t}`)}const r=[[/sepolia\.base|base-sepolia/,"base-sepolia"],[/goerli\.base|base-goerli/,"base-goerli"],[/base-mainnet/,"base"],[/polygon-mumbai|mumbai\.polygon/,"polygon-mumbai"],[/polygon-amoy|amoy\.polygon/,"polygon-amoy"],[/polygon-zkevm|zkevm|zkevm[-.]polygon/,"polygon-zkevm"],[/arbitrum.*sepolia|sepolia.*arbitrum/,"arbitrum-sepolia"],[/arbitrum.*goerli|goerli.*arbitrum/,"arbitrum-goerli"],[/arbitrum-nova|nova[-.]arbitrum/,"arbitrum-nova"],[/optimism-sepolia|sepolia[-.]optimism/,"optimism-sepolia"],[/optimism-goerli|goerli[-.]optimism/,"optimism-goerli"],[/avalanche-fuji|fuji[-.]avalanche|avax-test/,"avalanche-fuji"],[/bsc-testnet|testnet[-.]bsc|data-seed-prebsc/,"bsc-testnet"],[/base(?![-.]sepolia|[-.]goerli)/,"base"],[/polygon(?![-.]mumbai|[-.]amoy)/,"polygon"],[/arbitrum(?![-.]nova)/,"arbitrum"],[/optimism(?![-.]sepolia|[-.]goerli)/,"optimism"],[/avalanche|avax(?![-.]test|[-.]fuji)/,"avalanche"],[/bsc|binance(?![-.]testnet)/,"bsc"],[/eth-sepolia|sepolia(?![-.]base|[-.]arbitrum|[-.]optimism)/,"sepolia"],[/eth-goerli|goerli(?![-.]base|[-.]arbitrum|[-.]optimism)/,"goerli"],[/eth-mainnet|ethereum|eth\.rpc/,"ethereum"],[/mainnet/,"ethereum"]];for(const[e,o]of r)if(e.test(t))return o;for(const[e,t]of r)if(e.test(o))return t;throw new Error("Failed to get network from RPC URL")};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiia-vault-sdk",
3
- "version": "1.1.26",
3
+ "version": "1.1.27",
4
4
  "description": "SDK for AIIA Vault Contract",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",