From 303a2024b250860582636e81d932383e64e91f6a Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Sat, 21 Oct 2023 02:44:57 +0530 Subject: [PATCH 1/6] native client dev --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index b15e325..7185c44 100644 --- a/config.json +++ b/config.json @@ -9,7 +9,7 @@ "SKIP_FAILED_REQUESTS": false } }, - "NATIVE_CLIENT": false, + "NATIVE_CLIENT": true, "DEBUG": true, "evmchains": [ { From f04abb5090b827e640524253ad636e640ca556e1 Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Wed, 25 Oct 2023 15:23:11 +0530 Subject: [PATCH 2/6] coupon service --- CouponService/couponService.ts | 155 ++ client/src/components/FaucetForm.tsx | 53 +- client/src/components/ReCaptcha.ts | 6 +- config.json | 13 +- package-lock.json | 2427 +++++++++++++++++++++++++- package.json | 2 + server.ts | 37 +- types.ts | 4 +- vms/evm.ts | 102 +- vms/evmTypes.ts | 16 +- vms/utils.ts | 19 +- 11 files changed, 2728 insertions(+), 106 deletions(-) create mode 100644 CouponService/couponService.ts diff --git a/CouponService/couponService.ts b/CouponService/couponService.ts new file mode 100644 index 0000000..b4fc221 --- /dev/null +++ b/CouponService/couponService.ts @@ -0,0 +1,155 @@ +import { DynamoDBClient } from "@aws-sdk/client-dynamodb" +import { DynamoDBDocumentClient, UpdateCommand, ScanCommand } from "@aws-sdk/lib-dynamodb" +import { Mutex, MutexInterface } from 'async-mutex' + +type Coupon = { + id: string, + maxLimitAmount: number, + consumedAmount: number, + expiry: number, +} + +type CouponConfig = { + IS_ENABLED: boolean, + MAX_LIMIT_CAP: number, +} + +function validateCouponData(coupon: any, couponConfig: CouponConfig): Coupon | undefined { + if ( + coupon.id && + coupon.maxLimitAmount > 0 && + coupon.maxLimitAmount <= couponConfig.MAX_LIMIT_CAP && + coupon.consumedAmount <= coupon.maxLimitAmount && + coupon.expiry > 0 + ) { + return coupon + } + + return undefined +} + +export class CouponService { + private readonly mutex: MutexInterface + private readonly documentClient?: DynamoDBDocumentClient + private readonly couponConfig: CouponConfig + coupons: Map + + constructor(couponConfig: CouponConfig) { + this.mutex = new Mutex() + this.coupons = new Map() + this.couponConfig = couponConfig + + // Return early if coupon system is disabled + if (!couponConfig.IS_ENABLED) return + + const ddbClient = new DynamoDBClient({ region: 'us-east-1' }) + this.documentClient = DynamoDBDocumentClient.from(ddbClient) + + this.syncCoupons() + + // Syncs coupon between DynamoDB and memory at regular intervals + setInterval(() => { + this.syncCoupons() + }, 10_000) + } + + /** + * Syncs coupons in memory with database + * 1. Fetches new coupons from database into memory + * 2. Remove coupons which were deleted in database from memory + * 3. Updates coupon usage limits in database + * 4. TODO(raj): Delete expired (or few days after expiry) coupons from database + */ + private async syncCoupons(): Promise { + const params = new ScanCommand({ + TableName: 'coupons', + }) + + const result = await this.documentClient?.send(params) + + // Required for quick lookup of coupons in DB fetched list + const dbItemSet = new Set() + + // Fetches new coupons from database into memory + result?.Items?.forEach((item: Record) => { + const coupon: Coupon | undefined = validateCouponData(item, this.couponConfig) + if (coupon) { + dbItemSet.add(coupon.id) + + // Only load new coupons into memory + if (this.coupons.get(coupon.id) === undefined) { + this.coupons.set(coupon.id, coupon) + } + } else { + console.log("fetched invalid coupon data:", item) + } + }) + + // Remove coupons which were deleted in database from memory + for (const [id, _item] of this.coupons.entries()) { + if (!dbItemSet.has(id)) { + this.coupons.delete(id) + } + } + + // Updates coupon usage limits in database + await this.batchUpdateCoupons() + } + + // Iterates over every coupon in memory and updates database with their `consumedAmount` + async batchUpdateCoupons(): Promise { + this.coupons.forEach(async (couponItem, _id) => { + const updateRequest = { + TableName: 'coupons', + Key: { + id: couponItem.id, + }, + UpdateExpression: 'SET consumedAmount = :consumedAmount', + ExpressionAttributeValues: { + ':consumedAmount': couponItem.consumedAmount, + }, + } + + const params = new UpdateCommand(updateRequest) + await this.documentClient?.send(params) + }) + } + + async consumeCouponAmount(id: string, amount: number): Promise { + // Return `true` early, if coupon system is disabled (for debugging) + if (!this.couponConfig.IS_ENABLED) return true + + const release = await this.mutex.acquire() + try { + const coupon = this.coupons.get(id) + if ( + coupon && + coupon.expiry > (Date.now() / 1000) && + coupon.consumedAmount + amount < coupon.maxLimitAmount + ) { + coupon.consumedAmount += amount + return true + } + return false + } finally { + release() + } + } + + async reclaimCouponAmount(id: string, amount: number): Promise { + const release = await this.mutex.acquire() + + try { + const coupon = this.coupons.get(id) + if ( + coupon && + coupon.expiry > (Date.now() / 1000) && + coupon.consumedAmount - amount > 0 + ) { + coupon.consumedAmount -= amount + } + } finally { + release() + } + } +} \ No newline at end of file diff --git a/client/src/components/FaucetForm.tsx b/client/src/components/FaucetForm.tsx index e93e4f7..f438de2 100644 --- a/client/src/components/FaucetForm.tsx +++ b/client/src/components/FaucetForm.tsx @@ -16,9 +16,10 @@ const FaucetForm = (props: any) => { const [token, setToken] = useState(null) const [widgetID, setwidgetID] = useState(new Map()) const [recaptcha, setRecaptcha] = useState(undefined) - const [isV2, setIsV2] = useState(false) + const [isV2, setIsV2] = useState(true) const [chainConfigs, setChainConfigs] = useState([]) const [inputAddress, setInputAddress] = useState("") + const [couponId, setCouponId] = useState("") const [address, setAddress] = useState(null) const [faucetAddress, setFaucetAddress] = useState(null) const [options, setOptions] = useState([]) @@ -42,9 +43,17 @@ const FaucetForm = (props: any) => { )) updateChainConfigs() connectAccount(updateAddress, false) - }, []) + useEffect(() => { + if (window.grecaptcha) { + window.grecaptcha.ready(() => { + setIsV2(true) + recaptcha?.loadV2Captcha(props.config.V2_SITE_KEY, widgetID) + }) + } + }, [props.config.V2_SITE_KEY, recaptcha, widgetID, window.grecaptcha]) + // Update balance whenver chain changes or after transaction is processed useEffect(() => { updateBalance() @@ -182,7 +191,7 @@ const FaucetForm = (props: any) => { function getChainParams(): {chain: string, erc20: string} { let params = { chain: chainConfigs[chain!]?.ID, - erc20: chainConfigs[token!]?.ID + erc20: chainConfigs[chain!]?.ID === chainConfigs[token!]?.ID ? undefined : chainConfigs[token!]?.ID } return params @@ -229,11 +238,21 @@ const FaucetForm = (props: any) => { } } - function calculateBaseUnit(amount: string = "0", decimals: number = 18): BigInt { - for(let i = 0; i < decimals; i++) { - amount += "0" + function calculateBaseUnit(amount: string = "0", decimals: number = 18): bigint { + const parsedNumber = parseFloat(amount); + + if (!isFinite(parsedNumber)) { + throw new Error("Invalid number input for formatting base unit: " + amount); } - return BigInt(amount) + + const formattedNumber = parsedNumber.toFixed(decimals); + const [integerPart, decimalPart] = formattedNumber.split('.'); + + const bigInteger = BigInt(integerPart); + const bigDecimal = BigInt(decimalPart || '0'); + + const finalAmount = bigInteger * BigInt(10 ** decimals) + bigDecimal; + return finalAmount } function calculateLargestUnit(amount: string = "0", decimals: number = 18): string { @@ -275,6 +294,10 @@ const FaucetForm = (props: any) => { } } + function updateCouponId(couponId: any): void { + setCouponId(couponId!) + } + async function getCaptchaToken(index: number = 0): Promise<{token?:string, v2Token?: string}> { const { token, v2Token } = await recaptcha!.getToken(isV2, widgetID, index) return { token, v2Token } @@ -324,7 +347,8 @@ const FaucetForm = (props: any) => { token, v2Token, chain, - erc20 + erc20, + couponId }) data = response?.data } catch(err: any) { @@ -443,7 +467,7 @@ const FaucetForm = (props: any) => { ) const resetRecaptcha = (): void => { - setIsV2(false) + // setIsV2(false) recaptcha!.resetV2Captcha(widgetID) } @@ -521,6 +545,17 @@ const FaucetForm = (props: any) => { Connect + +
+ +
+ updateCouponId(e.target.value)} + /> +
+ {sendTokenResponse?.message}
diff --git a/client/src/components/ReCaptcha.ts b/client/src/components/ReCaptcha.ts index b6a333f..44bf290 100644 --- a/client/src/components/ReCaptcha.ts +++ b/client/src/components/ReCaptcha.ts @@ -19,7 +19,7 @@ export default class ReCaptcha { this.setWidgetID = setWidgetID } - async getToken(isV2 = false, widgetID: any, index: number = 0): Promise<{token?: string, v2Token?: string}> { + async getToken(isV2 = true, widgetID: any, index: number = 0): Promise<{token?: string, v2Token?: string}> { let token = "", v2Token = "" !isV2 && await window.grecaptcha.execute(this.siteKey, {action: this.action}) .then((res: string) => { @@ -39,7 +39,7 @@ export default class ReCaptcha { if(widgetID.get(index) || widgetID.get(index) == 0) { window.grecaptcha.reset(widgetID.get(index)) } - v2CaptchaContainer.style.display = "none" + // v2CaptchaContainer.style.display = "none" } } @@ -53,7 +53,7 @@ export default class ReCaptcha { } } else { v2CaptchaContainer.style.display = "block" - const newWidgetID = window.grecaptcha.render(v2CaptchaContainer, { + const newWidgetID = window.grecaptcha?.render(v2CaptchaContainer, { 'sitekey' : v2siteKey, 'theme': 'dark' }) diff --git a/config.json b/config.json index 7185c44..ca09b5e 100644 --- a/config.json +++ b/config.json @@ -10,7 +10,11 @@ } }, "NATIVE_CLIENT": true, - "DEBUG": true, + "DEBUG": false, + "couponConfig": { + "IS_ENABLED": false, + "MAX_LIMIT_CAP": 5000 + }, "evmchains": [ { "ID": "C", @@ -22,12 +26,13 @@ "IMAGE": "https://glacier-api.avax.network/proxy/chain-assets/main/chains/43113/chain-logo.png", "MAX_PRIORITY_FEE": "10000000000", "MAX_FEE": "100000000000", - "DRIP_AMOUNT": 2, + "DRIP_AMOUNT": 0.01, "DECIMALS": 18, "RECALIBRATE": 30, + "COUPON_REQUIRED": true, "RATELIMIT": { - "MAX_LIMIT": 1, - "WINDOW_SIZE": 1440 + "MAX_LIMIT": 5, + "WINDOW_SIZE": 60 } }, { diff --git a/package-lock.json b/package-lock.json index 56e84d7..af3a868 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { + "@aws-sdk/lib-dynamodb": "^3.433.0", + "async-mutex": "^0.4.0", "avalanche": "^3.13.3", "cors": "^2.8.5", "dotenv": "^16.0.0", @@ -31,6 +33,679 @@ "node": ">=17" } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "peer": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "peer": true, + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "peer": true, + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "peer": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "peer": true, + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + }, + "node_modules/@aws-sdk/client-dynamodb": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.433.0.tgz", + "integrity": "sha512-2ILYyeq+11mARlVaEnC5rkT0ZbqxnX5MDB3JalvFOE+y9EWnNbIKjUzFV9OOCyBRSxzQP3TV2xOPn0nv2iZHyg==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.433.0", + "@aws-sdk/core": "3.433.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-endpoint-discovery": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "@smithy/util-waiter": "^2.0.12", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.433.0.tgz", + "integrity": "sha512-L7ksMP7UnYH+w52ly+m+s5vk8662VtyqJ+UduFEMPqKUHTFEm7w+CCw4Xfk3hl5GlVvqPvYWqBqv8eLKSHpCEQ==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.433.0.tgz", + "integrity": "sha512-hQ+NLIcA1KRJ2qPdrtkJ3fOEVnehLLMlnB/I5mjg9K2UKjuiOufLao6tc5SyW9fseIL9AdX3fjJ8Unhg+y1RWg==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-sdk-sts": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.433.0.tgz", + "integrity": "sha512-wS5clEFFdNHbM6mCARUzdKDXgMGL2uWMGyEi8xvudgd/QN/ZotBUTCAe0mpKemV/UWdKKzIU1sp673i1gMjkNg==", + "peer": true, + "dependencies": { + "@smithy/smithy-client": "^2.1.12" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.433.0.tgz", + "integrity": "sha512-Vl7Qz5qYyxBurMn6hfSiNJeUHSqfVUlMt0C1Bds3tCkl3IzecRWwyBOlxtxO3VCrgVeW3HqswLzCvhAFzPH6nQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.433.0.tgz", + "integrity": "sha512-T+YhCOORyA4+i4T86FfFCmi/jPsmLOP6GAtScHp/K8XzB9XuVvJSZ+T8SUKeW6/9G9z3Az7dqeBVLcMdC6fFDA==", + "peer": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.433.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.433.0.tgz", + "integrity": "sha512-uOTBJszqGJIX5SrH2YdN501cv9rW4ghuSkasxI9DL+sVV5YRMd/bwu6I3PphRyK7z4dosDEbJ1xoIuVR/W04HQ==", + "peer": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-ini": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.433.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.433.0.tgz", + "integrity": "sha512-W7FcGlQjio9Y/PepcZGRyl5Bpwb0uWU7qIUCh+u4+q2mW4D5ZngXg8V/opL9/I/p4tUH9VXZLyLGwyBSkdhL+A==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.433.0.tgz", + "integrity": "sha512-vuc2X7q/1HUAO/NowfnNMpRDoHw8H2lyZZzUc0lmamy6PDrEFBi/VTm1nStGPuS9egCFrYlkRHsfp50ukYGa5w==", + "peer": true, + "dependencies": { + "@aws-sdk/client-sso": "3.433.0", + "@aws-sdk/token-providers": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.433.0.tgz", + "integrity": "sha512-RlwjP1I5wO+aPpwyCp23Mk8nmRbRL33hqRASy73c4JA2z2YiRua+ryt6MalIxehhwQU6xvXUKulJnPG9VaMFZg==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/endpoint-cache": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.310.0.tgz", + "integrity": "sha512-y3wipforet41EDTI0vnzxILqwAGll1KfI5qcdX9pXF/WF1f+3frcOtPiWtQEZQpy4czRogKm3BHo70QBYAZxlQ==", + "peer": true, + "dependencies": { + "mnemonist": "0.38.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.433.0.tgz", + "integrity": "sha512-RcDjyA/MQiU1261f0zFqZncKkbd0v9d4SdCY6LOx+hUHwCkdCj681C2d5LJAuTD24byhe3/YxSbnQ8LdbIOTuA==", + "dependencies": { + "@aws-sdk/util-dynamodb": "3.433.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.0.0" + } + }, + "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.433.0.tgz", + "integrity": "sha512-eGQcncEtnQs2wMpLkJoreba/5547/eDDojGLuGjBmKtbZbVNZ9nbyCC//WIsmgT5CR5Bg9D+bNSsijmYpU6Qpg==", + "peer": true, + "dependencies": { + "@aws-sdk/endpoint-cache": "3.310.0", + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.433.0.tgz", + "integrity": "sha512-mBTq3UWv1UzeHG+OfUQ2MB/5GEkt5LTKFaUqzL7ESwzW8XtpBgXnjZvIwu3Vcd3sEetMwijwaGiJhY0ae/YyaA==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.433.0.tgz", + "integrity": "sha512-We346Fb5xGonTGVZC9Nvqtnqy74VJzYuTLLiuuftA5sbNzftBDy/22QCfvYSTOAl3bvif+dkDUzQY2ihc5PwOQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.433.0.tgz", + "integrity": "sha512-HEvYC9PQlWY/ccUYtLvAlwwf1iCif2TSAmLNr3YTBRVa98x6jKL0hlCrHWYklFeqOGSKy6XhE+NGJMUII0/HaQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.433.0.tgz", + "integrity": "sha512-ORYbJnBejUyonFl5FwIqhvI3Cq6sAp9j+JpkKZtFNma9tFPdrhmYgfCeNH32H/wGTQV/tUoQ3luh0gA4cuk6DA==", + "peer": true, + "dependencies": { + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.433.0.tgz", + "integrity": "sha512-jxPvt59NZo/epMNLNTu47ikmP8v0q217I6bQFGJG7JVFnfl36zDktMwGw+0xZR80qiK47/2BWrNpta61Zd2FxQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.433.0.tgz", + "integrity": "sha512-jMgA1jHfisBK4oSjMKrtKEZf0sl2vzADivkFmyZFzORpSZxBnF6hC21RjaI+70LJLcc9rSCzLgcoz5lHb9LLDg==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.433.0.tgz", + "integrity": "sha512-xpjRjCZW+CDFdcMmmhIYg81ST5UAnJh61IHziQEk0FXONrg4kjyYPZAOjEdzXQ+HxJQuGQLKPhRdzxmQnbX7pg==", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.433.0.tgz", + "integrity": "sha512-Q6aYVaQKB+CkBLHQQlN8MHVpOzZv9snRfVz7SxIpdbHkRuGEHiLliCY3fg6Sonvu3AKEPERPuHcaC75tnNpOBw==", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.433.0.tgz", + "integrity": "sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-dynamodb": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.433.0.tgz", + "integrity": "sha512-uG7uSwfq+ctHo15tSE/zvWVVUrt7FDxNrRmxV814TItlS61sPqvTnJR3ASq06sMKeAgj1hWn5lyqRin5MyeT/A==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.433.0.tgz", + "integrity": "sha512-LFNUh9FH7RMtYjSjPGz9lAJQMzmJ3RcXISzc5X5k2R/9mNwMK7y1k2VAfvx+RbuDbll6xwsXlgv6QHcxVdF2zw==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.433.0.tgz", + "integrity": "sha512-2Cf/Lwvxbt5RXvWFXrFr49vXv0IddiUwrZoAiwhDYxvsh+BMnh+NUFot+ZQaTrk/8IPZVDeLPWZRdVy00iaVXQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.433.0.tgz", + "integrity": "sha512-yT1tO4MbbsUBLl5+S+jVv8wxiAtP5TKjKib9B2KQ2x0OtWWTrIf2o+IZK8va+zQqdV4MVMjezdxdE20hOdB4yQ==", + "peer": true, + "dependencies": { + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "peer": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, "node_modules/@cspotcode/source-map-consumer": { "version": "0.8.0", "license": "BSD-3-Clause", @@ -723,39 +1398,588 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/base64": "^5.6.0", - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" + "@ethersproject/base64": "^5.6.0", + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.6.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.6.0", + "@ethersproject/hash": "^5.6.0", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/properties": "^5.6.0", + "@ethersproject/strings": "^5.6.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", + "integrity": "sha512-YIJyefe1mi3GxKdZxEBEuzYOeQ9xpYfqnFmWzojCssRAuR7ycxwpoRQgp965vuW426xUAQhCV5rCaWElQ7XsaA==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.16.tgz", + "integrity": "sha512-1k+FWHQDt2pfpXhJsOmNMmlAZ3NUQ98X5tYsjQhVGq+0X6cOBMhfh6Igd0IX3Ut6lEO6DQAdPMI/blNr3JZfMQ==", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.18.tgz", + "integrity": "sha512-QnPBi6D2zj6AHJdUTo5zXmk8vwHJ2bNevhcVned1y+TZz/OI5cizz5DsYNkqFUIDn8tBuEyKNgbmKVNhBbuY3g==", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.12.tgz", + "integrity": "sha512-ZZQLzHBJkbiAAdj2C5K+lBlYp/XJ+eH2uy+jgJgYIFW/o5AM59Hlj7zyI44/ZTDIQWmBxb3EFv/c5t44V8/g8A==", + "peer": true, + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.4.tgz", + "integrity": "sha512-gIPRFEGi+c6V52eauGKrjDzPWF2Cu7Z1r5F8A3j2wcwz25sPG/t8kjsbEhli/tS/2zJp/ybCZXe4j4ro3yv/HA==", + "peer": true, + "dependencies": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.12.tgz", + "integrity": "sha512-fDZnTr5j9t5qcbeJ037aMZXxMka13Znqwrgy3PAqYj6Dm3XHXHftTH3q+NWgayUxl1992GFtQt1RuEzRMy3NnQ==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.12.tgz", + "integrity": "sha512-p5Y+iMHV3SoEpy3VSR7mifbreHQwVSvHSAz/m4GdoXfOzKzaYC8hYv10Ks7Deblkf7lhas8U+lAp9ThbBM+ZXA==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.14.tgz", + "integrity": "sha512-poUNgKTw9XwPXfX9nEHpVgrMNVpaSMZbshqvPxFVoalF4wp6kRzYKOfdesSVectlQ51VtigoLfbXcdyPwvxgTg==", + "peer": true, + "dependencies": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.3.tgz", + "integrity": "sha512-ZrQ0/YX6hNVTxqMEHtEaDbDv6pNeEji/a5Vk3HuFC5R3ZY8lfoATyxmOGxBVYnF3NUvZLNC7umEv1WzWGWvCGQ==", + "peer": true, + "dependencies": { + "@smithy/middleware-serde": "^2.0.12", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.18.tgz", + "integrity": "sha512-VyrHQRldGSb3v9oFOB5yPxmLT7U2sQic2ytylOnYlnsmVOLlFIaI6sW22c+w2675yq+XZ6HOuzV7x2OBYCWRNA==", + "peer": true, + "dependencies": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-retry": "^2.0.5", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.12.tgz", + "integrity": "sha512-IBeco157lIScecq2Z+n0gq56i4MTnfKxS7rbfrAORveDJgnbBAaEQgYqMqp/cYqKrpvEXcyTjwKHrBjCCIZh2A==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.6.tgz", + "integrity": "sha512-YSvNZeOKWLJ0M/ycxwDIe2Ztkp6Qixmcml1ggsSv2fdHKGkBPhGrX5tMzPGMI1yyx55UEYBi2OB4s+RriXX48A==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.3.tgz", + "integrity": "sha512-J6lXvRHGVnSX3n1PYi+e1L5HN73DkkJpUviV3Ebf+8wSaIjAf+eVNbzyvh/S5EQz7nf4KVfwbD5vdoZMAthAEQ==", + "peer": true, + "dependencies": { + "@smithy/property-provider": "^2.0.13", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.8.tgz", + "integrity": "sha512-KZylM7Wff/So5SmCiwg2kQNXJ+RXgz34wkxS7WNwIUXuZrZZpY/jKJCK+ZaGyuESDu3TxcaY+zeYGJmnFKbQsA==", + "peer": true, + "dependencies": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.13.tgz", + "integrity": "sha512-VJqUf2CbsQX6uUiC5dUPuoEATuFjkbkW3lJHbRnpk9EDC9X+iKqhfTK+WP+lve5EQ9TcCI1Q6R7hrg41FyC54w==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.8.tgz", + "integrity": "sha512-SHJvYeWq8q0FK8xHk+xjV9dzDUDjFMT+G1pZbV+XB6OVoac/FSVshlMNPeUJ8AmSkcDKHRu5vASnRqZHgD3qhw==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.12.tgz", + "integrity": "sha512-cDbF07IuCjiN8CdGvPzfJjXIrmDSelScRfyJYrYBNBbKl2+k7QD/KqiHhtRyEKgID5mmEVrV6KE6L/iPJ98sFw==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.12.tgz", + "integrity": "sha512-fytyTcXaMzPBuNtPlhj5v6dbl4bJAnwKZFyyItAGt4Tgm9HFPZNo7a9r1SKPr/qdxUEBzvL9Rh+B9SkTX3kFxg==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.5.tgz", + "integrity": "sha512-M0SeJnEgD2ywJyV99Fb1yKFzmxDe9JfpJiYTVSRMyRLc467BPU0qsuuDPzMCdB1mU8M8u1rVOdkqdoyFN8UFTw==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.2.tgz", + "integrity": "sha512-noyQUPn7b1M8uB0GEXc/Zyxq+5K2b7aaqWnLp+hgJ7+xu/FCvtyWy5eWLDjQEsHnAet2IZhS5QF8872OR69uNg==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.12.tgz", + "integrity": "sha512-6Kc2lCZEVmb1nNYngyNbWpq0d82OZwITH11SW/Q0U6PX5fH7B2cIcFe7o6eGEFPkTZTP8itTzmYiGcECL0D0Lw==", + "peer": true, + "dependencies": { + "@smithy/eventstream-codec": "^2.0.12", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.12.tgz", + "integrity": "sha512-XXqhridfkKnpj+lt8vM6HRlZbqUAqBjVC74JIi13F/AYQd/zTj9SOyGfxnbp4mjY9q28LityxIuV8CTinr9r5w==", + "peer": true, + "dependencies": { + "@smithy/middleware-stack": "^2.0.6", + "@smithy/types": "^2.4.0", + "@smithy/util-stream": "^2.0.17", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz", + "integrity": "sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz", + "integrity": "sha512-qgkW2mZqRvlNUcBkxYB/gYacRaAdck77Dk3/g2iw0S9F0EYthIS3loGfly8AwoWpIvHKhkTsCXXQfzksgZ4zIA==", + "peer": true, + "dependencies": { + "@smithy/querystring-parser": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "peer": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "peer": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.16.tgz", + "integrity": "sha512-Uv5Cu8nVkuvLn0puX+R9zWbSNpLIR3AxUlPoLJ7hC5lvir8B2WVqVEkJLwtixKAncVLasnTVjPDCidtAUTGEQw==", + "peer": true, + "dependencies": { + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.21.tgz", + "integrity": "sha512-cUEsttVZ79B7Al2rWK2FW03HBpD9LyuqFtm+1qFty5u9sHSdesr215gS2Ln53fTopNiPgeXpdoM3IgjvIO0rJw==", + "peer": true, + "dependencies": { + "@smithy/config-resolver": "^2.0.16", + "@smithy/credential-provider-imds": "^2.0.18", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.5.tgz", + "integrity": "sha512-1lyT3TcaMJQe+OFfVI+TlomDkPuVzb27NZYdYtmSTltVmLaUjdCyt4KE+OH1CnhZKsz4/cdCL420Lg9UH5Z2Mw==", + "peer": true, + "dependencies": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.5.tgz", + "integrity": "sha512-x3t1+MQAJ6QONk3GTbJNcugCFDVJ+Bkro5YqQQK1EyVesajNDqxFtCx9WdOFNGm/Cbm7tUdwVEmfKQOJoU2Vtw==", + "peer": true, + "dependencies": { + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.17.tgz", + "integrity": "sha512-fP/ZQ27rRvHsqItds8yB7jerwMpZFTL3QqbQbidUiG0+mttMoKdP0ZqnvM8UK5q0/dfc3/pN7g4XKPXOU7oRWw==", + "peer": true, + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "peer": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@ethersproject/wordlists": { - "version": "5.6.0", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", + "node_modules/@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "peer": true, "dependencies": { - "@ethersproject/bytes": "^5.6.0", - "@ethersproject/hash": "^5.6.0", - "@ethersproject/logger": "^5.6.0", - "@ethersproject/properties": "^5.6.0", - "@ethersproject/strings": "^5.6.0" + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "license": "MIT", + "node_modules/@smithy/util-waiter": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.12.tgz", + "integrity": "sha512-3sENmyVa1NnOPoiT2NCApPmu7ukP7S/v7kL9IxNmnygkDldn7/yK0TP42oPJLwB2k3mospNsSePIlqdXEUyPHA==", + "peer": true, + "dependencies": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + }, "engines": { - "node": ">=6" + "node": ">=14.0.0" } }, "node_modules/@szmarczak/http-timer": { @@ -973,6 +2197,14 @@ "version": "1.0.1", "license": "MIT" }, + "node_modules/async-mutex": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.4.0.tgz", + "integrity": "sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "license": "MIT" @@ -1148,6 +2380,12 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "peer": true + }, "node_modules/brorand": { "version": "1.1.0", "license": "MIT" @@ -2175,6 +3413,28 @@ "version": "2.1.0", "license": "MIT" }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "peer": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "license": "MIT", @@ -3062,6 +4322,15 @@ "node": ">=4" } }, + "node_modules/mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "peer": true, + "dependencies": { + "obliterator": "^1.6.1" + } + }, "node_modules/mock-fs": { "version": "4.14.0", "license": "MIT" @@ -3203,6 +4472,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", + "peer": true + }, "node_modules/oboe": { "version": "2.1.5", "license": "BSD", @@ -3775,6 +5050,12 @@ "npm": ">=3" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, "node_modules/swarm-js": { "version": "0.1.40", "license": "MIT", @@ -3977,6 +5258,11 @@ } } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/tunnel-agent": { "version": "0.6.0", "license": "Apache-2.0", @@ -4631,6 +5917,598 @@ } }, "dependencies": { + "@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "peer": true, + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "peer": true, + "requires": { + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "peer": true, + "requires": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "peer": true, + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "peer": true, + "requires": { + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "peer": true, + "requires": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "peer": true + } + } + }, + "@aws-sdk/client-dynamodb": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.433.0.tgz", + "integrity": "sha512-2ILYyeq+11mARlVaEnC5rkT0ZbqxnX5MDB3JalvFOE+y9EWnNbIKjUzFV9OOCyBRSxzQP3TV2xOPn0nv2iZHyg==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.433.0", + "@aws-sdk/core": "3.433.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-endpoint-discovery": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "@smithy/util-waiter": "^2.0.12", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true + } + } + }, + "@aws-sdk/client-sso": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.433.0.tgz", + "integrity": "sha512-L7ksMP7UnYH+w52ly+m+s5vk8662VtyqJ+UduFEMPqKUHTFEm7w+CCw4Xfk3hl5GlVvqPvYWqBqv8eLKSHpCEQ==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/client-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.433.0.tgz", + "integrity": "sha512-hQ+NLIcA1KRJ2qPdrtkJ3fOEVnehLLMlnB/I5mjg9K2UKjuiOufLao6tc5SyW9fseIL9AdX3fjJ8Unhg+y1RWg==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.433.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-sdk-sts": "3.433.0", + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/region-config-resolver": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/protocol-http": "^3.0.8", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/core": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.433.0.tgz", + "integrity": "sha512-wS5clEFFdNHbM6mCARUzdKDXgMGL2uWMGyEi8xvudgd/QN/ZotBUTCAe0mpKemV/UWdKKzIU1sp673i1gMjkNg==", + "peer": true, + "requires": { + "@smithy/smithy-client": "^2.1.12" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.433.0.tgz", + "integrity": "sha512-Vl7Qz5qYyxBurMn6hfSiNJeUHSqfVUlMt0C1Bds3tCkl3IzecRWwyBOlxtxO3VCrgVeW3HqswLzCvhAFzPH6nQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.433.0.tgz", + "integrity": "sha512-T+YhCOORyA4+i4T86FfFCmi/jPsmLOP6GAtScHp/K8XzB9XuVvJSZ+T8SUKeW6/9G9z3Az7dqeBVLcMdC6fFDA==", + "peer": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.433.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.433.0.tgz", + "integrity": "sha512-uOTBJszqGJIX5SrH2YdN501cv9rW4ghuSkasxI9DL+sVV5YRMd/bwu6I3PphRyK7z4dosDEbJ1xoIuVR/W04HQ==", + "peer": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.433.0", + "@aws-sdk/credential-provider-ini": "3.433.0", + "@aws-sdk/credential-provider-process": "3.433.0", + "@aws-sdk/credential-provider-sso": "3.433.0", + "@aws-sdk/credential-provider-web-identity": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.433.0.tgz", + "integrity": "sha512-W7FcGlQjio9Y/PepcZGRyl5Bpwb0uWU7qIUCh+u4+q2mW4D5ZngXg8V/opL9/I/p4tUH9VXZLyLGwyBSkdhL+A==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.433.0.tgz", + "integrity": "sha512-vuc2X7q/1HUAO/NowfnNMpRDoHw8H2lyZZzUc0lmamy6PDrEFBi/VTm1nStGPuS9egCFrYlkRHsfp50ukYGa5w==", + "peer": true, + "requires": { + "@aws-sdk/client-sso": "3.433.0", + "@aws-sdk/token-providers": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.433.0.tgz", + "integrity": "sha512-RlwjP1I5wO+aPpwyCp23Mk8nmRbRL33hqRASy73c4JA2z2YiRua+ryt6MalIxehhwQU6xvXUKulJnPG9VaMFZg==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/endpoint-cache": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.310.0.tgz", + "integrity": "sha512-y3wipforet41EDTI0vnzxILqwAGll1KfI5qcdX9pXF/WF1f+3frcOtPiWtQEZQpy4czRogKm3BHo70QBYAZxlQ==", + "peer": true, + "requires": { + "mnemonist": "0.38.3", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/lib-dynamodb": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.433.0.tgz", + "integrity": "sha512-RcDjyA/MQiU1261f0zFqZncKkbd0v9d4SdCY6LOx+hUHwCkdCj681C2d5LJAuTD24byhe3/YxSbnQ8LdbIOTuA==", + "requires": { + "@aws-sdk/util-dynamodb": "3.433.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-endpoint-discovery": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.433.0.tgz", + "integrity": "sha512-eGQcncEtnQs2wMpLkJoreba/5547/eDDojGLuGjBmKtbZbVNZ9nbyCC//WIsmgT5CR5Bg9D+bNSsijmYpU6Qpg==", + "peer": true, + "requires": { + "@aws-sdk/endpoint-cache": "3.310.0", + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.433.0.tgz", + "integrity": "sha512-mBTq3UWv1UzeHG+OfUQ2MB/5GEkt5LTKFaUqzL7ESwzW8XtpBgXnjZvIwu3Vcd3sEetMwijwaGiJhY0ae/YyaA==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.433.0.tgz", + "integrity": "sha512-We346Fb5xGonTGVZC9Nvqtnqy74VJzYuTLLiuuftA5sbNzftBDy/22QCfvYSTOAl3bvif+dkDUzQY2ihc5PwOQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.433.0.tgz", + "integrity": "sha512-HEvYC9PQlWY/ccUYtLvAlwwf1iCif2TSAmLNr3YTBRVa98x6jKL0hlCrHWYklFeqOGSKy6XhE+NGJMUII0/HaQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-sdk-sts": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.433.0.tgz", + "integrity": "sha512-ORYbJnBejUyonFl5FwIqhvI3Cq6sAp9j+JpkKZtFNma9tFPdrhmYgfCeNH32H/wGTQV/tUoQ3luh0gA4cuk6DA==", + "peer": true, + "requires": { + "@aws-sdk/middleware-signing": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-signing": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.433.0.tgz", + "integrity": "sha512-jxPvt59NZo/epMNLNTu47ikmP8v0q217I6bQFGJG7JVFnfl36zDktMwGw+0xZR80qiK47/2BWrNpta61Zd2FxQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.433.0.tgz", + "integrity": "sha512-jMgA1jHfisBK4oSjMKrtKEZf0sl2vzADivkFmyZFzORpSZxBnF6hC21RjaI+70LJLcc9rSCzLgcoz5lHb9LLDg==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/region-config-resolver": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.433.0.tgz", + "integrity": "sha512-xpjRjCZW+CDFdcMmmhIYg81ST5UAnJh61IHziQEk0FXONrg4kjyYPZAOjEdzXQ+HxJQuGQLKPhRdzxmQnbX7pg==", + "peer": true, + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/token-providers": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.433.0.tgz", + "integrity": "sha512-Q6aYVaQKB+CkBLHQQlN8MHVpOzZv9snRfVz7SxIpdbHkRuGEHiLliCY3fg6Sonvu3AKEPERPuHcaC75tnNpOBw==", + "peer": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.433.0", + "@aws-sdk/middleware-logger": "3.433.0", + "@aws-sdk/middleware-recursion-detection": "3.433.0", + "@aws-sdk/middleware-user-agent": "3.433.0", + "@aws-sdk/types": "3.433.0", + "@aws-sdk/util-endpoints": "3.433.0", + "@aws-sdk/util-user-agent-browser": "3.433.0", + "@aws-sdk/util-user-agent-node": "3.433.0", + "@smithy/config-resolver": "^2.0.16", + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/hash-node": "^2.0.12", + "@smithy/invalid-dependency": "^2.0.12", + "@smithy/middleware-content-length": "^2.0.14", + "@smithy/middleware-endpoint": "^2.1.3", + "@smithy/middleware-retry": "^2.0.18", + "@smithy/middleware-serde": "^2.0.12", + "@smithy/middleware-stack": "^2.0.6", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.8", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.16", + "@smithy/util-defaults-mode-node": "^2.0.21", + "@smithy/util-retry": "^2.0.5", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/types": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.433.0.tgz", + "integrity": "sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-dynamodb": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.433.0.tgz", + "integrity": "sha512-uG7uSwfq+ctHo15tSE/zvWVVUrt7FDxNrRmxV814TItlS61sPqvTnJR3ASq06sMKeAgj1hWn5lyqRin5MyeT/A==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.433.0.tgz", + "integrity": "sha512-LFNUh9FH7RMtYjSjPGz9lAJQMzmJ3RcXISzc5X5k2R/9mNwMK7y1k2VAfvx+RbuDbll6xwsXlgv6QHcxVdF2zw==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.433.0.tgz", + "integrity": "sha512-2Cf/Lwvxbt5RXvWFXrFr49vXv0IddiUwrZoAiwhDYxvsh+BMnh+NUFot+ZQaTrk/8IPZVDeLPWZRdVy00iaVXQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.433.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.433.0.tgz", + "integrity": "sha512-yT1tO4MbbsUBLl5+S+jVv8wxiAtP5TKjKib9B2KQ2x0OtWWTrIf2o+IZK8va+zQqdV4MVMjezdxdE20hOdB4yQ==", + "peer": true, + "requires": { + "@aws-sdk/types": "3.433.0", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "peer": true, + "requires": { + "tslib": "^2.3.1" + } + }, "@cspotcode/source-map-consumer": { "version": "0.8.0" }, @@ -4991,6 +6869,452 @@ "@sindresorhus/is": { "version": "0.14.0" }, + "@smithy/abort-controller": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", + "integrity": "sha512-YIJyefe1mi3GxKdZxEBEuzYOeQ9xpYfqnFmWzojCssRAuR7ycxwpoRQgp965vuW426xUAQhCV5rCaWElQ7XsaA==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/config-resolver": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.16.tgz", + "integrity": "sha512-1k+FWHQDt2pfpXhJsOmNMmlAZ3NUQ98X5tYsjQhVGq+0X6cOBMhfh6Igd0IX3Ut6lEO6DQAdPMI/blNr3JZfMQ==", + "peer": true, + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/types": "^2.4.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@smithy/credential-provider-imds": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.18.tgz", + "integrity": "sha512-QnPBi6D2zj6AHJdUTo5zXmk8vwHJ2bNevhcVned1y+TZz/OI5cizz5DsYNkqFUIDn8tBuEyKNgbmKVNhBbuY3g==", + "peer": true, + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "tslib": "^2.5.0" + } + }, + "@smithy/eventstream-codec": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.12.tgz", + "integrity": "sha512-ZZQLzHBJkbiAAdj2C5K+lBlYp/XJ+eH2uy+jgJgYIFW/o5AM59Hlj7zyI44/ZTDIQWmBxb3EFv/c5t44V8/g8A==", + "peer": true, + "requires": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/fetch-http-handler": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.4.tgz", + "integrity": "sha512-gIPRFEGi+c6V52eauGKrjDzPWF2Cu7Z1r5F8A3j2wcwz25sPG/t8kjsbEhli/tS/2zJp/ybCZXe4j4ro3yv/HA==", + "peer": true, + "requires": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/hash-node": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.12.tgz", + "integrity": "sha512-fDZnTr5j9t5qcbeJ037aMZXxMka13Znqwrgy3PAqYj6Dm3XHXHftTH3q+NWgayUxl1992GFtQt1RuEzRMy3NnQ==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/invalid-dependency": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.12.tgz", + "integrity": "sha512-p5Y+iMHV3SoEpy3VSR7mifbreHQwVSvHSAz/m4GdoXfOzKzaYC8hYv10Ks7Deblkf7lhas8U+lAp9ThbBM+ZXA==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-content-length": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.14.tgz", + "integrity": "sha512-poUNgKTw9XwPXfX9nEHpVgrMNVpaSMZbshqvPxFVoalF4wp6kRzYKOfdesSVectlQ51VtigoLfbXcdyPwvxgTg==", + "peer": true, + "requires": { + "@smithy/protocol-http": "^3.0.8", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-endpoint": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.3.tgz", + "integrity": "sha512-ZrQ0/YX6hNVTxqMEHtEaDbDv6pNeEji/a5Vk3HuFC5R3ZY8lfoATyxmOGxBVYnF3NUvZLNC7umEv1WzWGWvCGQ==", + "peer": true, + "requires": { + "@smithy/middleware-serde": "^2.0.12", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "@smithy/url-parser": "^2.0.12", + "@smithy/util-middleware": "^2.0.5", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-retry": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.18.tgz", + "integrity": "sha512-VyrHQRldGSb3v9oFOB5yPxmLT7U2sQic2ytylOnYlnsmVOLlFIaI6sW22c+w2675yq+XZ6HOuzV7x2OBYCWRNA==", + "peer": true, + "requires": { + "@smithy/node-config-provider": "^2.1.3", + "@smithy/protocol-http": "^3.0.8", + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-retry": "^2.0.5", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true + } + } + }, + "@smithy/middleware-serde": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.12.tgz", + "integrity": "sha512-IBeco157lIScecq2Z+n0gq56i4MTnfKxS7rbfrAORveDJgnbBAaEQgYqMqp/cYqKrpvEXcyTjwKHrBjCCIZh2A==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/middleware-stack": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.6.tgz", + "integrity": "sha512-YSvNZeOKWLJ0M/ycxwDIe2Ztkp6Qixmcml1ggsSv2fdHKGkBPhGrX5tMzPGMI1yyx55UEYBi2OB4s+RriXX48A==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/node-config-provider": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.3.tgz", + "integrity": "sha512-J6lXvRHGVnSX3n1PYi+e1L5HN73DkkJpUviV3Ebf+8wSaIjAf+eVNbzyvh/S5EQz7nf4KVfwbD5vdoZMAthAEQ==", + "peer": true, + "requires": { + "@smithy/property-provider": "^2.0.13", + "@smithy/shared-ini-file-loader": "^2.2.2", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/node-http-handler": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.8.tgz", + "integrity": "sha512-KZylM7Wff/So5SmCiwg2kQNXJ+RXgz34wkxS7WNwIUXuZrZZpY/jKJCK+ZaGyuESDu3TxcaY+zeYGJmnFKbQsA==", + "peer": true, + "requires": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/protocol-http": "^3.0.8", + "@smithy/querystring-builder": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/property-provider": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.13.tgz", + "integrity": "sha512-VJqUf2CbsQX6uUiC5dUPuoEATuFjkbkW3lJHbRnpk9EDC9X+iKqhfTK+WP+lve5EQ9TcCI1Q6R7hrg41FyC54w==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/protocol-http": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.8.tgz", + "integrity": "sha512-SHJvYeWq8q0FK8xHk+xjV9dzDUDjFMT+G1pZbV+XB6OVoac/FSVshlMNPeUJ8AmSkcDKHRu5vASnRqZHgD3qhw==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/querystring-builder": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.12.tgz", + "integrity": "sha512-cDbF07IuCjiN8CdGvPzfJjXIrmDSelScRfyJYrYBNBbKl2+k7QD/KqiHhtRyEKgID5mmEVrV6KE6L/iPJ98sFw==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/querystring-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.12.tgz", + "integrity": "sha512-fytyTcXaMzPBuNtPlhj5v6dbl4bJAnwKZFyyItAGt4Tgm9HFPZNo7a9r1SKPr/qdxUEBzvL9Rh+B9SkTX3kFxg==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/service-error-classification": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.5.tgz", + "integrity": "sha512-M0SeJnEgD2ywJyV99Fb1yKFzmxDe9JfpJiYTVSRMyRLc467BPU0qsuuDPzMCdB1mU8M8u1rVOdkqdoyFN8UFTw==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.2.tgz", + "integrity": "sha512-noyQUPn7b1M8uB0GEXc/Zyxq+5K2b7aaqWnLp+hgJ7+xu/FCvtyWy5eWLDjQEsHnAet2IZhS5QF8872OR69uNg==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/signature-v4": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.12.tgz", + "integrity": "sha512-6Kc2lCZEVmb1nNYngyNbWpq0d82OZwITH11SW/Q0U6PX5fH7B2cIcFe7o6eGEFPkTZTP8itTzmYiGcECL0D0Lw==", + "peer": true, + "requires": { + "@smithy/eventstream-codec": "^2.0.12", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.4.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.5", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/smithy-client": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.12.tgz", + "integrity": "sha512-XXqhridfkKnpj+lt8vM6HRlZbqUAqBjVC74JIi13F/AYQd/zTj9SOyGfxnbp4mjY9q28LityxIuV8CTinr9r5w==", + "peer": true, + "requires": { + "@smithy/middleware-stack": "^2.0.6", + "@smithy/types": "^2.4.0", + "@smithy/util-stream": "^2.0.17", + "tslib": "^2.5.0" + } + }, + "@smithy/types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz", + "integrity": "sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/url-parser": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz", + "integrity": "sha512-qgkW2mZqRvlNUcBkxYB/gYacRaAdck77Dk3/g2iw0S9F0EYthIS3loGfly8AwoWpIvHKhkTsCXXQfzksgZ4zIA==", + "peer": true, + "requires": { + "@smithy/querystring-parser": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "peer": true, + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "peer": true, + "requires": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-defaults-mode-browser": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.16.tgz", + "integrity": "sha512-Uv5Cu8nVkuvLn0puX+R9zWbSNpLIR3AxUlPoLJ7hC5lvir8B2WVqVEkJLwtixKAncVLasnTVjPDCidtAUTGEQw==", + "peer": true, + "requires": { + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-defaults-mode-node": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.21.tgz", + "integrity": "sha512-cUEsttVZ79B7Al2rWK2FW03HBpD9LyuqFtm+1qFty5u9sHSdesr215gS2Ln53fTopNiPgeXpdoM3IgjvIO0rJw==", + "peer": true, + "requires": { + "@smithy/config-resolver": "^2.0.16", + "@smithy/credential-provider-imds": "^2.0.18", + "@smithy/node-config-provider": "^2.1.3", + "@smithy/property-provider": "^2.0.13", + "@smithy/smithy-client": "^2.1.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-middleware": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.5.tgz", + "integrity": "sha512-1lyT3TcaMJQe+OFfVI+TlomDkPuVzb27NZYdYtmSTltVmLaUjdCyt4KE+OH1CnhZKsz4/cdCL420Lg9UH5Z2Mw==", + "peer": true, + "requires": { + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-retry": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.5.tgz", + "integrity": "sha512-x3t1+MQAJ6QONk3GTbJNcugCFDVJ+Bkro5YqQQK1EyVesajNDqxFtCx9WdOFNGm/Cbm7tUdwVEmfKQOJoU2Vtw==", + "peer": true, + "requires": { + "@smithy/service-error-classification": "^2.0.5", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-stream": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.17.tgz", + "integrity": "sha512-fP/ZQ27rRvHsqItds8yB7jerwMpZFTL3QqbQbidUiG0+mttMoKdP0ZqnvM8UK5q0/dfc3/pN7g4XKPXOU7oRWw==", + "peer": true, + "requires": { + "@smithy/fetch-http-handler": "^2.2.4", + "@smithy/node-http-handler": "^2.1.8", + "@smithy/types": "^2.4.0", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "peer": true, + "requires": { + "tslib": "^2.5.0" + } + }, + "@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "peer": true, + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/util-waiter": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.12.tgz", + "integrity": "sha512-3sENmyVa1NnOPoiT2NCApPmu7ukP7S/v7kL9IxNmnygkDldn7/yK0TP42oPJLwB2k3mospNsSePIlqdXEUyPHA==", + "peer": true, + "requires": { + "@smithy/abort-controller": "^2.0.12", + "@smithy/types": "^2.4.0", + "tslib": "^2.5.0" + } + }, "@szmarczak/http-timer": { "version": "1.1.2", "requires": { @@ -5153,6 +7477,14 @@ "async-limiter": { "version": "1.0.1" }, + "async-mutex": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.4.0.tgz", + "integrity": "sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==", + "requires": { + "tslib": "^2.4.0" + } + }, "asynckit": { "version": "0.4.0" }, @@ -5266,6 +7598,12 @@ "unpipe": "1.0.0" } }, + "bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "peer": true + }, "brorand": { "version": "1.1.0" }, @@ -5989,6 +8327,15 @@ "fast-json-stable-stringify": { "version": "2.1.0" }, + "fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "peer": true, + "requires": { + "strnum": "^1.0.5" + } + }, "finalhandler": { "version": "1.2.0", "requires": { @@ -6505,6 +8852,15 @@ "mkdirp": "*" } }, + "mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "peer": true, + "requires": { + "obliterator": "^1.6.1" + } + }, "mock-fs": { "version": "4.14.0" }, @@ -6590,6 +8946,12 @@ "object-keys": "^1.1.1" } }, + "obliterator": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", + "peer": true + }, "oboe": { "version": "2.1.5", "requires": { @@ -6967,6 +9329,12 @@ "is-hex-prefixed": "1.0.0" } }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, "swarm-js": { "version": "0.1.40", "requires": { @@ -7103,6 +9471,11 @@ "yn": "3.1.1" } }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "tunnel-agent": { "version": "0.6.0", "requires": { diff --git a/package.json b/package.json index 334c66a..bb9caa4 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "author": "", "license": "ISC", "dependencies": { + "@aws-sdk/lib-dynamodb": "^3.433.0", + "async-mutex": "^0.4.0", "avalanche": "^3.13.3", "cors": "^2.8.5", "dotenv": "^16.0.0", diff --git a/server.ts b/server.ts index bf97b60..ced0844 100644 --- a/server.ts +++ b/server.ts @@ -1,9 +1,7 @@ import express from 'express' -import bodyParser from 'body-parser' import cors from 'cors' import path from 'path' import dotenv from 'dotenv' -import { BN } from 'avalanche' import { RateLimiter, VerifyCaptcha, parseBody, parseURI } from './middlewares' import EVM from './vms/evm' @@ -18,10 +16,12 @@ import { import { evmchains, erc20tokens, + couponConfig, GLOBAL_RL, NATIVE_CLIENT, DEBUG, } from './config.json' +import { CouponService } from './CouponService/couponService' dotenv.config() @@ -55,6 +55,8 @@ new RateLimiter(app, [ } }) +const couponService = new CouponService(couponConfig) + const captcha: VerifyCaptcha = new VerifyCaptcha(app, process.env.CAPTCHA_SECRET!, process.env.V2_CAPTCHA_SECRET!) let evms = new Map() @@ -73,7 +75,8 @@ const getChainByID = (chains: ChainType[], id: string): ChainType | undefined => // Populates the missing config keys of the child using the parent's config const populateConfig = (child: any, parent: any): any => { Object.keys(parent || {}).forEach((key) => { - if(!child[key]) { + // Do not copy COUPON config (in ERC20 tokens) from host chain + if(key !== 'COUPON_REQUIRED' && !child[key]) { child[key] = parent[key] } }) @@ -82,7 +85,7 @@ const populateConfig = (child: any, parent: any): any => { // Setting up instance for EVM chains evmchains.forEach((chain: ChainType): void => { - const chainInstance: EVM = new EVM(chain, process.env[chain.ID] || process.env.PK) + const chainInstance: EVM = new EVM(chain, (process.env[chain.ID] || process.env.PK)!) evms.set(chain.ID, { config: chain, @@ -107,18 +110,36 @@ router.post('/sendToken', captcha.middleware, async (req: any, res: any) => { const address: string = req.body?.address const chain: string = req.body?.chain const erc20: string | undefined = req.body?.erc20 + const coupon: string | undefined = req.body?.couponId const evm: EVMInstanceAndConfig = evms.get(chain)! - if(evm) { + if( + couponConfig.IS_ENABLED && + ( + (erc20 && evm.instance.contracts.get(erc20)?.config.COUPON_REQUIRED) || + (erc20 === undefined && evm.config.COUPON_REQUIRED) + ) + ) { + if(!coupon || !(await couponService.consumeCouponAmount(coupon, evm.config.DRIP_AMOUNT))) { + res.status(400).send({message: "Invalid or expired coupon passed!"}) + return + } + } + DEBUG && console.log( "address:", address, "chain:", chain, "erc20:", erc20, "ip:", req.headers["cf-connecting-ip"] || req.ip ) - evm?.instance.sendToken(address, erc20, (data: SendTokenResponse) => { + evm.instance.sendToken(address, erc20, async (data: SendTokenResponse) => { const { status, message, txHash } = data + + // validate and consume coupon if required + if (evm.config.COUPON_REQUIRED && coupon && txHash === undefined) { + await couponService.reclaimCouponAmount(coupon, evm.config.DRIP_AMOUNT) + } res.status(status).send({message, txHash}) }) } else { @@ -149,12 +170,12 @@ router.get('/getBalance', (req: any, res: any) => { const evm: EVMInstanceAndConfig = evms.get(chain)! - let balance: BN = evm?.instance.getBalance(erc20) + let balance: bigint = evm?.instance.getBalance(erc20) if(balance) { balance = balance } else { - balance = new BN(0) + balance = BigInt(0) } res.status(200).send({ diff --git a/types.ts b/types.ts index 850437c..48a7d40 100644 --- a/types.ts +++ b/types.ts @@ -36,6 +36,7 @@ export type ChainType = { MAX_FEE: string, DRIP_AMOUNT: number, RECALIBRATE?: number, + COUPON_REQUIRED?: boolean, RATELIMIT: { WINDOW_SIZE: number, MAX_LIMIT: number @@ -50,11 +51,12 @@ export type ERC20Type = { CONTRACTADDRESS: string, GASLIMIT: string, DRIP_AMOUNT: number, - DECIMALS: number + DECIMALS: number, RATELIMIT: { WINDOW_SIZE: number, MAX_LIMIT: number }, + COUPON_REQUIRED?: boolean, IMAGE?: string, RECALIBRATE?: number, RPC?: string, diff --git a/vms/evm.ts b/vms/evm.ts index 9c7a537..f92062b 100644 --- a/vms/evm.ts +++ b/vms/evm.ts @@ -1,10 +1,10 @@ -import { BN } from 'avalanche' import Web3 from 'web3' import { asyncCallWithTimeout, calculateBaseUnit } from './utils' import Log from './Log' import ERC20Interface from './ERC20Interface.json' -import { ChainType, SendTokenResponse, RequestType } from './evmTypes' +import { ChainType, SendTokenResponse, RequestType, ContractType, QueueType } from './evmTypes' +import { ERC20Type } from '../types' // cannot issue tx if no. of pending requests is > 16 const MEMPOOL_LIMIT = 15 @@ -12,13 +12,13 @@ const MEMPOOL_LIMIT = 15 // pending tx timeout should be a function of MEMPOOL_LIMIT const PENDING_TX_TIMEOUT = 40 * 1000 // 40 seconds -const BLOCK_FAUCET_DRIPS_TIMEOUT = 60 * 1000 // 60 seconds +const BLOCK_FAUCET_DRIPS_TIMEOUT = 1 * 1000 // 60 seconds export default class EVM { - web3: any + web3: Web3 account: any NAME: string - DRIP_AMOUNT: BN + DRIP_AMOUNT: bigint DECIMALS: number LEGACY: boolean MAX_PRIORITY_FEE: string @@ -28,22 +28,22 @@ export default class EVM { pendingTxNonces: Set hasError: Map nonce: number - balance: any + balance: bigint isFetched: boolean isUpdating: boolean recalibrate: boolean waitingForRecalibration: boolean waitArr: any[] - queue: any[] + queue: QueueType[] error: boolean log: Log - contracts: any + contracts: Map requestCount: number queuingInProgress: boolean blockFaucetDrips: boolean recalibrateNowActivated: boolean - constructor(config: ChainType, PK: string | undefined) { + constructor(config: ChainType, PK: string) { this.web3 = new Web3(config.RPC) this.account = this.web3.eth.accounts.privateKeyToAccount(PK) this.contracts = new Map() @@ -63,7 +63,7 @@ export default class EVM { this.pendingTxNonces = new Set() this.nonce = -1 - this.balance = new BN(0) + this.balance = BigInt(0) this.isFetched = false this.isUpdating = false @@ -144,13 +144,16 @@ export default class EVM { // increasing request count before processing request this.requestCount++ - let amount: BN = this.DRIP_AMOUNT + let amount: bigint = this.DRIP_AMOUNT // If id is provided, then it is ERC20 token transfer, so update the amount - if(this.contracts.get(id)) { - const dripAmount: number = this.contracts.get(id).config.DRIP_AMOUNT - if(dripAmount) { - amount = calculateBaseUnit(dripAmount.toString(), this.contracts.get(id).config.DECIMALS || 18) + if(id) { + const contract = this.contracts.get(id) + if (contract) { + const dripAmount: number = contract.config.DRIP_AMOUNT + if(dripAmount) { + amount = calculateBaseUnit(dripAmount.toString(), contract.config.DECIMALS || 18) + } } } @@ -213,7 +216,7 @@ export default class EVM { } } - getBalance(id?: string): BN { + getBalance(id?: string): bigint { if(id && this.contracts.get(id)) { return this.getERC20Balance(id) } else { @@ -221,13 +224,13 @@ export default class EVM { } } - getERC20Balance(id: string): BN { - return this.contracts.get(id)?.balance + getERC20Balance(id: string): bigint { + return this.contracts.get(id)?.balance ?? BigInt(0) } async fetchERC20Balance(): Promise { - this.contracts.forEach(async (contract: any) => { - contract.balance = new BN(await contract.methods.balanceOf(this.account.address).call()) + this.contracts.forEach(async (contract: ContractType) => { + contract.balance = BigInt(await contract.methods.balanceOf(this.account.address).call()) }) } @@ -239,14 +242,15 @@ export default class EVM { this.isUpdating = true try { - [this.nonce, this.balance] = await Promise.all([ + const [nonce, balance] = await Promise.all([ this.web3.eth.getTransactionCount(this.account.address, 'latest'), this.web3.eth.getBalance(this.account.address), ]) - await this.fetchERC20Balance() + this.nonce = nonce + this.balance = BigInt(balance) - this.balance = new BN(this.balance) + await this.fetchERC20Balance() this.error && this.log.info("RPC server recovered!") this.error = false @@ -266,15 +270,19 @@ export default class EVM { } balanceCheck(req: RequestType): Boolean { - const balance: BN = this.getBalance(req.id) - if(req.id && this.contracts.get(req.id)) { - if(this.contracts.get(req.id).balance.gte(req.amount)) { - this.contracts.get(req.id).balance = this.contracts.get(req.id).balance.sub(req.amount) - return true + const contractId = req.id + const amt = req.amount + if(contractId) { + const contract = this.contracts.get(contractId) + if (contract) { + if(contract.balance >= amt) { + contract.balance -= BigInt(amt) + return true + } } } else { - if(this.balance.gte(req.amount)) { - this.balance = this.balance.sub(req.amount) + if(this.balance >= amt) { + this.balance -= BigInt(amt) return true } } @@ -307,12 +315,12 @@ export default class EVM { // pops the 1st request in queue, and call the utility function to issue the tx async executeQueue(): Promise { - const { amount, receiver, nonce, id } = this.queue.shift() + const { amount, receiver, nonce, id } = this.queue.shift()! this.sendTokenUtil(amount, receiver, nonce, id) } async sendTokenUtil( - amount: number, + amount: bigint, receiver: string, nonce: number, id?: string @@ -352,7 +360,7 @@ export default class EVM { async getTransaction( to: string, - value: BN | number, + value: bigint, nonce: number | undefined, id?: string ): Promise { @@ -363,7 +371,7 @@ export default class EVM { to, maxPriorityFeePerGas: this.MAX_PRIORITY_FEE, maxFeePerGas: this.MAX_FEE, - value + value: value.toString() } if(this.LEGACY) { @@ -373,12 +381,16 @@ export default class EVM { tx.type = 0 } - if(this.contracts.get(id)) { - const txObject = this.contracts.get(id)?.methods.transfer(to, value) - tx.data = txObject.encodeABI() - tx.value = 0 - tx.to = this.contracts.get(id)?.config.CONTRACTADDRESS - tx.gas = this.contracts.get(id)?.config.GASLIMIT + + if(id) { + const contract = this.contracts.get(id) + if (contract) { + const txObject = contract.methods.transfer(to, value.toString()) + tx.data = txObject.encodeABI() + tx.value = 0 + tx.to = contract.config.CONTRACTADDRESS + tx.gas = contract.config.GASLIMIT + } } let signedTx @@ -394,14 +406,14 @@ export default class EVM { return { txHash, rawTransaction } } - async getGasPrice(): Promise { + async getGasPrice(): Promise { return this.web3.eth.getGasPrice() } // get expected price from the network for legacy txs async getAdjustedGasPrice(): Promise { try { - const gasPrice: number = await this.getGasPrice() + const gasPrice: number = parseInt(await this.getGasPrice()) const adjustedGas: number = Math.floor(gasPrice * 1.25) return Math.min(adjustedGas, parseInt(this.MAX_FEE)) } catch(err: any) { @@ -445,10 +457,10 @@ export default class EVM { } } - async addERC20Contract(config: any) { + async addERC20Contract(config: ERC20Type) { this.contracts.set(config.ID, { - methods: (new this.web3.eth.Contract(ERC20Interface, config.CONTRACTADDRESS)).methods, - balance: 0, + methods: (new this.web3.eth.Contract(JSON.parse(JSON.stringify(ERC20Interface)), config.CONTRACTADDRESS)).methods, + balance: BigInt(0), config }) } diff --git a/vms/evmTypes.ts b/vms/evmTypes.ts index a23d184..37edbde 100644 --- a/vms/evmTypes.ts +++ b/vms/evmTypes.ts @@ -1,4 +1,4 @@ -import { BN } from 'avalanche' +import { ERC20Type } from '../types' export type ChainType = { ID: string, @@ -26,7 +26,17 @@ export type SendTokenResponse = { export type RequestType = { receiver: string, - amount: BN | number, + amount: bigint, id?: string, requestId?: string, -} \ No newline at end of file +} + +export type QueueType = RequestType & { + nonce: number, +} + +export type ContractType = { + methods: any, + balance: bigint, + config: ERC20Type, +} diff --git a/vms/utils.ts b/vms/utils.ts index 0493e2f..7a8d813 100644 --- a/vms/utils.ts +++ b/vms/utils.ts @@ -1,14 +1,21 @@ -import { BN } from 'avalanche' +export function calculateBaseUnit(amount: string, decimals: number): bigint { + const parsedNumber = parseFloat(amount); -export function calculateBaseUnit(amount: string, decimals: number): BN { - for(let i = 0; i < decimals; i++) { - amount += "0" + if (!isFinite(parsedNumber)) { + throw new Error("Invalid number input for formatting base unit: " + amount); } - return new BN(amount) + const formattedNumber = parsedNumber.toFixed(decimals); + const [integerPart, decimalPart] = formattedNumber.split('.'); + + const bigInteger = BigInt(integerPart); + const bigDecimal = BigInt(decimalPart || '0'); + + const finalAmount = bigInteger * BigInt(10 ** decimals) + bigDecimal; + return finalAmount } -export const asyncCallWithTimeout = async (asyncPromise: Promise, timeLimit: number, timeoutMessage: string) => { +export const asyncCallWithTimeout = async (asyncPromise: Promise, timeLimit: number, timeoutMessage: string) => { let timeoutHandle: NodeJS.Timeout; const timeoutPromise = new Promise((_resolve, reject) => { From c063bb358caea2b767db6bfb19bcf4571ce19303 Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Wed, 25 Oct 2023 16:37:44 +0530 Subject: [PATCH 3/6] enable coupon system --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index ca09b5e..bf027ca 100644 --- a/config.json +++ b/config.json @@ -12,7 +12,7 @@ "NATIVE_CLIENT": true, "DEBUG": false, "couponConfig": { - "IS_ENABLED": false, + "IS_ENABLED": true, "MAX_LIMIT_CAP": 5000 }, "evmchains": [ From 82b07eca1e4244fe44a049d13a2cfb00047010a4 Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Wed, 22 Nov 2023 12:41:49 +0530 Subject: [PATCH 4/6] cleanup and custom coupon amount --- CouponService/couponService.ts | 20 +++++--- server.ts | 87 +++++++++++++++++++++------------- types.ts | 7 ++- vms/evm.ts | 19 +++++--- vms/evmTypes.ts | 2 + 5 files changed, 89 insertions(+), 46 deletions(-) diff --git a/CouponService/couponService.ts b/CouponService/couponService.ts index b4fc221..96922b8 100644 --- a/CouponService/couponService.ts +++ b/CouponService/couponService.ts @@ -1,12 +1,16 @@ import { DynamoDBClient } from "@aws-sdk/client-dynamodb" import { DynamoDBDocumentClient, UpdateCommand, ScanCommand } from "@aws-sdk/lib-dynamodb" import { Mutex, MutexInterface } from 'async-mutex' +import { CouponValidity } from "../types" type Coupon = { id: string, + faucetConfigId: string, maxLimitAmount: number, consumedAmount: number, expiry: number, + amountPerCoupon: number, + } type CouponConfig = { @@ -17,6 +21,7 @@ type CouponConfig = { function validateCouponData(coupon: any, couponConfig: CouponConfig): Coupon | undefined { if ( coupon.id && + coupon.faucetConfigId && coupon.maxLimitAmount > 0 && coupon.maxLimitAmount <= couponConfig.MAX_LIMIT_CAP && coupon.consumedAmount <= coupon.maxLimitAmount && @@ -115,22 +120,25 @@ export class CouponService { }) } - async consumeCouponAmount(id: string, amount: number): Promise { + async consumeCouponAmount(id: string, faucetConfigId: string, amount: number): Promise { // Return `true` early, if coupon system is disabled (for debugging) - if (!this.couponConfig.IS_ENABLED) return true + if (!this.couponConfig.IS_ENABLED) return { isValid: true, amount } const release = await this.mutex.acquire() try { const coupon = this.coupons.get(id) + const couponAmount = coupon?.amountPerCoupon ?? amount if ( coupon && + coupon.faucetConfigId === faucetConfigId && coupon.expiry > (Date.now() / 1000) && - coupon.consumedAmount + amount < coupon.maxLimitAmount + coupon.consumedAmount + couponAmount < coupon.maxLimitAmount ) { - coupon.consumedAmount += amount - return true + console.log(coupon, couponAmount) + coupon.consumedAmount += couponAmount + return { isValid: true, amount: couponAmount} } - return false + return { isValid: false, amount: couponAmount} } finally { release() } diff --git a/server.ts b/server.ts index ced0844..5f03896 100644 --- a/server.ts +++ b/server.ts @@ -10,7 +10,7 @@ import { SendTokenResponse, ChainType, EVMInstanceAndConfig, - ERC20Type + CouponValidity } from './types' import { @@ -94,7 +94,7 @@ evmchains.forEach((chain: ChainType): void => { }) // Adding ERC20 token contracts to their HOST evm instances -erc20tokens.forEach((token: ERC20Type, i: number): void => { +erc20tokens.forEach((token: any, i: number): void => { if(token.HOSTID) { token = populateConfig(token, getChainByID(evmchains, token.HOSTID)) } @@ -112,39 +112,60 @@ router.post('/sendToken', captcha.middleware, async (req: any, res: any) => { const erc20: string | undefined = req.body?.erc20 const coupon: string | undefined = req.body?.couponId - const evm: EVMInstanceAndConfig = evms.get(chain)! - if(evm) { - if( - couponConfig.IS_ENABLED && - ( - (erc20 && evm.instance.contracts.get(erc20)?.config.COUPON_REQUIRED) || - (erc20 === undefined && evm.config.COUPON_REQUIRED) - ) - ) { - if(!coupon || !(await couponService.consumeCouponAmount(coupon, evm.config.DRIP_AMOUNT))) { - res.status(400).send({message: "Invalid or expired coupon passed!"}) - return - } - } + // initialize instances + const evm = evms.get(chain) + const erc20Instance = evm?.instance?.contracts?.get(erc20 ?? "") - DEBUG && console.log( - "address:", address, - "chain:", chain, - "erc20:", erc20, - "ip:", req.headers["cf-connecting-ip"] || req.ip - ) - evm.instance.sendToken(address, erc20, async (data: SendTokenResponse) => { - const { status, message, txHash } = data - - // validate and consume coupon if required - if (evm.config.COUPON_REQUIRED && coupon && txHash === undefined) { - await couponService.reclaimCouponAmount(coupon, evm.config.DRIP_AMOUNT) - } - res.status(status).send({message, txHash}) - }) - } else { - res.status(400).send({message: "Invalid parameters passed!"}) + // validate parameters + if (evm === undefined || (erc20 && erc20Instance === undefined)) { + res.status(400).send({ message: 'Invalid parameters passed!' }) + return } + + // unique id for each token + const faucetConfigId = erc20Instance?.config.ID ?? evm?.config.ID + + // drip amount (native or erc20 token) for this request as per config + const dripAmount = erc20Instance?.config.DRIP_AMOUNT ?? evm.config.DRIP_AMOUNT + + // validate coupon + let couponValidity: CouponValidity = {isValid: false, amount: dripAmount} + + if ( + couponConfig.IS_ENABLED && + (erc20Instance && erc20Instance.config.COUPON_REQUIRED) || + (erc20Instance === undefined && evm.config.COUPON_REQUIRED) + ) { + // if coupon is required but not passed in request + if (coupon === undefined) { + res.status(400).send({message: "Coupon is required for this chain or token!"}) + return + } + couponValidity = await couponService.consumeCouponAmount(coupon, faucetConfigId, dripAmount) + if (!couponValidity.isValid) { + res.status(400).send({message: "Invalid or expired coupon passed!"}) + return + } + } + + // logging requests (if enabled) + DEBUG && console.log( + "address:", address, + "chain:", chain, + "erc20:", erc20, + "ip:", req.headers["cf-connecting-ip"] || req.ip + ) + + // send request + evm.instance.sendToken(address, erc20, couponValidity.amount, async (data: SendTokenResponse) => { + const { status, message, txHash } = data + + // reclaim coupon if transaction is failed + if (coupon && couponValidity.isValid && txHash === undefined) { + await couponService.reclaimCouponAmount(coupon, dripAmount) + } + res.status(status).send({message, txHash}) + }) }) // GET request for fetching all the chain and token configurations diff --git a/types.ts b/types.ts index 48a7d40..1817e1b 100644 --- a/types.ts +++ b/types.ts @@ -56,7 +56,6 @@ export type ERC20Type = { WINDOW_SIZE: number, MAX_LIMIT: number }, - COUPON_REQUIRED?: boolean, IMAGE?: string, RECALIBRATE?: number, RPC?: string, @@ -64,4 +63,10 @@ export type ERC20Type = { EXPLORER?: string, MAX_PRIORITY_FEE?: string, MAX_FEE?: string, + COUPON_REQUIRED?: boolean, +} + +export type CouponValidity = { + isValid: boolean, + amount: number, } \ No newline at end of file diff --git a/vms/evm.ts b/vms/evm.ts index f92062b..2dad74c 100644 --- a/vms/evm.ts +++ b/vms/evm.ts @@ -118,6 +118,7 @@ export default class EVM { async sendToken( receiver: string, id: string | undefined, + customAmount: number | undefined, cb: (param: SendTokenResponse) => void ): Promise { if(this.blockFaucetDrips) { @@ -144,19 +145,23 @@ export default class EVM { // increasing request count before processing request this.requestCount++ - let amount: bigint = this.DRIP_AMOUNT + let amount = this.DRIP_AMOUNT + let decimals = this.DECIMALS // If id is provided, then it is ERC20 token transfer, so update the amount if(id) { const contract = this.contracts.get(id) if (contract) { - const dripAmount: number = contract.config.DRIP_AMOUNT - if(dripAmount) { - amount = calculateBaseUnit(dripAmount.toString(), contract.config.DECIMALS || 18) - } + amount = contract.dripAmount + decimals = contract.decimals } } + // use custom amount + if(customAmount) { + amount = calculateBaseUnit(customAmount.toString(), decimals) + } + const requestId = receiver + id + Math.random().toString() this.processRequest({ receiver, amount, id, requestId }) @@ -461,7 +466,9 @@ export default class EVM { this.contracts.set(config.ID, { methods: (new this.web3.eth.Contract(JSON.parse(JSON.stringify(ERC20Interface)), config.CONTRACTADDRESS)).methods, balance: BigInt(0), - config + config, + dripAmount: calculateBaseUnit(config.DRIP_AMOUNT.toString(), config.DECIMALS || 18), + decimals: config.DECIMALS || 18, }) } diff --git a/vms/evmTypes.ts b/vms/evmTypes.ts index 37edbde..c98e9e2 100644 --- a/vms/evmTypes.ts +++ b/vms/evmTypes.ts @@ -39,4 +39,6 @@ export type ContractType = { methods: any, balance: bigint, config: ERC20Type, + dripAmount: bigint, + decimals: number, } From 0f36ed82a6ce902e4616819f36797526e582cde4 Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Wed, 22 Nov 2023 12:47:42 +0530 Subject: [PATCH 5/6] nit --- CouponService/couponService.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/CouponService/couponService.ts b/CouponService/couponService.ts index 96922b8..2ba76bf 100644 --- a/CouponService/couponService.ts +++ b/CouponService/couponService.ts @@ -134,7 +134,6 @@ export class CouponService { coupon.expiry > (Date.now() / 1000) && coupon.consumedAmount + couponAmount < coupon.maxLimitAmount ) { - console.log(coupon, couponAmount) coupon.consumedAmount += couponAmount return { isValid: true, amount: couponAmount} } From bf72d68c0aa274845f1ed2b8a7081920c8f3e26d Mon Sep 17 00:00:00 2001 From: Raj Ranjan Date: Mon, 27 Nov 2023 21:01:01 +0530 Subject: [PATCH 6/6] coupon reset --- CouponService/couponService.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CouponService/couponService.ts b/CouponService/couponService.ts index 2ba76bf..984f87e 100644 --- a/CouponService/couponService.ts +++ b/CouponService/couponService.ts @@ -10,7 +10,7 @@ type Coupon = { consumedAmount: number, expiry: number, amountPerCoupon: number, - + reset: boolean, } type CouponConfig = { @@ -82,7 +82,8 @@ export class CouponService { dbItemSet.add(coupon.id) // Only load new coupons into memory - if (this.coupons.get(coupon.id) === undefined) { + if (this.coupons.get(coupon.id) === undefined || coupon.reset) { + coupon.reset = false this.coupons.set(coupon.id, coupon) } } else {